Spring Aspect获取request和response

来源:互联网 发布:淘宝卖家信用等级2笔 编辑:程序博客网 时间:2024/05/19 03:23

最近在项目中把给客户端的protobuf结构转换成给网页端的json,可以直接使用spring的aspect拦截controller层的方法,然后拿到request和response进行转换。spring我使用的是全注解方式。其实这里有2个坑:

  1. 如何在spring aspect中获取HttpServletRequest和HttpServletResponse。
  2. 获取到request和response后pb转json重新输出出现乱码。会抛出java.io.CharConversionException: Not an ISO 8859-1 character异常。

其实在spring的aspect中很好获取HttpServletRequest和HttpServletResponse,通过spring-web模块下的RequestContextHolder就能获取到。spring-web对servlet的上下文进行了封装,可以看到是通过NamedThreadLocal进行封装的。

这里写图片描述

通过静态方法getRequestAttributes取出。

这里写图片描述

可以通过如下代码获取request:

HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();

而response可以这样:

HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();

pb转换json也不复杂,使用google提供的工具类JsonFormat.printToString即可。但是在通过response输出时会遇到剩下的那俩个问题。当输出json有中文时,会出现字符集无法转换的异常,网上给出的解决方案是用从response中获取PrintWriter对象,但是如果使用PrintWriter就会出现接下来的writer已经被调用的问题,产生java.lang.IllegalStateException: getOutputStream() has already been called for this response异常,所以还是转回SerlvetOutPutStream。

最后完整的代码如下:

@Aspect@Componentpublic class PB2JsonAspect {    public static final Logger LOGGER = LogManager.getLogger(PB2JsonAspect.class);    private static final String RESPONSE_CHARSET = "UTF-8";    @Pointcut("execution(* fm.jiecao.rest.*.controller.*.*(..))")    public void PB2JsonAfter() {    }    @AfterReturning(pointcut = "PB2JsonAfter()", returning = "returnValue")    public void afterReturning(Object returnValue) {        LOGGER.info("PB2JsonAspect afterReturning...");        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();//获取request        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();//获取response        if (checkHasFlag(request) && checkReturnValueIsPb(returnValue)) {            String json = JsonFormat.printToString((Message) returnValue);//转换json            ServletOutputStream out = null;            try {                response.setCharacterEncoding(RESPONSE_CHARSET);                response.setContentType("text/json;charset=" + RESPONSE_CHARSET);                out = response.getOutputStream();                out.write(json.getBytes(RESPONSE_CHARSET));                LOGGER.debug("pb->json:" + json);            } catch (IOException e) {                e.printStackTrace();            } finally {                if (null != out) {                    try {                        out.flush();                        out.close();                    } catch (IOException e) {                        e.printStackTrace();                    }                }            }        }    }    private boolean checkReturnValueIsPb(Object returnValue) {        if (returnValue instanceof Message) {//检查是否是pb            return true;        } else {            return false;        }    }    private boolean checkHasFlag(HttpServletRequest request) {        if (null == request) return false;        String contentType = request.getContentType();        String accept = request.getHeader("Accept");        //检查accept和content-type        if (StringUtils.isNotBlank(contentType) && contentType.contains("application/json") || StringUtils.isNotBlank(accept) && accept.contains("application/json") ) {            return true;        } else {            return false;        }    }}
0 0