我的任务可不简单。非常遗留的项目(Spring 4.3、xml-configuration、web.xml 等) Spring Controller 只生成一种媒体类型(application/xml)。客户决定他还需要 application/json。毫无疑问,一些重构,添加必要的注释和魔术作品。在配置中添加了默认使用 application/xml 的说明。全部在本地测试,一切正常。 问题 - 客户有一个旧应用程序,它使用 org.springframework.web.client.RestTemplate,并且在没有任何标头的情况下使用它。惊喜!带有空标头的 RestTemplate,在发送请求之前添加默认标头。端点接收带有标头 Accept="application/octet-stream, application/json, application/*+json, /" 的 httprequest。客户收到 json 格式的对象(但等待 xml)。 决定 - 不太好,但原样 - 添加过滤器,它将检查 Accept 的标头,如果它包含不止一种媒体类型,则将其替换为 application/xml。过滤器工作正常,所有需要的标题都被替换了。调试器显示控制器已经接收到新的标头,但仍然继续在响应正文中返回 application/json。 怎么了?
config.xml
...
<bean id="mvcContentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="favorParameter" value="true"/>
<property name="mediaTypes">
<value>
xml=application/xml
json=application/json
</value>
</property>
<property name="defaultContentType" value="application/xml"/>
</bean>
...
web.xml
...
<filter>
<filter-name>acceptFilter</filter-name>
<filter-class>la.la.AcceptFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>acceptFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
...
AcceptFilter.java
...
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) servletRequest;
String accept = req.getHeader("Accept");
if (accept.split(",").length > 1) {
MutableHttpServletRequest mutableRequest = new MutableHttpServletRequest(req);
mutableRequest.putHeader("accept", "application/xml");
mutableRequest.putHeader("Content-Type", "application/xml");
((HttpServletResponse) servletResponse).setHeader("Accept", "application/xml");
((HttpServletResponse) servletResponse).setHeader("Content-Type", "application/xml");
servletResponse.setContentType("application/xml");
filterChain.doFilter(mutableRequest, servletResponse);
} else {
filterChain.doFilter(servletRequest, servletResponse);
}
}
final class MutableHttpServletRequest extends HttpServletRequestWrapper {
...
LaLaController.java
...
@RestController
@RequestMapping(value = CONTROLLER_PATH,
produces = {APPLICATION_XML_VALUE, APPLICATION_JSON_VALUE})
public class LaLaController {
@GetMapping("/firstEndpoint")
public JustObject firstEndpoint() {
return new JustObject("some information", "some details");
}
...
请求示例:
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<byte[]> responseEntity = restTemplate.exchange(url, HttpMethod.GET, null, byte[].class);
byte[] body = responseEntity.getBody();
我试过拦截器,但也没有办法改变标题。我没有想法。如果在请求中设置接受 - 一切正常。 如果有人为我的问题提供更好的决定,我将不胜感激。