Fork me on GitHub

ResponseBodyAdvice如何处理返回值是字符串的问题

项目中使用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);
    }
}
posted @ 2020-07-17 13:36  爱跑步的星仔  阅读(3979)  评论(0编辑  收藏  举报