第一种:Filter拦截Request、Response
@WebFilter(urlPatterns="/*")
public class WebFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
//请求URI
String requestUril = httpServletRequest.getRequestURI();
//请求方法
String method = httpServlet.getMethod();
//请求ip
String ip = HttpUtils.getIp(httpServletRequest);
//请求内容类型
String contentType = servletRequest.getContentType();
//使用包装器类型封装request response
RequestWrapper requestWrapper = new RequestWrapper(httpServletRequest);
ResponseWrapper responseWrapper = new ResponseWrapper(httpServletResponse);
String param = parseParams(requestWrapper);
//继续请求调用连
filterChain.doFilter(requestWrapper, responseWrapper);
String respBody = responseWrapper.getResponseBody();
//ip 请求方法 url 请求类型 参数 返回值
log.info("{} {} {} {} {} {}", ip, method, url, contentType, param, respBody);
//因为响应流只能写一次,已经写到responseWrapper离了,所以要把返回值写回到响应提
byte[] byteArr = respBody.getBytes(StandardCharsets.UTF8);
httpServletResponse.setStatus(200);
httpServletResponse.setHeader(MediaType.APPLICATION_JSON_UTF8_VALUE);
httpServletResponse.setContentLength(byteArr.length);
httpServletResponse.getOutputStream().write(byteArr);
}
@Override
public void destroy() {
}
private String parseParams(RequestWrapper wrapper) {
//JSON格式直接返回
if(MediaType.APPLICATION_JSON_VALUE.equls(wrapper.getContentType())) {
return wrapper.getBody();
}
//组装参数数组
else {
String[] parameters = wrapper.getParameterNames();
String[] data = new String[parameters.length];
int i=0;
for(String name :wrapper.getParameterNames()) {
data[i++] = name+"="+wrapper.getParameter(name);
}
return StringUtils.join(data,"&");
}
}
}
第二种:通过RequestBodyAdvice/ResponseBodyAdvice
@ControllerAdvice(annotations = {Controller.class, RestController.class})
public class WebRequestHandler implements RequestBodyAdvice {
@Override
public boolean supports(MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
//为true时可以执行建议的方法,即所有请求都执行
return true;
}
@Override
public Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
return inputMessage;
}
@Override
public HttpInputMessage beforeBodyRead(final HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) throws IOException {
return inputMessage;
}
@Override
public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
String method = parameter.getMethod().getName();
StringBuilder sb = new StringBuilder();
sb.append("请求:"+method);
sb.append("类:" + parameter.getDeclaringClass().getName());
sb.append("方法:"+parameter.getMethod().getName());
sb.append("入参:"+String.valueOf(body));
System.out.println(sb.toString());
return body;
}
}
@ControllerAdvice(annotations = {Controller.class, RestController.class})
public class WebResponseHandler implements ResponseBodyAdvice {
@Override
public boolean supports(MethodParameter methodParameter, Class aClass) {
return true;
}
@Override
public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
String requestPath = serverHttpRequest.getURI().getPath();
StringBuilder sb = new StringBuilder();
sb.append("路径:" + requestPath);
sb.append("返回结果:" + JSON.toJSONString(o));
System.out.println(sb.toString());
return o;
}
}
在这里踩了一个坑,即不能同时继承,否则会出现问题:requestAdvice执行两次而resposneAdvice不执行。探索了下原因是RequestResponseBodyAdviceChain.initAdvice方法中,if-else结构导致不能同时继承。
if (RequestBodyAdvice.class.isAssignableFrom(beanType)) {
this.requestBodyAdvice.add(advice);
}
else if (ResponseBodyAdvice.class.isAssignableFrom(beanType)) {
this.responseBodyAdvice.add(advice);
}