gpt4 book ai didi

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

转载 作者:塔克拉玛干 更新时间:2023-11-01 21:54:26 24 4
gpt4 key购买 nike

我是 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.validationorg.hibernate.validator 到底有什么区别?

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

因此,当提交登录表单时,它会生成 HttpRequest 并向 /login 资源发出请求,该资源由声明到 Controller 类中的此方法处理:

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

OK,现在我对这个方法有如下疑惑:

  1. 将此对象作为输入参数:@Valid User 用户。谁传给它?我认为这可能取决于我在表单中指定 commandName="user" 的事实,因此 Spring 会自动执行此操作。是否正确?

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

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

最佳答案

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。您可以查看 API 类,例如 this Maven dependency .

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 中处理程序方法的值由接口(interface) HandlerMethodArgumentResolver 的实现提供.在您的情况下,将调用以解析 User 参数的实现可能是 ServletModelAttributeMethodProcessor .您可以查看这些类的源代码和 JavaDocs 以了解它们的内部工作方式。


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 调用,也就是前面提到的class 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 类提供给 Controller 处理程序方法,该类再次实现 HandlerMethodArgumentResolver


TLDR:您在这个问题中提出的很多问题都可以追溯到 HandlerMethodArgumentResolver 的各种实现。我建议浏览这些类并使用调试器逐步浏览它们以更好地理解它们。

关于java - Spring MVC 如何解析和验证处理程序方法参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33053553/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com