【问题标题】:Spring 2.5 Form Validation Errors found in Validator Implementation don't update View <form:error/> tagsSpring 2.5 Form Validation Errors found in Validator Implementation 不会更新 View <form:error/> 标签
【发布时间】:2023-03-17 04:18:01
【问题描述】:

作为参考,我主要使用这个: http://www.mkyong.com/spring-mvc/spring-mvc-form-handling-example/

基本上,我有一个名为 EJournalValidator.java 的类:

package com.blah.blah.validator;

import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;
import com.blah.blah.EJournalForm;

public class EJournalValidator implements Validator{

    public boolean supports(Class clazz) {
        return EJournalForm.class.isAssignableFrom(clazz);
    }

    public void validate(Object target, Errors errors) {
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "strStartDate",
                "ejournal.strStartDate", "Field name is required.");
    }

}

它映射到我的 servlet.xml 中的控制器,其中包含我的 spring 2.5 beans 列表中的一些重要方面:

<bean name="/app/eJournal.html" class="com.blah.blah.EJournalController">
    <property name="formView" value="/app/eJournal"/>
    <property name="validator">
        <bean class="com.blah.blah.EJournalValidator" />
    </property> 
</bean>
<bean name="/app/eJournalResult.html" class="com.blah.blah.EJournalResultController"></bean>

<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
    <property name="basenames">
      <list>
        <value>/WEB-INF/messages/message</value>
      </list>
    </property>
</bean>

<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver"/>

<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
    <property name="prefix" value="/WEB-INF/jsp/"/>
    <property name="suffix" value=".jsp"/>
</bean>

它验证我的表单中的搜索条件,由我们的模型 .java 文件和一个用于表单加载和提交的控制器(对于我们的 showForm() 和 handleRequest())表示。问题是,我的标签在 .jsp 中的位置似乎没有更新:

<td><form:input id="strStartDate" path="strStartDate"/></td>
<td><form:errors path="strStartDate" cssClass="error" /></td>

不幸的是,即使我知道当我通过我的 EJournalValidator.java 文件中的断点为该字段提交 null 时,正确地标记了一个错误,但该错误并未在视图中更新。知道为什么会这样吗?有人说如果你使用类似的东西重定向:

return "redirect:/spring/person/list";

那么这可能会导致这样的事情,但这里似乎不是这种情况。

在调试过程中,如果我在 EJournalValidator.java 的验证方法中设置断点并在我尝试在我正在检查的字段中提交空白时检查错误变量,则会发现这些错误:

org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 个错误 字段“strStartDate”上的对象“ej”中的字段错误:拒绝值 []; 代码 [ejournal.strStartDate.ej.strStartDate,ejournal.strStartDate.strStartDate,ejournal.strStartDate.java.lang.String,ejournal.strStartDate]; 论据 [];默认消息[字段名称为必填项。]

任何想法为什么调试时发现的错误不会出现在用户面前?

编辑:添加Controller的handleRequest方法,以备不时之需。

protected ModelAndView handleRequest(HttpServletRequest request,
        HttpServletResponse response, Object command, BindException errors)
        throws Exception {
    EJournalForm form = (EJournalForm) command;
    form.setUser(getUser());

    form.load(request, false);

    HttpSession session = request.getSession(false);
    session.setAttribute(LBIBOConstants.SESSION_VAR_TAB_ALERT_MSG, null);

    return new ModelAndView(getFormView(), getCommandName(), form);
}

编辑 2:从 SimpleFormController 添加 sn-p,这似乎是它所坚持的。除非在检查时不存在错误,否则它永远不会命中我的 Controller 的 handleRequest() 方法:

protected ModelAndView processFormSubmission(
        HttpServletRequest request, HttpServletResponse response, Object command, BindException errors)
        throws Exception {

    if (errors.hasErrors()) {
        if (logger.isDebugEnabled()) {
            logger.debug("Data binding errors: " + errors.getErrorCount());
        }
        return showForm(request, response, errors);
    }
    else if (isFormChangeRequest(request, command)) {
        logger.debug("Detected form change request -> routing request to onFormChange");
        onFormChange(request, response, command, errors);
        return showForm(request, response, errors);
    }
    else {
        logger.debug("No errors -> processing submit");
        return onSubmit(request, response, command, errors);
    }
}

我注意到了一些进一步的事情......因此,我将覆盖我的 Controller 方法,但意识到我正在扩展 SessionSimpleFormController 而不是 SimpleFormController。现在研究一下为什么有人会扩展一个或另一个,因为我首先基于其他人的工作,然后在我上面显示的链接中注意到他们使用的是 SimpleFormController。

