通常情况下,如果我们的API接口需要返回 JSON、XML 等格式化的数据时,只需要在控制器上注解@ResponseBody
且指定produces = "application/json;charset=UTF-8"
数据类型即可,参考代码如下:
/** * 登录提交 */ @RequestMapping(value = "loginSubmit", produces = "application/json;charset=UTF-8") @ResponseBody public String loginSubmit(LoginRequest loginRequest) { // 登录的业务逻辑 //...... return "{"\code\": \"0\", \"msg\": \"登录成功\"}" }
但是每个接口都加上这段代码:produces = "application/json;charset=UTF-8"
,貌似不那么清爽,于是想到是否能在“拦截器”里做些手脚,让它自动输出这个JSON文档类型(即 Http Json头信息),但实践证明,针对 @ResponseBody
,在“拦截器”中的设置是无效的,如:
package com.wenjianbao.interceptor; import cn.hutool.core.util.StrUtil; import org.springframework.lang.Nullable; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * 系统拦截器 */ public class SystemInterceptor extends HandlerInterceptorAdapter { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 针对 @ResponseBody 标注的控制器,这段代码是无效的! response.setHeader("Content-Type", "application/json;charset=UTF-8"); return true; } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception { // 针对 @ResponseBody 标注的控制器,这段代码是无效的! response.setHeader("Content-Type", "application/json;charset=UTF-8"); } }
通过这篇文章:SpringBoot ResponseBodyAdvice 接口实现自定义返回数据类型(响应头)学习到,
通过实现ResponseBodyAdvice
接口,可对返回的字符串(json/xml等)对象,做一些强制篡改,包括 Http头信息的修改,参考代码如下:
package com.wanma.printer.interceptor; import cn.hutool.core.util.StrUtil; import com.wanma.printer.util.RequestUtil; import org.springframework.core.MethodParameter; import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServerHttpResponse; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; @ControllerAdvice public class ResponseBodyInterceptor implements ResponseBodyAdvice<Object> { /** * 判断哪些需要拦截 */ @Override public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) { return true; } @Override public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { if (body instanceof String) { String bodyStr = String.valueOf(body); // 输出 XML 头信息 String inAjax = RequestUtil.getRequest().getParameter("inAjax"); if (inAjax != null && inAjax.equals("1")) { response.getHeaders().setContentType(MediaType.TEXT_XML); } // 输出 JSON 头信息 if (StrUtil.startWith(bodyStr, "{") && StrUtil.endWith(bodyStr, "}")) { response.getHeaders().setContentType(MediaType.APPLICATION_JSON); } } return body; } }
以后,Api控制器,就无需加上:produces = "application/json;charset=UTF-8"
,简化如下:
/** * 登录提交 */ @RequestMapping(value = "loginSubmit") @ResponseBody public String loginSubmit(LoginRequest loginRequest) { // 登录的业务逻辑 //...... return "{"\code\": \"0\", \"msg\": \"登录成功\"}" }