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配置获取日志的更多相关文章
- SpringBoot下如何配置实现跨域请求?
一.什么是跨域请求? 跨域请求,就是说浏览器在执行脚本文件的ajax请求时,脚本文件所在的服务地址和请求的服务地址不一样.说白了就是ip.网络协议.端口都一样的时候,就是同一个域,否则就是跨域.这是由 ...
- springboot下slf4j配置
我们在引用的时候直接写 private static final Logger logger = LoggerFactory.getLogger(XXXServiceImpl.class); log. ...
- springboot下@webfilter的使用
启动类加了@ServletComponentScan,无论过滤器类加不加@Componment urlPatterns = {"/test/*"}都可以生效 单使用@Compone ...
- SpringBoot优雅地配置日志
本文主要给大家介绍SpringBoot中如何通过sl4j日志组件优雅地记录日志.其实,我们入门 JAVA 的第一行代码就是一行日志,那你现在还在使用System.out.println("H ...
- springboot 通过@WebFilter(urlPatterns )配置Filter过滤路径
springboot 通过@WebFilter(urlPatterns )配置Filter过滤路径,没有配置/*,输入任何路径都能进过滤器 2019年04月25日 12:51:33 peigui.hu ...
- SpringBoot下Druid连接池的使用配置
Druid是一个JDBC组件,druid 是阿里开源在 github 上面的数据库连接池,它包括三部分: * DruidDriver 代理Driver,能够提供基于Filter-Chain模式的插件体 ...
- JAVAEE——SpringBoot日志篇:日志框架SLF4j、日志配置、日志使用、切换日志框架
Spring Boot 日志篇 1.日志框架(故事引入) 小张:开发一个大型系统: 1.System.out.println(""):将关键数据打印在控制台:去掉?写在一个文件 ...
- Centos下Nginx配置WEB访问日志并结合shell脚本定时切割
在一个成熟的WEB系统里,没有日志管理是不可以的,有了日志,可以帮助你得到用户地域来源.跳转来源.使用终端.某个URL访问量等相关信息:通过错误日志,你可以得到系统某个服务或server的性能瓶颈等. ...
- SpringBoot | 第四章:日志配置(转)
前言 介于平时工作中,对于日志这块没有过多的接触,也就未有过多的了解.故在编写本文时,上官网查看了相关资料,奈何每个字母我都认识,但合起来就有点晕了,英文阅读水平还是有待大大的提高呀.最后觉得还是转载 ...
随机推荐
- 【Leetcode_easy】868. Binary Gap
problem 868. Binary Gap solution1: class Solution { public: int binaryGap(int N) { ; vector<int&g ...
- WXS --注释
- 《ucore lab5》实验报告
资源 ucore在线实验指导书 我的ucore实验代码 练习1: 加载应用程序并执行(需要编码) 题目 do_execv函数调用load_icode(位于kern/process/proc.c中) 来 ...
- java junit4-JUnit测试报 No socket available 错误
问题描述 JUnit测试报 No socket available 错误 Eclipse进行JUnit测试时,总弹出 No socket available 窗口,导致测试不能进行. 解决方案一: 打 ...
- [DevExpress] - 使得 XtraEditors.TextEdit 失去焦点(LostFocus)的方法
场景 WinForm 应用,使用了 DevExpress.XtraEditors.TextEdit 控件的 KeyPress 和 Leave 事件.期望在 TextEdit 上按下回车键或者当 Tex ...
- 创建线程的三种方式(Thread、Runnable、Callable)
方式一:继承Thread类实现多线程: 1. 在Java中负责实现线程功能的类是java.lang.Thread 类. 2. 可以通过创建 Thread的实例来创建新的线程. 3. 每个线程都是通过某 ...
- Linux基础-14-ssh服务、apache服务
1. ssh服务 ssh服务是一个守护进程(demon),系统后台监听客户端的连接,ssh服务端的进程名为sshd,负责实时监听客户端的请求(IP 22端口),包括公共秘钥等交换等信息. ssh服务端 ...
- PAT甲级题分类汇编——杂项
本文为PAT甲级分类汇编系列文章. 集合.散列.数学.算法,这几类的题目都比较少,放到一起讲. 题号 标题 分数 大意 类型 1063 Set Similarity 25 集合相似度 集合 1067 ...
- MySQL8.0新特性总览
1.消除了buffer pool mutex (Percona的贡献) 2.数据字典全部采用InnoDB引擎存储,支持DDL原子性.crash safe.metadata管理更完善(可以利用ibd2s ...
- webpack css文件编译、自动添加前缀、剥离
1.css文件编译 webpack默认只能编译js文件,引入css需要loader支持 // css文件写入js中 npm i style-loader -D // css文件loader npm i ...