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;

    @Override
    public 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;
    }


    @Override
    public 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");
    }

    //覆盖(重写)父类的方法
    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(getInputStream()));
    }
    //覆盖(重写)父类的方法
    @Override
    public ServletInputStream getInputStream() throws IOException {
        final ByteArrayInputStream bais = new ByteArrayInputStream(body);
        return new ServletInputStream() {
            @Override
            public boolean isFinished() {
                return false;
            }

            @Override
            public boolean isReady() {
                return false;
            }

            @Override
            public void setReadListener(ReadListener readListener) {

            }

            @Override
            public 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);
    }

    @Override
    public ServletOutputStream getOutputStream() throws IOException {
        return servletOutputStream;
    }

    @Override
    public PrintWriter getWriter() throws IOException {
        return new PrintWriter(new OutputStreamWriter(byteArrayOutputStream, StandardCharsets.UTF_8));
    }

    @Override
    public 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;
        }

        @Override
        public boolean isReady() {
            return false;
        }

        @Override
        public void setWriteListener(WriteListener listener) {
        }

        @Override
        public 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");
    }
}

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

9.vector的使用介绍和模拟实现

1.vector的介绍及使用 1.1 vector的介绍 vector的文档介绍 vector是表示可变大小数组的序列容器。 就像数组一样&#xff0c;vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问&#xff0c;和数组一样高效。但是又不像数组&#xff0c…

【MATLAB源码-第18期】基于matlab的(2,1,7)卷积码硬判决和软判决误码率对比仿真

1、算法描述 **217卷积码原理**&#xff1a; 217卷积码是一种纠错编码技术&#xff0c;通常用于数字通信&#xff0c;特别是在误差严重的通信信道中。它的原理如下&#xff1a; 1. **生成多项式**&#xff1a;217卷积码由生成多项式定义。这些多项式决定了如何将输入数据转换…

月入过万的地推网推人,他们都在做这五款拉新项目

地推网推拉新平台哪几个靠谱&#xff1f;这一定是刚加入地推网推拉新行业的“萌新”们最关心的问题。毕竟知晓了这个问题的答案&#xff0c;就能够让自己的拉新之行少走弯路。 今天我们就带大家总结5个以“聚小推”为首的&#xff0c;常见的地推网推拉新平台&#xff0c;旨在科…

《QT实用小工具·二十》存款/贷款计算器

1、概述 源码放在文章末尾 该项目实现了用于存款和贷款的计算器的功能&#xff0c;如下图所示&#xff1a; 项目部分代码如下&#xff1a; #ifndef WIDGET_H #define WIDGET_H#include <QWidget>namespace Ui { class Widget; }class Widget : public QWidget {Q_OBJ…

libVLC 视频界面分割

先看看分割后的界面吧&#xff0c;根据分割的数量&#xff0c;来分割视频画面。 其实视频界面分割很简单&#xff0c;看过叠加窗口的这篇文章&#xff0c;不难理解&#xff0c;如何分割。 libVLC 视频窗口上叠加透明窗口-CSDN博客 如果还是不懂的话&#xff0c;我讲解一下原理…

信号完整性之哪来的串扰?

原文来自微信公众号&#xff1a;工程师看海&#xff0c;与我联系&#xff1a;chunhou0820 看海原创视频教程&#xff1a;《运放秘籍》 大家好&#xff0c;我是工程师看海。 我们经常听说PCB走线间距大于等于3倍线宽时可以抑制70%的信号间干扰&#xff0c;这就是3W原则&#…

EEPROM读写案例(以AT24C02为例)

本篇文章主要是在学习单片机串行接口时的学习经历&#xff0c;主要侧重于驱动程序的讲解。下文将通过ESP32S3、STM32两款MCU进行编写驱动案例。 1、AT24C02简要说明 AT24C02是美国微芯科技公司生产的电擦写式只读存储器系列中的一款&#xff0c;其容量为2K位&#xff08;即256字…

Google 推出 Gemini 1.5 Pro能处理音频;iOS 18或带来Safari 浏览助手;Llama 3 开源模型下个月推出

Google 推出 Gemini 1.5 Pro 公共预览版&#xff0c;能处理音频 Google 宣布将通过其 AI 应用平台 Vertex AI 向公众提供 Gemini 1.5 Pro&#xff0c;并且还赋予其「听力」&#xff0c;帮助用户处理音频内容。 用户可以上传会议录音、电视节目等音频内容&#xff0c;无需书面记…

