项目地址:https://github.com/wannengdek/spring-boot-seckill
如果项目对您有所帮助,麻烦帮忙点亮小⭐⭐
参数校验+全局异常处理器
1、使用 Vaild 进行检验
依赖:
<!-- 自定义参数校验器+全局异常处理器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
在形参前加上@Vaild ,然后在实体类的属性上加上注解。
@NotNull
@IsMobile
private String mobile;
@NotNull
@Length(min=32)
private String password;
notNull 的意思就是不为空,isMobile 就是验证是否为电话号码。
2 自定义异常处理
@ControllerAdvice
@ResponseBody
public class GlobalExceptionHandler {
@ExceptionHandler(value=Exception.class)
//异常拦截
public Result<String> exceptionHandler(HttpServletRequest request, Exception e){
e.printStackTrace();
if(e instanceof GlobalException) {
GlobalException ex = (GlobalException)e;
return Result.error(ex.getCm());
}else if(e instanceof BindException) {
BindException ex = (BindException)e;
List<ObjectError> errors = ex.getAllErrors();
ObjectError error = errors.get(0);
String msg = error.getDefaultMessage();
return Result.error(CodeMsg.BIND_ERROR.fillArgs(msg));
//将捕捉到的异常信息传递给状态码 显示到前端
}else {
return Result.error(CodeMsg.SERVER_ERROR);
}
}
}
首先是异常捕获,将捕获到的异常进行处理,然后使用包装类包装成需要的数据返回给后端.
Service 层的login 方法:
效果如下:
手机号如果是2 开头会报错
分布式Session
现在的服务器基本都是集群,比如用户A登录到了服务器A,session也存放到了服务器A,但当用户使用其他服务,跳转到服务器B时,服务器B没有用户A的登录信息,又让用户登陆一次,这是很不友好的.所以需要解决session一致性问题.
可以使用redis 将session 中的信息存放到redis中,每个服务器需要使用的时候去redis 中获取,也就不会出现session 不一致的问题.
(图片来自于:https://blog.csdn.net/xlgen157387/article/details/79191900)
本项目使用的解决方式是: 当用户的登录成功之后将他的相关信息返回到后端,生成token 存放到cookie 中,以后每次访问页面都带着token去访问,而通过解析cookile中的请求头中的token 就可以拿到用户的个人信息,不用去数据库中查询.
大概是这样的一个流程,感觉理解的不是很透彻,还需要加强.
使用 ArgumentResolvers 来直接将 User 信息注入到controller 中,方便操作.
@Service
public class UserArgumentResolver implements HandlerMethodArgumentResolver {
/**
* 接口说明:
* supportsParameter:用于判定是否需要处理该参数分解,返回true为需要,并会去调用下面的方法resolveArgument。
* resolveArgument:真正用于处理参数分解的方法,返回的Object就是controller方法上的形参对象。
*/
@Autowired
MiaoshaUserService userService;
/**
* 判断是否为指定对象
* @param parameter
* @return
*/
@Override
public boolean supportsParameter(MethodParameter parameter) {
Class<?> clazz = parameter.getParameterType();
return clazz== MiaoshaUser.class;
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);
String paramToken = request.getParameter(MiaoshaUserService.COOKI_NAME_TOKEN);
try {
String cookieToken = getCookieValue(request, MiaoshaUserService.COOKI_NAME_TOKEN);
//判断是否有cookie
if(StringUtils.isEmpty(cookieToken) && StringUtils.isEmpty(paramToken)) {
// System.out.println("清除cookie 后没有 cookie 返回null");
return new GlobalException(CodeMsg.SERVER_ERROR);
}
String token = StringUtils.isEmpty(paramToken)?cookieToken:paramToken;
// System.out.println("判断是否有cookie----resolveArgument");
return userService.getByToken(response, token);
}catch (Exception e1){
return new GlobalException(CodeMsg.SERVER_ERROR);
}
}
参考:
https://blog.csdn.net/fanrenxiang/article/details/81738634
https://blog.csdn.net/zhangli_wei0403/article/details/84328218