最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Springboot如何利用攔截器攔截請求信息收集到日志詳解

 更新時間:2021年08月12日 10:55:26   作者:Leil_blogs  
一些系統(tǒng)經常需要關注用戶請求的具體信息,如用戶信息、請求參數(shù)、響應結果等等,在SpringBoot應用中可通過攔截器的方式統(tǒng)一處理,下面這篇文章主要給大家介紹了關于Springboot如何利用攔截器攔截請求信息收集到日志的相關資料,需要的朋友可以參考下

1、需求

最近在工作中遇到的一個需求,將請求中的客戶端類型、操作系統(tǒng)類型、ip、port、請求方式、URI以及請求參數(shù)值收集到日志中,網上找資料說用攔截器攔截所有請求然后收集信息,于是就開始了操作:

2、問題

試了之后發(fā)現(xiàn)當請求方式為POST,前端發(fā)送數(shù)據(jù)json時只能用request.getReader()流獲取,自信滿滿從流中獲取之后發(fā)現(xiàn)請求之后報錯:

getInputStream() has already been called for this request...

于是網上找答案,發(fā)現(xiàn)是ServletRequest的getReader()和getInputStream()兩個方法只能被調用一次,而且不能兩個都調用。那么如果Filter中調用了一次,在Controller里面就不能再調用了。

然后又開始找解決方法,說既然ServletInputStream不支持重新讀寫,就把流讀出來后用容器存儲起來,后面就可以多次利用了。

于是繼承 HttpServletRequestWrapper類(http請求包裝器,其基于裝飾者模式實現(xiàn)了HttpServletRequest界面)并實現(xiàn)想要重新定義的方法以達到包裝原生HttpServletRequest對象。還需要在過濾器里將原生的HttpServletRequest對象替換成我們的RequestWrapper對象。

測試發(fā)現(xiàn)POST請求參數(shù)值可以在攔截器類中獲取到了,本以為大功告成,又發(fā)現(xiàn)GET請求不好使了,開始報錯Stream closed,一頓操作發(fā)現(xiàn)需要在過濾器進行判斷,如果是POST請求走自己的繼承的HttpServletRequestWrapper類請求,否則走普通的請求。終于成功!突然舒服了。

2、獲取

1)導入依賴為了獲取客戶端類型、操作系統(tǒng)類型、ip、port

<dependency>
            <groupId>eu.bitwalker</groupId>
            <artifactId>UserAgentUtils</artifactId>
            <version>1.21</version>
</dependency>

2)封裝獲取body字符串的工具類

package com.btrc.access.util;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;

public class RequestUtil {
    public static String getBodyString(HttpServletRequest request) {
        StringBuilder sb = new StringBuilder();
        try (
                InputStream inputStream = request.getInputStream();
               BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")))
        ) {
            String line;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return sb.toString();
    }
}

3)攔截器類

package com.btrc.access.filter;

import com.btrc.access.util.RequestUtil;
import eu.bitwalker.useragentutils.UserAgent;
import org.apache.commons.lang.StringUtils;
import org.springframework.http.HttpMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 請求攔截器:攔截請求目的是將請求的信息收集到日志
 */
public class RequestInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("user-agent"));
        //客戶端類型
        String clientType = userAgent.getOperatingSystem().getDeviceType().getName();
        //客戶端操作系統(tǒng)類型
        String osType = userAgent.getOperatingSystem().getName();
        //客戶端ip
        String clientIp = request.getRemoteAddr();
        //客戶端port
        int clientPort = request.getRemotePort();
        //請求方式
        String requestMethod = request.getMethod();
        //客戶端請求URI
        String requestURI = request.getRequestURI();
        //客戶端請求參數(shù)值
        String requestParam;
        //如果請求是POST獲取body字符串,否則GET的話用request.getQueryString()獲取參數(shù)值
        if(StringUtils.equalsIgnoreCase(HttpMethod.POST.name(), requestMethod)){
            requestParam = RequestUtil.getBodyString(request);
        }else{
            requestParam = request.getQueryString();
        }
        //客戶端整體請求信息
        StringBuilder clientInfo = new StringBuilder();
        clientInfo.append("客戶端信息:[類型:").append(clientType)
                .append(", 操作系統(tǒng)類型:").append(osType)
                .append(", ip:").append(clientIp)
                .append(", port:").append(clientPort)
                .append(", 請求方式:").append(requestMethod)
                .append(", URI:").append(requestURI)
                .append(", 請求參數(shù)值:").append(requestParam.replaceAll("\\s*", ""))
                .append("]");
        
        //***這里的clientInfo就是所有信息了,請根據(jù)自己的日志框架進行收集***
        System.out.println(clientInfo);
        
		//返回ture才會繼續(xù)執(zhí)行,否則一直攔截住
        return true;
    }
}

4)繼承 HttpServletRequestWrapper類

package com.btrc.access.filter;

import com.btrc.access.util.RequestUtil;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
import java.nio.charset.Charset;

public class AccessRequestWrapper extends HttpServletRequestWrapper {
    private final byte[] body;

