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.mzph.cn/news/808517.shtml

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

相关文章

antd+Vue 3实现table行内upload文件图片上传【超详细图解】

目录 一、背景 二、效果图 三、代码 一、背景 一名被组长逼着干前端的苦逼后端&#xff0c;在一个晴天霹雳的日子&#xff0c;被要求前端订单产品实现上传产品图片并立刻回显图片。 二、效果图 三、代码 <template><a-table :dataSource"dataSource" :c…

如何使用固定公网地址SSH远程访问本地内网openEuler系统

文章目录 1. 本地SSH连接测试2. openEuler安装Cpolar3. 配置 SSH公网地址4. 公网远程SSH连接5. 固定连接SSH公网地址6. SSH固定地址连接测试 欧拉操作系统(openEuler, 简称“欧拉”)是面向数字基础设施的操作系统,支持服务器、云计算、边缘openEuler是面向数字基础设施的操作系…

【图论】Dijkstra单源最短路径-朴素方法-简单模板(迪杰斯特拉算法)

Dijkstra单源最短路径 问题描述 输入n 表示n个结点&#xff0c;m表示m条边&#xff0c;求编号1的结点到每个点的最短路径 输出从第一个点到第n个点的最短路径 思路 将图g[][]中所有的权值初始化为0x3f表示正无穷 将dist[]中所有的值初始化为0x3f表示从第一个点到所有点的距离…

NX/UG二次开发—CAM—一些外挂刀路选择方案对比

在做一刀轨编辑工具时&#xff0c;大家希望实现类似NX刀轨编辑中选择刀路的功能&#xff0c;以下我罗列了几种目前外挂里使用的几种方式&#xff0c;自己也做了一些对比&#xff1a; 涉及一些运算时间&#xff0c;参考电脑配置(内存32G&#xff0c;CPUi9-12950HX) 1、刀路转成…

PCB封装库的创建及引入

法1 1.创建lib 2.放置 找到你想要画的封装的器件的数据手册了解相关信息。 直插式选Multi-layer 贴片选Top-layer 焊盘尺寸 焊盘空尺寸 法2 嘉立创eda直接copy 再嘉立创中找到你想要的pcb&#xff0c;导出为ad 然后再ad中找到我们导出的文件 复制他 然后再库中粘贴 pcb库…

sky光遇加速器推荐 steam光遇低延迟稳定的加速器推荐

在光遇游戏中&#xff0c;子民指的就是游戏中的人影&#xff0c;玩家在游戏里面需要找到蓝色人影并触碰它&#xff0c;然后跟随光点&#xff0c;这样的话我们就可以看到一个深灰色的石像&#xff0c;点燃石像上的火苗&#xff0c;它就会教我们一个新的互动姿势。玩家找到黄色人…

Python中Python-docx 包的run介绍

先对run做一个简单地介绍。每个paragraph对象都包含一个run对象的列表。举例&#xff1a; 这是一个简短的段落。 from docx import Document doc Document("1.docx") #上面这段话保存在1.docx中 print("这一段的run个数是&#xff1a;",len(doc.paragr…

《一》Qt的概述

1.1 什么是Qt Qt是一个跨平台的C图形用户界面应用程序框架。它为应用程序开发者提供建立图形界面所需的所有功能。它是完全面向对象的&#xff0c;很容易扩展&#xff0c;并且允许真正的组件编程。 1.2 Qt的发展史 1991年 Qt最早由芬兰奇趣科技开发 1996年 进入商业领域&#x…

未来课堂革命:OpenAI 发布 ChatGPT 使用指南,探索生成式 AI 如何重塑教育景观

随着新学期的来临&#xff0c;众多初登教师舞台的 00 后们&#xff0c;也完成了他们的第一个教师身份下的暑期生活。 对于开学的抵触情绪&#xff0c;不仅学生们普遍存在&#xff0c;许多 00 后的新晋教师们也同样感同身受。某种程度上&#xff0c;这些抗拒上班的年轻教师群体…

Mac上的最佳3D建模工具-犀牛Rhinoceros 8 for Mac v8.6.24101.05002完美兼容激活

