思路
Controller层有两种校验场景
单个参数的校验
// 用户登录 Controller 方法@PostMapping("/login")public Message login(String verifyCode,String account,String password){ //.... return null; }
实体类的校验
实体类User里,有多个字段需要校验,比如用户名不能为空,密码不能为空等等
// 添加用户 Controller 方法@PostMapping("/add")public Message addUser(User user){ //.... return null; }
下面介绍GET参数校验的实现方法。
环境
注意,Spring boot 内已经集成了Hibernate validator
Spring boot
Hibernate validator
lombok
Hibernate 参数校验 - GET参数校验模式 的实现
编写配置类
package com.spz.demo.security.config;import lombok.extern.slf4j.Slf4j;import org.hibernate.validator.HibernateValidator;import org.springframework.boot.autoconfigure.EnableAutoConfiguration;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;import javax.validation.ValidatorFactory;/** * 配置 Hibernate 参数校验 * 参考:https://blog.csdn.net/u010454030/article/details/53009327 */@Slf4j(topic = "SYSTEM_LOG")//日志模块@Configuration@EnableAutoConfigurationpublic class ValidatorConfig { @Bean public MethodValidationPostProcessor methodValidationPostProcessor() { MethodValidationPostProcessor postProcessor = new MethodValidationPostProcessor(); postProcessor.setValidator(validator());//快速校验,只要有错马上返回 return postProcessor; } @Bean public Validator validator(){ ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class ) .configure() .addProperty( "hibernate.validator.fail_fast", "true" ) .buildValidatorFactory(); Validator validator = validatorFactory.getValidator(); return validator; } }
编写验证错误信息提示
校验未通过时,将抛出ConstraintViolationException异常,此时需要在异常处理方法里获取错误信息,并进行返回
package com.spz.demo.security.config;import com.spz.demo.security.bean.Message;import org.springframework.http.HttpStatus;import org.springframework.stereotype.Component;import org.springframework.web.bind.annotation.ControllerAdvice;import org.springframework.web.bind.annotation.ExceptionHandler;import org.springframework.web.bind.annotation.ResponseBody;import org.springframework.web.bind.annotation.ResponseStatus;import javax.validation.ConstraintViolation;import javax.validation.ConstraintViolationException;import javax.validation.ValidationException;import java.util.Set;@ControllerAdvice@Componentpublic class GlobalExceptionHandler { /** * hibernate 参数校验出错会抛出 ConstraintViolationException 异常 * 在此方法中处理,将错误信息输出 * @param exception * @return */ @ExceptionHandler @ResponseBody @ResponseStatus(HttpStatus.BAD_REQUEST) public Object handle(ValidationException exception) { String errorInfo = ""; if(exception instanceof ConstraintViolationException){ ConstraintViolationException exs = (ConstraintViolationException) exception; Set<ConstraintViolation<?>> violations = exs.getConstraintViolations(); for (ConstraintViolation<?> item : violations) { errorInfo = errorInfo + "[" + item.getMessage() + "]"; } } return new Message().setErrorMessage(errorInfo); } }
Message类是包装请求返回,一般在Controller层使用,用于返回json格式数据
package com.spz.demo.security.bean;import com.fasterxml.jackson.annotation.JsonInclude;import com.spz.demo.security.common.MessageCode;import lombok.Data;import java.io.Serializable;import java.util.HashMap;import java.util.Map;/** * 请求响应Bean * 使用JSON包装请求返回,使用jackson库 * * @author spz */@Data@JsonInclude(JsonInclude.Include.NON_NULL)public class Message implements Serializable { private int code ; private String message ; private Map<String,Object> data = new HashMap<String, Object>(); /** * 自定义返回 * @param code * @param message * @return */ public Message setMessage(int code, String message){ this.code = code; this.message = message; return this; } /** * 返回成功 * @return */ public Message setSuccessMessage(){ this.code = MessageCode.SUCCESS ; this.message = "操作成功" ; return this; } /** * 返回成功 * @param message * @return */ public Message setSuccessMessage(String message){ this.code = MessageCode.SUCCESS ; this.message = message ; return this; } /** * 返回错误 * @param message * @return */ public Message setErrorMessage(String message){ this.code = MessageCode.ERROR ; this.message = message ; return this; } /** * 返回警告 * @param message * @return */ public Message setWarnMessage(String message){ this.code = MessageCode.WARN ; this.message = message ; return this; } /** * 返回未登录 * @param message * @return */ public Message setNoLoginMessage(String message){ this.code = MessageCode.NO_LOGIN ; this.message = message ; return this; } /** * 返回没有权限 * @param message * @return */ public Message setPermissionDeniedMessage(String message){ this.code = MessageCode.PERMISSION_DENIED ; this.message = message ; return this; } }
Controller 层使用校验
package com.spz.demo.security.controller;import com.spz.demo.security.bean.Message;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.redis.core.StringRedisTemplate;import org.springframework.validation.annotation.Validated;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import javax.validation.constraints.NotEmpty;/** * 用户控制器 * * @author spz */@Slf4j(topic = "USER_LOG")@RestController@RequestMapping("/user")@Validated//需要使用Hibernate非实体类参数校验,需要加入此注解public class UserController { @Autowired StringRedisTemplate redis; /** * 用户登录 * @return */ @PostMapping("/login") public Message login(@NotEmpty(message = "账号不能为空") String account, @NotEmpty(message = "密码不能为空") String password, @NotEmpty(message = "验证码不能为空") String verifyCode){ //.... return new Message().setSuccessMessage(); } }
使用时,发送用户登录请求,如果参数校验失败,将返回错误信息:
{ "code": 5000, "message": "[验证码不能为空]", "data": { } }
作者:萌璐琉璃
链接:https://www.jianshu.com/p/aa8b3163b30a