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

不多说 直接上代码

第一步

java 复制代码
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() {

    }
}

第二步:

java 复制代码
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;
    }
}

第三步

java 复制代码
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);
        }
    }
}

第五步:

java 复制代码
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);
    }

}

第六步:

java 复制代码
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");
    }
}

测试

完美收工

相关推荐
愿你天黑有灯下雨有伞1 分钟前
Spring Boot集成RabbitMQ高级篇:可靠性与性能提升
spring boot·rabbitmq·java-rabbitmq
yyf9601261 小时前
hiveserver2与beeline进行远程连接hive配置及遇到的问题
数据仓库·hive
yyf9601262 小时前
hive在配置文件中添加了hive.metastore.uris之后进入hive输入命令报错
hive
曼岛_2 小时前
[Java实战]Spring Boot 整合 Redis(十八)
java·spring boot·redis
jiedaodezhuti3 小时前
hive两个表不同数据类型字段关联引发的数据倾斜
数据仓库·hive·hadoop
IvanCodes3 小时前
五、Hive表类型、分区及数据加载
大数据·数据仓库·hive
cainiao0806054 小时前
《Spring Boot 4.0新特性深度解析》
java·spring boot·后端
呆萌很4 小时前
基于 Spring Boot 瑞吉外卖系统开发(十二)
spring boot
计算机学姐5 小时前
基于SpringBoot的小区停车位管理系统
java·vue.js·spring boot·后端·mysql·spring·maven
小鸡脚来咯5 小时前
请求参数:Header 参数,Body 参数,Path 参数,Query 参数分别是什么意思,什么样的,分别通过哪个注解获取其中的信息
java·spring boot·后端