Linux Shell:`alias`命令

Linux Shell&#xff1a;alias命令 alias命令是Linux和Unix系统中Shell的内置命令&#xff0c;用于创建命令的简短名称&#xff0c;即别名。这些别名通常用来缩短长命令或为常用命令序列创建便捷的缩写&#xff0c;从而提高工作效率。别名在当前Shell会话中有效&#xff0c;除…

【随笔】Git 高级篇 -- 整理提交记录(下)rebase -i(十六)

&#x1f48c; 所属专栏&#xff1a;【Git】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &#x1f496; 欢迎大…

快速生成二维码——Python QRCode库详解

&#x1f340; 前言 博客地址&#xff1a; CSDN&#xff1a;https://blog.csdn.net/powerbiubiu &#x1f44b; 简介 QRCode码是由日本于1994年9月研制的一种矩阵二维码符号&#xff0c;它具有一维条码及其它二维条码所具有的信息容量大、可靠性高、可表示汉字及图象多种文字…

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

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

学习大数据,所需要的java(Maven)基础(1)

文章目录 使用Maven的优势第三方jar包添加第三方jar包获取jar包之间的依赖关系jar包之间的冲突处理将项目拆分成多个工程模块 实现项目的分布式部署Maven是什么自动化构建工具构建的概念构建环节自动化构建 Maven如何使用安装Maven核心程序maven联网问题Maven中的settings配置在…

Spring整合Redis

在 Spring Boot 中整合、使用 Redis 2023-09-25 教程 &#x1f381;开发者新年礼物&#x1f193;免费领香港云服务器 12 个月 永久免费 CDN 服务 免费 VPS广告 Redis 是一款开源的&#xff0c;使用 C 开发的高性能内存 Key/Value 数据库&#xff0c;支持 String、Set、Has…

每日Bug汇总--Day04

Bug汇总—Day04 一、项目运行报错 二、项目运行Bug 1、**问题描述&#xff1a;**下拉框关联数据&#xff0c;选择下拉框数据后&#xff0c;联动输入框中的数据查询不到&#xff0c;在后台接收到的是null 原因分析&#xff1a; 前端是否正确接收到了参数’jishigonghao’(判…

【记录】Prompt模板|作为甲方怎么清晰专业地描述自己的需求(又名“乙方,给你的甲方扔个GPT解放自己吧”)

这篇Prompt摘抄并修改自朋友送给我的书的第49页5.2.3让ChatGPT构建提示&#xff0c;质量挺不错&#xff0c;支持一下她的博客&#xff1a;【好书推荐2】AI提示工程实战&#xff1a;从零开始利用提示工程学习应用大语言模型。 书长这样&#xff1a; 不啰嗦了&#xff0c;正文如…

取数游戏(dfs)

前言&#xff1a; 该题取自洛谷P1123&#xff0c;题主用的dfs&#xff08;深度优先搜索&#xff09; 题目描述&#xff1a; 数据范围&#xff1a; 思路&#xff1a; 思路见代码&#xff0c;注释的很清晰嗷 AC代码&#xff1a; #include <iostream> #include <alg…

经营稳健,李子园业绩稳步提升

4月9日&#xff0c;李子园发布2023年年度报告&#xff0c;披露了2023年业绩及经营数据。 单位&#xff1a;元 币种&#xff1a;人民币 2023年&#xff0c;李子园实现营业收入约14.1亿元&#xff0c;同比增长0.6%&#xff1b;实现归属于上市公司股东的扣非净利润约2.19亿元&am…

人工智能技术创业机会有哪些?

&#x1f482; 个人主页: 同学来啦&#x1f91f; 版权: 本文由【同学来啦】原创、在CSDN首发、需要转载请联系博主 &#x1f4ac; 如果文章对你有帮助&#xff0c;欢迎关注、点赞、收藏和订阅专栏哦 文章目录 &#x1f96d; 一、城市治理&#x1f34e; 二、社交创新&#x1f3…

Unity开发Android,关于StreamingAssets和持久化路径坑点

一、Android平台下&#xff0c;使用File去读取StreamingAssets目录下的文件无法读到 原因&#xff1a;在Android平台下&#xff0c;Unity打包出来的文件&#xff0c;StreamingAssets目录会被压缩成一个jar的包&#xff0c;因此使用File无法读取到路径。 解决&#xff1a;可以使…