java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > springboot JSR-303请求参数校验

Spring Boot中使用JSR-303实现请求参数校验

作者:Miaow.Y.Hu

这篇文章主要介绍了Spring Boot中使用JSR-303实现请求参数校验,JSR-303校验我们一般都是对Java的实体类对象进行校验,主要检验JSR-303是Java中的一个规范,用于实现请求参数校验在我们的实体类对象的属性上,感兴趣的朋友跟随小编一起看看吧

JSR-303是Java中的一个规范,用于实现请求参数校验。它定义了一组注解,可以应用于JavaBean的字段上,用于验证输入参数的合法性。下面是一些常用的JSR-303注解及其介绍:

@NotNull:用于验证字段值不能为null。
@NotEmpty:用于验证字符串字段不能为空。
@NotBlank:用于验证字符串字段不能为空,并且长度必须大于0。
@Min:用于验证数字字段的最小值。
@Max:用于验证数字字段的最大值。
@Size:用于验证字符串、集合或数组字段的长度或大小。
@Pattern:用于验证字符串字段是否匹配指定的正则表达式。
@Email:用于验证字符串字段是否符合Email格式。
@Range:用于验证数字字段的取值范围。
@Valid:用于嵌套验证,可以对对象中的字段进行递归验证。
其他如下图所示:

通过在JavaBean的字段上添加这些注解,可以在接收请求参数时进行自动校验。如果校验失败,可以通过异常处理机制来处理校验错误。

需要注意的是,JSR-303只提供了基本的验证注解,如果需要更复杂的校验逻辑,可以自定义注解或使用第三方库,如Hibernate Validator等。
Hibernate Validator附加的constraint:

至于我们为啥使用JSR-303来校验我们的参数,主要是为了解决我们在实际开发过程中,前后端的参数校验导致的问题。比如:

JSR的定义标准

验证触发时机:

接下来我们将围绕我们在Spring Boot的实体类中,使用JSR-303校验。值得注意的是,JSR-303校验我们一般都是对Java的实体类对象进行校验,主要检验在我们的实体类对象的属性上。

还是利用我们==>上一篇 <===的相关依赖文件,这篇我就不在重复导入相关依赖文件了。本篇着重文件主要正在User类和UserController,所用的依赖pom.xml文件和application.properties均与上篇一样,就不在重复描述了。

PS: 你可以看到我在依赖中均采用了lombok,但是我却并未使用这个玩意,原因在于,我使用了lombok

@ApiModel(description = "用户实体")
public class User {
    @ApiModelProperty("用户编号")
    private Long id;
    @NotNull //校验定义的字段不能为空
    @Size(min = 2, max = 5)
    @ApiModelProperty("用户姓名")
    private String name;
    @NotNull
    @Max(100)
    @Min(10)
    @ApiModelProperty("用户年龄")
    private Integer age;
    @NotNull
    @Email
    @ApiModelProperty("用户邮箱")
    private String email;
    public User(Long id, String name, Integer age, String email) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.email = email;
    }
    public User() {
    }
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", email='" + email + '\'' +
                '}';
    }
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        User user = (User) o;
        return Objects.equals(id, user.id) && Objects.equals(name, user.name) && Objects.equals(age, user.age) && Objects.equals(email, user.email);
    }
    @Override
    public int hashCode() {
        return Objects.hash(id, name, age, email);
    }
}
@Api(tags = "用户管理")
@RestController
@RequestMapping(value = "/users")     // 通过这里配置使下面的映射都在/users下
public class UserController {
    // 创建线程安全的Map,模拟users信息的存储
    static Map<Long, User> users = Collections.synchronizedMap(new HashMap<>());
    @GetMapping("/")
    @ApiOperation(value = "获取用户列表")
    public List<User> getUserList() {
        List<User> r = new ArrayList<>(users.values());
        return r;
    }
    @PostMapping("/")
    @ApiOperation(value = "创建用户", notes = "根据User对象创建用户")
    public String postUser(@Valid @RequestBody User user) {
        users.put(user.getId(), user);
        return "success";
    }
    @GetMapping("/{id}")
    @ApiOperation(value = "获取用户详细信息", notes = "根据url的id来获取用户详细信息")
    public User getUser(@PathVariable Long id) {
        return users.get(id);
    }
    @PutMapping("/{id}")
    @ApiImplicitParam(paramType = "path", dataType = "Long", name = "id", value = "用户编号", required = true, example = "1")
    @ApiOperation(value = "更新用户详细信息", notes = "根据url的id来指定更新对象,并根据传过来的user信息来更新用户详细信息")
    public String putUser(@PathVariable Long id, @RequestBody User user) {
        User u = users.get(id);
        u.setName(user.getName());
        u.setAge(user.getAge());
        users.put(id, u);
        return "success";
    }
    @DeleteMapping("/{id}")
    @ApiOperation(value = "删除用户", notes = "根据url的id来指定删除对象")
    public String deleteUser(@PathVariable Long id) {
        users.remove(id);
        return "success";
    }
}

