Spring MVC - 表单生成新的模型对象实例

时间:2014-10-13 17:11:30

标签: spring-mvc

我有一个简单的mvc应用程序,它列出了数据库中的所有规则,并允许用户选择特定的行来删除该规则。控制器有一个简单的listRules()方法,它将两个模型对象添加到ModelMap中。

@Controller
public class RulesController {

    @Resource
    private RuleManager ruleManager;

    @RequestMapping(value = "/", method = RequestMethod.GET)
    public ModelAndView listRules() {
        ModelAndView mv = new ModelAndView("/rules"); 
        List<Rule> rules = this.ruleManager.getAllRules();
        ListRulesModel listRulesModel = new ListRulesModel();
        listRulesModel.setRules(rules);
        mv.addObject("listRulesModel",listRulesModel);
        SelectedRuleModel selectedRuleModel = new SelectedRuleModel();
        mv.addObject("selectedRuleModel",selectedRuleModel);
        return mv;
    }

    @RequestMapping(value = "/submit", method = RequestMethod.POST, params = {"delete"})
    public ModelAndView deleteRule(@ModelAttribute("selectedRuleModel") SelectedRuleModel selectedRuleModel,ModelMap model) {
        System.out.println("deleteRule "+selectedRuleModel.hashCode());
        System.out.println("model "+model);
        if(selectedRuleModel.getRuleId()!=null)
            getRuleManager().deleteRule(getRuleManager().getRule(selectedRuleModel.getRuleId()));
        return new ModelAndView("redirect:/");
    }

我的模型对象是

public class ListRulesModel {

    private List<Rule> rules = null;

    public List<Rule> getRules() {
        return rules;
    }

    public void setRules(List<Rule> rules) {
        this.rules = rules;
    }
}

public class SelectedRuleModel {

    @NotNull
    private Integer ruleId = null;

    public Integer getRuleId() {
        return ruleId;
    }

    public void setRuleId(Integer ruleId) {
        this.ruleId = ruleId;
    }

    @Override
    public String toString() {
        return String.format("SelectedRuleModel [ruleId=%s]", ruleId);
    }
}

我视图的主要元素是一个表格形式,将每个规则显示为一行。一个单选按钮应该填充“selectedRuleModel.ruleId”&#39;具有列表中规则值的字段。

<head>
<script type="text/javascript" src="<c:url value="/resources/js/jquery-2.1.1.min.js"/>"></script>
<script type="text/javascript" src="<c:url value="/resources/js/jquery.tablesorter.min.js"/>">  </script>
<script type="text/javascript" src="<c:url value="/resources/js/jquery.tablesorter.widgets.min.js"/>"></script>
<script type="text/javascript" src="<c:url value="/resources/js/rules.js"/>"></script>
<link href="<c:url value="/resources/css/base.css"/>" rel="stylesheet"/>
<link href="<c:url value="/resources/css/theme.blue.css"/>" rel="stylesheet"/>
<link href="<c:url value="/resources/css/rules.css"/>" rel="stylesheet"/>
</head>
<form:form method="POST" action="submit" modelAttribute="selectedRuleModel">
<button type="submit" name="delete" value="delete" class="btn btn-primary">Delete Selected Rule</button>
...
<c:forEach items="${listRulesModel.rules}" var="rule" varStatus="status">
<tr>
<td><form:radiobutton path="ruleId" value="${rule.id}"/></td>
<td>${rule.name}</td>
<td>${rule.batch}</td>
...
</form>

每次我提交&#34;删除行&#34;表格似乎是一个新的&#39; SelectedRuleModel&#39; object作为参数传递给deleteRule()方法,以便&#39; ruleId&#39; value始终为null。我的模型/方法映射有什么问题?

生成的HTML是

<form id="selectedRuleModel" action="submit" method="POST">
<button type="submit" name="amend" value="amend" class="btn btn-primary">Amend Selected Rule</button>
<button type="submit" name="branch" value="branch" class="btn btn-primary">Branch Selected Rule</button>
<button type="submit" name="delete" value="delete" class="btn btn-primary">Delete Selected Rule</button>
</div>

<!-- Add rule table -->
<table id="rulesTable" class="tablesorter">
<thead>
<tr>
<th>ID</th>
<th>Rule Name</th>
....
</tr>
</thead>
<tbody>
<tr>
<td><input id="ruleId2" name="ruleId" type="radio" value="20"/></td>
<td>Gender_Balance</td>
<td>*</td>
....

编辑 - 我更新了控制器方法deleteRule()以包含BindResult对象。

