亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

在SpringBoot框架中實現(xiàn)打印響應的日志

 更新時間:2024年05月22日 09:05:08   作者:小子寶丁  
這篇文章主要介紹了在SpringBoot框架中實現(xiàn)打印響應的日志,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

SpringBoot框架中打印響應的日志

在 Spring Boot 框架中,可以使用攔截器來打印響應的日志。

通過自定義一個攔截器,可以在響應返回給客戶端之前捕獲響應信息,并將其記錄到日志中。

以下是在 Spring Boot 框架中打印響應日志的步驟:

1.創(chuàng)建一個攔截器類并實現(xiàn)HandlerInterceptor接口

例如,您可以創(chuàng)建一個名為 ResponseLoggingInterceptor 的類。

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

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

public class ResponseLoggingInterceptor implements HandlerInterceptor {

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // 在響應返回給客戶端之后被調(diào)用
        // 記錄響應信息到日志
        String logMessage = "RESPONSE - " +
                "Status: " + response.getStatus() +
                " | Request URI: " + request.getRequestURI();
        // 使用日志框架打印日志,例如使用 SLF4J: LoggerFactory.getLogger(ResponseLoggingInterceptor.class).info(logMessage);
    }
}

在上面的示例中,我們在 postHandle 方法中記錄響應的狀態(tài)碼和請求的URI。

您可以根據(jù)需要擴展此方法,記錄更多的響應信息。

2.注冊攔截器

在您的配置類中,將攔截器注冊到 Spring Boot 應用程序中。

import org.springframework.context.annotation.Configuration;
   import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
   import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

   @Configuration
   public class WebConfig implements WebMvcConfigurer {

       @Override
       public void addInterceptors(InterceptorRegistry registry) {
           registry.addInterceptor(new ResponseLoggingInterceptor());
       }
   }

在上述示例中,我們實現(xiàn)了 WebMvcConfigurer 接口,并重寫了 addInterceptors 方法。

在該方法中,我們將自定義的攔截器 ResponseLoggingInterceptor 添加到攔截器注冊表中。

3.運行應用程序

現(xiàn)在,當您運行 Spring Boot 應用程序并發(fā)送請求時,攔截器將捕獲每個響應并將其記錄到日志中。

請注意:

  • 攔截器記錄的日志將在每個請求的響應之后生成。
  • 這意味著攔截器不會記錄在發(fā)生錯誤或異常時的響應。
  • 如果您需要記錄這些情況下的響應,您可能需要結合異常處理機制來實現(xiàn)。

SpringBoot日志打印的幾種方式

記錄一下springboot日志打印的三種方式,過濾器、攔截器、AOP

1.過濾器

創(chuàng)建LogFilter類實現(xiàn)Filter接口

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

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

@Component
public class LogFilter implements Filter {

    private static final Logger LOG = LoggerFactory.getLogger(LogFilter.class);

    @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;
        LOG.info("------------- LogFilter 開始 -------------");
        LOG.info("請求地址: {} {}", request.getRequestURL().toString(), request.getMethod());
        LOG.info("遠程地址: {}", request.getRemoteAddr());

        long startTime = System.currentTimeMillis();
        filterChain.doFilter(servletRequest, servletResponse);
        LOG.info("------------- LogFilter 結束 耗時:{} ms -------------", System.currentTimeMillis() - startTime);
    }
}

2.攔截器

(1)創(chuàng)建LogInterceptor類實現(xiàn)HandlerInterceptor接口

import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Component;
 import org.springframework.web.servlet.HandlerInterceptor;
 import org.springframework.web.servlet.ModelAndView;

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

 /**
  * 攔截器:Spring框架特有的,常用于登錄校驗,權限校驗,請求日志打印 /login
  */
 @Component
 public class LogInterceptor implements HandlerInterceptor {

     private static final Logger LOG = LoggerFactory.getLogger(LogInterceptor.class);

     @Override
     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
         // 打印請求信息
         LOG.info("------------- LogInterceptor 開始 -------------");
         LOG.info("請求地址: {} {}", request.getRequestURL().toString(), request.getMethod());
         LOG.info("遠程地址: {}", request.getRemoteAddr());

         long startTime = System.currentTimeMillis();
         request.setAttribute("requestStartTime", startTime);
         return true;
     }

     @Override
     public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
         long startTime = (Long) request.getAttribute("requestStartTime");
         LOG.info("------------- LogInterceptor 結束 耗時:{} ms -------------", System.currentTimeMillis() - startTime);
     }
 }

(2)創(chuàng)建SpringMvcConfig配置類實現(xiàn)WebMvcConfigurer接口,將上述類注冊到配置類中

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import javax.annotation.Resource;

@Configuration
public class SpringMvcConfig implements WebMvcConfigurer {

    @Resource
    LogInterceptor logInterceptor;

    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(logInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns();
    }

}

3.AOP

(1)打開pom.xml,添加AOP依賴

		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

(2)添加fastjson依賴,對于本代碼來說是必須的,因為本代碼在使用AOP時想要排除敏感字段,需要fastjson下的JSONObject。如果只是單純的使用AOP是不需要這個依賴的

		<dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.70</version>
        </dependency>

(3)創(chuàng)建LogAspect類

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.support.spring.PropertyPreFilters;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

@Aspect
@Component
public class LogAspect {

    private final static Logger LOG = LoggerFactory.getLogger(LogAspect.class);

    /** 定義一個切點 */
    @Pointcut("execution(public * com.jiawa.*.controller..*Controller.*(..))")
    public void controllerPointcut() {}

