SpringBoot下,@WebFilter配置获取日志
Posted qianjinyan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringBoot下,@WebFilter配置获取日志相关的知识,希望对你有一定的参考价值。
CREATE TABLE [dbo].[SWEBSERVICELOG]( [WLG_ID] [varchar](100) NOT NULL, [WLG_SESSIONID] [varchar](100) NULL, [WLG_REMOTEIPADDR] [varchar](20) NULL, [WLG_REQUESTURL] [varchar](100) NULL, [WLG_START_DT] [datetime2](7) NULL, [WLG_END_DT] [datetime2](7) NULL, [WLG_CLIENTHOST] [varchar](200) NULL, [WLG_USERAGENT] [varchar](500) NULL, [WLG_METHOD] [nvarchar](20) NULL, [WLG_PARAMS] [varchar](500) NULL, [WLG_PARAMSVALUE] [varchar](4000) NULL, [WLG_RETURN_MSG] [text] NULL, [WLG_EXCEPTION] [varchar](500) NULL, [WLG_CREATION_DT] [datetime] NULL, [WLG_UPDATE_DT] [datetime] NULL, [WLG_CREATIONUID] [varchar](50) NULL, [WLG_UPDATEUID] [varchar](50) NULL, [WLG_NAME] [varchar](100) NULL, [WLG_RETURN_CODE] [varchar](20) NULL, [WLG_RETURN_MESSAGE] [varchar](200) NULL, [WLG_SOURCE] [varchar](20) NULL, CONSTRAINT [SWEBSERVICELOG_WECHAT_WLG_ID_pk_4] PRIMARY KEY CLUSTERED ( [WLG_ID] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON [PRIMARY] ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] GO
package cn.com.acxiom.coty.wechat.ws.filter; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.Date; import java.util.UUID; import java.util.regex.Pattern; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ReadListener; import javax.servlet.ServletException; import javax.servlet.ServletInputStream; import javax.servlet.ServletOutputStream; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.WriteListener; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponseWrapper; import cn.com.acxiom.coty.wechat.ws.bean.po.WebserviceLogWechat; import cn.com.acxiom.coty.wechat.ws.common.CONST; import cn.com.acxiom.coty.wechat.ws.common.ResponseBean; import cn.com.acxiom.coty.wechat.ws.common.UUID16; import cn.com.acxiom.coty.wechat.ws.mapper.WebserviceLogWechatMapper; import com.alibaba.fastjson.JSONObject; import org.apache.commons.io.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; @SuppressWarnings("ALL") @WebFilter @Component("logFilter") public class LogFilter implements Filter static InetAddress ia = null; static try ia = InetAddress.getLocalHost(); catch (UnknownHostException e) e.printStackTrace(); private static final Logger logger = LoggerFactory.getLogger(LogFilter.class); private static final String NOTLOGIN = "NOT LOGIN"; private static final String LOGIN_PATH = "/account"; @Autowired private WebserviceLogWechatMapper webLogMapper; @Value("$sys.name") private String sysName; private Pattern ignore = Pattern.compile(".*/webjars/.*$|.*/v2/.*$|.*/swagger.*$|.*/configuration/.*$|.*/images/.*|.*/farvirate.ico|.*/actuator.*"); static final Pattern BLANK = Pattern.compile("\\\\t|\\r|\\n"); @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException long startTime = System.currentTimeMillis(); /* 判断如果是swagger界面请求的一些资源就不会走日志 */ HttpServletRequest request = (HttpServletRequest) req; if ("option".equalsIgnoreCase(request.getMethod())) System.out.println("OPTION"); HttpServletResponse response = (HttpServletResponse) res; String requestId = null; if (StringUtils.isEmpty(request.getHeader("sid"))) requestId = UUID.randomUUID().toString().replace("-", ""); request.setAttribute("sid", requestId); else requestId = request.getHeader("sid"); request.setAttribute("sid", request.getHeader("sid")); response.addHeader("sid", requestId); String requestURL = request.getRequestURI(); if (ignore.matcher(requestURL).matches()) chain.doFilter(req, res); return; // 2、RequestBody读取 // 创建包装对象 LoggerHttpServletRequest wrappedRequest = new LoggerHttpServletRequest(request); // 读取参数 String content = IOUtils.toString(wrappedRequest.getInputStream()); // 重设参数 wrappedRequest.resetServletInputStream(); // 返回输出值 wrappedRequest.setAttribute("sid", requestId); OutputStream outputStream = res.getOutputStream(); LoggerHttpServletResponse wrapperResponse = new LoggerHttpServletResponse(response); chain.doFilter(wrappedRequest, wrapperResponse); long endTime = System.currentTimeMillis(); byte[] responseContent = wrapperResponse.getData(); String responseContext = null; String responseContentType = wrapperResponse.getContentType(); if (!StringUtils.isEmpty(responseContentType) && responseContentType.contains("image")) responseContext = "[image]"; else responseContext = new String(wrapperResponse.getData(), "UTF-8"); outputStream.write(responseContent); /* 插入接口参数捕获日志 */ try insertWebServiceInvokeLog(wrappedRequest, wrapperResponse, responseContext, content, startTime, endTime, requestId); catch (Exception e) // TODO Auto-generated catch block e.printStackTrace(); private void insertWebServiceInvokeLog(LoggerHttpServletRequest wrappedRequest, LoggerHttpServletResponse wrapperResponse, String responseBody, String requestBody, long beginTime, long endTime, String requestId) String httpMethod = wrappedRequest.getMethod(); String remoteHost = wrappedRequest.getRemoteHost(); String params = wrappedRequest.getQueryString(); String userAgent = wrappedRequest.getHeader("user-agent"); String requestPath = wrappedRequest.getServletPath(); String responseContentType = wrapperResponse.getContentType(); String apiName =wrapperResponse.getHeader(CONST.RESPONS_API_NAME_KEY); // 创建系统日志 WebserviceLogWechat webLog = new WebserviceLogWechat(); webLog.setWlgId(UUID16.uuid()); webLog.setWlgCreationuid(sysName); webLog.setWlgCreationDt(new Date()); webLog.setWlgUpdateDt(new Date()); webLog.setWlgUpdateuid(sysName); webLog.setWlgRemoteipaddr(remoteHost); webLog.setWlgRequesturl(requestPath); webLog.setWlgStartDt(new Date(beginTime)); webLog.setWlgEndDt(new Date(endTime)); webLog.setWlgMethod(httpMethod); webLog.setWlgName(apiName); webLog.setWlgParams(params); webLog.setWlgParamsvalue(requestBody); webLog.setWlgReturnMsg(responseBody); try if (!StringUtils.isEmpty(responseContentType) && !responseContentType.contains("image")) ResponseBean responseBean = JSONObject.parseObject(responseBody, ResponseBean.class); webLog.setWlgReturnMessage(responseBean.getMessage()); webLog.setWlgReturnCode(responseBean.getCode()); catch (Exception e) e.printStackTrace(); webLog.setWlgUseragent(userAgent); webLog.setWlgClienthost(String.format("%s:%s", ia.getHostName(), ia.getHostAddress())); webLog.setWlgSessionid(requestId); webLog.setWlgSource(sysName); try webLogMapper.insertSelective(webLog); catch (Exception e) e.printStackTrace(); logger.error("requestId:[] Save log to db with some error",requestId); logger.error("requestId:[] Save log to file, Log Data: ",requestId, JSONObject.toJSONString(webLog)); /** * 包装HttpServletRequest */ private static class LoggerHttpServletRequest extends HttpServletRequestWrapper private byte[] data; private HttpServletRequest request; private LoggerServletInputStream servletInputStream; public LoggerHttpServletRequest(HttpServletRequest request) super(request); this.request = request; servletInputStream = new LoggerServletInputStream(); public void resetServletInputStream() try servletInputStream.inputStream = new ByteArrayInputStream(new String(data).getBytes("UTF-8")); catch (UnsupportedEncodingException e) logger.error(e.getMessage()); @Override public ServletInputStream getInputStream() throws IOException if (data == null) data = IOUtils.toByteArray(this.request.getReader()); servletInputStream.inputStream = new ByteArrayInputStream(data); return servletInputStream; private class LoggerServletInputStream extends ServletInputStream private InputStream inputStream; @Override public int read() throws IOException return inputStream.read(); @Override public boolean isFinished() return false; @Override public boolean isReady() return false; @Override public void setReadListener(ReadListener listener) /** * 包装的HttpServletResponse类 * * @author jacwan */ private static class LoggerHttpServletResponse extends HttpServletResponseWrapper private ByteArrayOutputStream byteStream; public LoggerHttpServletResponse(HttpServletResponse response) super(response); byteStream = new ByteArrayOutputStream(); @Override public ServletOutputStream getOutputStream() return new LoggerServletOutputStream(byteStream); @Override public PrintWriter getWriter() throws IOException return new PrintWriter(getOutputStream(), false); public byte[] getData() return byteStream.toByteArray(); public class LoggerServletOutputStream extends ServletOutputStream private DataOutputStream dataOutputStream; public LoggerServletOutputStream(OutputStream output) dataOutputStream = new DataOutputStream(output); @Override public void write(int b) throws IOException dataOutputStream.write(b); @Override public void write(byte[] b) throws IOException dataOutputStream.write(b); @Override public void write(byte[] b, int off, int len) throws IOException dataOutputStream.write(b, off, len); @Override public boolean isReady() return false; @Override public void setWriteListener(WriteListener listener) @Override public void init(FilterConfig filterConfig) throws ServletException @Override public void destroy()
1. 需要注意的是: 实现的接口Filter是javax.servlet包中的,不是util.logger中的
2. 有时候需要在运行的main函数头上加上@ServletComponentScan,有时候不需要添加, @WebFilter的使用还要深入看下,如果在filter类的头上加上@Component("小写的filter类名"),就可以不用添加@ServletComponentScan
直接上测试代码
DemoApplication中
package com.example.demo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.ServletComponentScan; import org.springframework.cache.annotation.EnableCaching; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.transaction.annotation.EnableTransactionManagement; @SpringBootApplication @EnableCaching @EnableTransactionManagement @EnableAsync public class DemoApplication implements CommandLineRunner private static Logger logger = LoggerFactory.getLogger(DemoApplication.class); public static void main(String[] args) SpringApplication.run(DemoApplication.class, args); @Override public void run(String... args) throws Exception logger.info("started"); System.out.println("startedstartedstartedstartedstarted====");
ResponseBean
package com.example.demo.pojo; import com.example.demo.common.Message; import com.fasterxml.jackson.annotation.JsonIgnore; public class ResponseBean<T> @JsonIgnore public boolean ok() return this.code.equalsIgnoreCase(Message.SUCCESS_CODE); public ResponseBean() this.code = Message.SUCCESS_CODE; this.message = Message.SUCCESS_MESSAGE; public ResponseBean(T data) this.code = Message.SUCCESS_CODE; this.message = Message.SUCCESS_MESSAGE; this.data = data; private T data; private String code; private String message; public T getData() return data; public void setData(T data) this.data = data; public String getCode() return code; public void setCode(String code) this.code = code; public String getMessage() return message; public void setMessage(String message) this.message = message;
IndexController
package com.example.demo.controller; import com.example.demo.pojo.ResponseBean; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class IndexController @GetMapping("/index") public ResponseBean index() ResponseBean responseBean = new ResponseBean(); String info = "=========Welcome==========="; responseBean.setData(info); return responseBean;
Message
package com.example.demo.common; public class Message public static final String SUCCESS_CODE = "0000"; public static final String SUCCESS_MESSAGE = "success";
FilterDemo01
package com.example.demo.config; import org.springframework.context.annotation.ComponentScan; import org.springframework.stereotype.Component; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import java.io.IOException; @WebFilter @Component("filterDemo01") public class FilterDemo01 implements Filter public void init(FilterConfig filterConfig) throws ServletException System.out.println("----FilterDemo01过滤器初始化----"); public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException // 对request和response进行一些预处理 request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=UTF-8"); System.out.println("FilterDemo01执行前!!!"); chain.doFilter(request, response); // 让目标资源执行,放行 System.out.println("FilterDemo01执行后!!!"); public void destroy() System.out.println("----过滤器销毁----");
Rest0PubFilter
package com.example.demo.config; import org.springframework.context.annotation.ComponentScan; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import java.io.IOException; @WebFilter @Component //(urlPatterns = "/*", filterName = "rest0PubFilter") //@Order(1)//指定过滤器的执行顺序,值越大越靠后执行 public class Rest0PubFilter implements Filter @Override public void init(FilterConfig filterConfig) //初始化过滤器 System.out.println("getFilterName:"+filterConfig.getFilterName());//返回<filter-name>元素的设置值。 System.out.println("getServletContext:"+filterConfig.getServletContext());//返回FilterConfig对象中所包装的ServletContext对象的引用。 System.out.println("getInitParameter:"+filterConfig.getInitParameter("cacheTimeout"));//用于返回在web.xml文件中为Filter所设置的某个名称的初始化的参数值 System.out.println("getInitParameterNames:"+filterConfig.getInitParameterNames());//返回一个Enumeration集合对象。 @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException if(false) //response.sendRedirect("http://localhost:8081/demo/test/login");//重定向 System.out.println("=========="); filterChain.doFilter(servletRequest, servletResponse);//doFilter将请求转发给过滤器链下一个filter , 如果没有filter那就是你请求的资源 @Override public void destroy()
启动程序的时候
调用接口
以上是关于SpringBoot下,@WebFilter配置获取日志的主要内容,如果未能解决你的问题,请参考以下文章