我找到了这个答案(让我更接近我的目标,但不完全):如何在MultiActionController中执行Spring验证? 根据javadoc,异常处理程序方法是具有参数
(HttpServletRequest request,HttpServletResponse response,ExceptionClass exception)
的控制器方法。据我所见(如果我错了,请纠正我),它看起来像工作流程如下:spring dispatcher-servlet转到控制器的请求方法,如果在其执行期间发生异常(例如由于验证失败而导致绑定异常),它将转到其异常处理程序方法,该异常参数与发生的异常匹配(如果有这样的异常处理程序方法)。
但与普通控制器的方法不同,这个异常处理程序方法没有命令对象参数。因此我想问,在这个方法中如何访问发送请求的命令对象,当出现绑定异常(由于验证错误)时? 例如,当我使用注释进行验证时,我在请求处理程序方法中有访问(作为方法参数)两个BindingResult和命令对象,因此在出现验证错误的情况下,我可以使用命令对象数据加载返回的ModelAndView。
然而,在我的MultiActionController中使用异常处理程序方法时,它以...结束。
BindException bindException = (BindException) bindingException.getRootCause();
return new ModelAndView("myFormView").addAllObjects(bindException.getModel());
——提交无效数据后,我会收到一个异常,说我的JSP视图(“myFormView”)无法呈现,因为找不到命令对象。
谢谢!
更多信息:
我的控制器(SearchBookController)中实际的请求处理方法如下:
public ModelAndView list(HttpServletRequest request, HttpServletResponse response, Book book) throws Exception {
ModelMap modelMap = new ModelMap();
//getting a list of books according to the propertiest of the command object book...
modelMap.addAttribute("bookList", bookDAO.listBooks(book));
return new ModelAndView("bookForm", modelMap);
}
我还向控制器添加了以下异常处理程序方法:
public ModelAndView hanldeBindException(HttpServletRequest request, HttpServletResponse response, ServletRequestBindingException bindingException) {
// do what you want right here
//I WOULD LIKE TO ADD HERE THE SUBMITTED BOOK AND THE FETCHED BOOKLIST TO THE ModelAndView, BUT I DO NOT KNOW HOW TO DO IT
BindException bindException = (BindException) bindingException.getRootCause();
return new ModelAndView("bookForm").addAllObjects(bindException.getModel());
}
这是我如何将验证器添加到我的Servlet-dispatcher.xml文件中的SearchBookController中的方法:
<bean name="/book/search.htm" class="com.books.web.SearchBookController" p:validators-ref="searchBookValidator" >
<property name="bookDAO" ref="myBookDAO" />
</bean>
<bean id="searchBookValidator" class="com.books.validator.SearchBookValidator" />
目前的验证器只是确保书籍属性通过ValidationUtils.rejectIfEmptyOrWhitespace进行验证。
我的视图(bookForm.jsp)同时显示提交字段和搜索结果(当结果视图被呈现时,它重新显示提交的字段)。因此,在提交后,视图应该获取书籍命令对象和bookList对象。
bookForm.jsp如下所示:
<tr>
<td>Details :</td>
<td><form:input path="details" /></td>
<td><form:errors path="details" cssClass="error"/></td>
</tr>
(details是Book的一个字段之一。)
这是我在尝试加载bookForm.jsp时收到的异常消息(甚至在提交之前,仅在我尝试加载页面以便填写表单时):
(*** 当我从servlet-dispatcher.xml中的控制器定义中删除p:validators-ref =“searchBookValidator”
时,jsp页面在提交之前和之后都可以正确加载。)
HTTP Status 500 -
--------------------------------------------------------------------------------
type Exception report
message
description The server encountered an internal error () that prevented it from fulfilling this request.
exception
org.apache.jasper.JasperException: An exception occurred processing JSP page /WEB-INF/jsp/bookForm.jsp at line 209
206: --%>
207: <tr>
208: <td>Details :</td>
209: <td><form:input path="details" /></td>
210: <td><form:errors path="details" cssClass="error"/></td>
211: </tr>
212: <tr>
Stacktrace:
org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:510)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:413)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:313)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:260)
javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:238)
org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:250)
org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1047)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:817)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:549)
javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
root cause
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'book' available as request attribute
org.springframework.web.servlet.support.BindStatus.<init>(BindStatus.java:141)
org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getBindStatus(AbstractDataBoundFormElementTag.java:174)
org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getPropertyPath(AbstractDataBoundFormElementTag.java:194)
org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getName(AbstractDataBoundFormElementTag.java:160)
org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.autogenerateId(AbstractDataBoundFormElementTag.java:147)
org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.resolveId(AbstractDataBoundFormElementTag.java:138)
org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.writeDefaultAttributes(AbstractDataBoundFormElementTag.java:122)
org.springframework.web.servlet.tags.form.AbstractHtmlElementTag.writeDefaultAttributes(AbstractHtmlElementTag.java:408)
org.springframework.web.servlet.tags.form.InputTag.writeTagContent(InputTag.java:140)
org.springframework.web.servlet.tags.form.AbstractFormTag.doStartTagInternal(AbstractFormTag.java:102)
org.springframework.web.servlet.tags.RequestContextAwareTag.doStartTag(RequestContextAwareTag.java:79)
org.apache.jsp.WEB_002dINF.jsp.bookForm_jsp._jspx_meth_form_005finput_005f0(bookForm_jsp.java:593)
org.apache.jsp.WEB_002dINF.jsp.bookForm_jsp._jspService(bookForm_jsp.java:326)
org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:377)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:313)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:260)
javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:238)
org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:250)
org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1047)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:817)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:549)
javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
更新:
根据下面的回答,我现在可以从异常处理方法中访问命令对象。不过我仍然有一个问题:如果我提交了应该触发错误消息的数据,例如通过
<tr>
<td>Details :</td>
<td><form:input path="details" /></td>
<td><form:errors path="details" cssClass="error"/></td>
</tr>
在结果视图JSP中 - 我没有看到错误消息。
我的验证器看起来像这样:
public class SearchBookValidator implements Validator {
//......
@Override
public void validate(Object target, Errors errors) {
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "details", "details.required");
}
}
我的 messages.properties 文件包含以下行:
details.required=details are required
为了帮助我查看发生了什么,我在控制器的handleBindException中包含了以下代码:
Map mp = bindException.getModel();
for (Object o : mp.entrySet()) {
Map.Entry pairs = (Map.Entry)o;
System.out.println(pairs.getKey() + " = " + pairs.getValue());
}
当我提交表单时,使用故意错误的数据(例如,详细信息文本字段为空),我会在控制台上获得以下输入:
command = com.books.domain.Book@1173447
org.springframework.validation.BindingResult.command = org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'command' on field 'details': rejected value []; codes [details.required.command.details,details.required.details,details.required.java.lang.String,details.required]; arguments []; default message [null]
你能看出为什么我通过 <form:errors path="details" cssClass="error"/>
没有收到任何错误信息吗?