Spring Boot (v2.0.5.RELEASE)
springboot
起步依赖自动添加了对hibernate validator
的依赖
或者也可以自己手动添加依赖
<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>6.0.13.Final</version> </dependency>
- 新建配置类
HibernateValidatorConfiguration.class
package com.futao.springmvcdemo.utils; import org.hibernate.validator.HibernateValidator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.validation.beanvalidation.MethodValidationPostProcessor; import javax.validation.Validation; import javax.validation.Validator; /** * @author futao * Created on 2018/9/23-20:00. * Hibernate Validator配置类 */ @Configuration public class HibernateValidatorConfiguration { /** * JSR和Hibernate validator的校验只能对Object的属性进行校验 * 不能对单个的参数进行校验 * spring 在此基础上进行了扩展 * 添加了MethodValidationPostProcessor拦截器 * 可以实现对方法参数的校验 * * @return */ @Bean public MethodValidationPostProcessor methodValidationPostProcessor() { MethodValidationPostProcessor processor = new MethodValidationPostProcessor(); processor.setValidator(validator()); return processor; } @Bean public static Validator validator() { return Validation .byProvider(HibernateValidator.class) .configure() //快速返回模式,有一个验证失败立即返回错误信息 .failFast(true) .buildValidatorFactory() .getValidator(); } // // public static <T> void validate(T obj) { // Set<ConstraintViolation<T>> constraintViolations = validator().validate(obj); // if (constraintViolations.size() > 0) { // throw LogicException.le(constraintViolations.iterator().next().getMessage()); // } // } }
2.定义错误消息(统一异常处理请查看)
package com.futao.springmvcdemo.model.entity.constvar; /** * @author futao * Created on 2018/9/21-15:29. * 错误提示集合类 * 错误码构成: 01程序员编号 * 001该程序员定义的错误码 * 后面再跟上错误信息 */ public final class ErrorMessage { public static final String SYSTEM_EXCEPTION = "系统繁忙,请稍后再试"; public static final String NOT_LOGIN = "01001_您还未登陆或者登陆已超时,请重新登陆"; public static final String MOBILE_ALREADY_REGISTER = "01002_该手机号已经被注册了"; public static final String LOGIC_EXCEPTION = "01003_对不起,你是真的没有我帅"; public static final String MOBILE_LEN_ILLEGAL = "01004_手机号长度不合法"; public static final String EMAIL_ILLEGAL = "01005_邮箱格式不合法"; public static final String USERNAME_LEN_ILLEGAL = "01006_名字长度不合法"; }
3.在全局异常处理类中拦截验证框架抛出的ConstraintViolationException
异常,
通过调试可以看到我们定义的异常信息在((ConstraintViolationException) e).getConstraintViolations().iterator().next().getMessage()
中
package com.futao.springmvcdemo.foundation; import com.alibaba.fastjson.JSONObject; import com.futao.springmvcdemo.model.entity.constvar.ErrorMessage; import com.futao.springmvcdemo.model.system.RestResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.validation.ConstraintViolationException; /** * @author futao * Created on 2018/9/21-15:13. * 异常统一处理, */ @ControllerAdvice public class GlobalExceptionHandler { private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class); @ExceptionHandler(value = Exception.class) @ResponseBody public Object logicExceptionHandler(HttpServletRequest request, Exception e, HttpServletResponse response) { //系统级异常,错误码固定为-1,提示语固定为系统繁忙,请稍后再试 RestResult result = new RestResult(false, "-1", e.getMessage(), ErrorMessage.SYSTEM_EXCEPTION); //如果是业务逻辑异常,返回具体的错误码与提示信息 if (e instanceof LogicException) { LogicException logicException = (LogicException) e; result.setCode(logicException.getCode()); result.setErrorMessage(logicException.getErrorMsg()); //Validator验证框架抛出的业务逻辑异常 } else if (e instanceof ConstraintViolationException) { String message = ((ConstraintViolationException) e).getConstraintViolations().iterator().next().getMessage(); result.setCode(message.substring(0, 5)); result.setErrorMessage(message.substring(6)); } else { //对系统级异常进行日志记录 logger.error("系统异常:" + e.getMessage(), e); } return JSONObject.toJSON(result); } }
3 使用
- 可以在进入业务逻辑之前的controller层对数据进行验证,即把参数验证注解打在controller的入参
3.1 将验证注解打在controller层
/** * @author futao * Created on 2018/9/19-15:05. */ @RequestMapping(path = "User", produces = MediaType.APPLICATION_JSON_UTF8_VALUE) @RestController @Validated public class UserController { @Resource private UserService userService; /** * 用户注册 * * @param username 用户名 * @param age 年龄 * @param mobile 手机号 * @param email 邮箱 * @param address 地址 * @return */ @PostMapping("register") public JSONObject register( /*使用@RequestBody注解需要保证该对象有默认的空的构造函数 * 是流的形式读取,那么流读了一次就没有了 * */ @RequestParam("username") @Size(min = 3, max = 8, message = ErrorMessage.USERNAME_LEN_ILLEGAL) String username, @RequestParam("age") String age, @Size(max = 11, message = ErrorMessage.MOBILE_LEN_ILLEGAL) @RequestParam("mobile") String mobile, @RequestParam("email") @Email(message = ErrorMessage.EMAIL_ILLEGAL) String email, @NotBlank @RequestParam("address") String address ) { JSONObject jsonObject = new JSONObject(); jsonObject.put("result", "注册失败"); if (userService.register(username, age, mobile, email, address)) { jsonObject.put("result", "注册成功"); } return jsonObject; } }
测试验证: