2010-08-31 2 views
2

Для недавнего проекта мы хотели поддержать XML и другой формат для наших репозиций.Обсуждение содержания Spring MVC с HttpMessageConverter

Однако мы не смогли контролировать заголовок 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 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.