1.需求:给某些请求接口记录日志,记录请求的数据和响应的数据和请求所花费的时间。这里采用非侵入式编程,也业务代码进行解耦。按照spring AOP 的编程思想。

2.编程设计:在spring 拦截器中植入日志代码。因为其刚好满足非侵入,且能捕获到请求和响应的数据。

3.了解spring 拦截器和过滤器的运行原理

  先执行过滤器,然后执行拦截器。

4. 分析:当在拦截器中获取请求的输入流和响应的输出流的时候发现,只能读取一次,拦截器在具体的业务代码之前执行,导致请求的输入流被拦截器使用,到controller 的时候将获取不到数据。当响应的数据流被拦截器的postHandler 使用之后,输出到客户端没有响应的数据。

  流程:先创建过滤器,过滤器是链式执行,配置的web.xml 的中。

  WrapperFilter  在web.xml 中的配置

  <filter>
<filter-name>sosWrapperFilter</filter-name>
<filter-class>com.xiao.handler.filter.WrapperFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>sosWrapperFilter</filter-name>
<!-- 过滤的url地址 -->
<url-pattern>/myTest/*</url-pattern>
</filter-mapping>

增加一个拦截器配置,配置需要过滤器的请求地址,走 spring mvc的拦截器,拦截的是请求地址(不包含上下文 eg:http://localost:8080/xiao)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> <mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/test/*"/>
<bean class="com.xiao.interceptor.SosOrderInterceptor"/>
</mvc:interceptor>
</mvc:interceptors> </beans>

 开始编写过滤器,拦截器

过滤器

/**
*
* @describ request 请求过滤器增强
* @date 2019-03-06
* @author coder_xiao
*/
public class WrapperFilter implements Filter { private static Log log = LogFactory.getLog(WrapperFilter.class); @Override
public void init(FilterConfig filterConfig) throws ServletException { } @Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
CacheContentRequestWrapper requestWrapper=null;
CacheContentResponseWrapper responseWrapper=null;
HttpServletRequest request=(HttpServletRequest)servletRequest;
HttpServletResponse response=(HttpServletResponse) servletResponse;
try {
requestWrapper = new CacheContentRequestWrapper(request);
responseWrapper = new CacheContentResponseWrapper(response);
}catch (Exception e){
log.error("获取requestWrapper失败!",e);
}finally {
if((requestWrapper!=null)&&(responseWrapper!=null)) {
filterChain.doFilter(requestWrapper, responseWrapper);
responseWrapper.reWriteResponse(responseWrapper,(HttpServletResponse) servletResponse);
}else{
filterChain.doFilter(servletRequest, servletResponse);
}
} } @Override
public void destroy() { }
}

拦截器

public class SosOrderInterceptor implements HandlerInterceptor {

    private final static Log logger = LogFactory.getLog(SosOrderInterceptor.class);

    @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception {
BufferedReader bufferedInput=null;
String data=null;
try{
String urlPath=request.getRequestURI();
String contentType=request.getContentType();
Boolean typeIndex=contentType==null?false:contentType.indexOf("application/json")>-1;
Boolean createIndex=urlPath.indexOf("createOrder")>-1;
Boolean buildIndex=urlPath.indexOf("buildDraftOrder")>-1;
Boolean urlIndex=(urlPath.indexOf("createSosOrder")+urlPath.indexOf("buildDraftSosOrder"))>-2;
//POST 请求 contentType=application/json
if(typeIndex&&urlIndex) {
//支持mark and reset 为使流复用
CacheContentRequestWrapper contentRequestWrapper= new CacheContentRequestWrapper(request);
data = contentRequestWrapper.getBodyString();
String requestId=UUIDUtil.uuid();
request.setAttribute("requestId",requestId);
BuildAudit audit=BeanTool.getBean(BuildAudit.class);
//创建订单
if (createIndex) {
logger.info("开始调用创建订单");
audit.buildData(data,"1","1","创建订单",requestId);
}
//创建草稿
if (buildIndex) {
logger.info("创建草稿单!");
audit.buildData(data,"2","1","创建草稿单",requestId);
}
}
}catch (Exception e){
e.printStackTrace();
logger.error(e);
}finally {
if(bufferedInput!=null) {
bufferedInput.close();
}
}
return true;
} @Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object o, ModelAndView modelAndView) throws Exception {
logger.info("postHandle");
try{
String urlPath=request.getRequestURI();
String contentType=request.getContentType();
Boolean typeIndex=contentType==null?false:contentType.indexOf("application/json")>-1;
Boolean createIndex=urlPath.indexOf("createOrder")>-1;
Boolean buildIndex=urlPath.indexOf("buildDraftOrder")>-1;
Boolean urlIndex=(urlPath.indexOf("createSosOrder")+urlPath.indexOf("buildDraftOrder"))>-2;
String requestId= request.getAttribute("requestId")==null?null:request.getAttribute("requestId").toString();
if(typeIndex&&urlIndex) {
CacheContentResponseWrapper cacheResponse =(CacheContentResponseWrapper)((WebStatFilter.StatHttpServletResponseWrapper) response).getResponse();
String data=new String(cacheResponse.getResponseData(),"UTF-8");
BuildAudit audit=BeanTool.getBean(BuildAudit.class);
//创建订单
if (createIndex) {
audit.buildData(data,"1","2",null,requestId);
}
//创建草稿
if (buildIndex) {
audit.buildData(data,"2","2",null,requestId);
}
//草稿单转正
if (urlPath.indexOf("buildDraftSosOrder") > -1) { }
}
}catch (Exception e){
logger.error(e);
}
} @Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
logger.info("afterCompletion");
try{ }catch (Exception ex){
logger.error(ex);
}
}

