springMVC基于hibernate validator的表单统一校验

具体实现:
1、本测试项目采用maven工程。在pom.xml文件中增加对validator.jar依赖的引入
由于这个项目是分布式的
所以我在parent项目的pom文件中添加jar包

		<properties>
			<version-hibernate-validate>5.4.0.Final</version-hibernate-validate>
		</properties>
		
		 <dependencyManagement>
			 <dependencies>
				<dependency>
		                <groupId>org.hibernate</groupId>
		                <artifactId>hibernate-validator</artifactId>
		                <version>${version-hibernate-validate}</version>
		        </dependency>
		    </dependencies>
		 </dependencyManagement>

2.配置是spring-mvc.xml(resource里面)

 <!-- validation -->
    <bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor"/>

    <!-- 国际化配置 -->
    <bean id="localeResolver" class="org.springframework.web.servlet.i18n.CookieLocaleResolver" />
    <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <property name="useCodeAsDefaultMessage" value="true" />
    </bean>
    <!-- 注册验证器 -->
    <mvc:annotation-driven validator="validator" />

    <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
        <property name="providerClass" value="org.hibernate.validator.HibernateValidator" />
        <!-- 这里配置将使用上面国际化配置的messageSource -->
        <property name="validationMessageSource" ref="messageSource" />
    </bean>

3.建立统一处理
这个我是写在BaseExceptionController里面的,分销商controller里面的一个类用来捕获各种异常。(有点像工具类一样,个人理解)

@ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public BaseResponse handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        logger.error("参数验证失败", e);
        BindingResult result = e.getBindingResult();

        BaseResponse baseResponse = new BaseResponse();
        // 取第一条返回
        for (ObjectError error : result.getAllErrors()) {
            String code = error.getCode();
            String message = error.getDefaultMessage();
            String description = String.format("%s:%s", code, message);
            baseResponse.setData("400");
            baseResponse.setSuccess(false);
            baseResponse.setMsg(description);
            break;
        }
        return baseResponse;
    }

补充:
HttpStatus.BAD_REQUEST:表示报400.
@ExceptionHandler:统一处理某一类异常,从而能够减少代码重复率和复杂度
我们接口规范要求返回baseResponse(data,message,success)

4.在vo上面加上注解
vo和实体类是不同的(单一职责)

public class UserVO {
   
    @NotEmpty(message="姓名不能为空")
    private String name;

    @Range(min=20,max=120,message="年龄在20到120岁之间")
    private int age;

    @NotEmpty(message="地址不能为空")
    private String address;

    ... getter 
    ... setter
}


5.测试controller

@Controller
@RequestMapping(value = "/operation/hello")
public class HelloController {

    public static final Logger LOG = LoggerFactory.getLogger(HelloController.class);

    @RequestMapping(value = "/testValidUser", method = RequestMethod.POST)
    @ResponseBody
    public String testValidUser(@RequestBody @Valid UserVO userVO){

        return baseResponse.getMessage.toJSON();
    }
}

6.测试结果
假设前端传的body是这样的

{
    "name":"",
    "age":130,
    "address":""
}

接口返回的结果是:

{
  "data": [
    "年龄在20到120岁之间",
    "姓名不能为空",
    "地址不能为空"
  ],
  "message": "参数不合法",
  "success": false
}

补充:
/

* Bean Validation 中内置的 constraint
*
* @Null 被注释的元素必须为 null
* @NotNull 被注释的元素必须不为 null
* @AssertTrue 被注释的元素必须为 true
* @AssertFalse 被注释的元素必须为 false
* @Min(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
* @Max(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
* @DecimalMin(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
* @DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
* @Size(max=, min=) 被注释的元素的大小必须在指定的范围内
* @Digits(integer, fraction) 被注释的元素必须是一个数字,其值必须在可接受的范围内
* @Past 被注释的元素必须是一个过去的日期
* @Future 被注释的元素必须是一个将来的日期
* @Pattern(regex=,flag=) 被注释的元素必须符合指定的正则表达式
*
* Hibernate Validator 附加的 constraint
*
* @NotBlank(message =) 验证字符串非null,且长度必须大于0
* @Email 被注释的元素必须是电子邮箱地址
* @Length(min=,max=) 被注释的字符串的大小必须在指定的范围内
* @NotEmpty 被注释的字符串的必须非空
* @Range(min=,max=,message=) 被注释的元素必须在合适的范围内
*/
**

新补充:后来发现用注解做不了所以,单独定义了规则来切我所有的控制层,用before来做校验

@Component
@Aspect
@SuppressWarnings("rawtypes")
public class ValidatorAspect {

    private static Logger             log = LoggerFactory.getLogger(ValidatorAspect.class);

    @Resource
    private LocalValidatorFactoryBean localValidatorFactoryBean;

    /**
     * 参数校验切面定义
     */
    @Pointcut("execution(public (com.ejavashop.core.BaseResponse) com.ejavashop.web.controller.*..*Controller.*(..))")
    public void parameterPointCut() {
        //pointcut
    }

    @Before("parameterPointCut()")
    public void validateParameter(JoinPoint joinPoint) {

        // 入参校验
        BaseRequest baseRequest = null;
        String token = null;

        Object[] args = joinPoint.getArgs();
        for (Object arg : args) {
            if (arg instanceof BaseRequest) {
                baseRequest = (BaseRequest) arg;
            } else if (isValidToken(arg)) {
                token = (String) arg;
            }
        }
        if (baseRequest == null) {
            return;
        }

        Set<ConstraintViolation<BaseRequest>> validErrors = localValidatorFactoryBean
            .validate(baseRequest, Default.class);
        Iterator iterator = validErrors.iterator();
        StringBuilder errorMsg = new StringBuilder();
        while (iterator.hasNext()) {
            ConstraintViolation constraintViolation = (ConstraintViolation) iterator.next();
            errorMsg.append(iterator.hasNext() ? constraintViolation.getMessage() + "; "
                : constraintViolation.getMessage());
        }
        if (!validErrors.isEmpty()) {
            log.error("[validate error]参数校验失败,失败原因:" + errorMsg.toString());
            throw new ValidateException(errorMsg.toString());
        }

        // 切面给baseRequest注入userId,userName
        if (token != null) {
            Integer userId = JWTUtil.getUserId(token);
            String userName = JWTUtil.getUsername(token);
            Integer grade = JWTUtil.getGrade(token);
            baseRequest.setUserId(userId);
            baseRequest.setUserName(userName);
            baseRequest.setGrade(grade);
        }

    }
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值