项目中使用ResponseBodyAdvice同一封装返回格式,对于一般的类型都没有问题,但是处理字符串时,遇到了类型转换的问题,debug一步一步跟踪,原来是对于字符串的ContentType是“text-plain”,ConverterType是StringHttpMessageConverter这个类型转换,由于将结果封装成了自定义的Result类型,所以有Result转换成String报错。
如何改正呢,其实很简单,将返回String的ContentType变成“application/json; charset=UTF-8“。然后将自定义的Result转换成json字符串,上代码:
1:想在前台js里面直接当成json使用,需要将返回String的ContentType变成“application/json; charset=UTF-8“,produces即完成此部分工作。@ResponseResult此注解是用来标识哪些类或者方法需要统一返回格式。
@RequestMapping(value = "/do_login",produces = "application/json; charset=UTF-8")
@ResponseBody
@ResponseResult
public String doLogin(HttpServletResponse response, @Valid LoginVo loginVo) {
log.info(loginVo.toString());
//登录
String token = userService.login(response, loginVo);
return token;
}
2:将自定义的Result转换成json字符串,下面对String类型处理为重点
/**
* 根据标识,统一返回类型
*/
@ControllerAdvice
public class ResponseResultHandler implements ResponseBodyAdvice{
private final Logger logger = LoggerFactory.getLogger(ResponseResultHandler.class);
@Override
public boolean supports(MethodParameter returnType, Class converterType) {
ServletRequestAttributes sr = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
HttpServletRequest request = sr.getRequest();
//这里是往request获取一个参数,这个参数标识是否需要统一返回格式,
//设置参数的过程就是写了一个拦截器,判断有无@ResponseResult注解,如果有存入这个标识参数
ResponseResult ResponseResult = (ResponseResult)request.getAttribute(ResponseResultInterceptor.RESPONSE_RESULT_ANN);
request.removeAttribute(ResponseResultInterceptor.RESPONSE_RESULT_ANN);
return ResponseResult == null ? false:true;
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType,
MediaType selectedContentType, Class selectedConverterType,
ServerHttpRequest request, ServerHttpResponse response) {
logger.info("进入返回体,重写格式中");
if(body instanceof GlobalException){
logger.info("返回值异常,做包装异常处理");
GlobalException gx = (GlobalException)body;
return Result.error(gx.getCm());
}
//已经是Result类型不做处理,全局异常处理就是返回的Result类型
//抛异常时先是全局异常处理程序处理,然后才是返回结果处理
if(body instanceof Result){
return body;
}
//当返回类型是String时,用的是StringHttpMessageConverter转换器,无法转换为Json格式
//必须在方法体上标注RequestMapping(produces = "application/json; charset=UTF-8")
if(body instanceof String){
String str = JSON.toJSONString(Result.success(body));
return str;
}
return Result.success(body);
}
}