1.建立RequestWrapper类

import com.g2.order.server.utils.HttpHelper;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.Enumeration; import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest; public class HttpServletRequestWrapper extends
javax.servlet.http.HttpServletRequestWrapper { private final byte[] body; public HttpServletRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
System.out.println("-------------------------------------------------");
Enumeration e = request.getHeaderNames() ;
while(e.hasMoreElements()){
String name = (String) e.nextElement();
String value = request.getHeader(name);
System.out.println(name+" = "+value); }
body = HttpHelper.getBodyString(request).getBytes(Charset.forName("UTF-8"));
} @Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(getInputStream()));
} @Override
public ServletInputStream getInputStream() throws IOException { final ByteArrayInputStream bais = new ByteArrayInputStream(body); return new ServletInputStream() {
@Override
public boolean isFinished() {
return true;
} @Override
public boolean isReady() {
return true;
} @Override
public void setReadListener(ReadListener listener) { } @Override
public int read() throws IOException {
return bais.read();
}
};
} @Override
public String getHeader(String name) {
return super.getHeader(name);
} @Override
public Enumeration<String> getHeaderNames() {
return super.getHeaderNames();
} @Override
public Enumeration<String> getHeaders(String name) {
return super.getHeaders(name);
} public String getStringBody(){
return new String(body);
}
}

2.定义ResponseWrapper

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException; import javax.servlet.ServletOutputStream;
import javax.servlet.WriteListener;
import javax.servlet.http.HttpServletResponse; public class HttpServletResponseWrapper extends javax.servlet.http.HttpServletResponseWrapper { private ByteArrayOutputStream buffer = null; private ServletOutputStream out = null; private PrintWriter writer = null; public HttpServletResponseWrapper(HttpServletResponse response) throws IOException{
super(response); buffer = new ByteArrayOutputStream();
out = new WapperedOutputStream(buffer);
writer = new PrintWriter(new OutputStreamWriter(buffer, "UTF-8"));
} //重载父类获取outputstream的方法
@Override
public ServletOutputStream getOutputStream() throws IOException {
return out;
} @Override
public PrintWriter getWriter() throws IOException {
return writer;
} @Override
public void flushBuffer() throws IOException {
if (out != null) {
out.flush();
}
if (writer != null) {
writer.flush();
}
} @Override
public void reset() {
buffer.reset();
} public String getResponseData(String charset) throws IOException {
flushBuffer();//将out、writer中的数据强制输出到WapperedResponse的buffer里面,否则取不到数据
byte[] bytes = buffer.toByteArray();
try {
return new String(bytes, "UTF-8");
} catch (UnsupportedEncodingException e) {
return "";
} } //内部类,对ServletOutputStream进行包装,指定输出流的输出端 private class WapperedOutputStream extends ServletOutputStream { private ByteArrayOutputStream bos = null; public WapperedOutputStream(ByteArrayOutputStream stream) throws IOException {
bos = stream;
} //将指定字节写入输出流bos
@Override
public void write(int b) throws IOException {
bos.write(b);
} @Override
public boolean isReady() {
return false;
} @Override
public void setWriteListener(WriteListener listener) { }
}
}

这里有三种实现方式 (过滤器 (Filter)、拦截器(Interceptors)和切面(Aspect))

3.1 建立过滤器

