zoukankan      html  css  js  c++  java
  • Validated 注解完成 Spring Boot 参数校验

    1.  @Valid 和 @Validated

      @Valid 注解,是 Bean Validation 所定义,可以添加在普通方法、构造方法、方法参数、方法返回、成员变量上,表示它们需要进行约束校验。
      @Validated 注解,是 Spring Validation 所定义,可以添加在类、方法参数、普通方法上,表示它们需要进行约束校验。并且,@Validated 具有 value 属性,支持分组校验。
    • 声明式校验
        @Validated
    • 分组检验
        @Validated
    • 嵌套校验
        @Valid

    2.  常用注解


    3. 快速入门

    • 创建Maven项目
    • 修改pom.xml
     1 <project xmlns="http://maven.apache.org/POM/4.0.0"
     2     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     3     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     4     <modelVersion>4.0.0</modelVersion>
     5     <groupId>com.c3stones</groupId>
     6     <artifactId>spring-boot-validated-demo</artifactId>
     7     <version>0.0.1-SNAPSHOT</version>
     8     <name>spring-boot-validated-demo</name>
     9     <description>Spring Boot Validated Demo</description>
    10 
    11     <parent>
    12         <groupId>org.springframework.boot</groupId>
    13         <artifactId>spring-boot-starter-parent</artifactId>
    14         <version>2.1.4.RELEASE</version>
    15     </parent>
    16 
    17     <properties>
    18         <java.version>1.8</java.version>
    19     </properties>
    20 
    21     <dependencies>
    22            <dependency>
    23             <groupId>org.projectlombok</groupId>
    24             <artifactId>lombok</artifactId>
    25         </dependency>
    26         <dependency>
    27             <groupId>org.springframework.boot</groupId>
    28             <artifactId>spring-boot-starter-web</artifactId>
    29         </dependency>
    30         <dependency>
    31             <groupId>org.springframework.boot</groupId>
    32             <artifactId>spring-boot-starter-test</artifactId>
    33             <scope>test</scope>
    34         </dependency>
    35     </dependencies>
    36 
    37 </project>
    • 创建启动类
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    @SpringBootApplication
    public class Application {
    
        public static void main(String[] args) {
            SpringApplication.run(Application.class, args);
        }
    }
    •  创建DTO
     1 import javax.validation.constraints.NotEmpty;
     2 import javax.validation.constraints.Pattern;
     3 
     4 import org.hibernate.validator.constraints.Length;
     5 
     6 import lombok.Data;
     7 
     8 /**
     9  * 用户保存DTO
    10  *
    11  */
    12 @Data
    13 public class UserSaveDto {
    14 
    15     /**
    16      * 用户名称
    17      */
    18     @NotEmpty(message = "用户名称不能为空")
    19     @Length(min = 6, max = 12, message = "账号长度为 6-12 位")
    20     @Pattern(regexp = "^[A-Za-z0-9]+$", message = "用户名称格式为数字或字母")
    21     private String username;
    22 
    23     /**
    24      * 密码
    25      */
    26     @NotEmpty(message = "密码不能为空")
    27     @Length(min = 6, max = 18, message = "密码长度为 6-18 位")
    28     private String password;
    29 }
    •  创建Controller
     1 import javax.validation.Valid;
     2 import javax.validation.constraints.Min;
     3 
     4 import org.slf4j.Logger;
     5 import org.slf4j.LoggerFactory;
     6 import org.springframework.validation.annotation.Validated;
     7 import org.springframework.web.bind.annotation.GetMapping;
     8 import org.springframework.web.bind.annotation.PostMapping;
     9 import org.springframework.web.bind.annotation.RequestMapping;
    10 import org.springframework.web.bind.annotation.RequestParam;
    11 import org.springframework.web.bind.annotation.RestController;
    12 
    13 import com.c3stones.dto.UserSaveDto;
    14 
    15 @RestController
    16 @RequestMapping("/user")
    17 @Validated
    18 public class UserController {
    19 
    20     private Logger logger = LoggerFactory.getLogger(getClass());
    21 
    22     @GetMapping("/get")
    23     public String get(@RequestParam("id") @Min(value = 1L, message = "id必须大于0") Integer id) {
    24         logger.info("获取用户信息,id:" + id);
    25         return "get success";
    26     }
    27 
    28     @PostMapping("/save")
    29     public String save(@Valid UserSaveDto saveDto) {
    30         logger.info("保存用户信息:", saveDto.toString());
    31         return "save success";
    32     }
    33 
    34 }
    • 启动项目
    • 测试get方法
     1 curl -X GET "http://localhost:8080/user/get?id=0"
     2 #返回:
     3 {
     4     "timestamp": "2020-05-20T03:27:23.667+0000",
     5     "status": 500,
     6     "error": "Internal Server Error",
     7     "message": "get.id: id必须大于0",
     8     "path": "/user/get"
     9 }
    10 
    11 curl -X GET "http://localhost:8080/user/get?id=1"
    12 #返回:
    13 get success
    • 测试save方法
     1 curl -X POST "http://localhost:8080/user/save?username=test&password=123"
     2 #返回:
     3 {
     4     "timestamp": "2020-05-20T03:29:46.684+0000",
     5     "status": 400,
     6     "error": "Bad Request",
     7     "errors": [
     8         {
     9             "codes": [
    10                 "Length.userSaveDto.username",
    11                 "Length.username",
    12                 "Length.java.lang.String",
    13                 "Length"
    14             ],
    15             "arguments": [
    16                 {
    17                     "codes": [
    18                         "userSaveDto.username",
    19                         "username"
    20                     ],
    21                     "arguments": null,
    22                     "defaultMessage": "username",
    23                     "code": "username"
    24                 },
    25                 12,
    26                 6
    27             ],
    28             "defaultMessage": "账号长度为 6-12 位",
    29             "objectName": "userSaveDto",
    30             "field": "username",
    31             "rejectedValue": "test",
    32             "bindingFailure": false,
    33             "code": "Length"
    34         },
    35         {
    36             "codes": [
    37                 "Length.userSaveDto.password",
    38                 "Length.password",
    39                 "Length.java.lang.String",
    40                 "Length"
    41             ],
    42             "arguments": [
    43                 {
    44                     "codes": [
    45                         "userSaveDto.password",
    46                         "password"
    47                     ],
    48                     "arguments": null,
    49                     "defaultMessage": "password",
    50                     "code": "password"
    51                 },
    52                 18,
    53                 6
    54             ],
    55             "defaultMessage": "密码长度为 6-18 位",
    56             "objectName": "userSaveDto",
    57             "field": "password",
    58             "rejectedValue": "123",
    59             "bindingFailure": false,
    60             "code": "Length"
    61         }
    62     ],
    63     "message": "Validation failed for object='userSaveDto'. Error count: 2",
    64     "path": "/user/save"
    65 }
    66 
    67 curl -X POST "http://localhost:8080/user/save?username=test001&password=123456"
    68 #返回:
    69 save success

    4. 分组校验

    • 编写实体类
     1 import javax.validation.constraints.NotEmpty;
     2 import javax.validation.constraints.NotNull;
     3 
     4 import lombok.AllArgsConstructor;
     5 import lombok.Data;
     6 import lombok.NoArgsConstructor;
     7 
     8 /**
     9  * 用户
    10  * 
    11  */
    12 @Data
    13 @NoArgsConstructor
    14 @AllArgsConstructor
    15 public class User {
    16 
    17     /**
    18      * 用户保存分组
    19      * 
    20      */
    21     public interface UserSaveGroup {
    22     }
    23 
    24     /**
    25      * 用户更新分组
    26      * 
    27      */
    28     public interface UserUpdateGroup {
    29     }
    30 
    31     /**
    32      * ID
    33      */
    34     @NotNull(message = "ID不能为空", groups = { UserUpdateGroup.class })
    35     private Integer id;
    36 
    37     /**
    38      * 用户名称
    39      */
    40     @NotEmpty(message = "用户名称不能为空", groups = { UserSaveGroup.class, UserUpdateGroup.class })
    41     private String username;
    42 
    43     /**
    44      * 密码
    45      */
    46     @NotEmpty(message = "密码不能为空", groups = { UserSaveGroup.class, UserUpdateGroup.class })
    47     private String password;
    48 }
    • Controller添加方法
     1 @PostMapping("/saveUser")
     2 public String saveUser(@Validated({ UserSaveGroup.class }) User user) {
     3     logger.info("保存用户信息:", user.toString());
     4     return "saveUser success";
     5 }
     6 
     7 @PutMapping("/updateUser")
     8 public String updateUser(@Validated({ UserUpdateGroup.class }) User user) {
     9     logger.info("更新用户信息:", user.toString());
    10     return "updateUser success";
    11 }
    •  测试UserSaveGroup分组
     1 curl -X POST "http://localhost:8080/user/saveUser"
     2 #返回:
     3 {
     4     "timestamp": "2020-05-20T03:45:15.357+0000",
     5     "status": 400,
     6     "error": "Bad Request",
     7     "errors": [
     8         {
     9             "codes": [
    10                 "NotEmpty.user.password",
    11                 "NotEmpty.password",
    12                 "NotEmpty.java.lang.String",
    13                 "NotEmpty"
    14             ],
    15             "arguments": [
    16                 {
    17                     "codes": [
    18                         "user.password",
    19                         "password"
    20                     ],
    21                     "arguments": null,
    22                     "defaultMessage": "password",
    23                     "code": "password"
    24                 }
    25             ],
    26             "defaultMessage": "密码不能为空",
    27             "objectName": "user",
    28             "field": "password",
    29             "rejectedValue": null,
    30             "bindingFailure": false,
    31             "code": "NotEmpty"
    32         },
    33         {
    34             "codes": [
    35                 "NotEmpty.user.username",
    36                 "NotEmpty.username",
    37                 "NotEmpty.java.lang.String",
    38                 "NotEmpty"
    39             ],
    40             "arguments": [
    41                 {
    42                     "codes": [
    43                         "user.username",
    44                         "username"
    45                     ],
    46                     "arguments": null,
    47                     "defaultMessage": "username",
    48                     "code": "username"
    49                 }
    50             ],
    51             "defaultMessage": "用户名称不能为空",
    52             "objectName": "user",
    53             "field": "username",
    54             "rejectedValue": null,
    55             "bindingFailure": false,
    56             "code": "NotEmpty"
    57         }
    58     ],
    59     "message": "Validation failed for object='user'. Error count: 2",
    60     "path": "/user/saveUser"
    61 }
    62 
    63 curl -X POST "http://localhost:8080/user/saveUser?username=zhangsan&password=123456"
    64 #返回:
    65 saveUser success
    •  测试UserUpdateGroup分组
     1 curl -X PUT "http://localhost:8080/user/updateUser"
     2 #返回:
     3 {
     4     "timestamp": "2020-05-20T03:52:01.350+0000",
     5     "status": 400,
     6     "error": "Bad Request",
     7     "errors": [
     8         {
     9             "codes": [
    10                 "NotEmpty.user.username",
    11                 "NotEmpty.username",
    12                 "NotEmpty.java.lang.String",
    13                 "NotEmpty"
    14             ],
    15             "arguments": [
    16                 {
    17                     "codes": [
    18                         "user.username",
    19                         "username"
    20                     ],
    21                     "arguments": null,
    22                     "defaultMessage": "username",
    23                     "code": "username"
    24                 }
    25             ],
    26             "defaultMessage": "用户名称不能为空",
    27             "objectName": "user",
    28             "field": "username",
    29             "rejectedValue": null,
    30             "bindingFailure": false,
    31             "code": "NotEmpty"
    32         },
    33         {
    34             "codes": [
    35                 "NotNull.user.id",
    36                 "NotNull.id",
    37                 "NotNull.java.lang.Integer",
    38                 "NotNull"
    39             ],
    40             "arguments": [
    41                 {
    42                     "codes": [
    43                         "user.id",
    44                         "id"
    45                     ],
    46                     "arguments": null,
    47                     "defaultMessage": "id",
    48                     "code": "id"
    49                 }
    50             ],
    51             "defaultMessage": "ID不能为空",
    52             "objectName": "user",
    53             "field": "id",
    54             "rejectedValue": null,
    55             "bindingFailure": false,
    56             "code": "NotNull"
    57         },
    58         {
    59             "codes": [
    60                 "NotEmpty.user.password",
    61                 "NotEmpty.password",
    62                 "NotEmpty.java.lang.String",
    63                 "NotEmpty"
    64             ],
    65             "arguments": [
    66                 {
    67                     "codes": [
    68                         "user.password",
    69                         "password"
    70                     ],
    71                     "arguments": null,
    72                     "defaultMessage": "password",
    73                     "code": "password"
    74                 }
    75             ],
    76             "defaultMessage": "密码不能为空",
    77             "objectName": "user",
    78             "field": "password",
    79             "rejectedValue": null,
    80             "bindingFailure": false,
    81             "code": "NotEmpty"
    82         }
    83     ],
    84     "message": "Validation failed for object='user'. Error count: 3",
    85     "path": "/user/updateUser"
    86 }
    87 
    88 curl -X PUT "http://localhost:8080/user/updateUser?id=1001&username=zhangsan&password=123123"
    89 #返回:
    90 updateUser success

    5. 国际化配置

    • 配置文件中添加
    1 spring:
    2 # i18 message 配置,对应 MessageSourceProperties 配置类
    3    messages:
    4       basename: i18n/messages # 文件路径基础名
    5       encoding: UTF-8 # 使用 UTF-8 编码
    • 在项目resource目录下创建i18n文件夹
    • 在i18n中添加国际化配置文件

    messages.properties

    1 Goods.id.NotNull=商品ID不能为空

    messages_en.properties

    1 Goods.id.NotNull=Goods id cannot be empty

    messages_ja.properties

    1 Goods.id.NotNull=商品IDは空にできません
    • 创建实体
     1 import javax.validation.constraints.NotNull;
     2 
     3 import lombok.AllArgsConstructor;
     4 import lombok.Data;
     5 import lombok.NoArgsConstructor;
     6 
     7 /**
     8  * 商品
     9  * 
    10  */
    11 @Data
    12 @NoArgsConstructor
    13 @AllArgsConstructor
    14 public class Goods {
    15 
    16     /**
    17      * 商品ID
    18      */
    19     @NotNull(message = "{Goods.id.NotNull}")
    20     private Integer id;
    21 
    22     /**
    23      * 商品名称
    24      */
    25     private String name;
    26 }
    • 创建Controller
     1 import javax.validation.Valid;
     2 
     3 import org.slf4j.Logger;
     4 import org.slf4j.LoggerFactory;
     5 import org.springframework.validation.annotation.Validated;
     6 import org.springframework.web.bind.annotation.PostMapping;
     7 import org.springframework.web.bind.annotation.RequestMapping;
     8 import org.springframework.web.bind.annotation.RestController;
     9 
    10 import com.c3stones.entity.Goods;
    11 12 @RestController 13 @RequestMapping("/goods") 14 @Validated 15 public class GoodsController { 16 17 private Logger logger = LoggerFactory.getLogger(getClass()); 18 19 @PostMapping("/save") 20 public String save(@Valid Goods goods) { 21 logger.info("保存商品信息:", goods.toString()); 22 return "save success"; 23 } 24 25 }
    • 测试(通过头部指定 Accept-Language 参数)
      1 #测试默认中文
      2 curl -X POST "http://localhost:8080/goods/save"
      3 #返回:
      4 {
      5     "timestamp": "2020-05-20T04:15:59.417+0000",
      6     "status": 400,
      7     "error": "Bad Request",
      8     "errors": [
      9         {
     10             "codes": [
     11                 "NotNull.goods.id",
     12                 "NotNull.id",
     13                 "NotNull.java.lang.Integer",
     14                 "NotNull"
     15             ],
     16             "arguments": [
     17                 {
     18                     "codes": [
     19                         "goods.id",
     20                         "id"
     21                     ],
     22                     "arguments": null,
     23                     "defaultMessage": "id",
     24                     "code": "id"
     25                 }
     26             ],
     27             "defaultMessage": "商品ID不能为空",
     28             "objectName": "goods",
     29             "field": "id",
     30             "rejectedValue": null,
     31             "bindingFailure": false,
     32             "code": "NotNull"
     33         }
     34     ],
     35     "message": "Validation failed for object='goods'. Error count: 1",
     36     "path": "/goods/save"
     37 }
     38 
     39 #测试英文
     40 curl -X POST -H "Accept-Language:en" "http://localhost:8080/goods/save"
     41 #返回:
     42 {
     43     "timestamp": "2020-05-20T04:16:15.078+0000",
     44     "status": 400,
     45     "error": "Bad Request",
     46     "errors": [
     47         {
     48             "codes": [
     49                 "NotNull.goods.id",
     50                 "NotNull.id",
     51                 "NotNull.java.lang.Integer",
     52                 "NotNull"
     53             ],
     54             "arguments": [
     55                 {
     56                     "codes": [
     57                         "goods.id",
     58                         "id"
     59                     ],
     60                     "arguments": null,
     61                     "defaultMessage": "id",
     62                     "code": "id"
     63                 }
     64             ],
     65             "defaultMessage": "Goods id cannot be empty",
     66             "objectName": "goods",
     67             "field": "id",
     68             "rejectedValue": null,
     69             "bindingFailure": false,
     70             "code": "NotNull"
     71         }
     72     ],
     73     "message": "Validation failed for object='goods'. Error count: 1",
     74     "path": "/goods/save"
     75 }
     76 
     77 #测试日文
     78 curl -X POST -H "Accept-Language:ja" "http://localhost:8080/goods/save"
     79 #返回:
     80 {
     81     "timestamp": "2020-05-20T04:16:35.011+0000",
     82     "status": 400,
     83     "error": "Bad Request",
     84     "errors": [
     85         {
     86             "codes": [
     87                 "NotNull.goods.id",
     88                 "NotNull.id",
     89                 "NotNull.java.lang.Integer",
     90                 "NotNull"
     91             ],
     92             "arguments": [
     93                 {
     94                     "codes": [
     95                         "goods.id",
     96                         "id"
     97                     ],
     98                     "arguments": null,
     99                     "defaultMessage": "id",
    100                     "code": "id"
    101                 }
    102             ],
    103             "defaultMessage": "商品IDは空にできません",
    104             "objectName": "goods",
    105             "field": "id",
    106             "rejectedValue": null,
    107             "bindingFailure": false,
    108             "code": "NotNull"
    109         }
    110     ],
    111     "message": "Validation failed for object='goods'. Error count: 1",
    112     "path": "/goods/save"
    113 }

    6. 项目地址

      https://github.com/C3Stones/blog

  • 相关阅读:
    ABA问题怎么解:AtomicStampedReference和AtomicMarkableReference
    原子类型累加器
    Spring Boot使用嵌入式容器,那怎么配置自定义Filter呢
    痞子衡嵌入式:语音处理工具pzh-speech诞生记
    痞子衡嵌入式:串口调试工具pzh-com诞生记(6)- 打包发布(PyInstaller3.3.1)
    痞子衡嵌入式:串口调试工具pzh-com诞生记(5)- 软件优化
    痞子衡嵌入式:串口调试工具pzh-com诞生记(4)- 联合调试(vspd, sscom, PyCharm2018.2)
    痞子衡嵌入式:串口调试工具pzh-com诞生记(3)- 串口功能实现(pySerial)
    痞子衡嵌入式:串口调试工具pzh-com诞生记(2)- 界面构建(wxFormBuilder3.8.0)
    痞子衡嵌入式:极易上手的可视化wxPython GUI构建工具(wxFormBuilder)
  • 原文地址:https://www.cnblogs.com/cao-lei/p/12938707.html
Copyright © 2011-2022 走看看