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> </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
andorg.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 thejavax.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