    @RequestMapping(value = "/submit", method = RequestMethod.POST, params = {"delete"})
public ModelAndView deleteRule(
        @Valid @ModelAttribute("selectedRuleModel") SelectedRuleModel selectedRuleModel,
        BindingResult result, ModelMap model) {
    System.out.println("deleteRule "+selectedRuleModel.getRuleId());
    System.out.println("model "+model.toString());
    System.out.println("BindingResult "+result.toString());
    if(selectedRuleModel.getRuleId()!=null)
        getRuleManager().deleteRule(getRuleManager().getRule(selectedRuleModel.getRuleId()));
    return new ModelAndView("redirect:/");
}

正如您在此方法的日志记录中所看到的,&#39; selectedRuleModel&#39;为null,但该模型具有“已选择的规则”模型。使用null&quot; ruleId&#39;值。

2014-10-14 11:18:21,428 INFO  [STDOUT] (http-127.0.0.1-8080-2) deleteRule null
2014-10-14 11:18:21,428 INFO  [STDOUT] (http-127.0.0.1-8080-2) model {selectedRuleModel=SelectedRuleModel [ruleId=null], org.springframework.validation.BindingResult.selectedRuleModel=org.springframework.validation.BeanPropertyBindingResult: 0 errors}
2014-10-14 11:18:21,428 INFO  [STDOUT] (http-127.0.0.1-8080-2) BindingResult org.springframework.validation.BeanPropertyBindingResult: 0 errors

编辑添加web.xml和applicationContext.xml,以防有人发现我没有正确初始化某些必需组件。

<web-app version="2.4"
         xmlns="http://java.sun.com/xml/ns/j2ee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>

    <servlet>
        <servlet-name>hedgingcorrection</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>namespace</param-name>
            <param-value>applicationContext</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>hedgingcorrection</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <jsp-config>
        <taglib>
            <taglib-uri>/spring</taglib-uri>
            <taglib-location>/WEB-INF/tld/spring-form.tld</taglib-location>
        </taglib>
    </jsp-config>
</web-app>

我的applicationContext.xml有

<?xml version="1.0" encoding="UTF-8"?>
<beans
    xmlns="http://www.springframework.org/schema/beans"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:context="http://www.springframework.org/schema/context"
    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
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <mvc:annotation-driven/>
    <mvc:resources mapping="/resources/**" location="/resources/"/>
    <mvc:view-controller path="/"/>

    <context:component-scan base-package="abc.xwz.web.correction.controller"/>

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

我从applicationContext.xml文件中删除了三个mvc元素,表单开始工作。

<mvc:annotation-driven/>
<mvc:resources mapping="/resources/**" location="/resources/"/>
<mvc:view-controller path="/"/>

周五编辑 - 我已将问题与jsp表单中的javascript元素包含在一起。如果没有包含javascript文件,表单会将数据提交给控制器。添加脚本时,表单数据似乎未正确绑定到ModelAttribute对象。 javascript文件主要用于启用html表上的tablesorting功能,因此我无法理解它们为什么影响提交按钮的操作。对于可以解释它的人来说,50分。

1 个答案:

答案 0 :(得分:0)

我唯一能想到的是rules.js或其他一个javascript导入可能会在提交之前禁用单选按钮 - 在这种情况下,POST操作中不会提交任何值,这会使感觉为什么ModelAttribute没有被人口化。