import com.g2.order.server.api.HttpServletRequestWrapper;
import com.g2.order.server.api.HttpServletResponseWrapper;
import com.g2.order.server.utils.HttpHelper; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import java.io.IOException; import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; @WebFilter(filterName = "accessLog", urlPatterns = "/*")
public class AccessLogFilter implements Filter {
private static Logger logger = LoggerFactory.getLogger(AccessLogFilter.class); @Override
public void init(FilterConfig filterConfig) throws ServletException { } @Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequestWrapper requestWrapper;
if (request instanceof HttpServletRequestWrapper) {
requestWrapper = (HttpServletRequestWrapper) request;
} else {
requestWrapper = new HttpServletRequestWrapper((HttpServletRequest) request);
} HttpServletResponseWrapper responseWrapper = new HttpServletResponseWrapper((HttpServletResponse) response);
chain.doFilter(requestWrapper, responseWrapper);
String result = responseWrapper.getResponseData(response.getCharacterEncoding());
response.getOutputStream().write(result.getBytes());
logger.info("请求值链接:{},method:{},body:{},header:{},response:{}"
, requestWrapper.getRequestURI()
, requestWrapper.getMethod()
, requestWrapper.getStringBody()
, HttpHelper.getStringHeaders(requestWrapper)
, result);
} @Override
public void destroy() { }
}

4.启动类

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.web.servlet.ServletComponentScan; /**
* 程序入口
*/
@SpringBootApplication
@ServletComponentScan
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}

5.建立controller

import com.g2.order.dao.mapper.user.UserMapper;
import com.g2.order.server.vo.user.UserLoginReq;
import com.g2.order.dao.model.user.UserDao;
import com.g2.order.server.vo.user.UserLoginResp;
import com.g2.order.server.vo.user.UserModel; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*; @Api(value = "HomeController", description = "用户登录登出接口")
@RestController
@RequestMapping("/home")
public class HomeController { @Autowired
private UserMapper userMapper; @ApiOperation(value = "用户登录", notes = "用户登录接口")
@RequestMapping(value = "/login",
method = RequestMethod.POST,
consumes = MediaType.APPLICATION_JSON_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public UserLoginResp login(@RequestBody UserLoginReq req) {
UserDao userDao = userMapper.getById(1);
UserModel userModel = new UserModel();
userModel.setUserId(Integer.toString(userDao.getUserId()));
return new UserLoginResp(userModel);
}
}

6.请求后的日志

请求值链接:/home/login,method:POST,body:{ "userId":"123","password":"123444"},header:cache-control:no-cache
postman-token:a75b1ed5-27d4-47ea-ba21-ee368b463fc5
content-type:application/json
user-agent:PostmanRuntime/2.3.2
host:127.0.0.1:88
accept-encoding:gzip, deflate
content-length:42
connection:keep-alive

返回值:{"success":true,"errorMessage":"","payload":{"userId":"1","roleName":null,"roleId":null}}

如果使用 拦截器(Interceptors)代码会更加简单

import com.google.common.base.Strings;

import com.g2.order.server.api.HttpServletRequestWrapper;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.Arrays; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import static java.util.stream.Collectors.joining; public class AccessLogInterceptor extends HandlerInterceptorAdapter {
private static Logger logger = LoggerFactory.getLogger(AccessLogInterceptor.class); @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
String body = "";
logger.debug("Access Auth Interceptor - 进入拦截器");
if (request instanceof HttpServletRequestWrapper) {
HttpServletRequestWrapper requestWrapper = (HttpServletRequestWrapper) request;
body = requestWrapper.getStringBody();
}
if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
Class[] paramTypes = method.getParameterTypes();
String paramTypesString = Arrays.stream(paramTypes).map(p -> p.getName()).collect(joining(",")); Parameter[] methodParameters = method.getParameters();
if (methodParameters.length == 0) {
return false;
}
Parameter methodParameter = methodParameters[0];
String parameterName = methodParameter.getName();
String parameterClass = methodParameter.getType().getCanonicalName();
String parameterVelue = request.getParameter(parameterName);
if (Strings.isNullOrEmpty(parameterVelue)) {
parameterVelue = body;
}
logger.info("请求方法:{},请求参数类型:{},请求值:{}", method.getName(), parameterClass, parameterVelue);
}
return true;
} /**
* This implementation is empty.
*/
@Override
public void postHandle(
HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
throws Exception {
} /**
* This implementation is empty.
*/
@Override
public void afterCompletion(
HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
} /**
* This implementation is empty.
*/
@Override
public void afterConcurrentHandlingStarted(
HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
}
}

