Java Web参数验证

一. 前言

     java web项目中,前端和后端会进行数据交互,参数(包括入参和出参)校验不可避免。现在都9102年了,想必没人会傻到对数据来者不拒,在服务层通过if else的方式筛选数据吧?因此,这里有三种解决方案。

二. 解决方案

    1. javax.validation

    2. hibernate-validator (引入了javax.validation 极力推荐)

    3. 自定义注解

三. javax.validation

    1. maven pom.xml中引入jar

<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
    <version>1.1.0.Final</version>
</dependency>

  2. 在maven仓库中找到validation-api-1.1.0.Final.jar,打开如下图所示:

      

      红色框是javax.validation提供用于验证的注解,它们的作用如图:

      

     @NotEmplty: 只能标记字符串,字符串非null,且长度大于0

     @NotBlank: 只能标记字符串字符串非null,且trim后的长度大于0

     3. 下面分享一个实际项目中使用的案例: 

package uyun.jsm.api.vo;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.*;
import uyun.jsm.api.validation.ValidGroupAdd;
import uyun.jsm.api.validation.ValidGroupUpdate;
import uyun.jsm.api.vo.base.PageHelperVO;

import javax.validation.constraints.DecimalMax;
import javax.validation.constraints.DecimalMin;
import javax.validation.constraints.NotNull;
import java.util.Date;

/**
 * 事件
 */
@EqualsAndHashCode(callSuper = true)
@JsonInclude(JsonInclude.Include.NON_DEFAULT)
@AllArgsConstructor
@NoArgsConstructor
@Data
@Builder
public class ScheduleEventVO extends PageHelperVO {
    @NotNull(message = "事件id不允许为空", groups = {ValidGroupUpdate.class})
    private String id;
    @NotNull(message = "事件名称不允许为空", groups = {ValidGroupAdd.class, ValidGroupUpdate.class})
    private String name;

    //事件类别(0: 普通事件   1: 祝福事件   2: 节假日事件)
    @NotNull(message = "事件类别(type)不能为空,且只能填写0或1或2,其中0代表普通事件,1代表祝福事件,2代表节假日事件", groups = {ValidGroupAdd.class, ValidGroupUpdate.class})
    @DecimalMin(value = "0" , message = "事件类别(type)的最小值为0", groups = {ValidGroupAdd.class, ValidGroupUpdate.class})
    @DecimalMax(value = "2", message = "事件类别(type)的最大值为2", groups = {ValidGroupAdd.class, ValidGroupUpdate.class})
    private Integer type;

    private String description;

    @NotNull(message = "启用状态(enabled)不能为空,只能填写0或-1, 其中0代表启用, -1代表停用", groups = {ValidGroupAdd.class, ValidGroupUpdate.class})
    @DecimalMin(value = "-1", message = "启用状态(enabled)的最小值为-1", groups = {ValidGroupAdd.class, ValidGroupUpdate.class})
    @DecimalMax(value = "0",  message = "启用状态(enabled)的最大值为0", groups = {ValidGroupAdd.class, ValidGroupUpdate.class})
    private Integer enabled;

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date createTime;

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date updateTime;
}

    4. 最后,在Controller中使用@Valid 去标记需要使用注解验证的对象,在需要使用javax.validation的类上使用@validated即可,如果数据异常则会统一抛出exception,方便全局异常处理器统一处理。

四. hibernate-validator

    1. maven pom.xml中引入jar

<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.0.13.Final</version>
</dependency>

       如果你使用了spring-boot-starter-web,那么恭喜你,这个jar中除了spring-web、spring-webmvc外,已经引入了hibernate-validator。让我们看看hibernate-validator与javax.validation之间的关系吧:

   

      如图所示,hibernate-validator本身包含了validation-api。

      2. 除去validation-api包含的注解标签外,hibernate-validator还包含了以下注解:

           

          值得注意的是,在高版本中,官方对hibernate-validator提供的某些注解进行了升级,具体的代替品请参考官网链接:http://docs.jboss.org/hibernate/validator/6.0/api/index.html?org/hibernate/validator/constraints/NotEmpty.html

    有些人可能会遇到以下错误,这是hibernate-validator老版本的bug,在6.0.x版本后不会遇到此问题。如果你升级了6.0.x版本后仍然报如下错误,请将<groupId>org.hibernate</groupId> 修改成 <groupId>org.hibernate.validator</groupId>,亲测解决问题。

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is javax.validation.UnexpectedTypeException: HV000030: No validator could be found for constraint 'javax.validation.constraints.NotBlank' validating type 'java.lang.String'. Check configuration for 'name'

      3. 实际项目中,Controller层搭配org.springframework.validation.BindResult能得到验证结果

@PostMapping(value = "/updateEvent", produces = MediaType.APPLICATION_JSON_VALUE)
public RespResultBO updateEvent(HttpServletRequest request, @RequestBody @Validated (ValidGroupUpdate.class) ScheduleEventBO obj, BindingResult bindingResult){
        if(bindingResult.hasErrors()){
            return RespResultBO.<BindingResult>builder().code(ResponseEnum.CODE_400.getCode()).message(bindingResult.getFieldError().getDefaultMessage()).build();
        }else{
            return scheduleService.updateEvent(obj, getUser(request));
        }
}

五. 自定义注解

          TODO

发布了45 篇原创文章 · 获赞 13 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/miaomiao19971215/article/details/89434821