在表单提交时,controller都要验证从前端接受的参数,假如每个参数都手动判断会比较麻烦,可以采用验证框架来简化对参数的验证
1 导入依赖
<!--JSR303参数校验开始--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> <!--JSR303参数校验结束-->
2 controller层方法形参添加Valid注解
@RequestMapping("/do_login") @ResponseBody public Result<String> doLogin(HttpServletResponse response, @Valid LoginVo loginVo) { log.info(loginVo.toString()); //登录 String token = userService.login(response, loginVo); return Result.success(token); }
对请求参数的封装pojo
这里的NotNull 是框架自带的注解,IsMobile是自定义注解
public class LoginVo { @NotNull @IsMobile private String mobile; @NotNull @Length(min=6,max=16,message = "密码长度错误") private String password; public String getMobile() { return mobile; } public void setMobile(String mobile) { this.mobile = mobile; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public String toString() { return "LoginVo [mobile=" + mobile + ", password=" + password + "]"; } }
安装下面的方式自定义注解
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER }) @Retention(RUNTIME) @Documented @Constraint(validatedBy = {IsMobileValidator.class }) public @interface IsMobile { boolean required() default true; String message() default "手机号码格式错误"; Class<?>[] groups() default { }; Class<? extends Payload>[] payload() default { }; }
public class IsMobileValidator implements ConstraintValidator<IsMobile, String> { private boolean required = false; public void initialize(IsMobile constraintAnnotation) { required = constraintAnnotation.required(); } public boolean isValid(String value, ConstraintValidatorContext context) { if(required) { return ValidatorUtil.isMobile(value); }else { if(StringUtils.isEmpty(value)) { return true; }else { return ValidatorUtil.isMobile(value); } } } }
3 全局异常捕获
public class GlobalException extends RuntimeException{ private static final long serialVersionUID = 1L; private CodeMsg cm; public GlobalException(CodeMsg cm) { super(cm.toString()); this.cm = cm; } public CodeMsg getCm() { return cm; } }
@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); } } }
4 service层方法
public String login(HttpServletResponse response, LoginVo loginVo) { if(loginVo == null) { throw new GlobalException(CodeMsg.SERVER_ERROR); } String mobile = loginVo.getMobile(); String formPass = loginVo.getPassword(); //判断手机号是否存在 MiaoshaUser user = getById(Long.parseLong(mobile)); if(user == null) { throw new GlobalException(CodeMsg.MOBILE_NOT_EXIST); } //验证密码 String dbPass = user.getPassword(); String saltDB = user.getSalt(); String calcPass = MD5Util.formPassToDBPass(formPass, saltDB); if(!calcPass.equals(dbPass)) { throw new GlobalException(CodeMsg.PASSWORD_ERROR); } //生成cookie String token = UUIDUtil.uuid(); addCookie(response, token, user); return token; }
5 返回给前端的json
public class Result<T> { private int code; private String msg; private T data; /** * 成功时候的调用 * */ public static <T> Result<T> success(T data){ return new Result<T>(data); } /** * 失败时候的调用 * */ public static <T> Result<T> error(CodeMsg codeMsg){ return new Result<T>(codeMsg); } private Result(T data) { this.data = data; } private Result(int code, String msg) { this.code = code; this.msg = msg; } private Result(CodeMsg codeMsg) { if(codeMsg != null) { this.code = codeMsg.getCode(); this.msg = codeMsg.getMsg(); } } public int getCode() { return code; } public void setCode(int code) { this.code = code; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public T getData() { return data; } public void setData(T data) { this.data = data; } }
这样的好处是对参数验证只要添加注解就可以了。参数验证不通过会抛出异常,被异常处理器捕获,将错误信息直接返回 给前端。
而且异常处理器也会捕获自定义的全局异常。
原文:https://www.cnblogs.com/moris5013/p/12337335.html