Java SpringMVC如何解析和验证处理程序方法参数?
我是SpringMVC的新手,我已经导入了一个与服务器端验证相关的教程项目,我对它到底是如何工作的有些怀疑 因此,我有一个名为login.jsp的登录页面,其中包含以下登录表单:Java SpringMVC如何解析和验证处理程序方法参数?,java,spring,spring-mvc,hibernate-validator,spring-validator,Java,Spring,Spring Mvc,Hibernate Validator,Spring Validator,我是SpringMVC的新手,我已经导入了一个与服务器端验证相关的教程项目,我对它到底是如何工作的有些怀疑 因此,我有一个名为login.jsp的登录页面,其中包含以下登录表单: <form:form action="${pageContext.request.contextPath}/login" commandName="user" method="post"> <table> <tr> <td&g
<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>
因此,您可以看到,在用户名和密码字段中声明了@NotBlank和@Size验证注释
这里是第一个疑问:与使用的两个库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。
谁去了?我认为这可能取决于这样一个事实,即在我指定的commandName=“user”形式中,Spring会自动执行此操作。对吗
2) 据我所知,@Valid注释自动调用验证过程。这是怎么发生的?是否与Spring提供的AOP功能有关?还是怎样为什么此@Valid注释仅与javax.validation库相关,而不与Hibernate验证程序相关(因此此@Valid注释还验证用Hibernate验证程序注释的字段?为什么?)
3) 据我所知,如果用户在登录表单中插入错误的值,我可以通过BindingResult br输入参数获得此错误。使用调试器,我可以看到此对象包含由用户模型对象中定义的注释定义的错误消息。具体是如何工作的
Tnx
与2个使用过的库有什么区别
javax.validation和org.hibernate.validator
Bean验证是一个Java规范,它允许您通过注释表达对象模型上的约束,允许您以可扩展的方式编写自定义约束它只是一个完全没有实现的规范。
Hibernate验证器是该规范的一个实现。Hibernate验证器完全实现了Bean验证,它还具有Hibernate独有的一些特性。简而言之,javax.validation
是规范部分,org.hibernate.validator
是hibernate特有的特性
我可以只使用hibernate验证程序库做同样的事情吗?(一)
假设我可以使用
是否休眠验证程序
可以,但最好坚持使用javax.validation
名称空间,只使用供应商特定名称空间的独特功能,如org.hibernate.validator
。这种方法的好处是,您可以将Bean验证实现从Hibernate验证器切换到另一个,只需最少的更改
为什么在教程中同时使用这两种方法
因为@NotBlank
约束在Bean验证规范中不可用,并且仅由Hibernate验证器提供
它将此对象作为输入参数:@Valid User。谁去了
信息技术我认为这可能取决于这样一个事实,即
指定commandName=“user”以便Spring自动执行此操作。它是
对吗
可能您有GET
控制器用于login
url,它返回一个空的User
对象,该对象反过来又与spring标记绑定,如
。当用户填写表单并提交表单时,spring将收集这些标记值并创建user
的实例并将其传递给控制器
为什么这个@Valid注释只与javax.validation相关
库,而不是Hibernate验证程序(所以这个@Valid
注释还验证用Hibernate validator注释的字段
注释?为什么?)
已经解释过了,规范/实施故事
这里是第一个疑问:所使用的两个库javax.validation
和org.hibernate.validator
之间到底有什么区别
javax.validation
来自JSR-303API。例如,您可以在中查看API类
是JSR303的实现之一(实际上是参考实现),因此它实现了所有API,但添加了自己的扩展,例如您提到的@NotBlank
注释。JSR303的其他实现就是一个例子
它将此对象作为输入参数:
@Valid User
。谁将其传递给handler方法
SpringMVC中处理程序方法的值由接口的实现提供。在您的情况下,将被调用以解析用户
参数的实现可能是。您可以查看这些类的源代码和Javadoc,以了解它们在内部的工作方式
@Valid
注释将自动调用验证过程。这是怎么发生的?它使用AOP吗?为什么此@Valid
注释仅与javax.validation
库相关,而不与Hibernate验证程序相关(因此此@Valid
注释还验证用Hibernate验证程序注释的字段?)
验证过程由调用,这是前面提到的类ServletModelAttributeMethodProcessor
继承的。它包含以下方法:
@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";
}
}
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")
WebDataBinder binder = binderFactory.createBinder(webRequest, attribute, name);