Rhino 8是一款计算机辅助设计&#xff08;CAD&#xff09;和三维建模软件&#xff0c;由美国公司McNeel & Associates开发。它是Rhino系列的最新版本&#xff0c;用于创建、编辑、分析、渲染和动画三维模型。 以下是Rhino 8的一些主要特点和功能&#xff1a; 1. **强大的…

Spring Boot与Vue联手打造智能化学生选课平台

末尾获取源码作者介绍&#xff1a;大厂全栈码农|毕设实战开发&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。 更多项目&#xff1a;CSDN主页YAML墨韵 学如逆水行舟&#xff0c;不进则退。学习如赶路&#xff0c;不能慢一步。 目录 一、项目简介 二、开发技术与…

Scaffold-GS 代码阅读笔记

1. 系统启动部分 使用 python 中的 parser 库 为配置系统的参数设定, 和3DGS 类似&#xff0c;并且使用safe_state(args.quiet) 函数 为每一次的 log 输出加上对应的 时间戳 ## 配置参数的设定lp ModelParams(parser)op OptimizationParams(parser)pp PipelineParams(pars…

分布式向量数据库-安装部署

下载 GitHub - pgvector/pgvector: Open-source vector similarity search for Postgres 源码编译 ##文件解压缩 unzip pgvector-0.6.2.zip ##编译 make && make install 功能验证 #安装扩展CREATE EXTENSION vector;#创建测试表CREATE TABLE items (id bigseri…

【算法】哈希表

个人主页 &#xff1a; zxctscl 如有转载请先通知 题目 1. 1. 两数之和1.1 分析1.2 代码 2. 面试题 01.02. 判定是否互为字符重排2.1 分析2.2 代码 3. 217. 存在重复元素3.1 分析3.2 代码 4. 219. 存在重复元素 II4.1 分析4.2 代码 5. 49. 字母异位词分组5.1 分析5.2 代码 1. 1…

Gateway的简单介绍和使用

1、Gateway简介&#xff1a; Gateway 是一种 API 网关&#xff08;API Gateway&#xff09;技术&#xff0c;它作为微服务架构中的关键组件&#xff0c;负责为系统的外部请求与内部服务之间提供统一的接入点。Spring Cloud Gateway 是基于 Spring 生态系统实现的一个高性能、易…

2024.4.11

1.思维导图 2.指针形式验证大小端存储 #include<myhead.h>int main(int argc, const char *argv[]) {int num 0x12345678;char* ptr (char *)&num;if(*ptr 0x12){printf("big endian\n");}else if(*ptr 0x78){printf("little endian\n");}r…

MINI2440 开发板 给他干出来了

环境是ubuntu14.04。不要问我为什么是这个版本&#xff0c;因为之前的ubuntu12.04 环境干不出来&#xff0c;你去试试就知道了&#xff01;各种资源包下载不下来。 输入启动参数&#xff1a; 进入MINI2440&#xff1a;别说心里一万个开心&#xff0c;启动完成&#xff0c;输入p…

【电子通识】热风枪的结构与使用方法

热风枪的结构 热风枪是专门用来拆焊、焊接贴片元器件和贴片集成电路的焊接工具&#xff0c;它主要由主机和热风焊枪两大部分构成。 热风枪主要有电源开关、风速设置、温度设置、热风连接等部件组成。根据不同品牌和价位的热风枪&#xff0c;有一些功能齐全的也集成了烙铁功能。…

负荷预测 | Matlab基于TCN-LSTM-Attention单输入单输出时间序列多步预测

目录 效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.负荷预测 | Matlab基于TCN-LSTM-Attention单输入单输出时间序列多步预测&#xff1b; 2.单变量时间序列数据集&#xff0c;采用前12个时刻预测未来96个时刻的数据&#xff1b; 3.excel数据方便替换&#xff0c;运行…

【鸿蒙开发】系统组件Column

Column组件 Column沿垂直方向布局的容器。 接口&#xff1a; Column(value?: {space?: string | number}) 参数&#xff1a; 参数名 参数类型 必填 参数描述 space string | number 否 纵向布局元素垂直方向间距。 从API version 9开始&#xff0c;space为负数或者…