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 | 第四章:日志配置(转)
前言 介于平时工作中,对于日志这块没有过多的接触,也就未有过多的了解.故在编写本文时,上官网查看了相关资料,奈何每个字母我都认识,但合起来就有点晕了,英文阅读水平还是有待大大的提高呀.最后觉得还是转载 ...
随机推荐
- Given a family tree, find out if two people are blood related
Given a family tree for a few generations for the entire population and two people write a routine t ...
- 【网络开发】UDP组播接收端解析
UDP组播接收端解析 网络中的一台主机如果希望能够接收到来自网络中其它主机发往某一个组播组的数据报,那么这么主机必须先加入该组播组,然后就可以从组地址接收数据包.在广域网中,还涉及到路由器支持组播路由 ...
- popup demo
Django下实现: urls.py: from django.conf.urls import url from django.contrib import admin from app01 imp ...
- 微信小程序,内容组件中兼容的H5组件
受信任的HTML节点及属性 全局支持class和style属性,不支持id属性. 节点 属性 a abbr address article aside b bdi bdo ...
- spring结合shiro的学习总结
pom文件加入 <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-c ...
- php 文字转换成拼音
<?php //中文字转拼音 $d=array( array("a",-20319), array("ai",-20317), array("a ...
- LeetCode 404. 左叶子之和(Sum of Left Leaves)
404. 左叶子之和 404. Sum of Left Leaves LeetCode404. Sum of Left Leaves 题目描述 计算给定二叉树的所有左叶子之和. 示例: 3 / \ 9 ...
- [转帖]再谈IO的异步,同步,阻塞和非阻塞
再谈IO的异步,同步,阻塞和非阻塞 https://yq.aliyun.com/articles/53674?spm=a2c4e.11155435.0.0.48bfe8efHUE8wg krypt ...
- 关于 Visual Studio 的代码度量值
查看方式:Visual Studio -> Analyze -> Calculate code metrics feature 代码度量(Code Metrics)是用来测量专业标准的软件 ...
- [SVN] - 使用 TortoiseSVN 进行文件比对非常慢 之 解决
背景 Windows 10 + TortoiseSVN-v1.9.7使用默认的 TortoiseMerge 进行文件比对,打开速度非常非常慢. 解决 禁用 TortoiseMerge / Settin ...