java Spring MVC 表单输入值始终为空

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1052594/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 14:56:55  来源:igfitidea点击:

Spring MVC form input value is always null

javaspringjakarta-eespring-mvc

提问by Alex

I'm new to Spring MVC, but not new to web development in Java. I'm attempting to create a simple form->controller example.

我是 Spring MVC 的新手,但对 Java 的 Web 开发并不陌生。我正在尝试创建一个简单的表单-> 控制器示例。

I have a form, a form controller (configured in a context XML pasted below) and my model (a simple bean). When I submit the form the value of my text input is always null, regardless. Any ideas?

我有一个表单、一个表单控制器(在下面粘贴的上下文 XML 中配置)和我的模型(一个简单的 bean)。当我提交表单时,无论如何,我的文本输入的值始终为空。有任何想法吗?

Form controller spring configuration:

表单控制器弹簧配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- controllers -->

    <bean name="/home.html" class="atc.web.view.controller.HomeController" />

    <!--bean name="/mirror.html" class="atc.web.view.controller.MirrorController" -->

    <bean name="/url-cache.html" class="atc.web.view.controller.URLCacheFormController">
        <property name="synchronizeOnSession" value="true" />
        <!--property name="sessionForm" value="false"-->
        <property name="commandName" value="urlForm"/>
        <property name="commandClass" value="atc.web.view.model.URLBean"/>
        <property name="validator">
            <bean class="atc.web.view.validators.URLValidator"/>
        </property>
        <property name="formView" value="mirror"/>
        <property name="successView" value="url-cache.html"/>
        <property name="URLCachingService" ref="urlCachingService" />
    </bean>

    <!-- end controllers -->

    <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>

    <!-- custom beans -->

    <bean id="breakcrumbInjectionFilter" class="atc.web.view.filter.BreadcrumbInjectionFilter">
        <property name="contextPrefix" value="/home-web" />
    </bean>

    <!-- end custom beans -->
</beans>

The JSP that contains my form is as follows:

包含我的表单的 JSP 如下:

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ include file="/WEB-INF/jspf/core/taglibs.jspf" %>
<html>
<head><title>Simple tools</title></head>
<style>
.error s {
    color:#FF0000;
}
</style>
<body>
<%@ include file="/WEB-INF/jspf/nav/nav.jspf" %>
    Errors: <form:errors path="url" cssClass="error"/>
    <form:form method="post" commandName="urlForm">
        <form:input path="url" />
        <input type="submit" align="center" value="Execute" />
    </form:form>
</body>
</html>

Here's the full source of my controller:

这是我的控制器的完整来源:

public class URLCacheFormController extends SimpleFormController {
    private URLCachingService cachingService;

    private static Logger log = Logger.getLogger(URLCacheFormController.class);

    public ModelAndView onSubmit(Object command) throws ServletException {
        log.debug(String.format("URLCachingFormController received request with object '%s'", command));
        URLBean urlBean = (URLBean) command;
        try {
            URL url = new URL(urlBean.getUrl());
            URLCache cache = cachingService.cacheURL(url);
            cache.cacheToTempFile();

        } catch (IOException e) {
            log.error("Invalid URL...", e);
        }
        return new ModelAndView(new RedirectView(getSuccessView()));
    }

    protected Object formBackingObject(HttpServletRequest request) throws ServletException {
        log.debug("formBackingObject() ");
        return new URLBean();
    }

    public void setURLCachingService(URLCachingService cachingService) {
        this.cachingService = cachingService;
    }
}

All of the above produces the following HTML:

以上所有生成以下 HTML:

<html>
<head></head>
<body>
<div><span><a href="home.html">Home </a></span><span> | <a href="url-cache.html">Page Mirror</a></span></div>
<div id="breadcrumb"><span>Your trail:<a href=""/></span></div>Attrs:<div/>
<form id="urlForm" method="post" action="/home-web/url-cache.html">
<input id="url" type="text" value="" name="url"/>
<input type="submit" align="center" value="Execute"/>
</form>
</body>
</html>

I'm now overriding doSubmitAction(Object command)but I still do not hit the method. The form submits but the next thing I know I'm presented with the blank form (after formBackingObject(HttpServletRequest request)is called).

我现在覆盖doSubmitAction(Object command)但我仍然没有命中该方法。表单提交,但接下来我知道我看到的是空白表单(在formBackingObject(HttpServletRequest request)调用之后)。

