我们在系统中经常会遇到需要对输入的数据进行验证。
这里我们使用Spring Boot 结合Bean Validation API来进行数据验证。
Bean Validation API是Java定义的一个验证参数的规范。
具体可以参考:http://beanvalidation.org/specification/
依赖
在pom文件中加入spring-boot-starter-validation
org.springframework.boot
spring-boot-starter-validation
定义请求
例子中我们定义如下的请求消息。它包含id,username,password 三个属性。
package com.github.alex.validate.model;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
/**
* Created by ChenChang on 2017/4/8.
*/
public class UserRequest {
private Long id;
private String username;
private String password;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
编写Controller
我们使用Spring 提供的@RestController
注解。
做一个简单的CURD的Controller,如下
package com.github.alex.validate.web;
import com.github.alex.validate.model.User;
import com.github.alex.validate.model.UserRequest;
import com.github.alex.validate.util.HeaderUtil;
import com.github.alex.validate.util.IdWorker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import io.swagger.annotations.ApiOperation;
/**
* Created by ChenChang on 2017/4/8.
*/
@RestController
@RequestMapping(value = "/userResource")
public class UserResource {
private final Logger log = LoggerFactory.getLogger(UserResource.class);
static Map users = Collections.synchronizedMap(new HashMap());
IdWorker idWorker = new IdWorker(2);
@PostMapping
@ApiOperation(value = "新增用户", notes = "新增用户")
public ResponseEntity createUser(@RequestBody UserRequest request) throws URISyntaxException {
log.debug("REST request to create User: {}", request);
User user = new User();
BeanUtils.copyProperties(request, user);
user.setId(idWorker.nextId());
users.put(user.getId(), user);
return ResponseEntity.created(new URI("/userResource/" + user.getId()))
.headers(HeaderUtil.createEntityCreationAlert(User.class.getSimpleName(), user.getId().toString()))
.body(user);
}
@GetMapping("/{id}")
@ApiOperation(value = "获取用户", notes = "获取用户")
public ResponseEntity getUser(@PathVariable Long id) {
log.debug("REST request to get User : {}", id);
User user = users.get(id);
return Optional.ofNullable(user)
.map(result -> new ResponseEntity<>(
result,
HttpStatus.OK))
.orElse(new ResponseEntity<>(HttpStatus.NOT_FOUND));
}
@PutMapping
@ApiOperation(value = "更新用户", notes = "更新用户")
public ResponseEntity updateUser(@RequestBody UserRequest request)
throws URISyntaxException {
log.debug("REST request to update User : {}", request);
if (request.getId() == null) {
return ResponseEntity.badRequest().body(null);
}
User user = users.get(request.getId());
BeanUtils.copyProperties(request, user);
return ResponseEntity.ok()
.headers(HeaderUtil.createEntityUpdateAlert(User.class.getSimpleName(), user.getId().toString()))
.body(user);
}
}
进行测试看看是我们获得了什么
发送请求
curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d '{ \
"password": "1", \
"username": "string" \
}' 'http://localhost:8080/userResource'
获得了结果
Response Body
{
"id": 2128081075062784,
"username": "string",
"password": "1"
}
Response Code
201
可以看到我们的操作是成功的,但是没有对我们的数据进行校验。
现在我们有两个需求:
- username不能为空,并且长度大于三个字母
- password不能为空,并且长度大于6小于30
定义验证
修改UserRequest,在username和password属性上添加注解
@NotNull
@Size(min = 3)
private String username;
@NotNull
@Size(min = 6, max = 30)
private String password;
修改UserResource,在@RequestBody
前面添加注解@Validated
public ResponseEntity createUser(@Validated @RequestBody UserRequest request)
就这么简单 我们再看看会发生什么
curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d '{ \
"password": "1", \
"username": "1" \
}' 'http://localhost:8080/userResource'
结果
Response Body
{
"timestamp": 1491642036689,
"status": 400,
"error": "Bad Request",
"exception": "org.springframework.web.bind.MethodArgumentNotValidException",
"errors": [
{
"codes": [
"Size.userRequest.username",
"Size.username",
"Size.java.lang.String",
"Size"
],
"arguments": [
{
"codes": [
"userRequest.username",
"username"
],
"arguments": null,
"defaultMessage": "username",
"code": "username"
},
2147483647,
3
],
"defaultMessage": "个数必须在3和2147483647之间",
"objectName": "userRequest",
"field": "username",
"rejectedValue": "1",
"bindingFailure": false,
"code": "Size"
},
{
"codes": [
"Size.userRequest.password",
"Size.password",
"Size.java.lang.String",
"Size"
],
"arguments": [
{
"codes": [
"userRequest.password",
"password"
],
"arguments": null,
"defaultMessage": "password",
"code": "password"
},
30,
6
],
"defaultMessage": "个数必须在6和30之间",
"objectName": "userRequest",
"field": "password",
"rejectedValue": "1",
"bindingFailure": false,
"code": "Size"
}
],
"message": "Validation failed for object='userRequest'. Error count: 2",
"path": "/userResource"
}
Response Code
400
其他验证
hibernate-validator也对Bean Validation做了支持,增加了更多种类的验证
我们在UserRequest中加入新的字段email,它是一个必填项,而且要符合email的规则
@Email
@NotNull
private String email;
再来试试
Response Body
{
"timestamp": 1491642643358,
"status": 400,
"error": "Bad Request",
"exception": "org.springframework.web.bind.MethodArgumentNotValidException",
"errors": [
{
"codes": [
"Email.userRequest.email",
"Email.email",
"Email.java.lang.String",
"Email"
],
"arguments": [
{
"codes": [
"userRequest.email",
"email"
],
"arguments": null,
"defaultMessage": "email",
"code": "email"
},
[],
{
"codes": [
".*"
],
"arguments": null,
"defaultMessage": ".*"
}
],
"defaultMessage": "不是一个合法的电子邮件地址",
"objectName": "userRequest",
"field": "email",
"rejectedValue": "string",
"bindingFailure": false,
"code": "Email"
}
],
"message": "Validation failed for object='userRequest'. Error count: 1",
"path": "/userResource"
}
Response Code
400
如此简单-,- 给你的Rest接口也加上输入数据验证吧~
以上的代码例子 https://github.com/chc123456/ValidatingInputRestRequestSpringBoot/