SpringMvc框架非常强大,包括其中的BeanValidation,在request的参数上加上注解@Valid 即可完成对参数Bean的校验,其中的校验规则是JSR-349(Spring 4)。
看一下代码:
/**
* 修改密码.
* @return
*/
@PostMapping("/modifyPassword")
public ResponseEntity<BaseResponse> modifyPassword(@Valid @RequestBody BaseRequest<ModifyPasswordRequest> baseReq,
Principal principal, HttpServletRequest request) {
Map<String, Object> data = new HashMap<>();
if (principal != null && baseReq != null && baseReq.getData() != null) {
ModifyPasswordRequest req = baseReq.getData();
String phoneNum = principal.getName(); //用户名
boolean isSuccess = false;
try {
isSuccess = accountService.modifyPasswordByLogin(phoneNum, req.getOldpassword(), req.getNewpassword());
if (isSuccess) {
data.put("code", "success");
data.put("msg", "");
return BaseResponse.success(data);
}
} catch (Exception e) {
e.printStackTrace();
log.error("user {} modifyPassword error: {}", phoneNum, e.getMessage());
data.put("msg", e.getMessage());
}
}
data.put("code", "fail");
return BaseResponse.success(data);
}
/**
* API公共请求数据体.
* @author Wang.ch
*
*/
public class BaseRequest<T> implements Serializable {
/**
*
*/
private static final long serialVersionUID = -7363188610375974013L;
/**
* 版本号.
*/
@NotNull
private String ver;
/**
* 设备id.
*/
@NotNull
@JsonProperty(value = "deviceid")
private String deviceid;
/**
* token.
*/
private String token;
/**
* checksum数据校验.
*/
private String sign;
/**
* 数据体.
*/
//@Valid
private T data;
/**
* 时间戳.
*/
@NotNull
private Long timestamp;
public BaseRequest() {
}
public String getVer() {
return ver;
}
public void setVer(String ver) {
this.ver = ver;
}
public String getDeviceid() {
return deviceid;
}
public void setDeviceid(String deviceid) {
this.deviceid = deviceid;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public String getSign() {
return sign;
}
public void setSign(String sign) {
this.sign = sign;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public Long getTimestamp() {
return timestamp;
}
public void setTimestamp(Long timestamp) {
this.timestamp = timestamp;
}
}
这样验证没有问题,但是如果BaseRequest中的data字段Bean中也有valid,上面的写法将不会生效。
解决方法有两种:
- 在data字段上添加@Valid注解,让他递归校验。
- 自定义一个Validator,在校验了BaseRequest后,手动valid字段data
代码:
public class BaseRequestValidator implements Validator {
private Validator validator;
public BaseRequestValidator() {
}
public BaseRequestValidator(Validator validator) {
super();
this.validator = validator;
}
@Override
public boolean supports(Class<?> clazz) {
return clazz.isAssignableFrom(BaseRequest.class);
}
@Override
public void validate(Object target, Errors errors) {
BaseRequest<?> req = (BaseRequest<?>) target;
validator.validate(req, errors);
validator.validate(req.getData(), errors);
}
}
Validator通过Spring的Autowire自动注入。
Controller代码:
@Autowired
private Validator validator;
@InitBinder
public void initBinder(WebDataBinder binder) {
//添加一个spring自带的validator
binder.setValidator(new BaseRequestValidator(validator));
}
这里Spring自动产生的Validator
实际上为org.springframework.validation.beanvalidation.OptionalValidatorFactoryBean
我们想要手动valid的时候,只需要注入一个validtor,直接调用validate方法,就可以手动valid。