JSR 303 数据校验以及放入统一的返回结果
一、介绍
JSR是Java Specification Requests的缩写,意思是Java 规范提案。是指向JCP(Java Community Process)提出新增一个标准化技术规范的正式请求。任何人都可以提交JSR,以向Java平台增添新的API和服务。JSR已成为Java界的一个重要标准。
二、普通使用步骤
-
给Bean添加校验注解:javax.validation.constraints,并自定义 message提示
/** * 品牌名 */ @NotBlank(message = "品牌名必须提交") private String name;
-
在Controller层添加校验功能 @Valid
/** * 保存 */ @RequestMapping("/save") public R save(@Valid @RequestBody BrandEntity brand) { brandService.save(brand); return R.ok(); }
-
效果:在postman测试,会有默认的响应
{ "timestamp": "2020-04-21T03:53:31.757+0000", "status": 400, "error": "Bad Request", "errors": [ { "codes": [ "NotBlank.brandEntity.name", "NotBlank.name", "NotBlank.java.lang.String", "NotBlank" ], "arguments": [ { "codes": [ "brandEntity.name", "name" ], "arguments": null, "defaultMessage": "name", "code": "name" } ], "defaultMessage": "品牌名必须提交", "objectName": "brandEntity", "field": "name", "rejectedValue": "", "bindingFailure": false, "code": "NotBlank" } ], "message": "Validation failed for object='brandEntity'. Error count: 1", "path": "/product/brand/save" }
三、封装到统一返回结果
对实体类注明校验字段
@Data
@TableName("pms_brand")
public class BrandEntity implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 品牌id
*/
@TableId
private Long brandId;
/**
* 品牌名
*/
@NotBlank(message = "品牌名必须提交")
private String name;
/**
* 品牌logo地址
*/
@NotEmpty
@URL(message = "logo 必须是合法url地址")
private String logo;
/**
* 介绍
*/
private String descript;
/**
* 显示状态[0-不显示;1-显示]
*/
private Integer showStatus;
/**
* 检索首字母
*/
@NotEmpty
@Pattern(regexp = "/^[a-zA-Z]$/", message = "检索首字母必须是一个字母")
private String firstLetter;
/**
* 排序
*/
@NotNull
@Min(value = 0, message = "排序必须大于等于0")
private Integer sort;
}
对Controller方法做处理
BindingResult 是处理的校验结果,对此分析并放入统一的返回结果里
/**
* 保存
*
* @param brand
* @param result 校验结果
* @return
*/
@RequestMapping("/save")
// @RequiresPermissions("product:brand:save")
public R save(@Valid @RequestBody BrandEntity brand, BindingResult result) {
if (result.hasErrors()) {
Map<String, String> map = new HashMap<>();
// 获取校验的错误结果
result.getFieldErrors().forEach((item) -> {
// 错误提示
String message = item.getDefaultMessage();
// 错误的属性名
String field = item.getField();
map.put(field, message);
});
return R.error(400, "提交的数据不合法").put("data", map);
}
brandService.save(brand);
return R.ok();
}
测试结果
```json
{
"msg": "提交的数据不合法",
"code": 400,
"data": {
"logo": "不能为空",
"sort": "不能为null",
"firstLetter": "不能为空"
}
}
```
四、分组校验
一个字段在不同情况下会有不同校验逻辑,比如id,在新增时不用填写,此时数据库里是自增的,但更新时则必须填写,此时可以对它们标注分组以区分不同的情况。
对实体类注明校验字段
在字段上指定不同的情况下的校验情况,分组是一个空接口,仅用以区分
/**
* 品牌id
*/
@NotNull(message = "修改必须指定品牌id", groups = {UpdateGroup.class})
@Null(message = "新增不能指定品牌id", groups = {AddGroup.class})
@TableId
private Long brandId;
/**
* 品牌名
*/
@NotBlank(message = "品牌名必须提交", groups = {UpdateGroup.class, AddGroup.class})
private String name;
/**
* 品牌logo地址
*/
@NotBlank(groups = {AddGroup.class})
@URL(message = "logo 必须是合法url地址", groups = {AddGroup.class, UpdateGroup.class})
private String logo;
/**
* 介绍
*/
private String descript;
/**
* 显示状态[0-不显示;1-显示]
*/
private Integer showStatus;
/**
* 检索首字母
*/
@NotEmpty(groups = {AddGroup.class})
@Pattern(regexp = "/^[a-zA-Z]$/", message = "检索首字母必须是一个字母", groups = {UpdateGroup.class, AddGroup.class})
private String firstLetter;
/**
* 排序
*/
@NotNull(groups = {AddGroup.class})
@Min(value = 0, message = "排序必须大于等于0", groups = {UpdateGroup.class, AddGroup.class})
private Integer sort;
对Controller方法做处理
把之前的 JSR303提供的接口@Valid 变为 Spring提供的实现 @Validated。在不同方法上注明不同的情况
/**
* 保存
*
* @param brand
* @return
*/
@RequestMapping("/save")
public R save(@Validated({AddGroup.class}) @RequestBody BrandEntity brand) {
brandService.save(brand);
return R.ok();
}
/**
* 修改
*/
@RequestMapping("/update")
// @RequiresPermissions("product:brand:update")
public R update(@Validated(UpdateGroup.class) @RequestBody BrandEntity brand) {
brandService.updateById(brand);
return R.ok();
}
没有修不好的电脑