    @Before("controllerPointcut()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {

        // 開始打印請求日志
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        Signature signature = joinPoint.getSignature();
        String name = signature.getName();

        // 打印請求信息
        LOG.info("------------- 開始 -------------");
        LOG.info("請求地址: {} {}", request.getRequestURL().toString(), request.getMethod());
        LOG.info("類名方法: {}.{}", signature.getDeclaringTypeName(), name);
        LOG.info("遠程地址: {}", request.getRemoteAddr());

        // 打印請求參數(shù)
        Object[] args = joinPoint.getArgs();
		// LOG.info("請求參數(shù): {}", JSONObject.toJSONString(args));

		Object[] arguments  = new Object[args.length];
        for (int i = 0; i < args.length; i++) {
            if (args[i] instanceof ServletRequest
                    || args[i] instanceof ServletResponse
                    || args[i] instanceof MultipartFile) {
                continue;
            }
            arguments[i] = args[i];
        }
        // 排除字段,敏感字段或太長的字段不顯示
        String[] excludeProperties = {"password", "file"};
        PropertyPreFilters filters = new PropertyPreFilters();
        PropertyPreFilters.MySimplePropertyPreFilter excludefilter = filters.addFilter();
        excludefilter.addExcludes(excludeProperties);
        LOG.info("請求參數(shù): {}", JSONObject.toJSONString(arguments, excludefilter));
    }

    @Around("controllerPointcut()")
    public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();

//        執(zhí)行業(yè)務
        Object result = proceedingJoinPoint.proceed();

        // 排除字段,敏感字段或太長的字段不顯示
        String[] excludeProperties = {"password", "file"};
        PropertyPreFilters filters = new PropertyPreFilters();
        PropertyPreFilters.MySimplePropertyPreFilter excludefilter = filters.addFilter();
        excludefilter.addExcludes(excludeProperties);
        LOG.info("返回結果: {}", JSONObject.toJSONString(result, excludefilter));
        LOG.info("------------- 結束 耗時:{} ms -------------", System.currentTimeMillis() - startTime);
        return result;
    }

    /**
     * 使用nginx做反向代理,需要用該方法才能取到真實的遠程IP
     * @param request
     * @return
     */
    public String getRemoteIp(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

}

總結

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。 

相關文章

  • jpa異常No entity found for query問題解決

    jpa異常No entity found for query問題解決

    這篇文章主要為大家介紹了jpa異常之No entity found for query的異常問題解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步
    2022-03-03
  • java線程池實戰(zhàn)應用步驟詳解

    java線程池實戰(zhàn)應用步驟詳解

    這篇文章主要介紹了java線程池實戰(zhàn)應用小結,包括線程池的創(chuàng)建方式,本文給大家分享兩種方式,結合實例代碼給大家介紹的非常詳細,需要的朋友參考下吧
    2025-04-04
  • 詳解如何通過Java實現(xiàn)壓縮PDF文檔

    詳解如何通過Java實現(xiàn)壓縮PDF文檔

    PDF文檔是我們?nèi)粘^k公中使用最頻繁的文檔格式。但因為大多數(shù)PDF文檔都包含很多頁面圖像或大量圖片,這就導致PDF文檔過大,處理起來較為麻煩。本文將介紹如何通過Java應用程序壓縮PDF文檔,需要的可以了解一下
    2022-12-12
  • Java 順序表專題解讀

    Java 順序表專題解讀

    順序表,全名順序存儲結構,是線性表的一種。線性表用于存儲邏輯關系為“一對一”的數(shù)據(jù),順序表自然也不例外,不僅如此,順序表對數(shù)據(jù)物理存儲結構也有要求。順序表存儲數(shù)據(jù)時,會提前申請一整塊足夠大小的物理空間,然后將數(shù)據(jù)依次存儲起來,存儲時數(shù)據(jù)元素間不留縫隙
    2021-11-11
  • MyBatisPlus+Lombok實現(xiàn)分頁功能的方法詳解

    MyBatisPlus+Lombok實現(xiàn)分頁功能的方法詳解

    Lombok是一個Java類庫,提供了一組注解,簡化POJO實體類開發(fā)。本文將為大家介紹一下Lombok的使用以及如何利用MyBatisPlus+Lombok實現(xiàn)分頁功能,感興趣的可以動手嘗試一下
    2022-07-07
  • 如何使用Spring Security手動驗證用戶的方法示例

    如何使用Spring Security手動驗證用戶的方法示例

    這篇文章主要介紹了如何使用Spring Security手動驗證用戶的方法示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-05-05
  • 基于java中BlockingQueue的使用介紹

    基于java中BlockingQueue的使用介紹

    本篇文章小編為大家介紹,基于java中BlockingQueue的使用介紹。需要的朋友參考下
    2013-04-04
  • Java中的注解和反射實例詳解

    Java中的注解和反射實例詳解

    這篇文章主要給大家介紹了關于Java中注解和反射的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-03-03
  • Java異常處理操作實例小結

    Java異常處理操作實例小結

    這篇文章主要介紹了Java異常處理操作,結合實例形式總結分析了java異常處理常見操作情況與相關處理技巧,需要的朋友可以參考下
    2019-07-07
  • java 數(shù)據(jù)結構 冒泡排序?qū)崿F(xiàn)代碼

    java 數(shù)據(jù)結構 冒泡排序?qū)崿F(xiàn)代碼

    這篇文章主要介紹了java 數(shù)據(jù)結構 冒泡排序的相關資料,并附實例代碼,有需要的小伙伴可以參考下
    2016-09-09

最新評論