再建立Config 类

import com.g2.order.server.interceptor.AccessLogInterceptor;

import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; @Component
public class LogInterceptorConfig extends WebMvcConfigurerAdapter {
@Bean
public AccessLogInterceptor getAccessLogInterceptor() {
return new AccessLogInterceptor();
} @Override
public void addInterceptors(InterceptorRegistry registry) {
InterceptorRegistration addInterceptor = registry.addInterceptor(getAccessLogInterceptor()); // 排除配置
addInterceptor.excludePathPatterns("/error"); // 拦截配置
addInterceptor.addPathPatterns("/**");
}
}

3.3 对controller层使用切面(Aspect)(代码最简单,功能最强大)


import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component; import java.lang.reflect.Method; import javax.annotation.Resource; //开启AspectJ 自动代理模式,如果不填proxyTargetClass=true,默认为false,
@EnableAspectJAutoProxy(proxyTargetClass = true)
@Component
@Aspect
public class ControllerAspectConfig {
@Around("execution(* com.g2.order.server.controller.*.*(..))")
public Object handleControllerMethod(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("进入切面,执行before.."); //获取controller对应的方法.
org.aspectj.lang.reflect.MethodSignature methodSignature = (org.aspectj.lang.reflect.MethodSignature) proceedingJoinPoint.getSignature();
//获取方法所在的类(controller)
Class beanType = methodSignature.getDeclaringType();
//获取方法
Method method = methodSignature.getMethod(); //获取方法参数列表(无需处理讨厌的流了)
Object[] args = proceedingJoinPoint.getArgs();
for (Object arg : args) {
//获取参数的类型与值
System.out.println(arg.getClass().getName());
System.out.println("arg is " + arg);
} long startTime = System.currentTimeMillis();
System.out.println("进入其他切面或业务执行..");
Object obj = proceedingJoinPoint.proceed();
     System.out.println("业务完成,执行after..");
        //获取返回值的类型,与 Method.getReturnType()一致
Class responseClass=obj.getClass();
System.out.println("time aspect 耗时" + (System.currentTimeMillis() - startTime)); //方法的返回值是:
System.out.println("response is " + obj); return obj;
}
}
 

拦截器和过滤器的区别

spring boot RESTFul API拦截 以及Filter和interceptor 、Aspect区别

拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。

过滤器(Filter)         :可以拿到原始的http请求,但是拿不到你请求的控制器和请求控制器中的方法的信息。

拦截器(Interceptor):可以拿到你请求的控制器和方法,却拿不到请求方法的参数。

切片   (Aspect)       :  可以拿到方法的参数,但是却拿不到http请求和响应的对象

