如何以spring形式绑定子类对象提交为modelAttribute

时间:2016-06-02 11:21:40

标签: java spring jsp spring-mvc spring-form

我有

Class Shape {
      //Implementation
}
Class Round extends Shape{
      //Implementation
}

控制器 我有

@Requestmapping(value="/view/form")
public ModelAndView getForm(){
ModelAndView mav=new ModelAndView();
mav.addObject("shape",new Round());
}


@RequestMapping(value="/submit", method = RequestMethod.POST)    
public ModelAndView submitForm(@ModelAttribute("shape") Shape shape){
         if(shape instanceof Round){ //**Not giving positive result**

         }
    }

在Jsp中

<form:form action="/submit" commandName="shape" method="post">

//form tags

</form:form>

当我使用Round对象提交表单时。在控制器端,ModelAttribute没有给出Round的实例。它只给出形状的例子。怎么做

3 个答案:

答案 0 :(得分:3)

这将永远不会起作用

<form:form action="/submit" commandName="shape" method="post">

您是从表单提交shape并期待shape 在控制器方法

public ModelAndView submitForm(@ModelAttribute("shape") Shape shape)

永远不会给你一个Round对象。

只需从表单中提交一个Round对象并使用它。

 <form:form action="/submit" commandName="round" method="post">
 public ModelAndView submitForm(@ModelAttribute("round") Round round)

编辑: -

表单中有一个hiddenInput类型会告诉controller它传递的Shape类型,您可以动态更改隐藏代码的值 根据用户要求。

<input type="hidden" name="type" value="round">

获取contoller内的类型值并将其用于cast Shape对象

     public ModelAndView submitForm(
     @ModelAttribute("shape") Shape shape,
     @RequestParam("type") String type)
     {
     if(type.equals("round")){
      //if type is a round you can cast the shape to a round
      Round round = (Round)shape; 
       }
    }

答案 1 :(得分:0)

你不能这样做。因为这是两个不同的请求生命周期。

@Requestmapping(value="/view/form")
public ModelAndView getForm(){
ModelAndView mav=new ModelAndView();
mav.addObject("shape",new Round());
}

当执行上述请求时,即使您在Round中添加了mav对象,它也已转换为html响应并发送回客户端。

因此,当您提交表单时接下来请求时,它是一个完全独立的请求,并且spring无法确定为先前的请求添加了哪个对象类型。

@RequestMapping(value="/submit", method = RequestMethod.POST)    
public ModelAndView submitForm(@ModelAttribute("shape") Shape shape){
         if(shape instanceof Round){ //**Not giving positive result**

         }
    }

但您可以尝试浏览@SessionAttributes,使用此功能可以在不同的请求中维护相同的对象

答案 2 :(得分:0)

可以指定需要绑定的子类。您必须在表单中添加一个附加参数(隐藏输入),指定需要绑定的类型。此字段必须与此案例形状中的模型属性具有相同的名称。然后,您需要实现一个转换器,将此字符串参数值转换为您需要绑定到

的实际实例

以下是您需要实施的更改

1)在你的jsp中添加

中的隐藏输入
<form:form action="/submit" commandName="shape" method="post">
   <input type="hidden" name="shape" value="round"/>
//other form tags
</form:form>

2)实现转换器以从String转换为Shape

public class StringToShapeConverter implements Converter<String,Shape>{

   public Shape convert(String source){
      if("round".equalsIgnoreCase(source)){
          return new Round();
      }
      //other shapes
   }
}

3)然后注册转换器,以便Spring MVC知道它。如果您使用的是Java配置,则需要扩展WebMvcConfigurerAdapter并覆盖addFormatters方法

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter{

   @Override
   public void addFormatters(FormatterRegistry registry){
      registry.addConverter(new StringToShapeConverter());
   }
}

如果您使用的是xml配置,则可以使用mvc:annotation-driven元素指定要使用的转换服务。然后使用FormattingConversionSErviceFactoryBean注册转换器

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc" 
    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/context 
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <mvc:annotation-driven conversion-service="conversionService"/>

    <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
       <property name="converters">
           <set>
              <bean class="some.package.StringToShapeConverter"/>
           </set>
       </property>
    </bean>
</beans>