Validated 注解完成 Spring Boot 参数校验
1. @Valid 和 @Validated
- 声明式校验
- 分组检验
- 嵌套校验
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. 项目地址
Validated 注解完成 Spring Boot 参数校验的更多相关文章
- Spring Boot 参数校验
1.背景介绍 开发过程中,后台的参数校验是必不可少的,所以经常会看到类似下面这样的代码 这样写并没有什么错,还挺工整的,只是看起来不是很优雅而已. 接下来,用Validation来改写这段 2.Spr ...
- Spring Boot参数校验
1. 概述 作为接口服务提供方,非常有必要在项目中加入参数校验,比如字段非空,字段长度限制,邮箱格式验证等等,数据校验常用到概念:JSR303/JSR-349: JSR303是一项标准,只提供规范不提 ...
- spring boot输入数据校验(validation)
Spring Boot 集成教程 Spring Boot 介绍 Spring Boot 开发环境搭建(Eclipse) Spring Boot Hello World (restful接口)例子 sp ...
- spring mvc注解和spring boot注解
1 spring mvc和spring boot之间的关系 spring boot包含spring mvc.所以,spring mvc的注解在spring boot总都是可以用的吗? spring b ...
- spring boot 参数传递(spring boot 参数传数 arg0 每一个参数 arg0#{arg0},arg1 #{arg1})
spring boot 参数传数 arg0 每一个参数 arg0#{arg0},arg1 #{arg1} @Select("select * from sys_user where nam ...
- 使用AOP+自定义注解完成spring boot的接口权限校验
记使用AOP+自定义注解完成接口的权限校验,代码如下: pom文件添加所需依赖: 1 <dependency> 2 <groupId>org.aspectj</group ...
- Spring boot validation校验
使用 Hibernate validator 的步骤:1. 在 Pojo 类的字段上, 加上 Hibernate validator 注解2. 在Controller 函数的形参前加上 @Valid ...
- spring boot参数验证
必须要知道 简述 JSR303/JSR-349,hibernate validation,spring validation 之间的关系 JSR303 是一项标准,JSR-349 是其的升级版本,添加 ...
- Spring Boot (一) 校验表单重复提交
一.前言 在某些情况下,由于网速慢,用户操作有误(连续点击两下提交按钮),页面卡顿等原因,可能会出现表单数据重复提交造成数据库保存多条重复数据. 存在如上问题可以交给前端解决,判断多长时间内不能再次点 ...
随机推荐
- powertool
powertool简介 PowerTool 一款免费强大的进程管理器,支持进程强制结束,可以Unlock占用文件的进程,查看文件/文件夹被占用的情况,内核模块和驱动的查看和管理,进程模块的内存的dum ...
- phpmyadmin反序列化漏洞(WooYun-2016-199433)
简介 环境复现:https://github.com/vulhub/vulhub 线上平台:榆林学院内可使用协会内部的网络安全实验平台 phpMyAdmin是一套开源的.基于Web的MySQL数据库管 ...
- js替换div里的内容
<!DOCTYPE html><html><head><meta charset="utf-8"><title>< ...
- DocView 现在支持自定义 Markdown 模版了!
前言 有小伙伴反馈说希望可以自定义 Markdown 模版,这样就可以导出自己想要的样式了!这个功能可以有,毕竟大家不可能都生成一模一样的文档.现在来一起看看如何实现自定义模版吧! 设置模版 Sett ...
- FL Studio乐理教程之添加和弦
和弦是指有一定音程关系的一组声音,即将三个或以上的音,按照三度或非三度的叠置关系,在纵向上加以结合,就称为和弦. FL Studio可以编辑和弦吗?当然可以!首先我们使用FL Stuido20钢琴卷帘 ...
- 如何使用ABBYY FineReader 处理无法识别的字符?
在识别PDF文档时,我们可能会遇到文档中存在多种语言.多种不同类型文字字符的情况.在ABBYY FineReader 15(Windows系统)OCR文字识别软件的默认语言数据下,可能无法识别PDF文 ...
- Folx专业版任务计划功能详解
Folx专业版的任务计划功能允许用户以时间表的方式,制定下载计划.按照预先设定的时间计划,Folx会在指定的时间段内,自动开启或停止下载任务. 另外,用户还可以设置自动关机功能.当计划下载任务停止时, ...
- 项目开发中的git简单使用
原文地址: https://www.zhuyilong.fun/tech/the-blog-git.html 示例远程仓库地址: https://github.com/zhu-longge/gitWo ...
- python:列表的去重:两种方法的问题是:结果是没有保持原来的顺序。
列表的去重 1.使用set的特型,python的set和其他语言类似, 是一个无序不重复元素集 orgList = [1,0,3,7,7,5] #list()方法是把字符串str或元组转成数组 for ...
- FDR校正
一.假设检验 假设检验的基本思路是: 设立零假设(null hypothesis)H0,以及与零假设H0相对应的非零假设(alternative hypothesis)H1,在假设H0成立的前提下,计 ...