2010-12-08 49 views
1

我正在爲我的應用程序開發RESTful API。所有getter(使用HTTP GET)都可以正常工作。我無法使保存方法(使用POST)工作。REST + Spring + POST與自定義編組器

我正在使用HTML表單和RESTClient進行測試。

這裏是我的控制器

@Controller 
public class EntitiesController { 
@RequestMapping(value="/ci/save/", method = RequestMethod.POST) 
public ModelAndView saveConfigurationItem(@RequestBody ConfigurationItem body) { 
    System.out.println("saveConfigurationItem: body=" + body); 
    return createModelAndView("ci", Collections.emptyList()); 
} 
} 

這種方法有望被調用時,客戶端職位形態項目。 我正在使用自定義序列化格式。它不是XML或JSON。它是VCard或VCalendar格式。對於我的第一次測試我用下面的電子名片:

BEGIN:VCARD 
N:Pooh;Winnie 
FN:Winnie the Pooh 
TEL:tel:+441234567 
END:VCARD 

我張貼到URL http://localhost:8080/core.solution-1.0/data/ci/save/。 這是我得到的迴應:

415 
The server refused this request because the request entity is in a format not 
supported by the requested resource for the requested method() 

(*)形態項目是一個抽象類。 CardEntry擴展它。我嘗試了兩個。

我試圖將方法參數更改爲String。在這種情況下,該方法被調用,但字符串是空的。當遵循我在web中看到的推薦之一時,會發生同樣的情況,我將參數類型更改爲MultiValueMap並從簡單的HTML表單發送請求。

我看到marshal()根本沒有被調用。

怎麼了?

這是我的。 (我只把這裏的相關代碼。)

Spring配置

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

<import resource="classes/spring-config-prod.xml"/> 
<context:component-scan base-package="com.mycompany.solution.service" /> 


<bean class="org.springframework.web.servlet.view.BeanNameViewResolver" /> 

<bean id="ciCardView" class="com.mycompany.solution.service.VFormatView"> 
    <constructor-arg> 
    <bean class="com.mycompany.solution.service.VFormatMarshaller"> 
    <property name="packagesToScan" value="com.mycompany.solution.entity"/> 
    </bean> 
    </constructor-arg> 
</bean> 
</beans> 

的Marshaller

public class VFormatMarshaller implements Marshaller, Unmarshaller { 
@Override 
public void marshal(Object obj, Result result) 
    throws IOException/*, XmlMappingException*/ { 
    System.out.println("VFormatMarshaller.marshal(" + obj + ")"); 
    marshalStreamResult(obj, (StreamResult)result); 
} 

@Override 
public boolean supports(Class<?> paramClass) { 
    System.out.println("VFormatMarshaller.supports(" + paramClass + ")"); 
    boolean supports = new HashSet<String>(Arrays.asList(packagesToScan)).contains(paramClass.getPackage().getName()); 
    if (supports) { 
    return supports; 
    } 

    return Collection.class.isAssignableFrom(paramClass); 
} 

@Override 
public Object unmarshal(Source source) throws IOException/*, XmlMappingException*/ { 
    System.out.println("VFormatMarshaller.unmarshal(" + source + ")"); 
    return unmarshalStreamSource((StreamSource)source); 
} 
//// ............................. 
} 

查看(這僅寫入覆蓋內容類型)

public class VFormatView extends MarshallingView { 

public VFormatView() { 
    super(); 
    setContentType("application/vcard"); 
    System.out.println("VFormatView()"); 
} 

public VFormatView(Marshaller marshaller) { 
    super(marshaller); 
    setContentType("application/vcard"); 
    System.out.println("VFormatView(" + marshaller + ")"); 
} 
} 
+0

當你在控制器中使用類型的參數,你得到的日誌中的任何異常? – codelark 2010-12-08 15:55:36

回答

2

@RequestBody/@ResponseBody由層次結構HttpMessageConverter s支持,這與ViewResolver完全不同。

在你情況下,你需要配置適當的編組/解組和內容類型MarshallingHttpMessageConverter(或創建自己的HttpMessageConverter如果你不需要依賴於編組/解組的現有的實現),並提供一個配置實例到AnnotationMethodHandlerAdapter

配置自定義HttpMessageConveter侵入性最小的方法是創建一個BeanPostProcessor如下:

public class Configurer implements BeanPostProcessor { 
    public void postProcessAfterInitialization(String name, Object bean) { 
     if (bean instanceof AnnotationMethodHandlerAdapter) { 
      AnnotationMethodHandlerAdapter a = (AnnotationMethodHandlerAdapter) bean; 
      HttpMessageConverter[] convs = a.getMessageConverters(); 
      ... add new converter ... 
      a.setMessageConverters(convs); 
     } 
    } 
    ... 
} 
+0

謝謝!你有一個很好的參考配置示例嗎? – AlexR 2010-12-08 16:19:22