专车介绍
该趟专车是开往SpringBoot Web应用参数校验的实战专车,主要讲解如何对请求入参进行安全校验,防止不合法的数据进入系统。
专车问题
第一个问题:如何对请求入参进行校验
第二个问题:如何对入参对象中集合里面的对象进行参数校验
第三个问题:参数校验提示信息如何实现国际化展示
专车实战
第一步:在父模块下面新建一个名为boot-example-validate的子模块
第二步:子模块添加如下依赖
<code><dependencies>
<dependency>
<groupid>org.springframework.boot/<groupid>
<artifactid>spring-boot-starter-web/<artifactid>
/<dependency>
<dependency>
<groupid>org.projectlombok/<groupid>
<artifactid>lombok/<artifactid>
/<dependency>
/<dependencies>/<code>
第三步:创建启动类
<code>@SpringBootApplication
public class ValidateApplication {
public static void main(String[] args) {
SpringApplication.run(ValidateApplication.class, args);
}
}/<code>
第四步:创建控制器
<code>@RestController
@RequestMapping("/teachers")
public class TeacherController {
@PostMapping("/add")
public String add(@RequestBody @Valid Teacher user, BindingResult bindingResult) {
List<fielderror> list = bindingResult.getFieldErrors();
List<string> messageList = new ArrayList<>();
for (FieldError fieldError : list) {
messageList.add(fieldError.getDefaultMessage());
}
return messageList.toString();
}
}/<string>/<fielderror>/<code>
可以看到与之前不同的是,在需要校验的对象前面添加了@Valid注解,该注解的功能就是用来进行数据校验的
第五步:创建实体类
<code>@Data
public class Teacher {
@NotNull(message = "id.not.empty")
private Integer id;
@NotEmpty(message = "name.not.empty")
private String name;
@NotEmpty(message = "email.not.empty")
@Email(message = "email.invalid")
private String email;
}/<code>
第六步:发送请求
http://localhost:8080/teachers/add POST
输入错误的请求参数:
<code>{
\t"id":null,
\t"name":"",
\t"email":"a563830372"
}/<code>
响应结果:
<code>[name.not.empty, id.not.empty, email.invalid]/<code>
输入正确的请求参数:
<code>{
\t"id":100001,
\t"name":"test",
\t"email":"[email protected]"
}/<code>
响应结果:
<code>[]/<code>
如上可以得出如果想要对入参数据进行校验,在需要校验的对象前面使用@Valid注解标注,然后实体对象属性上使用相应校验规则的注解
场景导入:一个老师有很多学生是很正常的一件事情,依照这个思路,我们创建一个学生实体类
<code>@Data
public class Student {
@NotNull(message = "student.d.not.empty")
private Integer id;
@NotBlank(message = "student.name.not.empty")
private String name;
}/<code>
然后在Teacher实体类中持有学生集合对象
<code>@Data
public class Teacher {
@NotNull(message = "id.not.empty")
private Integer id;
@NotEmpty(message = "name.not.empty")
private String name;
@NotEmpty(message = "email.not.empty")
@Email(message = "email.invalid")
private String email;
@NotEmpty(message = "student list can not be empty")
private List<student> studentList;
}/<student>/<code>
接下来再来试试我们的参数校验功能,我们期望的是,如果Student中某个属性不符合校验规则也需要报错,那么事实是怎样的呢?
http://localhost:8080/teachers/add POST
请求参数:
<code>{
\t"id":100001,
\t"name":"test",
\t"email":"[email protected]",
\t"studentList":[{
\t\t"id":null,
\t\t"name":""
\t}]
}/<code>
响应结果:
<code>[]/<code>
如上响应结果返回一个空数组,也就是请求的参数没有问题,是合法的请求。这种结果完全不是我们想要的,那么该如何解决此问题的出现?
解决方法也很简单,我们只需要在集合对象上加上@Valid注解就可以了,再次请求我们的程序
http://localhost:8080/teachers/add POST
请求参数:
<code>{
\t"id":100001,
\t"name":"test",
\t"email":"[email protected]",
\t"studentList":[{
\t\t"id":null,
\t\t"name":""
\t}]
}/<code>
响应结果:
<code>[student.d.not.empty, student.name.not.empty]/<code>
看到这个结果我们第二个问题就解决了,那么如何实现提示信息的国际化呢?
想要实现国际化,我们需要针对不同的国家配置不同的提示信息,然后在请求的时候携带响应的语言,解析对应文件中的key,获取我们想要的提示信息
第一步:添加国际化配置
<code>@Configuration
public class ValidateConfigure {
@Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource
= new ReloadableResourceBundleMessageSource();
messageSource.setBasenames("classpath:messages");
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
@Bean
public LocalValidatorFactoryBean getValidator() {
LocalValidatorFactoryBean bean = new LocalValidatorFactoryBean();
bean.setValidationMessageSource(messageSource());
return bean;
}
}/<code>
第二步:在resources目录下添加国际化配置文件
英文配置:messages_en_US.properties
<code>id.not.empty=id can not be empty
name.not.empty=name can not be empty
email.not.empty=email can not be empty
email.invalid=please provided a valid email address
student.id.not.empty=student id can not be empty
student.name.not.empty=student name can not be empty/<code>
中文配置:messages_en_US.properties
<code>id.not.empty=老师编号不能为空
name.not.empty=老师姓名不能为空
email.not.empty=老师邮箱不能为空
email.invalid=请提供合法的邮箱地址
student.id.not.empty=学生编号不能为空
student.name.not.empty=学生名称不能为空/<code>
第三步:修改实体类
<code>@Data
public class Teacher {
@NotNull(message = "{id.not.empty}")
private Integer id;
@NotEmpty(message = "{name.not.empty}")
private String name;
@NotEmpty(message = "{email.not.empty}")
@Email(message = "{email.invalid}")
private String email;
@Valid
@NotEmpty(message = "{student.list.not.empty}")
private List<student> studentList;
}/<student>/<code>
<code>@Data
public class Student {
@NotNull(message = "{student.id.not.empty}")
private Integer id;
@NotBlank(message = "{student.name.not.empty}")
private String name;
}/<code>
第四步:发送请求
http://localhost:8080/teachers/add POST
请求参数:
<code>{
\t"id":null,
\t"name":"",
\t"email":"a563830372163.com",
\t"studentList":[{
\t\t"id":null,
\t\t"name":""
\t}]
}/<code>
响应结果:
<code>[姓名不能为空, 请提供合法的邮箱地址, 学生名称不能为空, 编号不能为空, 学生编号不能为空]/<code>
第五步:切换成英语
在请求的header中添加accept-language:en-US
请求参数:
<code>{
\t"id":null,
\t"name":"",
\t"email":"a563830372163.com",
\t"studentList":[{
\t\t"id":null,
\t\t"name":""
\t}]
}/<code>
响应j结果:
<code>[id can not be empty, name can not be empty, student id can not be empty, please provided a valid email address, student name can not be empty]/<code>
可以看到,想要切换语言,只需要在header中添加accept-language配置即可
专车总结
实现参数校验:
第一步:在需要校验的对象前面添加@Valid注解,其实添加@Validated也可以实现同样的功能
第二步:在实体类添加相应规则的注解,比如:@NotNull、@NotEmpty
实现集合对象的校验:
在集合对象上添加@Valid注解
实现国际化:
第一步:添加国际化配置
第二步:添加不同语言的配置文件
第三步:实体类提示信息使用{}包裹配置文件中指定的key
没别的意思,麻烦来个关注+点赞+留言+收藏。有问题的可以看我签名
閱讀更多 Java進階架構師 的文章