通常情况下,如果我们的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\": \"登录成功\"}"
}