(二)Java秒杀项目之实现登录功能

一、数据库设计

CREATE TABLE `miaosha_user` (
  `id` bigint(20) NOT NULL COMMENT '用户ID,手机号码',
  `nickname` varchar(255) NOT NULL,
  `password` varchar(32) DEFAULT NULL COMMENT 'MD5(MD5(pass明文+固定salt) salt)',
  `salt` varchar(10) DEFAULT NULL,
  `head` varchar(128) DEFAULT NULL COMMENT '头像,云存储的ID',
  `register_date` datetime DEFAULT NULL COMMENT '注册时间',
  `last_login_date` datetime DEFAULT NULL COMMENT '上登录时间',
  `login_count` int(11) DEFAULT '0' COMMENT '登录次数',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='秒杀用户表';

SET FOREIGN_KEY_CHECKS = 1;

二、明文密码两次MD5处理

1、用户端:pass = MD5(明文+固定salt)

2、服务端:pass = MD5(用户输入+随机salt)

第一次加密防止用户明文密码在网络上传输,第二次加密防止数据库被盗后将一次加密反向破解

引入依赖commons-codec和commons-lang3,使用commons-codec依赖下的DigestUtils类的md5Hex方法加密处理

安全起见,使用固定salt(就是一个字符串)中的部分字符与密码拼接后进行第一次加密

第二次加密使用随机salt,通过入参salt来传递

三、JSR303参数检验+全局异常处理器

jsr303参数校验

1、pom.xml 引入依赖spring-boot-starter-validation,该依赖包含了hibernate-validator依赖

2、LoginController.java 删除之前的参数校验部分,在doLogin方法的LoginVo类型入参前加上@Valid注解,该注解在validation-api依赖下,然而该依赖并没有手动引入,可能是新建SpringBoot项目时自动引入了。

3、LoginVo.java 在password变量前添加@NotNull注解,@Length注解;在mobile变量前添加@NotNull注解,@IsMobile注解,其中@NotNull和@Length在validation-api依赖下,@IsMobile注解为接下来要自定义的注解。

4、IsMobile.java 新建注解,拷贝@NotNull注解中的部分内容,仿照着@NotNull注解来写。在拷贝过来的@Constraint(validateBy={})中添加将要新建的IsMobileValidator.class类,做为校验器,改完之后为@Constraint(validateBy={IsMobileValidator.class})。添加boolean required() default true; 表示标注该注解的变量必需要传值。

5、IsMobileValidator.class 新建类,作为校验器,需要实现ConstraintValidator<A, T>接口,A处就填IsMobile,T处填了String。实现父接口中的两个方法,initialize和isValid方法。

6、运行测试,浏览器检查代码的Netword部分会提示需要的信息和异常信息。异常信息需要捕获,需要的信息才可以正常提示,见下节。

异常处理

标题:异常处理

1、GlobalExceptionHandler.java 新建类,添加exceptionHandler方法,该方法需标注@ExceptionHandler(value = Exception.class) 表示要拦截所有的异常,方法体内先拦截刚才的BindException,步骤依次为异常类型强转,获取所有错误信息,拿到第一个错误,拿到具体错误信息,最后拼接完后返回。拼接调用接下来的CodeMsg.java类中的fillArgs方法。

2、CodeMsg.java 添加绑定异常静态常量BIND_ERROR,注意他的msg参数处留一个位置。添加fillArgs方法,供第一步拼接时调用。

写在最后:这样,浏览器中的异常信息,经过上述代码就可以捕获并处理,最终友好的显示在浏览器页面。

标题:异常处理优化

0、导语:之前MiaoshaUserService.java类中login方法的返回值为CodeMsg类型,但是应该返回表达业务方法含义的方法,而不应该是CodeMsg类型。所以我们可以定义一个全局异常类,将异常直接抛出去,交给异常处理器处理。

1、GlobalException.java 新建异常类,封装CodeMsg类型变量,供抛出时实例化使用。

2、MiaoshaUserService.java 修改login方法返回类型为boolean,方法体内的错误直接通过实例化GlobalException类,并入参CodeMsg类型的静态常量,来将异常抛出去。

3、GlobalExceptionHandler.java 修改exceptionHandler方法,增加处理GlobalException异常的逻辑。

4、LoginController.java 修改doLogin方法,优化登录逻辑。

写在最后:方法的返回类型要根据业务方法含义来判断,方法体内遇到的错误可以通过自定义异常封装类和异常处理类来拦截再处理。

四、分布式Session

详见github上的提交https://github.com/yanguobin/mymiaosha

posted @ 2019-10-28 14:47  请叫我小老弟  阅读(1035)  评论(1编辑  收藏  举报