Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用MultiActionController进行Spring MVC表单验证_Java_Spring_Spring Mvc_Bean Validation - Fatal编程技术网

Java 使用MultiActionController进行Spring MVC表单验证

Java 使用MultiActionController进行Spring MVC表单验证,java,spring,spring-mvc,bean-validation,Java,Spring,Spring Mvc,Bean Validation,我正在尝试在MultiActionController上应用表单验证(我知道控制器类现在已经不推荐了) 我找到了这个答案(这让我更接近我的目标,但不是完全): 好的,根据,异常处理程序方法是控制器的方法,参数为(HttpServletRequest请求、HttpServletResponse响应、ExceptionClass异常) 据我所知(如果我错了,请纠正我),工作流程如下:spring dispatcher servlet转到控制器的请求方法,如果在执行过程中发生异常(例如,由于验证失败

我正在尝试在MultiActionController上应用表单验证(我知道控制器类现在已经不推荐了)

我找到了这个答案(这让我更接近我的目标,但不是完全):

好的,根据,异常处理程序方法是控制器的方法,参数为
(HttpServletRequest请求、HttpServletResponse响应、ExceptionClass异常)

据我所知(如果我错了,请纠正我),工作流程如下:spring dispatcher servlet转到控制器的请求方法,如果在执行过程中发生异常(例如,由于验证失败导致的绑定异常),它将转到异常处理程序方法,使其异常参数与发生的异常相匹配(如果存在这样的异常处理程序方法)

但与常规控制器的方法不同,此异常处理程序方法没有命令对象参数因此,我的问题是,如何在该方法中访问与发生绑定异常(由于验证错误)的请求一起发送的命令对象?

例如,当我使用注释验证时,我在请求处理程序方法中可以访问BindingResult和command对象(作为方法参数),因此在出现验证错误的情况下,我可以使用command对象数据加载返回的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);
}
    <tr>
        <td>Details :</td>
        <td><form:input path="details" /></td>
        <td><form:errors path="details" cssClass="error"/></td>
    </tr>
public class SearchBookValidator implements Validator {

    //......

    @Override
    public void validate(Object target, Errors errors) {
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "details", "details.required");
    }
}
我还向控制器添加了以下异常处理程序方法:

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" />
更新:

根据下面的答案,我现在可以从异常处理程序方法访问command对象。但我仍然有一个问题:如果我提交的数据本应触发错误消息,例如通过

<tr>
    <td>Details :</td>
    <td><form:input path="details" /></td>
    <td><form:errors path="details" cssClass="error"/></td>
</tr>
而my messages.properties包含以下行:

details.required=details are required
为了帮助我了解发生了什么,我在控制器的hanldeBindException中包含了以下代码:

    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]

你能看到为什么我没有通过Stacktrace消息得到任何错误消息吗

java.lang.IllegalStateException:bean名称“book”的BindingResult和普通目标对象都不能作为请求属性使用

<form:form commandName="book">
好吧,我假设您有一个如下所示的Spring表单(注意commandName属性)

改用

public ModelAndView list(HttpServletRequest request, HttpServletResponse response, Book book) throws Exception {
    return new ModelAndView("bookForm")
           .addAttribute("bookList", bookDAO.listBooks(book))
           .addAttribute(book);
}
注意:如果抛出的异常与作为参数的异常匹配,则只会调用异常处理程序

// It will be just called when some validation or binding Exception occurs
// Otherwise, Spring will bypass it
public ModelAndView hanldeBindException(HttpServletRequest request, HttpServletResponse response, ServletRequestBindingException bindingException) {
    BindException bindException = (BindException) bindingException.getRootCause();

    BindingResult bindingResult = (BindingResult) bindException.getModel().get(BindingResult.MODEL_KEY_PREFIX + "book");

    /**
      * bindingResult.getTarget() returns submitted Book object
      */

    return new ModelAndView("bookForm")
           .addAllObjects(bindException.getModel())
           .addAttribute("bookList", bookDAO.listBooks(bindingResult.getTarget()));
}
更新

您已注册您的消息源吗

<!--IT MUST BE CALLED messageSource-->
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
    <property name="basenames" value="ValidationMessages"/>
</bean>


前面的设置在类路径的根目录中使用ValidationMessages.properties。根据您的属性文件进行更新

我只是像您一样尝试在Spring MultiActionController中进行验证。对于从ResourceBundles获取消息,我仍然有问题(仍在查找),但我只是尝试在我的validator类(validate函数)中设置如下默认消息:

但是我仍然看不到jsp中的错误消息,然后我尝试在jsp中更改commmandName格式,如下所示:

<form:form action="update.htm" commandName="command">
   <!-- Form Field and so on -->
</form:form>

而且它有效!(请记住,在控制器中也要调整对象名称)我仍然在寻找一种方法,将commandName更改为自定义名称,例如在您的示例中的“book”,而不是默认的“command”对象名称


如果这没有帮助,很抱歉

这已经晚了4年,但希望这能帮助其他人。关于rapt的最后一个问题,关于为什么他仍然没有打印出
。这是因为MultiActionController的默认commandName是“command”(从他的日志输出中可以看到)

要获得正确的commandName,请重写getCommandName方法以返回所需的commandName(在rapt的情况下为“book”),或者按照如下命名约定派生它

protected String getCommandName(Object command) {
    return Conventions.getVariableName(command);
}

“详细信息”字段的错误现在应该出现。

您可以发布呈现页面的输出吗(“无法呈现,因为找不到命令对象”),谢谢。我刚刚在我的主要帖子标题下添加了输出和更多细节。谢谢。关于需要将命令对象添加到我从请求处理程序返回的ModelAndView,您是对的。我确实向ModelAndView添加了command对象,但在这里的代码中错误地忽略了它。顺便说一句,我还必须将它添加到从异常处理程序返回的ModelAndView中,因为我在视图中仍然需要它。
BindingResult BindingResult=(BindingResult)bindException.getModel().get(BindingResult.MODEL_KEY_PREFIX+“命令”)确实给了我访问comand对象的权限-谢谢!!!我想说的是后缀应该是“command”,而不是表单的commandName(在我的例子中是“book”)(对于
bindException.getModel().get(BindingResult.MODEL\u KEY\u PREFIX+“book”)
,我刚刚得到了null,因此我在映射
bindException.getModel()
中迭代,看到命令保存在名称“command”下)。但是我仍然有一个问题:JSP中的错误标记没有输出所需的错误消息。请在我的主要帖子标题“更新”下查看更多详细信息我确实有
。为了测试的目的,我在视图(bookForm.jsp)中添加了
,它确实显示了参数
所需的详细信息。但当我订阅时,不会显示错误消息
ValidationUtils.rejectIfEmpty(errors, "fieldName","required.field","this field requred!");
<form:form action="update.htm" commandName="command">
   <!-- Form Field and so on -->
</form:form>
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]
protected String getCommandName(Object command) {
    return Conventions.getVariableName(command);
}