Response流复制
背景
前段时间有个需求, 需要是要业务在web层增加操作日志。 实现基于 aop
实现的。但是有几个接口返回 void
, 实际的数据流通过 response.getWriter().write
这样返回的。对于业务结果是分成功和失败的, 但是aop中拿不到返回结果, 所以才有了以下的实现。
实现
分析: 由于spring中的流只能被消费一次, 所以本质上还是通过流复制来解决。实际解决如下
1 2 3 4 5 6 7 8 9
| public class LogRecordFilter extends OncePerRequestFilter {
@Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper(response); filterChain.doFilter(request, responseWrapper); responseWrapper.copyBodyToResponse(); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| @Around("@annotation(xxx.web.logrecord.annotation.LogRecord)") public Object logPointCut(ProceedingJoinPoint joinPoint) throws Throwable { Object ret = null;
MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); Object[] args = joinPoint.getArgs();
try { ret = joinPoint.proceed(); } catch (Throwable e) { throw e; }
if(Objects.nonNull(ret) && ret instanceof RespResult) { RespResult respResult = (RespResult)ret; if (respResult.getType() == 0) { return ret; } }
if (Objects.isNull(ret)) { try { HttpServletResponse response = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getResponse(); if (Objects.nonNull(response)) { byte[] contentAsByteArray = ((ContentCachingResponseWrapper) response).getContentAsByteArray(); RespResult respResult = objectMapper.readValue(contentAsByteArray, RespResult.class); if (respResult.getType() == 0) { LogRecordContext.clear(); return ret; } } } catch (Exception e) { log.error("[xxx] void response err", e); } }
return ret; }
|
最后
本文到此结束,感谢阅读。如果您觉得不错,请关注公众号【当我遇上你】,您的支持是我写作的最大动力。