springboot在使用 Servlet API中提供的javax.servlet.Filter 过滤器 对请求参数 和 响应参数 进行获取并记录日志方案

不多说 直接上代码
第一步

package com.xxx.init.webFilter;import com.alibaba.fastjson.JSONObject;
import com.xxx.api.constant.CommonConstant;
import com.xxx.api.entities.log.OperationLog;
import com.xxx.init.utils.JwtHelper;
import com.xxx.init.utils.RequestUtils;
import com.xxx.init.utils.WlUtils;
import com.xxx.init.webFilter.jsonWrapper.JsonParameterRequestWrapper;import com.xxx.init.webFilter.jsonWrapper.ResponseWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.Order;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;/*** User:Json* Date: 2024/4/3* 日志操作**/
@WebFilter(urlPatterns = {"/*"}, filterName = "OperationLogFilter")
@Order(-100)
@Slf4j
public class OperationLogFilter implements Filter {@Value("${spring.application.name}")private String serviceName;@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {HttpServletRequest httpServletRequest = (HttpServletRequest) request;HttpServletResponse httpServletResponse = (HttpServletResponse) response;if ("GET".equals(httpServletRequest.getMethod())) {chain.doFilter(request, response);return;}// 在请求到达 Servlet 前执行的逻辑boolean isDownload = false;// 检查响应头信息String contentDescription = httpServletRequest.getHeader("content-description");String contentTransferEncoding = httpServletRequest.getHeader("content-transfer-encoding");if (!StringUtils.isEmpty(contentDescription) &&!StringUtils.isEmpty(contentTransferEncoding)) {isDownload = true; // 设置为 true,表示需要下载}OperationLog operationLog = new OperationLog();operationLog.setOrg_id(0);operationLog.setTime(LocalDateTime.now());operationLog.setMethod(httpServletRequest.getMethod());operationLog.setRouter(httpServletRequest.getRequestURI());operationLog.setProtocol(httpServletRequest.getProtocol());operationLog.setIp(httpServletRequest.getRemoteAddr());operationLog.setService_name(serviceName);//获取请求类型为 Json的 数据 如果是form-data 类型的数据 目前没获取JsonParameterRequestWrapper jsonParameterRequestWrapper = null;if (WlUtils.isJsonReq(httpServletRequest)) {jsonParameterRequestWrapper = new JsonParameterRequestWrapper(httpServletRequest);operationLog.setRequest_data(getRequestJson(jsonParameterRequestWrapper));}ResponseWrapper responseWrapper = new ResponseWrapper(httpServletResponse);if (jsonParameterRequestWrapper == null) {chain.doFilter(request, responseWrapper);} else {chain.doFilter(jsonParameterRequestWrapper, responseWrapper);}String s = new String(responseWrapper.getContent(), "UTF-8");operationLog.setResponse_code(responseWrapper.getStatus());operationLog.setResponse_data(isDownload ? "文件下载" : s);// 在得到响应的数据之后,response的输出流中就无可用的数据,所以需要巴数据放回去ServletOutputStream outputStream = response.getOutputStream();outputStream.write(responseWrapper.getContent());outputStream.flush();outputStream.close();}private JSONObject getRequestJson(JsonParameterRequestWrapper jsonParameterRequestWrapper) throws IOException {String bodyMessage = jsonParameterRequestWrapper.getBodyMessage();JSONObject jsonObject = JSONObject.parseObject(bodyMessage);return jsonObject;}@Overridepublic void destroy() {}
}

第二步:

package com.xxx.init.webFilter.jsonWrapper;import com.xxx.init.utils.StreamUtil;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
/*** User:Json* Date: 2024/4/7**/
public class JsonParameterRequestWrapper extends HttpServletRequestWrapper {//用于保存读取body中数据private  byte[] body;private String bodyMessage;public JsonParameterRequestWrapper(HttpServletRequest request) throws IOException {super(request);//读取请求的数据保存到本类当中body = StreamUtil.readBytes(request.getReader(), "UTF-8");bodyMessage =  new String(body,"utf-8");}//覆盖(重写)父类的方法@Overridepublic BufferedReader getReader() throws IOException {return new BufferedReader(new InputStreamReader(getInputStream()));}//覆盖(重写)父类的方法@Overridepublic ServletInputStream getInputStream() throws IOException {final ByteArrayInputStream bais = new ByteArrayInputStream(body);return new ServletInputStream() {@Overridepublic boolean isFinished() {return false;}@Overridepublic boolean isReady() {return false;}@Overridepublic void setReadListener(ReadListener readListener) {}@Overridepublic int read() throws IOException {return bais.read();}};}/*** 获取body中的数据* @return*/public byte[] getBody() {return body;}/*** 把处理后的参数放到body里面* @param body*/public void setBody(byte[] body) {this.body = body;}public String getBodyMessage() {return bodyMessage;}
}

第三步

package com.xxx.init.webFilter.jsonWrapper;import javax.servlet.ServletOutputStream;
import javax.servlet.WriteListener;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.*;
import java.nio.charset.StandardCharsets;/*** User:Json* Date: 2024/4/7**/
public class ResponseWrapper extends HttpServletResponseWrapper {private ByteArrayOutputStream byteArrayOutputStream;private ServletOutputStream servletOutputStream;/*** Constructs a response adaptor wrapping the given response.* @param response The response to be wrapped* @throws IllegalArgumentException if the response is null*/public ResponseWrapper(HttpServletResponse response) throws IOException {super(response);byteArrayOutputStream = new ByteArrayOutputStream();servletOutputStream = new MyServletOutputStream(byteArrayOutputStream);}@Overridepublic ServletOutputStream getOutputStream() throws IOException {return servletOutputStream;}@Overridepublic PrintWriter getWriter() throws IOException {return new PrintWriter(new OutputStreamWriter(byteArrayOutputStream, StandardCharsets.UTF_8));}@Overridepublic void flushBuffer() {if (servletOutputStream != null) {try {servletOutputStream.flush();} catch (IOException e) {e.printStackTrace();}}}public byte[] getContent() {flushBuffer();// response中的数据return byteArrayOutputStream.toByteArray();}class MyServletOutputStream extends ServletOutputStream {// 把response输出流中的数据写入字节流中private ByteArrayOutputStream byteArrayOutputStream;public MyServletOutputStream(ByteArrayOutputStream byteArrayOutputStream) {this.byteArrayOutputStream = byteArrayOutputStream;}@Overridepublic boolean isReady() {return false;}@Overridepublic void setWriteListener(WriteListener listener) {}@Overridepublic void write(int b) throws IOException {byteArrayOutputStream.write(b);}}
}

第五步:

package com.xxx.init.utils;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
/*** User:Json* Date: 2024/4/7**/
public class StreamUtil {public static byte[] readStream(InputStream stream,int length) throws IOException {byte[]streamData=null;List<Integer> lengths = new ArrayList<Integer>();List<byte[]> buffers = new ArrayList<byte[]>();int l = 0;  int totalLength = 0;  byte[] buffer = null; //while (totalLength < length && l != -1) { //buffer = new byte[length];l = stream.read(buffer);if (l != -1) {lengths.add(new Integer(l));buffers.add(buffer);totalLength+=l;}}if(totalLength==0) {return null;}l=0;streamData = new byte[totalLength];length =buffers.size();int blength=0;byte[] bbuffer=null;for (int i = 0; i < length; i++) {blength = ((Integer) lengths.get(i)).intValue();bbuffer = (byte[]) buffers.get(i);System.arraycopy(bbuffer, 0, streamData, l,blength);l=l+blength;}stream=null; lengths=null; buffers=null;	buffer=null;return streamData;}public static byte[] readBytes(BufferedReader bufferedReader, String charset) throws IOException{StringBuffer sb = new StringBuffer();String s;while ((s = bufferedReader.readLine()) != null) {sb.append(s);}if(sb.length() == 0){return "".getBytes(charset);}return sb.toString().getBytes(charset);}}

第六步:

package com.xxx.init.utils;import javax.servlet.http.HttpServletRequest;/*** User:Json* Date: 2024/4/7**/
public class WlUtils {/*** 判断是否是JSON请求* @param request* @return*/public static Boolean isJsonReq(HttpServletRequest request){String header = request.getHeader("content-type");return header != null && header.toLowerCase().contains("json");}
}

测试
在这里插入图片描述
完美收工

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/307348.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【数据结构】07查找

查找 1. 基本概念2. 顺序表查找2.1 顺序查找2.2 顺序查找优化-哨兵 3. 有序表查找3.1 折半查找&#xff08;二分查找&#xff09; 4. 分块查找&#xff08;索引顺序查找&#xff09;5. Hash表&#xff08;散列表&#xff09;5.1 散列函数的设计5.2 代码实现5.2.1 初始化Hash表5…

个人简历主页搭建系列-06:jqcv 简历主题安装

jqcv 介绍 大家好呀&#xff0c;前段时间我在忙毕设的事情&#xff0c;这段时间继续写这个专题。 我们之前网站已经成功搭建起来了对吧&#xff0c;但是这个样式明显和我们的简历需求不符合&#xff0c;难道我们要自己配置 css 文件一点点进行修改吗&#xff1f; 其实并不用…

无人机概述

1、中英文对照表 中文中文简称英文全称英文简称无人驾驶飞机无人机Unmanned Aerial VehicleUAV无人机自组织网络无人机网络flying Ad-Hoc networkFANET 2、相关概念 2.1鲁棒性 网络鲁棒性是指网络系统在面对随机故障、蓄意攻击或其他异常情况时&#xff0c;能够保持其基本功…

记一次http访问超时服务器端调试

问题&#xff1a;http访问服务器时没有返回&#xff0c;没有超时&#xff0c;一直在阻塞 处理过程&#xff1a;telnet端口能连上&#xff0c;服务端程序也不存在处理时间过长的情况。 说明tcp连接没问题。推测是客户端连接后再发起请求&#xff0c;服务端阻塞了。因为很多客户…

C++:类与对象(三)

目录 再谈构造函数 构造函数体赋值 初始化列表 explicit关键字 static成员 友元 友元函数 友元类 内部类 再次理解封装 再谈构造函数 首先要明白声明、定义、初始化三个概念的不同。 声明&#xff1a;指定变量的名字和类型&#xff0c;可以多次声明。 定义&#xf…

c++ 指针总结

概述 内存地址 在计算机内存中&#xff0c;每个存储单元都有一个唯一的地址(内存编号)。通俗理解&#xff0c;内存就是房间&#xff0c;地址就是门牌号 指针和指针变量 指针&#xff08;Pointer&#xff09;是一种特殊的变量类型&#xff0c;它用于存储内存地址。指针的实质…

【Python】面向对象(专版提升2)

面向对象 1. 概述1.1面向过程1.2 面向对象 2. 类和对象2.1 语法2.1.1 定义类2.1.2 实例化对象 2.2 实例成员2.2.1 实例变量2.2.2 实例方法2.2.3 跨类调用 3. 三大特征3.1 封装3.1.1 数据角度3.1.2 行为角度3.1.3 案例:信息管理系统3.1.3.1 需求3.1.3.2 分析3.1.3.3 设计 3.2 继…

有关格式输入输出的问题

对于格式输入输出问题&#xff0c;我们最好用c语言编写代码&#xff01;&#xff01;&#xff01; 成绩统计 难点&#xff1a;格式化输出 #include <cstdio> using namespace std; typedef long long ll;ll n,score,a,b;int main() {//及格>60 优秀>85 求及格率…

javaEE初阶——多线程(四)

T04BF &#x1f44b;专栏: 算法|JAVA|MySQL|C语言 &#x1faf5; 小比特 大梦想 此篇文章与大家分享多线程专题的第四篇(关于多线程代码案例中的单例模式) 如果有不足的或者错误的请您指出! 目录 九、多线程代码案例(单例模式)1.单例模式1.1饿汉模式1.2懒汉模式1.3使用场景1.4上…

【刷题】图论——最小生成树:Prim、Kruskal【模板】

假设有n个点m条边。 Prim适用于邻接矩阵存的稠密图&#xff0c;时间复杂度是 O ( n 2 ) O(n^2) O(n2)&#xff0c;可用堆优化成 O ( n l o g n ) O(nlogn) O(nlogn)。 Kruskal适用于稀疏图&#xff0c;n个点m条边&#xff0c;时间复杂度是 m l o g ( m ) mlog(m) mlog(m)。 Pr…

华媒舍:7种方式,打造出旅游媒体套餐

现如今&#xff0c;伴随着旅游业发展与繁荣&#xff0c;更多旅游业发展从业人员越来越重视产品营销品牌基本建设&#xff0c;希望可以将自己的度假旅游产品和服务营销推广给更多的潜在用户。而建立一个优秀的旅游业发展媒体套餐内容品牌是吸引目标客户的重要步骤。下面我们就详…

streamlit 大模型前段界面

结合 langchain 一起使用的工具&#xff0c;可以显示 web 界面 pip install streamlit duckduckgo-search 运行命令 streamlit run D:\Python_project\NLP\大模型学习\test.py import os from dotenv import load_dotenv from langchain_community.llms import Tongyi load…

Flutter仿Boss-6.底部tab切换

效果 实现 图片资源采用boss包中的动画webp资源。Flutter采用Image加载webp动画。 遇到的问题 问题&#xff1a;Flutter加载webp再次加载无法再次播放动画问题 看如下代码&#xff1a; Image.asset(assets/images/xxx.webp,width: 40.w,height: 30.w, )运行的效果&#xf…

图片过大怎么改小?图片尺寸在线修改的方法

在通过电子邮件或即时消息传递应用程序发送图片时&#xff0c;某些平台上传图片的时候经常遇到尺寸不符合的情况&#xff0c;通过在线修改图片尺寸&#xff0c;您可以调整图片的大小&#xff0c;以满足限制要求&#xff0c;并确保图片可以顺利地通过电子邮件或消息传递应用程序…

HarmonyOS4 页面路由

Index.ets: import router from ohos.routerclass RouterInfo {// 页面路径url: string// 页面标题title: stringconstructor(url: string, title: string) {this.url urlthis.title title} }Entry // 入口組件 Component struct Index {State message: string 页面列表// …

Selenium+Chrome Driver 爬取搜狐页面信息

进行selenium包和chromedriver驱动的安装 安装selenium包 在命令行或者anaconda prompt 中输入 pip install Selenium 安装 chromedriver 先查看chrome浏览器的版本 这里是 123.0.6312.106 版 然后在http://npm.taobao.org/mirrors/chromedriver/或者https://googlechrom…

【深度学习实战(2)】如何使用matplotlib.pyplot模块记录自己的训练,验证损失

一、matplotlib库 在我们自己训练模型时&#xff0c;常常会使用matplotlib库来绘制oss和accuracy的曲线图&#xff0c;帮助我们分析模型的训练表现。 matplotlib库安装&#xff1a;pip install matplotlib 二、代码 import matplotlib.pyplot as plt import torch import to…

2024年蓝桥杯40天打卡总结

2024蓝桥杯40天打卡总结 真题题解其它预估考点重点复习考点时间复杂度前缀和二分的两个模板字符串相关 String和StringBuilderArrayList HashSet HashMap相关蓝桥杯Java常用算法大数类BigInteger的存储与运算日期相关考点及函数质数最小公倍数和最大公约数排序库的使用栈Math类…

Redis系列之基于Linux单机安装

Redis 是一个开源的使用 ANSI C 语言编写、遵守 BSD 协议、支持网络、可基于内存、分布式、可选持久性的键值对(Key-Value)存储数据库&#xff0c;并提供多种语言的 API。最近学习需要用到Redis&#xff0c;所以就去Linux服务器上部署一个&#xff0c;做下记录&#xff0c;方便…

【网站项目】数学辅导微信小程序

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…