常见的业务开发中无可避免的会进行请求参数校验,一般对于复杂的业务参数校验,可以通过校验类单独的校验方法进行处理,通常对于一些与业务无关简单的参数校验可以采用javax.validation 和 hibernate-validator通过注解的方式实现校验。
注解 | 说明 |
---|---|
@Length(min=,max=) | 检查所属的字段的长度是否在min和max之间,只能用于字符串 |
@Range(min=,max=,message=) | 被注释的元素必须在合适的范围内 |
@Max | 该字段的值只能小于或等于该值 |
@Min | 该字段的值只能大于或等于该值 |
@NotNull | 不能为null |
@NotBlank | 不能为空,检查时会将空格忽略 |
@NotEmpty | 不能为空,这里的空是指空字符串 |
@Pattern(regex=,flag=) | 被注释的元素必须符合指定的正则表达式 |
注意:
1.正则表达式@Pattern注解只用于String类型的字段上。数字类型的可用@Range注解。
2.需要在Controller中请求对象或者参数前加@Validated或@Valid注解一起使用,
@Validated和@Valid注解区别不是很大,一般情况下任选一个即可,区别如下:
注解 | @Validated | @Valid |
---|---|---|
所属的包 | 属于org.springframework.validation.annotation包下的,是spring提供的 | 属于javax.validation包下,是jdk给提供的 |
是否支持分组和排序 | 是 | 否 |
虽然@Validated比@Valid更加强大,在@Valid之上提供了分组功能和验证排序功能,不过在实际项目中一直没有用到过 Hibernate-validate框架中的注解是需要加在实体中一起使用的
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.5.0</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>category</artifactId> <version>0.0.1-SNAPSHOT</version> <name>category</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.4</version> </dependency> <!--数据库连接诶--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!--常用工具--> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>30.1.1-jre</version> </dependency> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.6.3</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> </dependency> <!--swagger2--> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.6.1</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.6.1</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.6</version> </dependency> <!--字段校验--> <dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>2.0.1.Final</version> </dependency> <dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>6.0.13.Final</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
1.实体类
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import org.hibernate.validator.constraints.Length; import org.hibernate.validator.constraints.Range; import javax.validation.constraints.*; /** * 员工实体类 * * @author zrj * @since 2021/7/31 **/ @Data @ApiModel(value = "Employee", description = "员工信息") public class Employee { @NotNull(message = "userId is empty") @ApiModelProperty(value = "员工ID") private Integer id; @NotBlank(message = "员工姓名不能为空") @Length(min = 1, max = 100, message = "员工姓名长度不能超过50字") @ApiModelProperty(value = "员工姓名") private String name; @Range(min = 1, max = 200, message = "年龄范围[1,200]") @ApiModelProperty(value = "年龄") private Integer age; @Pattern(regexp = "^[0-1]$", message = "员工类型范围[0,1]") @ApiModelProperty(value = "员工类型(0行政岗;1基础岗") private String type; @Pattern(regexp = "^[1][^0^1^2][0-9]{9}$", message = "员工手机号码不合法") @ApiModelProperty(value = "员工手机号码") private String phone; @Email(message = "员工邮箱不合法") @Length(min = 1, max = 50, message = "员工邮箱长度") @ApiModelProperty(value = "员工邮箱") private String email; @Length(min = 0, max = 200, message = "备注长度不能超过100字") @ApiModelProperty(value = "备注") private String remarks; }
2.控制类
import com.example.category.entity.Employee; import com.example.category.entity.Response; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.web.bind.annotation.*; import javax.validation.Valid; /** * 员工控制类 * * @author zrj * @since 2021/7/31 **/ @RestController @RequestMapping("/employee") @Api(value = "employee", description = "员工管理") public class EmployeeController { @GetMapping("/test") @ApiOperation(value = "test测试", notes = "test测试", httpMethod = "GET") public Response test() { return Response.success("查询成功", null); } /** * Valid测试 * 这里职位测试@Valid,所以不在写其他各层 */ @PostMapping("/validEpmloyee") @ApiOperation(value = "Valid测试", notes = "Valid测试", httpMethod = "POST") public Response<Employee> validEpmloyee(@Valid @RequestBody Employee employee) { System.out.println("测试请求对象:" + employee); if (employee != null) { return Response.success("查询成功", employee); } return Response.fail("查询失败"); } }
3.结果集响应码
package com.example.category.entity; import lombok.Data; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; /** * 结果集封装 * * @author zrj * @date 2021/6/2 * @since V1.0 **/ @Data @Component public class Response<T> { private static ResponseCode responseCode; /** * 提示消息 */ private String message; /** * 具体返回的数据 */ private T data; /** * 状态码 */ private String code; private Response(String code, String message, T data) { this.message = message; this.code = code; this.data = data; } private Response(String code, String msg) { this.message = msg; this.code = code; } @Autowired public Response(ResponseCode responseCode) { Response.responseCode = responseCode; } /** * 返回成功Response对象 */ public static <T> Response<T> success(String successMessage, T data) { return new Response<>(responseCode.getSuccessCode(), successMessage, data); } /** * 返回错误Response对象 */ public static <T> Response<T> fail(String errorMessage) { return new Response<>(responseCode.getErrorCode(), errorMessage); } }
import lombok.Data; import org.springframework.stereotype.Component; /** * 响应码 * * @author zrj * @date 2021/6/2 * @since V1.0 **/ @Data @Component public class ResponseCode { public String successCode = "200"; public String errorCode = "500"; public String authErrorCode = "300"; }
4.异常切面封装类
import com.example.category.entity.Response; import com.fasterxml.jackson.databind.JsonMappingException; import lombok.extern.slf4j.Slf4j; import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.util.CollectionUtils; import org.springframework.validation.ObjectError; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.MissingServletRequestParameterException; 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.method.HandlerMethod; import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException; import javax.validation.ConstraintViolation; import javax.validation.ConstraintViolationException; import java.util.List; import java.util.Set; /** * 异常切面封装类 * * @author zrj * @since 2021/7/31 **/ @ControllerAdvice @ResponseBody @Slf4j public class ExceptionHandlerAdvice { /** * Exception */ @ExceptionHandler(Exception.class) public Response<String> handleGlobalException(Exception exception, HandlerMethod handlerMethod) { if (exception instanceof MethodArgumentNotValidException) { List<ObjectError> errors = ((MethodArgumentNotValidException) exception).getBindingResult().getAllErrors(); StringBuilder sb = new StringBuilder(); if (!CollectionUtils.isEmpty(errors)) { for (ObjectError error : errors) { if (sb.length() != 0) { sb.append(","); } sb.append(error.getDefaultMessage()); } } return Response.fail(sb.toString()); } // 约束异常 if (exception instanceof ConstraintViolationException) { Set<ConstraintViolation<?>> exceptionSet = ((ConstraintViolationException) exception).getConstraintViolations(); StringBuilder sb = new StringBuilder(); if (!CollectionUtils.isEmpty(exceptionSet)) { for (ConstraintViolation<?> set : exceptionSet) { if (sb.length() != 0) { sb.append(","); } sb.append(set.getMessageTemplate()); } } return Response.fail(sb.toString()); } // 参数类型转换异常处理 if (exception instanceof MethodArgumentTypeMismatchException) { return Response.fail(((MethodArgumentTypeMismatchException) exception).getName() + " 类型不匹配"); } if (exception instanceof JsonMappingException) { return Response.fail("JSON格式错误, " + exception.getLocalizedMessage()); } if (exception instanceof HttpMessageNotReadableException) { return Response.fail("请求体格式错误, " + exception.getLocalizedMessage()); } if (exception instanceof MissingServletRequestParameterException) { String paramName = ((MissingServletRequestParameterException) exception).getParameterName(); return Response.fail(paramName + " 不能为空"); } //if (exception instanceof MarketingException) { // MarketingException marketingException = (MarketingException) exception; // return RdfaResult.fail(marketingException.getErrorCodeEnum().getCode(), exception.getMessage()); //} // 其他异常打印日志 log.error("{}.{} error, ", handlerMethod.getBeanType().getSimpleName(), handlerMethod.getMethod().getName(), exception); //if (exception instanceof RpcException) { // return RdfaResult.fail(ErrorCodeEnum.RPC_ERROR.getCode(), "RPC调用错误,请稍后重试"); //} return Response.fail("服务器内部错误,请联系开发人员!"); } }