代码之家  ›  专栏  ›  技术社区  ›  toolkit

使用HttpMessageConverter的Spring MVC内容协商

  •  2
  • toolkit  · 技术社区  · 14 年前

    在最近的一个项目中,我们希望支持XML和其他格式。

    但是,我们无法控制Accept头。因此,我们将ContentNegotingViewResolver配置为使用请求参数:

    <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实现来简化需要维护的代码量。

    但是,有没有类似的方法来确保将request参数用于内容协商,而不是Accept头?

    2 回复  |  直到 11 年前
        1
  •  3
  •   toolkit    14 年前

    有一个解决方法,如中所述 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>
    
        2
  •  0
  •   Community CDub    7 年前

    ContentNegotiationManagerFactoryBean 您可以创建一个内容协商管理器,该管理器正好满足您的需要。看我的 answer to a related question .

    推荐文章