How can I influence the process of choosing a message converter in AnnotationMethodHandlerAdapter for resulting POJO by url extension?
I would like to have more representations of one data object, while data representation should be chosen by the requested url extension e.g. /users/2.xml or /users/2.json.
Current configuration of message handlers, which should be chosen based on url extension:
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
    <property name="messageConverters">
        <list>
            <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" />
            <bean class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter"
                p:marshaller-ref="xmlMarshaller" p:unmarshaller-ref="xmlMarshaller" />
        </list>
    </property>
</bean>
There is one way, which I'm nearly comfortable with and that is using ContentNegotiatingViewResolver, however I would like to bypass the process of view resolution and directly use message converters. Also when creating actions, using ResponseEn开发者_开发百科tity in public ResponseEntity<User> showUser() provides fine grained control of resulting http status codes definitions (OK, NOT_FOUND, NO_CONTENT, ..). I couldn't find a way of using ResponseEntity with ContentNegotiatingViewResolver, which would also satisfy my needs.
Another way could be by modifying the request accept header to application/xml or application/json based on the url extension. This way, all the processing should go directly to the configured message converter. However I don't know a reasonable way to tamper the request headers.
Thanks.
Since the choose of HttpMessageConverters uses the Accept request header, perhaps the simpliest way to implement a content negotiation is to replace this header with the desired media type specified by the URL extension. 
This can be implemented either as a Filter (using HttpServletRequestWrapper to replace header value) or by overriding AnnotationMethodHanlderAdapter.createHttpInputMessage() as suggested in SPR-7517 (requires Spring 3.0.2).
See also SPR-6993.
I had this same need and hacked together a servlet filter to accomplish the task. Not a work of art, but gets the job done:
public class UrlExtensionFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
    HttpServletRequest httpServletRequest = (HttpServletRequest)request;
    if (httpServletRequest.getRequestURI().endsWith(".json")) {
        MyAcceptHeaderRequest acceptHeaderRequest = new MyAcceptHeaderRequest(httpServletRequest);
        acceptHeaderRequest.setAcceptHeader("application/json");
        filterChain.doFilter(acceptHeaderRequest, response);
    } else if (httpServletRequest.getRequestURI().endsWith(".xml")) {
        MyAcceptHeaderRequest acceptHeaderRequest = new MyAcceptHeaderRequest(httpServletRequest);
        acceptHeaderRequest.setAcceptHeader("text/xml");
        filterChain.doFilter(acceptHeaderRequest, response);
    } else {
        filterChain.doFilter(request, response);
    }
}
public void destroy() {
}
public class MyAcceptHeaderRequest extends HttpServletRequestWrapper {
    private String accept = "application/json";
    public MyAcceptHeaderRequest(HttpServletRequest request) throws IOException {
        super(request);
    }
    public void setAcceptHeader(String value) {
        accept = value;
    }
    @Override
    public String getHeader(String name) {
        if (name.equalsIgnoreCase("accept") || name.equalsIgnoreCase("content-type")) {
            return accept;
        } else {
            return super.getHeader(name);
        }
    }
    @Override
    public Enumeration getHeaders(String name) {
        if (name.equalsIgnoreCase("accept") || name.equalsIgnoreCase("content-type")) {
            Enumeration enumeration = new StringTokenizer(accept);
            return enumeration;
        } else {
            return super.getHeaders(name);
        }
    }
    @Override
    public String getContentType() {
        return accept;
    }
    @Override
    public String getParameter(String name) {
        // When we're using this class and it is a POST operation then the body is JSON or XML so don't allow
        // attempts to retrieve parameter names to consume the input stream
        if (this.getMethod().equals("POST")) {
            return null;
        } else {
            return super.getParameter(name);
        }
    }
    @Override
    public String[] getParameterValues(String name) {
        // When we're using this class and it is a POST operation then the body is JSON or XML so don't allow
        // attempts to retrieve parameter names to consume the input stream
        if (this.getMethod().equals("POST")) {
            return null;
        } else {
            return super.getParameterValues(name);
        }
    }
}
}
 
         
                                         
                                         
                                         
                                        ![Interactive visualization of a graph in python [closed]](https://www.devze.com/res/2023/04-10/09/92d32fe8c0d22fb96bd6f6e8b7d1f457.gif) 
                                         
                                         
                                         
                                         加载中,请稍侯......
 加载中,请稍侯......
      
精彩评论