如何简单实现一个自定义校验注解。

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" %>
    <title>Title</title>
</head>
    <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" %>
    <title>Title</title>
</head>
    <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对象,至于方法里面的逻辑如何判断
,各位就见仁见智了。