自定义校验注解(org.hibernate.validator)
如何简单实现一个自定义校验注解。
validator实现了java的校验器API,里面提供了很多校验器注解,但是有时候这些注解不能满足我们的业务校验。
validator也提供了自定义注解的接口,我们只要继承这个接口,并且实现它的方法,就能完成一个简单的自定义注解
注解类
package com.custom; import javax.validation.Constraint; import javax.validation.Payload; import java.lang.annotation.Retention; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.*; import static java.lang.annotation.RetentionPolicy.RUNTIME; //这个注解能使用在哪里 @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
//这个注解什么时候执行 @Retention(RUNTIME)
//这个注解对应的校验器类,(这个类一般实现了校验器接口) @Constraint(validatedBy = { ParamNotNullValidator2.class }) public @interface ParamNotNull2 {
//异常消息 String message() default "参数不能为空----自定义注解"; //剩下的自己按需要加 Class<?>[] groups() default { }; Class<? extends Payload>[] payload() default { }; }
校验器类
package com.custom; import com.service.DeptService; import org.springframework.beans.factory.annotation.Autowired; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; //第一个参数指定注解类,第二个指定校验值类型 public class ParamNotNullValidator2 implements ConstraintValidator<ParamNotNull2,String> { @Autowired private DeptService deptService;
//校验方法,里面写自己需要校验的逻辑 public boolean isValid(String value, ConstraintValidatorContext context) {
//先判断这个值是否为null和"" if( value == null || value.equals("") ){ return false; } //调用业务类方法 String name = deptService.queryOne(value); if(name == null){ return true; }else { return false; } } }
控制器类
package com.controller; import com.entity.Dept; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.RequestMapping; import javax.validation.Valid; @Controller public class TestDeptController { //使用@Valid声明使用校验器 @RequestMapping("/queryOne") public String queryOne(@Valid Dept dept, BindingResult bindingResult, Model model){ if(bindingResult.hasErrors()){ model.addAttribute("msg",bindingResult.getFieldError("name")); }else { model.addAttribute("msg","这个名字可以用"); } return "index"; } }
实体类
package com.entity; import com.custom.ParamNotNull2; public class Dept { private int id; public int getId() { return id; } public void setId(int id) { this.id = id; } @ParamNotNull2 private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Dept{" + "id=" + id + ", name='" + name + '\'' + '}'; } }
主页面JSP
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <form action="/queryOne" method="post"> <input type="text" name="name"/> <input type="submit" value="提交"/> </form> </body> </html>
成功或者失败跳转JSP
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <h1>${msg}</h1> </body> </html>
这样我们就实现了一个基于Spring Mvc的自定义校验器
说一说常见的异常:
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is javax.validation.ValidationException: HV000028: Unexpected exception during isValid call. org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014) org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) javax.servlet.http.HttpServlet.service(HttpServlet.java:635) org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) javax.servlet.http.HttpServlet.service(HttpServlet.java:742) org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
这个异常:说明你写的自定义控制器里面的isValid方法里面执行出现了异常,常见的错误:用户界面使用form表单提交,那么控制器方法的value参数,当用户没有传参的时候,是一个null对象,如果使用
equals判断这个value是否为"",会出现这个异常,下面还有一条异常提示NullPointerException,这说明这个value没有值时会给个null对象,使用equals是会出现异常的,因为它是在校验器方法执行的
所以会报上面的异常,解决办法,去掉equals("")判断,换成==null,或者让equals在后面判断
如果不使用form表单提交的数据,如果用户没有传值的情况下,不会给null对象给value,会给一个"",说明:get请求方法是通过Url传值,所以会给一个"",post请求会给一个null对象,至于方法里面的逻辑如何判断
,各位就见仁见智了。