本文共 2407 字,大约阅读时间需要 8 分钟。
经常看到有些很逗的项目,用AOP切Controller去打印日志,我只能说呵呵,aop是让你们这些人乱用的吗?不会用就不要用,是,我承认AOP切controller完全可以做到打印日志,但是,这种严重破坏对象封装并且完全不理解aop应用场景的做法完全不可取,如果什么事情都用aop,那么请问spring security项目为什么全都采用filter的方式,而非aop呢??
言归正传,打印日志的方式应该是我们自己定义一个过滤器,这个过滤器专门用来打印日志,打印完日志之后,再进行到下一个过滤器继续处理数据,但是从流中读取数据的难点在于,本次从流中读出了数据,那么下行程序链将无法再次读取流中数据,所以重点在于HttpServletRequestWrapper类
1.创建类RequestWrapper 继承 HttpServletRequestWrapper,然后重写
getInputStream()和getReader()两个方法public class MyRequestWrapper extends HttpServletRequestWrapper { public String body; public MyRequestWrapper(HttpServletRequest request) throws IOException { super(request); StringBuilder sb = new StringBuilder(); String line; InputStream stream = request.getInputStream(); BufferedReader br = new BufferedReader(new InputStreamReader(stream)); while ((line = br.readLine()) != null) { sb.append(line); } body = sb.toString(); } @Override public ServletInputStream getInputStream() throws IOException { final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes()); ServletInputStream servletInputStream = new ServletInputStream() { @Override public int read() throws IOException { return byteArrayInputStream.read(); } @Override public boolean isFinished() { return false; } @Override public boolean isReady() { return false; } @Override public void setReadListener(ReadListener listener) { } }; return servletInputStream; } @Override public BufferedReader getReader() throws IOException { return new BufferedReader(new InputStreamReader(getInputStream())); }}
2.创建类RequestFilter实现 Filter
@Order(0)//注意这里,无需再从web.xml中配置了@WebFilter(filterName = "MyFilter", urlPatterns = "/*")public class MyFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("过滤器,开始打日志"); MyRequestWrapper wrapper = new MyRequestWrapper((HttpServletRequest) request); System.out.println("body内容:" + wrapper.body); chain.doFilter(wrapper, response); } @Override public void destroy() { }}
3.如果项目是spring boot,那么需要扫描到WebFilter注解,需要在启动类添加
@SpringBootApplication//扫描servlet相关注解@ServletComponentScanpublic class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); }}
转载地址:http://athws.baihongyu.com/