基于SSH的预约挂号系统之注册验证

注册页面描述

  注册页面主要内容如下

前端验证

  在鼠标光标离开输入框,并且输入框内容有改变时进行验证。

 

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="更换图片" οnclick="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

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值