下面提供一种springmvc的校验方案,一般没有校验或者手动写validator的话都要写好多代码好多if判断,使用JSR-303规范校验只需要在Pojo字段上加上相应的注解就可以实现校验了
1.依赖的jar包,我直接贴pom了
UTF-8
4.1.1.RELEASE
com.fasterxml.jackson.core
jackson-core
2.4.0
com.fasterxml.jackson.core
jackson-databind
2.4.0
commons-fileupload
commons-fileupload
1.3.1
javax.servlet
javax.servlet-api
3.1.0
javax.validation
validation-api
1.1.0.Final
org.hibernate
hibernate-validator
5.1.3.Final
org.springframework
spring-orm
${spring.version}
org.springframework
spring-context
${spring.version}
org.springframework
spring-web
${spring.version}
org.springframework
spring-webmvc
${spring.version}
org.springframework
spring-test
${spring.version}
org.slf4j
slf4j-log4j12
1.7.7
junit
junit
4.11
test
org.aspectj
aspectjweaver
1.8.4
javax.el
javax.el-api
3.0.0
2.springmvc配置
先建一个User类
public class User {
@NotNull
private String username;
@NotNull(message = "密码不能为空")
private String password;
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试试
@ResponseBody
@RequestMapping("/test1")
public AjaxResponse validateTest1(@Valid User user, BindingResult result){
AjaxResponse ajaxResponse = new AjaxResponse();
Map map = new HashMap<>();
if(result.hasErrors()){
ajaxResponse.setSuccess(false);
ajaxResponse.setHasErrors(true);
map.put("errors", result.getAllErrors());
}
else {
map.put("now", new Date());
map.put("user", user);
}
ajaxResponse.setData(map);
return ajaxResponse;
}
方法逻辑比较简单,调用result.hasErrors()看校验有没有错误,有错误的话就把所有的错误放进结果返回给客户端,如果没有错误就返回当前时间跟user对象
然后写个测试方法试试
@Test
public void test1() throws Exception{
this.mockMvc.perform(post("/validator/test1")).andDo(print());
this.mockMvc.perform(post("/validator/test1").param("username", "testusername").param("password", "testpassword")).andDo(print());
}
{"success":false,"message":null,"hasErrors":true,"data":[{"name":"user","message":"may not be null"},{"name":"user","message":"密码不能为空"}]}
{"success":true,"message":null,"hasErrors":false,"data":{"now":1420788232169,"user":{"username":"testusername","password":"testpassword"}}}
用起来还是很简单的,但是如果我不想每次都在controller方法里写if(result.hasErrors())怎么办呢,写个切面,把if写在切面里,如果有errors直接就返回了,不用再执行controller方法了
@Aspect
public class ValidAspect {
@Autowired private Validator validator;
@Around("@annotation(org.springframework.web.bind.annotation.ResponseBody)")
public Object doTest(ProceedingJoinPoint pjp) throws Throwable{
MethodSignature signature = (MethodSignature) pjp.getSignature();
Method method = signature.getMethod();
if(!AjaxResponse.class.equals(method.getReturnType())){
pjp.proceed();
}
Object[] args = pjp.getArgs();
Annotation[][] annotations = method.getParameterAnnotations();
for(int i = 0; i < annotations.length; i++){
if(!hasValidAnnotation(annotations[i])){
continue;
}
if(!(i < annotations.length-1 && args[i+1] instanceof BindingResult)){
//验证对象后面没有跟bindingResult,事实上如果没有应该到不了这一步
continue;
}
BindingResult result = (BindingResult) args[i+1];
if(result.hasErrors()){
AjaxResponse ajaxResponse = new AjaxResponse();
ajaxResponse.setSuccess(false);
ajaxResponse.setHasErrors(true);
ajaxResponse.setData(processErrors(result));
return ajaxResponse;
}
}
return pjp.proceed();
}
private boolean hasValidAnnotation(Annotation[] annotations){
if(annotations == null){
return false;
}
for(Annotation annotation : annotations){
if(annotation instanceof Valid){
return true;
}
}
return false;
}
private List processErrors(BindingResult result){
if(result != null && result.hasErrors()){
List list = new ArrayList();
for(ObjectError error : result.getAllErrors()){
BindingError be = new BindingError();
be.setMessage(error.getDefaultMessage());
be.setName(error.getObjectName());
list.add(be);
}
return list;
}
return null;
}
}
然后再写个方法逻辑跟上面的类似
@ResponseBody
@RequestMapping("/test2")
public AjaxResponse validateTest2(@Valid User user, BindingResult result){
AjaxResponse ajaxResponse = new AjaxResponse();
Map map = new HashMap<>();
map.put("now", new Date());
map.put("user", user);
ajaxResponse.setData(map);
return ajaxResponse;
}
写测试方式试一下
@Test
public void test2() throws Exception{
this.mockMvc.perform(post("/validator/test2")).andDo(print());
this.mockMvc.perform(post("/validator/test2").param("username", "testusername").param("password", "testpassword")).andDo(print());
}
{"success":false,"message":null,"hasErrors":true,"data":[{"name":"user","message":"密码不能为空"},{"name":"user","message":"may not be null"}]}
第二个请求结果是
{"success":true,"message":null,"hasErrors":false,"data":{"now":1420788479105,"user":{"username":"testusername","password":"testpassword"}}}
效果跟上面是一样的
JSR-303原生支持的校验注解也是有限的,如果要实现其他的验证,可以自己拓展,拓展方法就下次再说了,我也才刚接触。