Spring Boot如何按URL配置不同默认Content-Type或用过滤器补充请求头
两种实现方案均可行,可根据业务场景选择
方案1:自定义内容协商策略(优先推荐)
不需要额外新增过滤器/拦截器,直接替换原有全局固定默认Content-Type的配置,通过Spring MVC原生提供的默认ContentType策略扩展点,按路径匹配返回对应媒体类型即可,该逻辑直接内嵌在内容协商流程中,性能损耗最低。
修改原有配置代码如下:
@Override public void configureContentNegotiation(final ContentNegotiationConfigurer configurer) { configurer.defaultContentTypeStrategy(new ContentNegotiationStrategy() { @Override public List<MediaType> resolveMediaTypes(NativeWebRequest webRequest) throws HttpMediaTypeNotAcceptableException { HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class); String requestPath = request.getRequestURI(); // 按实际业务规则匹配需要返回JSON的路径,支持前缀、正则、精确路径匹配 if (requestPath.startsWith("/your-json-prefix/") || requestPath.matches(".*/json-interface-rule")) { return Collections.singletonList(MediaType.APPLICATION_JSON); } // 其余路径默认返回XML return Collections.singletonList(MediaType.APPLICATION_XML); } }); }
方案2:Servlet过滤器提前补全Content-Type请求头
如果需要在请求体解析(如JSON/XML报文反序列化阶段)也能读取到正确的Content-Type,可通过最高优先级的Servlet过滤器,在请求进入Spring MVC核心流程前,对未携带Content-Type的请求按路径补全对应头信息。
注意:不要使用HandlerInterceptor实现该逻辑,拦截器执行时机晚于内容协商、参数解析流程,会出现配置不生效的问题。
实现代码如下:
@Component @Order(Ordered.HIGHEST_PRECEDENCE) public class ContentTypeFillFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { // 仅处理未携带Content-Type的请求 if (StringUtils.isBlank(request.getContentType())) { String requestPath = request.getRequestURI(); String targetContentType = requestPath.startsWith("/your-json-prefix/") ? MediaType.APPLICATION_JSON_VALUE : MediaType.APPLICATION_XML_VALUE; // 通过RequestWrapper包装请求,覆写头读取逻辑 filterChain.doFilter(new ContentTypeRequestWrapper(request, targetContentType), response); return; } filterChain.doFilter(request, response); } private static class ContentTypeRequestWrapper extends HttpServletRequestWrapper { private final String contentType; public ContentTypeRequestWrapper(HttpServletRequest request, String contentType) { super(request); this.contentType = contentType; } @Override public String getContentType() { return contentType; } @Override public String getHeader(String name) { if (HttpHeaders.CONTENT_TYPE.equals(name)) { return contentType; } return super.getHeader(name); } @Override public Enumeration<String> getHeaders(String name) { if (HttpHeaders.CONTENT_TYPE.equals(name)) { return Collections.enumeration(Collections.singletonList(contentType)); } return super.getHeaders(name); } } }
选型参考
- 仅需要差异化设置响应默认媒体类型,选方案1,代码更轻量无侵入。
- 需要请求参数解析、报文转换阶段也能读取到正确Content-Type,选方案2。
内容的提问来源于stack exchange,提问作者Ramachandran Murugaian
相关产品推荐
相关产品推荐

