当前位置: 首页 > 知识库问答 >
问题:

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

方权
2023-03-14

我是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>
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
    ...............................................
    ...............................................
}

因此,如您所见,在username和password字段上声明了@notblank和@size验证注释。

这里的第一个疑问是:与两个常用库javax.validation和org.hibernate.validator到底有什么不同?

为什么在教程中两者都用?我可以只使用hibernate验证器库做同样的事情吗?(我认为我可以使用Hibernate验证器指定一个字符串的有效lenght,还是不能)?

@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";
    }
}

3)据我所知,如果用户在登录表单中插入错误的值,我可以通过BindingResult br输入参数获得此错误。使用调试器,我可以看到此对象包含由定义到用户模型对象的注释定义的错误消息。具体如何工作?

TNX

共有1个答案

鲜于喜
2023-03-14

这里的第一个疑问是:两个常用库javax.validationorg.hibernate.validator之间到底有什么区别?

javax.validation来自JSR-303 API。例如,您可以查看这个Maven依赖项中的API类。

Hibernate validator是JSR303的实现之一(实际上是引用实现),因此它实现了所有API,但添加了自己的扩展,例如您提到的@notblank注释。JSR303的其他实现例如是Apache BVAL。

@valid注释将自动调用验证过程。这是怎么发生的?它使用AOP吗?为什么这个@valide注释只与javax.validation库相关,而与Hibernate验证器无关(所以这个@valide注释也验证了用Hibernate验证器注释注释的字段?)

验证过程由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")

让我们回到ModelAttributeMethodProcessor类。它的resolveargument方法中有以下代码:

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

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

TLDR:您在本问题中询问的许多问题都可以追溯到HandlerMethodArgumentResolver的各种实现。我建议使用调试器对这些类进行一步一步的检查,以便更好地理解它们。

 类似资料:
  • 本文向大家介绍springmvc处理模型数据Map过程解析,包括了springmvc处理模型数据Map过程解析的使用技巧和注意事项,需要的朋友参考一下 这篇文章主要介绍了springmvc处理模型数据Map过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 SpringmvcTest.java Index.jsp success.jsp 启动

  • 本文向大家介绍SpringMVC上传和解析Excel方法,包括了SpringMVC上传和解析Excel方法的使用技巧和注意事项,需要的朋友参考一下 示例:导入相关数据(Excel文件),相关的文件数据编辑好。 XML文件配置 再spring的xml文件中配置要上传文件的大小 Jsp界面配置 js文件 Controller配置 分层没有那么的详细,再Controller中做的处理 工具类ExcelU

  • 我试图验证方法的参数是否为空,但我没有找到解决方案。。。 有人可以告诉我该怎么做吗? 我正在尝试这样的事情:

  • 本文向大家介绍springmvc处理响应数据的解析,包括了springmvc处理响应数据的解析的使用技巧和注意事项,需要的朋友参考一下 1. ModelAndView 相关的成员变量和方法 private Object view; 描述视图信息 private ModelMap model 描述模型数据(响应数据) public void setViewName(String viewName)

  • 本文向大家介绍SpringMVC Controller解析ajax参数过程详解,包括了SpringMVC Controller解析ajax参数过程详解的使用技巧和注意事项,需要的朋友参考一下 在使用ajax发送请求时,如果发送的JSON数据的参数是一个类中的不同属性,在Controller类的方法中使用@RequestBody Object obj会直接封装进obj对象中 例如: 前端部分代码 J

  • 当作为参数传递时,为什么调用具有类型为的参数的方法,而不是调用具有类型为的参数的方法?