编程语言
首页 > 编程语言> > java – Spring MVC如何解析和验证处理程序方法参数?

java – Spring MVC如何解析和验证处理程序方法参数?

作者:互联网

我是Spring MVC的新手,我已经导入了一个与服务器端验证相关的教程项目,我对它究竟是如何工作有一些疑问.

所以我有一个名为login.jsp的登录页面,其中包含以下登录表单:

<form:form action="${pageContext.request.contextPath}/login" commandName="user" method="post">

    <table>

        <tr>
            <td><label>Enter Username : </label></td>
            <td><form:input type="text" path="username" name="username" />
                <br> <form:errors path="username" style="color:red;"></form:errors>
            </td>
        </tr>

        <tr>
            <td><label>Enter Password : </label></td>
            <td><form:input type="password" path="password" name="password" />
                <br> <form:errors path="password" style="color:red;"></form:errors>
            </td>
        </tr>

        <tr>
            <td>&nbsp</td>
            <td align="center"><input type="submit" value="Login" /></td>
        </tr>

    </table>

</form:form>

我认为使用从模型中检索到的commandName =“user”属性指定的对象(如果我做了错误的断言,请核对我)来存储用户插入的用户名和密码.

此commandName =“user”是此User类的实例:

import javax.validation.constraints.Size;
import org.hibernate.validator.constraints.NotBlank;

public class User {

    @NotBlank(message="Username can not be blank")
    private String username;

    @Size(min=6,message="Password must be atleast 6 characters long")
    private String password;

    private String gender;
    private String vehicle;
    private String country;
    private String image;

    ...............................................
    ...............................................
    GETTER AND SETTER METHODS
    ...............................................
    ...............................................
}

因此,您可以看到在用户名和密码字段中声明了@NotBlank和@Size验证注释.

这里是第一个疑问:与2使用的库javax.validation和org.hibernate.validator的区别究竟是什么?

教程中为什么同时使用?我可以只使用hibernate验证器库做同样的事情吗? (我认为我可以使用Hibernate验证器指定字符串的有效长度,或者不是)?

因此,当提交登录表单时,它会生成和HttpRequest,这个/ login资源由声明为控制器类的此方法处理:

@RequestMapping(value="/login" , method=RequestMethod.POST)
public String do_login(HttpServletRequest req , Model md , HttpSession session , @Valid User user, BindingResult br)
{
    try
    {
        //System.out.println(br.getAllErrors().size());

        String username = req.getParameter("username");
        String password = req.getParameter("password");

        System.out.println("Username and pasword are : "+username +"  "+ password);
        if(br.getAllErrors().size() > 0){
            System.out.println("Server side validation takes place....");
        }
        else{
        Login_Model lm = new Login_Model();
        String message = lm.do_login_process(username, password);

        if(message.equals("login success"))
        {
            session.setAttribute("username", username);
            return "redirect:/myprofile";
        }
        else
        {
            md.addAttribute("error_msg", message);
        }
        }
        return "login";
    }
    catch(Exception e)
    {
        return "login";
    }
}

好的,现在我对这个方法有以下疑问:

1)将此对象作为输入参数:@Valid User user.
谁传递给它?我认为它可能取决于我指定commandName =“user”的形式,所以Spring自动执行它.这是对的吗?

2)根据我的理解,@ Valid注释会自动调用验证过程.怎么会发生?与Spring提供的AOP功能有关吗?或者是什么?为什么这个@Valid注释只与javax.validation库相关,而不是与Hibernate验证器相关(所以@Valid注释也验证了用Hibernate验证器注释注释的字段?为什么?)

3)根据我的理解,如果用户在登录表单中插入了错误的值,我可以通过BindingResult br输入参数获取此错误.使用调试器,我可以看到该对象包含由定义到User模型对象中的注释定义的错误消息.究竟如何运作?

TNX

解决方法:

And here the first doubt: what exactly is the difference between the 2 used libraries javax.validation and org.hibernate.validator?

javax.validation来自JSR-303 API.您可以在this Maven dependency中查看API类.

Hibernate validator是JSR 303的实现之一(实际上是参考实现),因此它实现了所有API,但添加了自己的扩展,例如你提到的@NotBlank注释. JSR 303的其他实现是例如Apache BVal.

It takes this object as input parameter: @Valid User user. Who passes it to the handler method?

Spring MVC中处理程序方法的值由接口HandlerMethodArgumentResolver的实现提供.在您的情况下,将调用以解析User参数的实现可能是ServletModelAttributeMethodProcessor.您可以查看这些类的源代码和JavaDoc,以了解它们如何在内部工作.

The @Valid annotation will automatically call the validation process. How does this happend? Does it use AOP? Why this @Valid annotation is related only to the javax.validation library and not also to the Hibernate validator (so this @Valid annotation validate also the field annotated with Hibernate validator annotation?)

验证过程由ModelAttributeMethodProcessor调用,这是前面提到的ServletModelAttributeMethodProcessor继承的类.它包含以下方法:

protected void validateIfApplicable(WebDataBinder binder, MethodParameter parameter) {
    Annotation[] annotations = parameter.getParameterAnnotations();
    for (Annotation ann : annotations) {
        if (ann.annotationType().getSimpleName().startsWith("Valid")) {
            Object hints = AnnotationUtils.getValue(ann);
            binder.validate(hints instanceof Object[] ? (Object[]) hints : new Object[] {hints});
            break;
        }
    }
}

如果仔细观察,您将看到以下表达式的条件:

ann.annotationType().getSimpleName().startsWith("Valid")

这意味着如果参数具有以Valid开头的任何注释,Spring将调用验证.它可能是JSR 303的@Valid或Spring的@Validated,它支持验证组.它甚至可以是您的自定义注释,只要它的名称以Valid开头即可.

From what I have understand if the user inserts wrong values into the login form I can obtain this error from the BindingResult handler parameter. Using the debugger I can see that this object contain the error message defined by the annotation defined into the User model object. How exactly works?

让我们回到ModelAttributeMethodProcessor类. resolveArgument方法中有以下代码:

WebDataBinder binder = binderFactory.createBinder(webRequest, attribute, name);

这将创建WebDataBinder实例,在前面提到的validateIfApplicable方法中调用验证.验证本身填充BindingResult,然后通过ErrorsMethodArgumentResolver类将其提供给控制器处理程序方法,该类再次实现HandlerMethodArgumentResolver.

TLDR:你在这个问题中提出的许多问题都可以追溯到HandlerMethodArgumentResolver的各种实现.我建议通过这些课程并使用调试器逐步完成它们以更好地理解它们.

标签:hibernate-validator,spring-validator,java,spring,spring-mvc
来源: https://codeday.me/bug/20190722/1503986.html