当@Valid失败时,Spring MVC控制器返回null modelAttribute

时间:2017-10-15 18:42:46

标签: java spring spring-mvc model-view-controller

我在这个问题上长时间一直在摸不着头脑。我正在开发一个拥有超过20个控制器的网络应用程序,我只有其中一个有这个奇怪的问题。无论我与一个工作的人比较多久,我似乎都找不到任何差异。基本上,只要不验证失败,我就可以添加一个接口实体没问题。如果我试图保存说一个完全空的对象(或者将一个必填字段留空),我会收到此错误:

java.lang.IllegalStateException:BindingResult和bean名称'intface'的普通目标对象都不可用作请求属性

以下是相关代码:

查看:

<form:form method="POST" modelAttribute="intface" class="form-style-7">
            <form:input type="hidden" path="id" id="id"/>
            <table>
                <tr>
                    <td><label for="name">Name: </label> </td>
                    <td><form:input path="name" id="name"/></td>
                    <td><form:errors path="name" cssClass="error"/></td>
                </tr>
                <tr>
                    <td><label for="type">Type: </label> </td>
                    <td><form:input path="type" id="type"/></td>
                    <td><form:errors path="type" cssClass="error"/></td>
                </tr>
                <tr>
                    <td><label for="ip">IP: </label> </td>
                    <td><form:input path="ip" id="ip"/></td>
                    <td><form:errors path="ip" cssClass="error"/></td>
                </tr>
                <tr>
                    <td><label for="port">Port: </label> </td>
                    <td><form:input path="port" id="port"/></td>
                    <td><form:errors path="port" cssClass="error"/></td>
                </tr>
                <tr>
                    <td><label for="test">Test: </label> </td>
                    <td><form:checkbox path="test" id="test"/></td>
                    <td><form:errors path="test" cssClass="error"/></td>
                </tr>
                <tr>
                    <td colspan="3">
                        <c:choose>
                            <c:when test="${edit}">
                                <input type="submit" value="Update Interface"/>
                            </c:when>
                            <c:otherwise>
                                <input type="submit" value="Add Interface"/>
                            </c:otherwise>
                        </c:choose>
                    </td>
                </tr>
            </table>
        </form:form>

控制器:

@RequestMapping(value = {"/newInterface"}, method = RequestMethod.POST)
public String saveInterface(@Valid Interface intface, BindingResult result, ModelMap model) 
{
    if (result.hasErrors()) 
    {
        return "interfaceDataAccess";
    }
    interfaceService.saveInterface(intface);
    return "redirect:/interfaces/list";
}

实体:

 @RequestMapping(value = {"/newInterface"}, method = RequestMethod.POST)
public String saveInterface(@Valid Interface intface, BindingResult result, ModelMap model) 
{
    if (result.hasErrors()) 
    {
        return "interfaceDataAccess";
    }
    interfaceService.saveInterface(intface);
    return "redirect:/interfaces/list";
}

你会注意到这个@Unique注释是我建立的东西。从本质上讲,它允许我检查用户输入的值之一是否已经存在,并且在我的其他实体上工作正常。我尝试完全删除它,一旦验证失败,我仍然会得到此异常。我确实有超过20个控制器以完全相同的方式工作,一行一行,它们工作正常。这完全让我困惑,我确信这是非常愚蠢的事情。我可以为工作实体提供MVC代码,以便在需要时进行比较。

由于

*编辑*

以下是我的heightUnit类的一些工作代码:

控制器:

@RequestMapping(value = {"/newHeightUnit"}, method = RequestMethod.GET)
public String newHeightUnit(ModelMap model) 
{
    HeightUnit heightUnit = new HeightUnit();
    model.addAttribute("heightUnit", heightUnit);
    model.addAttribute("edit", false);
    return "heightUnitDataAccess";
}

@RequestMapping(value = {"/newHeightUnit"}, method = RequestMethod.POST)
public String saveHeightUnit(@Valid HeightUnit heightUnit, BindingResult result, ModelMap model) 
{
    if (result.hasErrors()) 
    {
        return "heightUnitDataAccess";
    }
    heightUnitService.saveHeightUnit(heightUnit);
    return "redirect:/heightUnits/list";
}

查看:

<form:form method="POST" modelAttribute="heightUnit" class="form-style-7">
            <form:input type="hidden" path="id" id="id"/>
            <ul>
                <li>
                    <label for="name">Name: </label>
                    <form:input path="name" id="name"/>
                    <span><form:errors path="name" cssClass="error"/></span>
                </li>
                <c:choose>
                    <c:when test="${edit}">
                        <input type="submit" value="Update Height Unit"/>
                    </c:when>
                    <c:otherwise>
                        <input type="submit" value="Add Height Unit"/>
                    </c:otherwise>
                </c:choose>
            </ul>
        </form:form>

实体:

private int id;
private String name;

@Id
@GeneratedValue
public int getId() 
{
    return id;
}

public void setId(int id) 
{
    this.id = id;
}

@Size(min = 1, max = 15, message = "Name must be between 1 and 15 characters long")
@Unique(entityType = "heightUnit", field = "name", message = "The name needs to be unique!")
@Column(nullable = false, unique = true, length = 15)
public String getName() 
{
    return name;
}

public void setName(String name) 
{
    this.name = name;
}

@Override
public boolean equals(Object obj) 
{
    if (obj instanceof HeightUnit)
    {
        HeightUnit heightUnit = (HeightUnit)obj;
        if (id == heightUnit.getId())
        {
            return true;
        }
    }
    return false;
}

@Override
public int hashCode() 
{
    int hash = 7;
    hash = 37 * hash + this.id;
    hash = 37 * hash + Objects.hashCode(this.name);
    return hash;
}

这非常有效,我在尝试破解验证规则时会在表单上收到错误。

2 个答案:

答案 0 :(得分:0)

您的问题是您正在前往表单页面,它正在寻找一个预先实例化的模型,它不可用。您需要做的是将Interface对象添加为模型的属性:

model.addAttribute("intface", new Interface());

请记住将其添加到@RequestMapping带注释的方法,该方法会将您带到表单页面,如下所示:

@RequestMapping(value = "/", method = RequestMethod.GET) 
public String displayNewInterfaceLogin(Model model) { 
    model.addAttribute("intface", new Interface()); 
    return "newInterface"; 
}

答案 1 :(得分:0)

我终于弄明白了。无论出于什么废话,我都必须将控制器的saveInterface方法的签名更改为:

$(this).parents('.thumbnail').find('a:first-of-type').attr('href', link);

我没有想法为什么当我所有实体类型的CRUD操作以完全相同的方式构建时,只有这个实体抱怨这个,但是你去了!

希望这最终有助于某人!