如何簡單實現一個自定義校驗注解。
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對象,至於方法里面的邏輯如何判斷
,各位就見仁見智了。