    public AccessRequestWrapper(HttpServletRequest request) {
        super(request);
        body = RequestUtil.getBodyString(request).getBytes(Charset.forName("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 int read() throws IOException {
                return bais.read();
            }

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

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

            @Override
            public void setReadListener(ReadListener readListener) {

            }
        };
    }
}

5)過濾器類

package com.btrc.access.filter;

import org.apache.commons.lang.StringUtils;
import org.springframework.http.HttpMethod;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class AccessFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        //如果是POST走自己的繼承的HttpServletRequestWrapper類請求,否則走正常的請求
        if(StringUtils.equalsIgnoreCase(HttpMethod.POST.name(), request.getMethod())){
            //一定要在判斷中new對象,否則還會出現(xiàn)Stream closed問題
            filterChain.doFilter(new AccessRequestWrapper(request),servletResponse);
        }else{
            filterChain.doFilter(servletRequest,servletResponse);
        }
    }

    @Override
    public void destroy() {

    }
}

6)攔截器過濾器配置類

package com.btrc.access.config;

import com.btrc.access.filter.AccessFilter;
import com.btrc.access.filter.RequestInterceptor;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import javax.servlet.Filter;

/**
 * 攔截器過濾器配置類
 */
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Bean
    public FilterRegistrationBean httpServletRequestReplacedFilter() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(new AccessFilter());
        // /* 是全部的請求攔截,和Interceptor的攔截地址/**區(qū)別開
        registration.addUrlPatterns("/*");
        registration.setName("accessRequestFilter");
        registration.setOrder(1);
        return registration;
    }


    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new RequestInterceptor()).addPathPatterns("/**");
    }
}

總結

到此這篇關于Springboot如何利用攔截器攔截請求信息收集到日志的文章就介紹到這了,更多相關Springboot攔截請求信息到日志內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • JVM工作原理和工作流程簡述

    JVM工作原理和工作流程簡述

    這篇文章主要介紹了關于JVM工作原理簡述,主要弄清楚jvm運行的來龍去脈,感興趣的可以一起來了解一下
    2020-07-07
  • Java中空指針異常該如何避免詳解

    Java中空指針異常該如何避免詳解

    空指針(Null Pointer Exception,NPE)是Java中最常見不過的異常了,其原因雖然顯而易見,但是開發(fā)人員往往會忽略,或未能及時采取措施,下面這篇文章主要給大家介紹了關于Java中空指針異常該如何避免的相關資料,需要的朋友可以參考下
    2022-03-03
  • Jenkins自動部署Net Core過程圖解

    Jenkins自動部署Net Core過程圖解

    這篇文章主要介紹了Jenkins自動部署Net Core過程圖解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-12-12
  • Spring Boot 與 mybatis配置方法

    Spring Boot 與 mybatis配置方法

    這篇文章主要介紹了Spring Boot 與 mybatis配置方法,需要的朋友可以參考下
    2017-06-06
  • MyBatis在SQL語句中如何獲取list的大小

    MyBatis在SQL語句中如何獲取list的大小

    這篇文章主要介紹了MyBatis在SQL語句中如何獲取list的大小問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • SpringBoot2.0如何自定義404頁面渲染

    SpringBoot2.0如何自定義404頁面渲染

    這篇文章主要介紹了SpringBoot2.0如何自定義404頁面渲染問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • Java如何獲取當前進程ID以及所有Java進程的進程ID

    Java如何獲取當前進程ID以及所有Java進程的進程ID

    本篇文章主要介紹了Java如何獲取當前進程ID以及所有Java進程的進程ID,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • 幾句話說清session,cookie和token的區(qū)別及說明

    幾句話說清session,cookie和token的區(qū)別及說明

    這篇文章主要介紹了幾句話說清session,cookie和token的區(qū)別及說明,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • mybatis中批量更新多個字段的2種實現(xiàn)方法

    mybatis中批量更新多個字段的2種實現(xiàn)方法

    當我們使用mybatis的時候,可能經常會碰到一批數(shù)據(jù)的批量更新問題,因為如果一條數(shù)據(jù)一更新,那每一條數(shù)據(jù)就需要涉及到一次數(shù)據(jù)庫的操作,本文主要介紹了mybatis中批量更新多個字段的2種實現(xiàn)方法,感興趣的可以了解一下
    2023-09-09
  • java對于目錄下文件的單詞查找操作代碼實現(xiàn)

    java對于目錄下文件的單詞查找操作代碼實現(xiàn)

    這篇文章主要介紹了java對于目錄下文件的單詞查找操作代碼實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-11-11

最新評論

哈尔滨市| 彭阳县| 方山县| 沙雅县| 丽江市| 麦盖提县| 儋州市| 肇东市| 青海省| 太白县| 青岛市| 长寿区| 金平| 樟树市| 凤庆县| 化州市| 伊吾县| 乐至县| 新晃| 宁德市| 长宁县| 东城区| 大余县| 兴山县| 绵阳市| 苍溪县| 宜都市| 安乡县| 子洲县| 泸水县| 当雄县| 铜陵市| 南昌县| 铁岭县| 谢通门县| 灵武市| 蓝山县| 沅陵县| 定西市| 呈贡县| 鄄城县|