And*_*ili 3 java spring spring-mvc hibernate-validator spring-validator
我是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>
Run Code Online (Sandbox Code Playgroud)
我认为使用从模型中检索到的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
...............................................
...............................................
}
Run Code Online (Sandbox Code Playgroud)
因此,您可以看到在用户名和密码字段中声明了@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";
}
}
Run Code Online (Sandbox Code Playgroud)
好的,现在我对这个方法有以下疑问:
1)将此对象作为输入参数:@Valid User user.谁传递给它?我认为它可能取决于我指定commandName ="user"的形式,所以Spring自动执行它.这是对的吗?
2)根据我的理解,@ Valid注释会自动调用验证过程.怎么会发生?与Spring提供的AOP功能有关吗?或者是什么?为什么这个@Valid注释只与javax.validation库相关,而不是与Hibernate验证器相关(所以@Valid注释也验证了用Hibernate验证器注释注释的字段?为什么?)
3)根据我的理解,如果用户在登录表单中插入了错误的值,我可以通过BindingResult br输入参数获取此错误.使用调试器,我可以看到该对象包含由定义到User模型对象中的注释定义的错误消息.究竟如何运作?
TNX
这里的第一个疑问:究竟是什么2个使用的库之间的差异
javax.validation和org.hibernate.validator?
javax.validation来自JSR-303 API.您可以在此Maven依赖项中查看API类.
Hibernate验证器是JSR 303的实现之一(实际上是参考实现),因此它实现了所有的API,但添加了自己的扩展,例如@NotBlank您提到注释.JSR 303的其他实现是例如Apache BVal.
它将此对象作为输入参数:
@Valid User user.谁将它传递给处理程序方法?
Spring MVC中处理程序方法的值由接口的实现提供HandlerMethodArgumentResolver.在您的情况下,将调用解析User参数的实现可能是ServletModelAttributeMethodProcessor.您可以查看这些类的源代码和JavaDoc,以了解它们在内部的工作方式.
该
@Valid注释将自动调用验证过程.这是怎么回事?它使用AOP吗?为什么这个@Valid注释只与javax.validation库有关,而不与Hibernate验证器有关(所以这个@Valid注释也验证了用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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果仔细观察,您将看到以下表达式的条件:
ann.annotationType().getSimpleName().startsWith("Valid")
Run Code Online (Sandbox Code Playgroud)
这意味着如果参数具有以任何开头的注释,Spring将调用验证Valid.它可能是JSR 303 @Valid或Spring @Validated,它支持验证组.它甚至可以是您的自定义注释,只要它的名称以它开头即可Valid.
根据我的理解,如果用户在登录表单中插入了错误的值,我可以从
BindingResulthandler参数中获取此错误.使用调试器,我可以看到该对象包含由定义到User模型对象中的注释定义的错误消息.究竟如何运作?
我们回到ModelAttributeMethodProcessor课堂吧.其resolveArgument方法中有以下代码:
WebDataBinder binder = binderFactory.createBinder(webRequest, attribute, name);
Run Code Online (Sandbox Code Playgroud)
这将创建WebDataBinder在前面提到的validateIfApplicable方法中调用验证的实例.验证本身会填充BindingResult然后通过ErrorsMethodArgumentResolver类提供给控制器处理程序方法,然后再次实现HandlerMethodArgumentResolver.
TLDR:你在这个问题上提出的许多问题都可以追溯到各种实现HandlerMethodArgumentResolver.我建议通过这些课程并使用调试器逐步完成它们以更好地理解它们.
| 归档时间: |
|
| 查看次数: |
1600 次 |
| 最近记录: |