Spring @Validated和@InitBinder的异常

时间:2018-06-06 08:25:49

标签: spring spring-mvc

当我使用Spring @Validated进行验证时,我遇到了一个奇怪的问题。

这是核心代码。

Java模型:

@Getter 
@Setter
public class User {

    private String userName;
    private String password;
    private String email;

}

自定义UserValidate

    public class UserValidate implements Validator {

    @Override 
    public boolean supports(Class<?> arg0) {
        System.out.println("ee:"+arg0+","+User.class.isAssignableFrom(arg0));
        return User.class.isAssignableFrom(arg0);
    }

    @Override 
    public void validate(Object target, Errors errors) {
        //ValidationUtils.rejectIfEmpty(errors, "userName", "user.userName.required", "username can not be empty");
        //ValidationUtils.rejectIfEmpty(errors, "password", "user.password.required", "password can not be empty");
        //ValidationUtils.rejectIfEmpty(errors, "email", "user.email.required", "email can not be empty");
        User user = (User) target;
        int length = user.getUserName().length();
        if (length > 20) {
            errors.rejectValue("userName", "user.userName.too_long", "Username cannot exceed {20} characters");
        }
        length = user.getPassword().length();
        if (length < 6) {
            errors.rejectValue("password", "user.password.too_short", "Password is too short to be less than {6} characters");
        } else if (length > 20) {
            errors.rejectValue("password", "user.password.too_long", "Password is too long to be longer than {20} characters");
        }
        int index = user.getEmail().indexOf("@");
        if (index == -1) {
            errors.rejectValue("email", "user.email.invalid_email", "Bad mailbox format");
        }
    }
}

Thymeleaf表格:

<html>
<head>
</head>
<body>

    <br /><hr />

    <form action="#" th:action="@{/addUser}"  method="POST">
        userName :<input type="text" name="userName"  /><br />
        password :<input type="text" name="password" /><br />
        email :<input type="text" name="email" /><br />
        result:<div style="font-size:18px;"><span th:text="${result}"></span></div>
        <input type="submit" />
    </form>

</body>

控制器:

import java.util.List;
import java.util.function.Consumer;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.servlet.ModelAndView;

import com.example.demo.app.model.User;
import com.example.demo.app.validate.UserValidate;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableListMultimap.Builder;

@Controller
public class UserController {

    @GetMapping("/userInfo")
    public ModelAndView userInfo() {
        ModelAndView userView = new ModelAndView("user");
        return userView;
    }


    @PostMapping("/addUser")
    public String addBook(@Validated User user,BindingResult result, Model model) {

        if(result.hasErrors()){
            List<ObjectError> allErrors = result.getAllErrors();
            Builder<String, String> builder = ImmutableListMultimap.builder();
            allErrors.stream().forEach(new Consumer<ObjectError>() {

                @Override
                public void accept(ObjectError t) {
                    builder.put(t.getObjectName(), t.getDefaultMessage());
                }
            });

            ImmutableListMultimap<String, String> build = builder.build();
            model.addAttribute("result",build);
        }else {
            model.addAttribute("result","success");
        }
        return "user";
    }

    @InitBinder
    public void initBinder(WebDataBinder binder) {
        binder.addValidators(new UserValidate());
    }

}

提交后,异常异常。异常的结果是ImmutableListMultimap类还执行UserValidate的验证过程。为什么会这样?

异常堆栈:

