2010-08-31 36 views
2

對於最近的項目,我們希望支持XML和另一種格式的resopnses。使用HttpMessageConverter進行Spring MVC內容協商

但是,我們無法控制Accept頭。因此,我們配置了一個ContentNegotiatingViewResolver使用,而不是一個請求參數:

<bean id="viewResolver" class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver"> 
    <property name="favorParameter" value="true" /> 
    <property name="parameterName" value="format" /> 
    <property name="ignoreAcceptHeader" value="true" /> 
    <property name="defaultContentType" value="application/xml" /> 
    <property name="mediaTypes"> 
     <map> 
      <entry key="xml" value="application/xml" /> 
      <entry key="foo" value="application/x-foo" /> 
     </map> 
    </property> 
    <property name="viewResolvers"> 
     <list> 
      <bean class="org.springframework.web.servlet.view.ResourceBundleViewResolver" > 
       <property name="basename" value="views-xml" /> 
      </bean> 
      <bean class="org.springframework.web.servlet.view.ResourceBundleViewResolver" > 
       <property name="basename" value="views-foo" /> 
      </bean> 
     </list> 
    </property> 
</bean> 

但是現在,我在想,如果我可以移動使用和@ResponseBody實現HttpMessageConverter簡化的代碼,我需要保持量。

但是,是否有類似的方法來確保reqeust參數用於內容協商而不是Accept頭?

回答

3

有一種變通方法,如在https://jira.springframework.org/browse/SPR-7517

描述創建AnnotationMethodHandlerAdapter上的一個子類:

package org.nkl.spring; 

import java.util.Map; 

import javax.servlet.http.HttpServletRequest; 

import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 
import org.springframework.http.HttpInputMessage; 
import org.springframework.http.MediaType; 
import org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter; 

public class MyAnnotationMethodHandlerAdapter extends AnnotationMethodHandlerAdapter { 

    private Logger logger = LoggerFactory.getLogger(MyAnnotationMethodHandlerAdapter.class); 
    private String requestParam = "accept"; 
    private Map<String, MediaType> mediaTypesMap; 

    @Override protected HttpInputMessage createHttpInputMessage(HttpServletRequest request) throws Exception { 
     HttpInputMessage message = super.createHttpInputMessage(request); 
     String accept = request.getParameter(requestParam); 
     if (accept == null || accept.isEmpty()) { 
     logger.info(String.format("Request parameter [%s] not found. Using standard HttpInputMessage", requestParam)); 
     return message; 
     } else { 
     logger.info(String.format("Request parameter [%s] was [%s]", requestParam, accept)); 
     MediaType mediaType = mediaTypesMap.get(accept); 
     if (mediaType == null) { 
      logger.info(String.format("Suitable MediaType not found. Using standard HttpInputMessage")); 
      return message; 
     } else { 
      logger.info(String.format("Suitable MediaType [%s] found. Using custom HttpInputMessage", mediaType)); 
      return new MyHttpInputMessage(message, mediaTypesMap.get(accept)); 
     } 
     } 
    } 

    public void setMediaTypesMap(Map<String, MediaType> mediaTypesMap) { 
     this.mediaTypesMap = mediaTypesMap; 
    } 

    public void setRequestParam(String requestParam) { 
     this.requestParam = requestParam; 
    } 
} 

創建HttpInputMessage的裝飾:

package org.nkl.spring; 

import java.io.IOException; 
import java.io.InputStream; 
import java.util.Arrays; 

import org.springframework.http.HttpHeaders; 
import org.springframework.http.HttpInputMessage; 
import org.springframework.http.MediaType; 

public class MyHttpInputMessage implements HttpInputMessage { 

    private HttpInputMessage delegate; 

    public MyHttpInputMessage(HttpInputMessage delagate, MediaType mediaType) { 
     this.delegate = delagate; 
     this.delegate.getHeaders().setAccept(Arrays.asList(mediaType)); 
    } 

    @Override public InputStream getBody() throws IOException { 
     return this.delegate.getBody(); 
    } 

    @Override public HttpHeaders getHeaders() { 
     return this.delegate.getHeaders(); 
    } 
} 

配置你的bean,如:

<bean class="org.nkl.spring.MyAnnotationMethodHandlerAdapter"> 
     <property name="requestParam" value="format" /> 
     <property name="mediaTypesMap"> 
     <util:map> 
      <entry key="plain" value="text/plain" /> 
      <entry key="xml" value="text/xml" /> 
     </util:map> 
     </property> 
     <property name="messageConverters"> 
     <util:list> 
      ... converters go here ... 
     </util:list> 
     </property> 
    </bean> 
0

Spring的較新版本現在可以做到這一點。 ContentNegotiationManagerFactoryBean可以創建一個內容協商管理器,它完全按照您的要求進行操作。看我的answer to a related question