三种实现日志过滤器的方式 (过滤器 (Filter)、拦截器(Interceptors)和切面(Aspect))的更多相关文章

  1. ASP.NET Core应用的错误处理[1]:三种呈现错误页面的方式

    由于ASP.NET Core应用是一个同时处理多个请求的服务器应用,所以在处理某个请求过程中抛出的异常并不会导致整个应用的终止.出于安全方面的考量,为了避免敏感信息的外泄,客户端在默认的情况下并不会得 ...

  2. Js之Dom学习-三种获取页面元素的方式、事件、innerText和innerHTML的异同

    一.三种获取页面元素的方式: getElementById:通过id来获取 <body> <input type="text" value="请输入一个 ...

  3. .NET提供了三种后台输出js的方式:

    .NET提供了三种后台输出js的方式: 首先创建 js文件testjs.js {    Page.ClientScript.RegisterClientScriptInclude("keys ...

  4. Hive中的三种不同的数据导出方式介绍

    问题导读:1.导出本地文件系统和hdfs文件系统区别是什么?2.带有local命令是指导出本地还是hdfs文件系统?3.hive中,使用的insert与传统数据库insert的区别是什么?4.导出数据 ...

  5. 6_1 持久化模型与再次加载_探讨(1)_三种持久化模型加载方式以及import_meta_graph方式加载持久化模型会存在的变量管理命名混淆的问题

    笔者提交到gitHub上的问题描述地址是:https://github.com/tensorflow/tensorflow/issues/20140 三种持久化模型加载方式的一个小结论 加载持久化模型 ...

  6. Android中三种超实用的滑屏方式汇总(转载)

    Android中三种超实用的滑屏方式汇总   现如今主流的Android应用中,都少不了左右滑动滚屏这项功能,(貌似现在好多人使用智能机都习惯性的有事没事的左右滑屏,也不知道在干什么...嘿嘿),由于 ...

  7. HttpClient 三种 Http Basic Authentication 认证方式,你了解了吗?

    Http Basic 简介 HTTP 提供一个用于权限控制和认证的通用框架.最常用的 HTTP 认证方案是 HTTP Basic authentication.Http Basic 认证是一种用来允许 ...

  8. Filter(过滤器) 和 interceptor(拦截器)的区别

    Filter(过滤器) 和 interceptor(拦截器)的区别 1.拦截器是基于java反射机制的,而过滤器是基于函数回调的. 2.过滤器依赖于Servlet容器,而拦截器不依赖于Servlet容 ...

  9. Haproxy的三种保持客户端会话保持方式

    2017-03-25 15:41:41   haproxy 三种保持客户端Seesion; 一.源地址hash(用户IP识别) haroxy 将用户IP经过hash计算后 指定到固定的真实服务器上(类 ...

随机推荐

  1. Oracle 用户验证日志

    1.sysdba/sysoper 权限用户验证日志;2.非sysdba/sysoper 权限用户验证日志;3.关于sqlcode; 1.sysdba/sysoper 权限用户验证日志:在数据库设置了参 ...

  2. [GO]面向对象编程

    对于面向对象编程的支GO语言的设计简洁而优雅,因为,GO语言没有沿袭传统面向对象中的诸多概念 比如继承(不支持继承,尽管匿名字段的内存布局和行为类似继承,但它并不是继承) 尽管GO语言没有封装.继承. ...

  3. eclipse Multiple annotations found at this line

    参考:http://blog.csdn.net/li396864285/article/details/42745071 这样的错不影响编程,是eclipse的校验问题 去掉相应的Build就行了

  4. 更改文本的编码jsp.xml.java

    JSP改为UTF-8编码 更改xml workspace resource

  5. 利用predis操作redis方法大全

    predis是PHP连接Redis的操作库,由于它完全使用php编写,大量使用命名空间以及闭包等功能,只支持php5.3以上版本,故实测性能一般,每秒25000次读写. 将session数据存放到re ...

  6. Introduction MBG

    文档地址 http://www.mybatis.org/generator/configreference/xmlconfig.html 源码地址 https://github.com/mybatis ...

  7. centos 学习总结

    我用的是6.4 添加中文输入法 .su root .yum install "@Chinese Support" .exit .回到桌面,system->preference ...

  8. 【前端布局】px与rpx的简述

    本文只以移动设备为例说明. 注意:设计师以iphone6为标准出设计稿的话,1rpx=0.5px=1物理像素.Photoshop里面量出来的尺寸为物理像素点.所以可以直接使用标注尺寸数据. [像素Pi ...

  9. 阿里云ECS云服务器编译安装PHP遇到virtual memory exhausted: Cannot allocate memory

    阿里云编译安装php时遇到virtual memory exhausted: Cannot allocate memory 买了个服务器, 1G 的内存阿里云服务器,编译东西按说应该够了,安装相关的内 ...

  10. C++对象在内存中的布局

    (1)C++对象模型 (2)单一继承无虚函数 (3)单一继承有虚函数 (4)多重继承 (5)虚拟继承(vc++) (6)虚拟继承(g++) 参考:<深度探索C++对象模型>