接下来启动项目,当然启动类还是需要加:
@EnableSwagger2Doc这个注解

之后,我们可以通过使用相关工具比如Postman等测试工具发起,也可以使用curl发起,比如:

curl -X POST \
  http://localhost:8080/users/ \
  -H 'Content-Type: application/json' \
  -H 'Postman-Token: 114db0f0-bdce-4ba5-baf6-01e5104a68a3' \
  -H 'cache-control: no-cache' \
  -d '{
    "name": "abcdefg",
    "age": 8,
    "email": "aaaa"
}'

得到相关信息:

{
    "timestamp": "2019-10-05T06:24:30.518+0000",
    "status": 400,
    "error": "Bad Request",
    "errors": [
        {
            "codes": [
                "Size.user.name",
                "Size.name",
                "Size.java.lang.String",
                "Size"
            ],
            "arguments": [
                {
                    "codes": [
                        "user.name",
                        "name"
                    ],
                    "arguments": null,
                    "defaultMessage": "name",
                    "code": "name"
                },
                5,
                2
            ],
            "defaultMessage": "个数必须在2和5之间",
            "objectName": "user",
            "field": "name",
            "rejectedValue": "abcdefg",
            "bindingFailure": false,
            "code": "Size"
        },
        {
            "codes": [
                "Min.user.age",
                "Min.age",
                "Min.java.lang.Integer",
                "Min"
            ],
            "arguments": [
                {
                    "codes": [
                        "user.age",
                        "age"
                    ],
                    "arguments": null,
                    "defaultMessage": "age",
                    "code": "age"
                },
                10
            ],
            "defaultMessage": "最小不能小于10",
            "objectName": "user",
            "field": "age",
            "rejectedValue": 8,
            "bindingFailure": false,
            "code": "Min"
        },
        {
            "codes": [
                "Email.user.email",
                "Email.email",
                "Email.java.lang.String",
                "Email"
            ],
            "arguments": [
                {
                    "codes": [
                        "user.email",
                        "email"
                    ],
                    "arguments": null,
                    "defaultMessage": "email",
                    "code": "email"
                },
                [],
                {
                    "defaultMessage": ".*",
                    "codes": [
                        ".*"
                    ],
                    "arguments": null
                }
            ],
            "defaultMessage": "不是一个合法的电子邮件地址",
            "objectName": "user",
            "field": "email",
            "rejectedValue": "aaaa",
            "bindingFailure": false,
            "code": "Email"
        }
    ],
    "message": "Validation failed for object='user'. Error count: 3",
    "path": "/users/"
}

其中返回名称的各参数含义如下:

timestamp:请求时间
status:HTTP返回的状态码,这里返回400,即:请求无效、错误的请求,通常参数校验不通过均为400
error:HTTP返回的错误描述,这里对应的就是400状态的错误描述:Bad Request
errors:具体错误原因,是一个数组类型;因为错误校验可能存在多个字段的错误,比如这里因为定义了两个参数不能为Null,所以存在两条错误记录信息
message:概要错误消息,返回内容中很容易可以知道,这里的错误原因是对user对象的校验失败,其中错误数量为2,而具体的错误信息就定义在上面的errors数组中
path:请求路径

从errors数组中各个错误明细,知道各个字段的defaultMessage,可以看到很清晰的错误描述。

浏览器访问:
http://localhost:8080/swagger-ui.html

我们可以看到校验的部分限制。

到此这篇关于Spring Boot中使用JSR-303实现请求参数校验的文章就介绍到这了,更多相关springboot JSR-303请求参数校验内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文