ee:class com.example.demo.app.model.User,true
ee:class com.google.common.collect.ImmutableListMultimap,false
2018-06-06 18:07:40.172 ERROR 10696 --- [nio-8088-exec-1] o.a.c.c.C.[.[.[.[dispatcherServlet]      : Servlet.service() for servlet [dispatcherServlet] in context with path [/spring-demo] threw exception [Request processing failed; nested exception is java.lang.IllegalStateException: Invalid target for Validator [com.example.demo.app.validate.UserValidate@2a8b1054]: {user=[Password is too short to be less than {6} characters, Bad mailbox format]}] with root cause

java.lang.IllegalStateException: Invalid target for Validator [com.example.demo.app.validate.UserValidate@2a8b1054]: {user=[Password is too short to be less than {6} characters, Bad mailbox format]}
    at org.springframework.validation.DataBinder.assertValidators(DataBinder.java:568) ~[spring-context-4.3.17.RELEASE.jar:4.3.17.RELEASE]
    at org.springframework.validation.DataBinder.setValidator(DataBinder.java:558) ~[spring-context-4.3.17.RELEASE.jar:4.3.17.RELEASE]
    at com.example.demo.app.controller.UserController.initBinder(UserController.java:56) ~[classes/:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_144]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_144]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_144]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_144]
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) ~[spring-web-4.3.17.RELEASE.jar:4.3.17.RELEASE]
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133) ~[spring-web-4.3.17.RELEASE.jar:4.3.17.RELEASE]
    at org.springframework.web.method.annotation.InitBinderDataBinderFactory.initBinder(InitBinderDataBinderFactory.java:64) ~[spring-web-4.3.17.RELEASE.jar:4.3.17.RELEASE]
    at org.springframework.web.bind.support.DefaultDataBinderFactory.createBinder(DefaultDataBinderFactory.java:57) ~[spring-web-4.3.17.RELEASE.jar:4.3.17.RELEASE]
    at org.springframework.web.method.annotation.ModelFactory.updateBindingResult(ModelFactory.java:218) ~[spring-web-4.3.17.RELEASE.jar:4.3.17.RELEASE]
    at org.springframework.web.method.annotation.ModelFactory.updateModel(ModelFactory.java:204) ~[spring-web-4.3.17.RELEASE.jar:4.3.17.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.getModelAndView(RequestMappingHandlerAdapter.java:931) ~[spring-webmvc-4.3.17.RELEASE.jar:4.3.17.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:832) ~[spring-webmvc-4.3.17.RELEASE.jar:4.3.17.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) ~[spring-webmvc-4.3.17.RELEASE.jar:4.3.17.RELEASE]
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) ~[spring-webmvc-4.3.17.RELEASE.jar:4.3.17.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967) ~[spring-webmvc-4.3.17.RELEASE.jar:4.3.17.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901) ~[spring-webmvc-4.3.17.RELEASE.jar:4.3.17.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) ~[spring-webmvc-4.3.17.RELEASE.jar:4.3.17.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872) ~[spring-webmvc-4.3.17.RELEASE.jar:4.3.17.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:661) ~[tomcat-embed-core-8.5.31.jar:8.5.31]
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) ~[spring-webmvc-4.3.17.RELEASE.jar:4.3.17.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) ~[tomcat-embed-core-8.5.31.jar:8.5.31]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-8.5.31.jar:8.5.31]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.31.jar:8.5.31]
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) ~[tomcat-embed-websocket-8.5.31.jar:8.5.31]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.31.jar:8.5.31]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.31.jar:8.5.31]
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) ~[spring-web-4.3.17.RELEASE.jar:4.3.17.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.17.RELEASE.jar:4.3.17.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.31.jar:8.5.31]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.31.jar:8.5.31]
    at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:109) ~[spring-web-4.3.17.RELEASE.jar:4.3.17.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.17.RELEASE.jar:4.3.17.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.31.jar:8.5.31]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.31.jar:8.5.31]
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81) ~[spring-web-4.3.17.RELEASE.jar:4.3.17.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.17.RELEASE.jar:4.3.17.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.31.jar:8.5.31]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.31.jar:8.5.31]
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) ~[spring-web-4.3.17.RELEASE.jar:4.3.17.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.17.RELEASE.jar:4.3.17.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.31.jar:8.5.31]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.31.jar:8.5.31]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) ~[tomcat-embed-core-8.5.31.jar:8.5.31]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.31.jar:8.5.31]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:496) [tomcat-embed-core-8.5.31.jar:8.5.31]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.31.jar:8.5.31]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81) [tomcat-embed-core-8.5.31.jar:8.5.31]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.31.jar:8.5.31]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) [tomcat-embed-core-8.5.31.jar:8.5.31]
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803) [tomcat-embed-core-8.5.31.jar:8.5.31]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.31.jar:8.5.31]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:790) [tomcat-embed-core-8.5.31.jar:8.5.31]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1468) [tomcat-embed-core-8.5.31.jar:8.5.31]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.31.jar:8.5.31]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_144]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_144]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.31.jar:8.5.31]
    at java.lang.Thread.run(Thread.java:748) [na:1.8.0_144]

0 个答案:

没有答案