美文网首页
使用Bean Validation 做RestApi请求数据验证

使用Bean Validation 做RestApi请求数据验证

作者: alex官人 | 来源:发表于2017-04-08 17:22 被阅读0次

    我们在系统中经常会遇到需要对输入的数据进行验证。

    这里我们使用Spring Boot 结合Bean Validation API来进行数据验证。

    Bean Validation API是Java定义的一个验证参数的规范。

    具体可以参考:http://beanvalidation.org/specification/

    依赖

    在pom文件中加入spring-boot-starter-validation

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-validation</artifactId>
    </dependency>
    

    定义请求

    例子中我们定义如下的请求消息。它包含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<Long, User> users = Collections.synchronizedMap(new HashMap<Long, User>());
        IdWorker idWorker = new IdWorker(2);
    
        @PostMapping
        @ApiOperation(value = "新增用户", notes = "新增用户")
        public ResponseEntity<User> 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<User> 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<User> 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
    

    可以看到我们的操作是成功的,但是没有对我们的数据进行校验。
    现在我们有两个需求:

    1. username不能为空,并且长度大于三个字母
    2. 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<User> 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/

    相关文章

      网友评论

          本文标题:使用Bean Validation 做RestApi请求数据验证

          本文链接:https://www.haomeiwen.com/subject/cealattx.html