注册页面描述
注册页面主要内容如下
前端验证
在鼠标光标离开输入框,并且输入框内容有改变时进行验证。
1、昵称:判断是否为空-->正则表达式判断是否合法
/*判断用户名是否为空 是否合法(2-6个汉字)*/ $(":input[name=username]").change(function() { var val = $(this).val().trim(); if(val != "") { var pattern = /^[\u4e00-\u9fa5]{2,6}$/; if(!pattern.test(val)) { $("#_username_msg").html("昵称不合法").css("color", "red"); }else { $("#_username_msg").html("该昵称可用").css("color", "#7CFC00"); } }else { $("#_username_msg").html("用户名不能为空").css("color", "red"); } });
2、登录账号:判断是否为空-->正则表达式判断是否合法-->AJAX判断是否已存在
/* 判断账号是否为空 是否合法(英文字母或数字组成的4-16个字符) 发送 AJAX 请求校验账号是否可用*/ $(":input[name=account]").change(function() { var val = $(this).val(); val = $.trim(val); if(val != "") { var pattern = /^\w{4,16}$/ if(!pattern.test(val)) { $("#_account_msg").html("账号不合法").css("color", "red"); }else { var url = "user-validateAccount.action"; var args = {"account": val, "time": new Date()}; $.post(url, args, function(data) { if(data.hasAccount === true) { $("#_account_msg").html("该账号已存在").css("color", "red"); }else { $("#_account_msg").html("该账号可用").css("color", "#7CFC00"); } }); } }else{ $("#_account_msg").html("登录账号不能为空").css("color", "red"); } });
对于AJAX请求,后端验证需要注意的点
①由于我希望后端返回的是 JSON 格式,需要导入 struts2 相应的 json 包:struts2-json-plugin-2.3.35.jar
②struts 配置文件中ajax请求所在的包继承自 json-default:extends="json-default"
③对应的 result 为(其中 dataMap 用于返回数据):
<result name="ajax-success" type="json"> <param name="root">dataMap</param> </result>
④action 中对应的代码:
// 用于返回 ajax 请求的信息 使用 Map, struts2会将数据转为 json 格式 private Map<String, Object> dataMap = new HashMap<>(); public Map<String, Object> getDataMap() { return dataMap; } public void setDataMap(Map<String, Object> dataMap) { this.dataMap = dataMap; }
/** * 检验登录账号是否可用 */ private String account; public void setAccount(String account) { this.account = account; } public String validateAccount() { boolean flag = UserService.validateAccount(account); if(flag) { dataMap.put("hasAccount", false);//账号可用 }else { dataMap.put("hasAccount", true);//账号已存在 } return "ajax-success"; }
3、密码:判断是否为空-->正则表达式判断是否合法
$(":input[name=password]").change(function() { var val = $(this).val().trim(); if(val == "") { $("#_password_msg").html("密码不能为空").css("color", "red"); }else { if(val.length < 6) { $("#_password_msg").html("密码长度不能少于6位").css("color", "red"); } /*密码输入框已经限制了输入字符数*/ /*else if(val.length > 16) { $("#_password_msg").html("密码长度不能多于16位").css("color", "red"); }*/ else { $("#_password_msg").html(""); } } });
4、确认密码:判断是否和密码一致
$(":input[name=repassword]").blur(function() { var val = $(this).val().trim(); if(val != "") { var val2 = $(":input[name=password]").val().trim(); if(val != val2) { $("#_repassword_msg").html("两次密码不相同").css("color", "red"); }else { $("#_repassword_msg").html(""); } } });
5、手机号码:判断是否为空-->正则表达式判断是否合法-->AJAX判断是否已被注册
/*手机号码*/ $(":input[name=phone]").change(function() { var val = $(this).val().trim(); if(val != "") { /*判断手机号码格式是否正确*/ var pattern = /^1[34578]\d{9}$/ if(!pattern.test(val)) { $("#_phone_msg").html("手机号码有误").css("color", "red"); }else { /* AJAX 请求检验该手机号是否注册过 */ var url = "user-validatePhone.action"; var args = {"phone": val, "time": new Date()}; $.post(url, args, function(data) { if(data.hasPhone === true) { $("#_phone_msg").html("该手机号已被注册").css("color", "red"); }else { $("#_phone_msg").html(""); } }); } }else { $("#_phone_msg").html("手机号不能为空").css("color", "red"); } });
AJAX请求与账号类似
6、邮箱:判断是否为空-->正则表达式判断是否合法-->AJAX判断是否已被注册
/*邮箱 */ $(":input[name=email]").change(function() { var val = $(this).val().trim(); if(val != "") { /*判断邮箱格式是否正确*/ var pattern = /^\w{3,}(\.\w+)*@[A-z0-9]+(\.[A-z]{2,5}){1,2}$/ if(!pattern.test(val)) { $("#_email_msg").html("邮箱格式有误").css("color", "red"); }else { /*AJAX 请求验证邮箱是否被注册过*/ var url = "user-validateEmail.action"; var args = {"email": val, "time": new Date()}; $.post(url, args, function(data) { if(data.hasEmail === true) { $("#_email_msg").html("该邮箱已被注册").css("color", "red"); }else { $("#_email_msg").html(""); } }); } }else { $("#_email_msg").html("邮箱不能为空").css("color", "red"); } });
AJAX请求与账号类似
完成日期:2018/11/28
后端验证
由于前端验证只是一个提示作用,我并没有在点击注册按钮生效前再次进行验证,需要struts的验证器对这些字段进行验证
1、在 Action 所在的包新建一个 xml 文件:UserAction-user-register-validation.xml
UserAction 对应 ActionClassName,user-register 对应 action 请求,validation.xml固定写法
UserAction-user-register-validation.xml 内容如下:
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.2//EN" "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd"> <validators> <!-- 昵称验证 --> <field name="username"> <!-- 开启短路验证 验证是否为空--> <field-validator type="requiredstring" short-circuit="true"> <!-- 验证前去掉前后空格 --> <param name="trim">true</param> <message key="error.username.isnull" /> </field-validator> <!-- 验证是否合法 --> <field-validator type="regex"> <param name="regexExpression"><![CDATA[([\u4e00-\u9fa5]{2,6})]]></param> <message key="error.username.regex" /> </field-validator> </field> <!-- 账号验证 --> <field name="account"> <field-validator type="requiredstring" short-circuit="true"> <param name="trim">true</param> <message key="error.account.isnull"></message> </field-validator> <field-validator type="regex"> <param name="regexExpression"><![CDATA[(\w{4,16})]]></param> <message key="error.account.regex" /> </field-validator> </field> <!-- 密码验证 --> <field name="password"> <field-validator type="requiredstring" short-circuit="true"> <message key="error.password.isnull"></message> </field-validator> <field-validator type="stringlength"> <param name="minLength">6</param> <message key="error.password.length"></message> </field-validator> </field> <!-- 字段验证 两次密码输入是否一致 --> <field name="repassword"> <field-validator type="fieldexpression"> <param name="expression"><![CDATA[repassword==password]]></param> <message key="error.password.unequal"></message> </field-validator> </field> <!-- 非字段验证 两次密码输入是否一致 --> <!-- <validator type="expression"> <param name="expression"><![CDATA[repassword==password]]></param> <message key="error.password.unequal"></message> </validator> --> <!-- 手机号码验证 --> <field name="phone"> <field-validator type="requiredstring" short-circuit="true"> <param name="trim">true</param> <message key="error.phone.isnull"></message> </field-validator> <field-validator type="regex"> <param name="regexExpression"><![CDATA[(1[34578]\d{9})]]></param> <message key="error.phone.regex" /> </field-validator> </field> <!-- 邮箱验证 --> <field name="email"> <field-validator type="requiredstring" short-circuit="true"> <param name="trim">true</param> <message key="error.email.isnull"></message> </field-validator> <field-validator type="regex"> <param name="regexExpression"><![CDATA[(\w{3,}(\.\w+)*@[A-z0-9]+(\.[A-z]{2,5}){1,2})]]></param> <message key="error.email.regex" /> </field-validator> </field> </validators>
错误提示信息文件 i18n.properties(方便后面做国际化)
error.username.isnull=\u6635\u79F0\u4E0D\u80FD\u4E3A\u7A7A error.username.regex=\u8BE5\u6635\u79F0\u4E0D\u5408\u6CD5 error.account.isnull=\u8D26\u53F7\u4E0D\u80FD\u4E3A\u7A7A error.account.regex=\u8BE5\u8D26\u53F7\u4E0D\u53EF\u7528 error.password.isnull=\u5BC6\u7801\u4E0D\u80FD\u4E3A\u7A7A error.password.length=\u5BC6\u7801\u957F\u5EA6\u4E0D\u80FD\u5C11\u4E8E${minLength}\u4F4D error.password.unequal=\u4E24\u6B21\u5BC6\u7801\u8F93\u5165\u4E0D\u4E00\u81F4 error.phone.isnull=\u624B\u673A\u53F7\u7801\u4E0D\u80FD\u4E3A\u7A7A error.phone.regex=\u624B\u673A\u53F7\u7801\u6709\u8BEF error.email.isnull=\u90AE\u7BB1\u4E0D\u80FD\u4E3A\u7A7A error.email.regex=\u90AE\u7BB1\u683C\u5F0F\u6709\u8BEF
需要在 struts 配置文件中添加:<constant name="struts.custom.i18n.resources" value="i18n"></constant>
前端页面通过 OGNL 表达式获取错误信息:${fieldErrors.xxx[0] }
2、当通过 struts 的验证器后,进入 UserAction 中的注册方法
①、实现 ModelDriven, Preparable 接口
实现 ModelDriven 可将各个字段封装在 javaBean 中
实现 Preparable 接口可在调用目标方法前对该方法的 Model 进行处理
Preparable 接口有一个 prepare() 方法,默认是执行的,由于我希望每个 action 方法对应一个自己的 prepare 方法,在配置文件中将 prepare() 方法改为不执行
在所在的 package 中定义,
<!-- 定义新的拦截器栈, 配置 prepare 拦截器栈的 alwaysInvokePrepare 参数值为 false --> <interceptors> <interceptor-stack name="appointmentStack"> <interceptor-ref name="paramsPrepareParamsStack"> <param name="prepare.alwaysInvokePrepare">false</param> </interceptor-ref> </interceptor-stack> </interceptors> <!-- 使用新的拦截器栈 --> <default-interceptor-ref name="appointmentStack"></default-interceptor-ref>
②、由于我的 User 没有“确认密码”对应的字段,需要准备一个 String 类型的字符串来保存它,当时由于这个原因导致我的密码和确认密码的验证一直无法通过
private String repassword;// 获取确认密码 public void setRepassword(String repassword) { this.repassword = repassword; } public String getRepassword() { return repassword; }
核心方法
public String register() { // 注册失败时可用于回显 request.put("username", user.getUsername()); request.put("account", user.getAccount()); request.put("phone", user.getPhone()); request.put("email", user.getEmail()); // 先判断验证码 if (checkCode != null && checkCode.equals(session.get("check"))) { user.setRegisterTime(new Date());// 设置注册时间 String flag = UserService.register(user); if (flag == "Account") { request.remove("account");// 让该字段不回显 request.put("hasAccount", "该账号已存在!!"); return "input"; } else if (flag == "Phone") { request.remove("phone"); request.put("hasPhone", "该手机号已被注册!!"); return "input"; } else if (flag == "Email") { request.remove("email"); request.put("hasEmail", "该邮箱已被注册!!"); return "input"; } else { return "success"; } } else { request.put("checkImg", "验证码输入错误"); return "input"; } } public void prepareRegister() { user = new User(); }
前端通过 EL 表达式获取错误提示信息
验证码
①、新建一个验证码 action:CheckImgAction.java
package com.zhc.actions; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.util.Map; import java.util.Random; import javax.imageio.ImageIO; import org.apache.struts2.ServletActionContext; import org.apache.struts2.interceptor.SessionAware; import com.opensymphony.xwork2.ActionSupport; public class CheckImgAction extends ActionSupport implements SessionAware { /** * */ private static final long serialVersionUID = -4133833024670509406L; @Override public String execute() throws Exception { int width = 120; int height = 30; // 1、准备一张图片 BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); // 2、图片背景颜色 Graphics graphics = bufferedImage.getGraphics(); // 指定颜色 graphics.setColor(getRandColor(200, 250)); graphics.fillRect(0, 0, width, height); // 3、绘制边框 graphics.setColor(Color.WHITE); graphics.drawRect(0, 0, width - 1, height - 1); // 4、四个随机数字 Graphics2D graphics2d = (Graphics2D) graphics; // 输出字体 graphics2d.setFont(new Font("宋体", Font.BOLD, 18)); String words = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890"; //生成随机数 Random random = new Random(); StringBuffer sb = new StringBuffer(); int x = 10; for(int i = 0; i < 4; i++) { graphics2d.setColor(new Color(20 + random.nextInt(110), 20 + random.nextInt(110), 20 + random.nextInt(110))); //角度旋转 -30 - 30 int angle = random.nextInt(60) - 30; //换算弧度 double theta = angle * Math.PI / 180; //生成一个随机数字 int index = random.nextInt(words.length()); //获得字母或数字 char c = words.charAt(index); sb.append(c); //输出到图片 graphics2d.rotate(theta, x, 20); graphics2d.drawString(String.valueOf(c), x, 20); graphics2d.rotate(-theta, x, 20); x += 30; } //将字符串放入 session 用于Action,不能忘了toString方法 session.put("check", sb.toString()); //5、绘制干扰线 graphics.setColor(getRandColor(160, 200)); int x1; int x2; int y1; int y2; for(int i =0; i < 30; i++) { x1 = random.nextInt(width); x2 = random.nextInt(12); y1 = random.nextInt(height); y2 = random.nextInt(12); graphics.drawLine(x1, y1, x1 + x2, y1 + y2); } //释放资源 graphics.dispose(); //将图片输出到浏览器 ImageIO.write(bufferedImage, "jpg", ServletActionContext.getResponse().getOutputStream()); return NONE; } private Color getRandColor(int fc, int bc) { Random random = new Random(); if (fc > 255) { fc = 255; } if (bc > 255) { bc = 255; } int r = fc + random.nextInt(bc - fc); int g = fc + random.nextInt(bc - fc); int b = fc + random.nextInt(bc - fc); return new Color(r, g, b); } private Map<String, Object> session; @Override public void setSession(Map<String, Object> session) { this.session = session; } }
②、Spring 配置文件中配置 bean:applicationContext-beans.xml
<!-- 验证码Action --> <bean id="checkImgAction" class="com.zhc.actions.CheckImgAction" scope="prototype"></bean>
③、struts 配置文件中配置 Action
<!-- 验证码Action --> <action name="checkImg" class="checkImgAction"></action>
④、前端页面
<li class="layout"> <span class="register_label">验证码:</span> <div class="register_input"> <input class="inp_lon" type="text" name="checkCode" autocomplete="off"/> <img id="checkImg" src="${pageContext.request.contextPath}/checkImg.action" alt="更换图片" onclick="ChangeCodeImg()" title="点击更换图片" /> <span id="_checkImg_msg" >${requestScope.checkImg }</span> </div> </li>
⑤、jquery 切换文件
/*更换验证码图片*/ $("#checkImg").click(function() { $("#checkImg").attr(‘src‘, "${pageContext.request.contextPath}/checkImg.action?"+new Date().getTime()); });
完成日期:2018/11/29
原文地址:https://www.cnblogs.com/zhanghongcan/p/10048565.html