转载请注明: TheViper http://www.cnblogs.com/TheViper
基于JSR303注解校验
问题的出现
一个很常见的场景,对于一个model(pojo) User(属性有id,name,pwd密码,email),在登陆注册页面中,登陆校验和注册校验
1.需要校验的属性不同。登陆只需校验name和pwd就可以了,不像注册需要校验全部属性。
2.校验同一属性的目的不同。比如,注册的时候,需要校验name属性是否为空,还有长度是否符合要求;登陆的时候就只用校验是否为空就可以了。pwd同理。
3.由于校验的目的不同,相应的返回的信息也不同。
可以看到此时如果只是在model属性上单纯的用注解是无能为力的,好在spring mvc为我们提供了解决方法。
解决
先看下最终效果
下面从头到尾说下步骤:
1.下载spring framework,添加spring mvc必须的jar
例子里面没有用到数据库,所以少了很多jar.
2.添加org.json包,用于生成json格式字符串。当然也可以用其他可以生成json字符串的包。
3.添加hibernate-validator.jar,validation-api.jar,使spring mvc支持JSR303注解式的校验
4.添加commons-logging.jar,jboss-logging.jar。否则启动服务器出现错误。
5.添加classmate.jar,否则出现java.lang.ClassNotFoundException: com.fasterxml.classmate.Filter
6.在model上添加校验注解,并为相应注解分组。比如
public class User { private int id; @NotEmpty(message="用户名不能为空",groups={LoginCheck.class,RegCheck.class}) @Size(min=3,max=12,message="登录名必须3-12位",groups={RegCheck.class}) private String name; @NotEmpty(message="密码不能为空",groups={LoginCheck.class,RegCheck.class}) @Size(min=6,max=16,message="密码必须6-16位",groups={RegCheck.class}) private String pwd; @NotEmpty(message="邮箱不能为空",groups={RegCheck.class}) @Email(message="不符合邮箱格式",groups={RegCheck.class}) private String email; }
可以看到注册和登陆分别被”分到“了RegCheck.class和LoginCheck.class。这里的分组必须显式表明校验注解所属于的组。
7.新建LoginCheck类,RegCheck类
public interface RegCheck { } public interface LoginCheck { }
8.在业务类中添加@Validated注解,设置value值表示属于哪个校验组,当然前提是参数注入@ModelAttribute到model中
需要注意的地方
1.json字符串的生成,返回用org.json的json.toString()就可以了,不用像网上或书上说的用spring mvc的MappingJackson,还要去设置一下才能用。在返回数据类型上用@ResponseBody String就可以了。spring mvc会自动为响应添Content-Type:application/json。不过这样返回的json字符串会乱码
@RequestMapping(value = "/login",produces = {"application/json;charset=UTF-8"})就可以了。当然,也可以用网上说的其他方法。
2.关于错误信息的设置,可以到jar包里面设置。本屌这里是写了个封装,直接取出用的。
public static JSONObject formatError(List<FieldError> errors) throws JSONException{ JSONObject wrap = new JSONObject(); JSONObject jsonObject= new JSONObject(); for(FieldError fieldError:errors) jsonObject.put(fieldError.getField(),fieldError.getDefaultMessage()); wrap.put("errors", jsonObject); return wrap; }
bindingResult.hasErrors():校验中是否有错误。
bindingResult.getFieldErrors():返回List,里面是FieldError,FieldError类getField()返回校验的属性名,getDefaultMessage()返回的就是自定义的错误信息。
3.关于注册中的重复密码(repwd)的校验,可以用网上说的实现Validator接口。这里是在User类中定义repwd属性。
注意,由于要用到@AssertTrue,repwd属性在这里不能有getter方法,而是isRepwd()
private String repwd; @AssertTrue(message="密码两次输入不一致",groups={RegCheck.class}) private boolean isRepwd() { return this.pwd.equals(this.repwd); }
还可以参考http://jinnianshilongnian.iteye.com/blog/1990081,其实spring mvc3就已经支持JSR303 group注解校验了。
https://kevinpotgieter.wordpress.com/2012/02/20/jsr303-spring-mvc-selective-validations/