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

测试

完美收工

相关推荐
【D'accumulation】1 小时前
令牌主动失效机制范例(利用redis)注释分析
java·spring boot·redis·后端
2401_854391081 小时前
高效开发:SpringBoot网上租赁系统实现细节
java·spring boot·后端
wxin_VXbishe1 小时前
springboot合肥师范学院实习实训管理系统-计算机毕业设计源码31290
java·spring boot·python·spring·servlet·django·php
OEC小胖胖2 小时前
Spring Boot + MyBatis 项目中常用注解详解(万字长篇解读)
java·spring boot·后端·spring·mybatis·web
2401_857617622 小时前
SpringBoot校园资料平台:开发与部署指南
java·spring boot·后端
quokka562 小时前
Springboot 整合 logback 日志框架
java·spring boot·logback
计算机学姐2 小时前
基于SpringBoot+Vue的在线投票系统
java·vue.js·spring boot·后端·学习·intellij-idea·mybatis
2401_854391083 小时前
Spring Boot大学生就业招聘系统的开发与部署
java·spring boot·后端
杨荧4 小时前
【JAVA开源】基于Vue和SpringBoot的洗衣店订单管理系统
java·开发语言·vue.js·spring boot·spring cloud·开源
2401_857610034 小时前
SpringBoot实现:校园资料分享平台开发指南
服务器·spring boot·php