That's to say, when I submit, the logging call on line 1 of doSubmitActionin the form controller is never executed.The validator executes, and fails (adds error messages correctly) because the value it's checking is always null (or put correctly, it's never set). The call to formBackingObjectalways occurs however. The request attribute of my form (the form input 'url') is always null.

也就是说,当我提交时,doSubmitAction永远不会执行表单控制器中第1 行的日志记录调用。验证器执行并失败(正确添加错误消息),因为它检查的值始终为 null (或正确放置,它从未设置)formBackingObject但是,始终会调用。我的表单(表单输入“url”)的请求属性始终为空。

Update:OK, so after some serious debugging as suggested by serg555, and removing validation, I can confirm the issue seems to be with mapping the request parameters - such as the value of 'url' from the form - to my command/bean; i.e. the URL is never being set on my bean, or the bean is being recreated.

更新:好的,所以在按照 serg555 的建议进行一些认真的调试并删除验证之后,我可以确认问题似乎是将请求参数(例如表单中的“url”的值)映射到我的命令/bean;即从未在我的 bean 上设置 URL,或者正在重新创建 bean。

Please help?

请帮忙?

采纳答案by Alex

The cause was the fact that my form bean was not adhering to the Java Bean contract - the setter returned instead of being void and thus couldn't be matched by Spring to invoke.

原因是我的表单 bean 没有遵守 Java Bean 契约——setter 返回而不是 void,因此无法被 Spring 匹配以进行调用。

回答by serg

I don't know where is the problem, let me show you my controller that works and maybe you will be able to figure out what's wrong:

我不知道问题出在哪里,让我向您展示我的控制器有效,也许您将能够找出问题所在:

public class TestController extends SimpleFormController  {

    public TestController () {
        setFormView("testView");
        setSuccessView("testView");
        setCommandClass(TestCmd.class);
        setCommandName("cmd");
    }

    protected Object formBackingObject(HttpServletRequest request)throws Exception {
        Object o = super.formBackingObject(request);
        TestCmd cmd = (TestCmd) o;

        return cmd;
    }


    public ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response, Object obj, BindException errors) throws Exception {

        TestCmd cmd = (TestCmd) obj;

        log.debug("test value = " + cmd.getTestValue());

        return super.onSubmit(request, response, obj, errors);
    }

}

Form:

形式:

<form method="post" action="/test.html">
    <form:input path="cmd.testValue"/>
    <input type="submit">
</form>

Inside App-servlet.xml:

在 App-servlet.xml 中:

    <bean id="urlMapping"
        class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="alwaysUseFullPath" value="true" />
        <property name="mappings">
            <props>
                <prop key="/test.html">testController</prop>
            </props>
        </property>
    </bean>
    <bean id="testController"
        class="com.sample.TestController">
        <property name="synchronizeOnSession" value="true" />
        <property name="validator">
            <bean class="com.sample.TestValidator"/>
        </property>
    </bean>

Validator:

验证器:

public class TestValidator implements Validator {

    public boolean supports(Class clazz) {
        return (TestCmd.class.equals(clazz));
    }

    public void validate(Object obj, Errors errors) {
        TestCmd cmd = (TestCmd) obj;
        if (obj == null) {
            // nothing
        } else {

            ValidationUtils.rejectIfEmptyOrWhitespace(errors, "testValue", null, "<b>Value</b> is required");

        }
    }

}

Command:

命令:

public class TestCmd {

    private String testValue;

    public TestCmd() {
    }

    public String getTestValue() {
        return testValue;
    }

    public void setTestValue(String testValue) {
        this.testValue = testValue;
    }

}

回答by Jacob Mattison

OK, you've verified that a url set within the controller does come through to the JSP, which suggests that the mapping is correct to the command bean.

好的,您已经验证控制器中设置的 url 确实传递到 JSP,这表明映射到命令 bean 是正确的。

One more thing. If the "onSubmit" code is never being reached, that may be a problem with the controller figuring out whether it's a form submission. It might help to add a name attribute to the submit button, and override "isFormSubmission" to check whether that name is present (i.e. whether the submit button has been clicked). If so, isFormSubmission should return true. (This shouldn't be necessary -- by default the controller assumes that any POST request is a form submission -- but if it helps you'll know more about the problem, and you'll have a work-around fix, at least.)

还有一件事。如果从未到达“onSubmit”代码,那可能是控制器确定它是否是表单提交的问题。将名称属性添加到提交按钮可能会有所帮助,并覆盖“isFormSubmission”以检查该名称是否存在(即是否已单击提交按钮)。如果是这样,isFormSubmission 应该返回 true。(这不是必需的——默认情况下,控制器假定任何 POST 请求都是表单提交——但如果它有助于您了解更多有关问题的信息,并且您将至少有一个解决方法.)

回答by naXa

I once spent a lot of time investigating a similar issue. Finally I found the culprit inside a Binder's initialization method:

我曾经花了很多时间调查类似的问题。最后我在 Binder 的初始化方法中找到了罪魁祸首:

@InitBinder
void allowFields(final WebDataBinder binder) {
    binder.setAllowedFields("name");
}

This method sets a restriction on fields that are allowed for binding. And all the other fields stay unbound, naturally resulting in nullvalues.

此方法对允许绑定的字段设置限制。所有其他字段保持未绑定状态,自然会产生null值。

回答by HVT7

Try to put the following code in the aplication-context.xml. This could be your solution if you are having your form encType=multipart/form-data.

尝试将以下代码放在 aplication-context.xml 中。如果您的表单 encType=multipart/form-data,这可能是您的解决方案。

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="10000000"/>
</bean>

Also try to remove the content Type from the jsp page. Well in my case this helped me...!!

也尝试从jsp页面中删除内容类型。好吧,就我而言,这对我有帮助......!!