两个缓存器

package com.lacesar.handler.wrapper;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader; import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; /**
* @description 包装spring 的 HttpServletRequestWrapper
*/
public class CacheContentRequestWrapper extends HttpServletRequestWrapper { private static Log log = LogFactory.getLog(CacheContentRequestWrapper.class); /**
* 存储body数据的容器
*/
private final byte[] body; private String requestId; public CacheContentRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
// 将body数据存储起来
String bodyStr = getBodyString(request);
body = bodyStr.getBytes("UTF-8");
} /**
* 获取请求Body
*
* @param request request
* @return String
*/
public String getBodyString(final ServletRequest request) {
try {
return inputStream2String(request.getInputStream());
} catch (IOException e) {
log.error("", e);
throw new RuntimeException(e);
}
} /**
* 获取请求Body
*
* @return String
*/
public String getBodyString() {
if (body != null) {
final InputStream inputStream = new ByteArrayInputStream(body);
return inputStream2String(inputStream);
} else {
return null;
}
} /**
* 将inputStream里的数据读取出来并转换成字符串
*
* @param inputStream inputStream
* @return String
*/
private String inputStream2String(InputStream inputStream) {
StringBuilder sb = new StringBuilder();
BufferedReader reader = null; try {
reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
String line;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
log.error("", e);
throw new RuntimeException(e);
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
log.error("", e);
}
}
} return sb.toString();
} public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(getInputStream()));
} public ServletInputStream getInputStream() throws IOException { final ByteArrayInputStream inputStream = new ByteArrayInputStream(body); return new ServletInputStream() {
public int read() throws IOException {
return inputStream.read();
} public boolean isFinished() {
return false;
} public boolean isReady() {
return false;
} public void setReadListener(ReadListener readListener) {
}
};
} public String getRequestId() {
return requestId;
} public void setRequestId(String requestId) {
this.requestId = requestId;
}
}
package com.lacesar.handler.wrapper;

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;
import javax.servlet.http.HttpServletResponseWrapper; public class CacheContentResponseWrapper extends HttpServletResponseWrapper {
private ByteArrayOutputStream buffer = null;
private ServletOutputStream out = null;
private PrintWriter writer = null; public CacheContentResponseWrapper(HttpServletResponse resp) throws IOException {
super(resp);
buffer = new ByteArrayOutputStream();
out = new WapperedOutputStream(buffer);
writer = new PrintWriter(new OutputStreamWriter(buffer, "UTF-8"));
} /**
* 重新写入response 数据
*
* @param wrapperResponse
* @param response
*/
public void reWriteResponse(CacheContentResponseWrapper wrapperResponse, HttpServletResponse response) {
String result = null;
try {
result = new String(wrapperResponse.getResponseData(), "UTF-8");
//解决可能在运行的过程中页面只输出一部分
response.setContentLength(-1);
response.setCharacterEncoding("UTF-8");
PrintWriter out = null;
out = response.getWriter();
if (out != null) {
out.write(result);
out.flush();
out.close();
}
} catch (Exception e) {
e.printStackTrace();
}
} public ServletOutputStream getOutputStream() throws IOException {
return out;
} public PrintWriter getWriter() throws UnsupportedEncodingException {
return writer;
} public void flushBuffer() throws IOException {
if (out != null) {
out.flush();
}
if (writer != null) {
writer.flush();
}
} public void reset() {
buffer.reset();
} public byte[] getResponseData() throws IOException {
flushBuffer();
return buffer.toByteArray();
} private class WapperedOutputStream extends ServletOutputStream {
private ByteArrayOutputStream bos = null; public WapperedOutputStream(ByteArrayOutputStream stream) throws IOException {
bos = stream;
} @Override
public void write(int b) throws IOException {
bos.write(b);
} @Override
public void write(byte[] b) throws IOException {
bos.write(b, 0, b.length);
} public boolean isReady() {
return false;
} public void setWriteListener(WriteListener writeListener) { }
}
}

最新文章

  1. GPU 加速NLP任务(Theano+CUDA)
  2. HTTP请求中的Body构建——.NET客户端调用JAVA服务进行文件上传
  3. 曝光卖假币的店铺和旺旺ID
  4. TreeComboBox控件范例
  5. supesite 标签语法
  6. 用Delphi的TIdHttp控件发起POST请求和Java的Servlet响应
  7. java后台开发- NOTE
  8. CodeForces 525D Arthur and Walls
  9. window下查看端口命令
  10. Java多机部署下的定时任务处理方案(mysql)
  11. C++11 作用域内枚举
  12. mysql下载安装及常见问题
  13. c编译动态库可以编译但是无法导入解决方法
  14. Workspace in use or cannot be created, choose a different one.
  15. BZOJ3028食物——生成函数+泰勒展开
  16. Spring Boot 打war包后自定义404页面不生效解决方法
  17. spring boot集成MyBatis
  18. 用Java构建一个简单的WebSocket聊天项目之新增HTTP接口调度
  19. [Linux] 关于Unix哲学
  20. Linux下查找命令

热门文章

  1. TModJS:使用tmodjs
  2. ORM学习 一 : JPA JDBC
  3. PHPstorm相同变量标识
  4. 怎么在Ubuntu下设置程序的快捷键
  5. mongodb &quot;$&quot;的作用
  6. 1.6-1.10 使用Sqoop导入数据到HDFS及一些设置
  7. 模板 - 洲阁筛 + min25筛
  8. 让group tableview每个section拥有阴影和圆角
  9. MonogoDb的角色分类
  10. GraphicsLab Project之再谈Shadow Map