【问题讨论】:

  • 你是否在配置中定义了属性文件(包含ejournal.strStartDate)?
  • 我认为是这样,在我用于国际化的 message.properties 文件中,我知道该文件适用于其余视图,我有以下条目:ejournal.strStartDate=日期条目无效
  • 我应该将其命名为不同的消息,例如 ejournal.strStartDateError 或指示这是错误消息的消息,但是,是的,在这方面似乎很好。
  • 在控制器的handleRequest方法中,为什么要使用getFormView()和getCommandName()?您可以直接将您想要的视图名称传递给您在该视图中指定的错误和命令名称。
  • 由于没有传递实际的绑定错误,您正在破坏正确的错误消息。您应该执行return new ModelAndView(getFormView(), errors.getModel()) 之类的操作,因为这样可以保留错误。您正在构建一个全新的(空的)模型,忽略错误。

标签: java forms spring validation spring-mvc


【解决方案1】:

如果在验证期间发生错误,请更改您的 handleRequest 方法以返回现有的表单/模型对象。当您返回新的 ModelAndView 时,它会清除错误,因此您不会在视图中看到它们。尝试使用 RedirectView 重定向到相同的视图,而不会丢失绑定到您的表单/模型的错误:

    protected ModelAndView handleRequest(HttpServletRequest request,
            HttpServletResponse response, Object command, BindException errors)
            throws Exception {
        EJournalForm form = (EJournalForm) command;
        form.setUser(getUser());
        form.load(request, false);

        HttpSession session = request.getSession(false);
        session.setAttribute(LBIBOConstants.SESSION_VAR_TAB_ALERT_MSG, null);

        if(errors.hasErrors()){
            return new ModelAndView(new RedirectView(getFormView()));
        }else{
            return new ModelAndView("anotherView", "commandName", form);
        }   
    }

从 Spring 3+ 开始,getFormView() 和 getCommandName() 已被弃用。

【讨论】:

  • 遗憾的是,这似乎不起作用,因为当我调试它时,它从来没有到达这一点来检查错误。这是因为当我逐步完成时,它会进入 SimpleFormController,它会根据是否有错误执行不同的操作(有关更多信息,请参阅我上面的编辑)。
  • @Prasad 整个 SimpleFormController 在 Spring 3.x 中已被弃用,并在 Spring 4 中被删除。
  • @M. Deinum 是正确的,但如果您看到 aohm1989 使用的是 spring 2.5 版本。
【解决方案2】:

我确实解决了这个问题,最后我开始使用 SimpleFormController 而不是 SessionSimpleFormController,并改变了一些东西。

最后,它看起来像这样......但也许有一种方法仍然可以让它与 Session 控制器一起工作。

public class EJournalController extends SimpleFormController {

public EJournalController() {
    setCommandClass(EJournalForm.class);
    setCommandName("ej"); 
}

@Override
protected ModelAndView showForm (HttpServletRequest request,
        HttpServletResponse response, BindException errors) throws Exception {

    Calendar cal = Calendar.getInstance();
    Calendar calMidnight= Calendar.getInstance();
    calMidnight.set(Calendar.HOUR_OF_DAY, 0);
    calMidnight.set(Calendar.MINUTE, 0);
    calMidnight.set(Calendar.SECOND, 0);

    HttpSession session = request.getSession(true);

    ModelAndView view = null;

    LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request);
    localeResolver.setLocale(request, response, LocaleUtilities.getUsersLocale(session));

    EJournalForm form = new EJournalForm();
    view = new ModelAndView(getFormView(), getCommandName(), form);
    form.setStrStartDate(form.getSdfDate().format(cal.getTime()).toString());
    form.setStrEndDate(form.getSdfDate().format(cal.getTime()).toString());
    form.setStrStartTime(form.getSdfTime().format(calMidnight.getTime()).toString());
    form.setStrEndTime(form.getSdfTime().format(cal.getTime()).toString());

    return view;
}

protected ModelAndView handleRequest(HttpServletRequest request,
        HttpServletResponse response, Object command, BindException errors)
        throws Exception {

    EJournalForm form = (EJournalForm) command;

    if(errors.hasErrors()){
        return onSubmit(request, response, command, errors);
    }
    else{
        form.load(request, false);          
        HttpSession session = request.getSession(false);
        session.setAttribute(LBIBOConstants.SESSION_VAR_TAB_ALERT_MSG, null);
        return new ModelAndView("app/eJournal", "ej", form);
    }  
}

@Override
protected ModelAndView processFormSubmission(HttpServletRequest request, HttpServletResponse response, Object command, BindException errors) throws Exception {
        return handleRequest(request, response, command, errors);
}

}

【讨论】:

  • 这基本上破坏了SimpleFormController 中的整个流程。一般来说,您应该只需要实现onSubmit 方法,而您有一个handleRequest,它不是正常流程的一部分。
  • 会的,感谢您的澄清,因为这正是我可以开始工作的,我相当有信心可以改进。
猜你喜欢
  • 1970-01-01
  • 2014-09-24
  • 2021-04-28
  • 1970-01-01
  • 1970-01-01
  • 2016-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多