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

spring boot如何使用AOP統(tǒng)一處理web請求

 更新時(shí)間:2019年12月02日 10:43:27   作者:慕塵  
這篇文章主要介紹了spring boot如何使用AOP統(tǒng)一處理web請求,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

為了保證服務(wù)的高可用,及時(shí)發(fā)現(xiàn)問題,迅速解決問題,為應(yīng)用添加log是必不可少的。

但是隨著項(xiàng)目的增大,方法增多,每個(gè)方法加單獨(dú)加日志處理會有很多冗余

那在SpringBoot項(xiàng)目中如何統(tǒng)一的處理Web請求日志?

基本思想:

采用AOP的方式,攔截請求,寫入日志

AOP 是面向切面的編程,就是在運(yùn)行期通過動(dòng)態(tài)代理的方式對代碼進(jìn)行增強(qiáng)處理

基于AOP不會破壞原來程序邏輯,因此它可以很好的對業(yè)務(wù)邏輯的各個(gè)部分進(jìn)行隔離,從而使得業(yè)務(wù)邏輯各部分之間的耦合度降低,提高程序的可重用性,同時(shí)提高了開發(fā)的效率。

1.添加依賴

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

引入spring-boot-starter-web 依賴之后無需在引入相關(guān)的日志依賴,spring-boot-starter-web中已經(jīng)集成了slf4j 的依賴

引入spring-boot-starter-aop 依賴之后,AOP 的功能即是啟動(dòng)狀態(tài)

2.配置

application.properties添加

# AOP
spring.aop.auto=true
spring.aop.proxy-target-class=true

logback-spring.xml,主要是ControllerRequest那部分

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">

  <property name="log.path" value="logs" />

  <!--0. 日志格式和顏色渲染 -->
  <!-- 彩色日志依賴的渲染類 -->
  <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
  <conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
  <conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
  <!-- 彩色日志格式 -->
  <property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>

  <!--1. 輸出到控制臺-->
  <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
    <!--此日志appender是為開發(fā)使用,只配置最底級別,控制臺輸出的日志級別是大于或等于此級別的日志信息-->
    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
      <level>info</level>
    </filter>
    <encoder>
      <Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
      <!-- 設(shè)置字符集 -->
      <charset>UTF-8</charset>
    </encoder>
  </appender>

  <!--2. 輸出到文檔-->
  <!-- 2.1 level為 DEBUG 日志,時(shí)間滾動(dòng)輸出 -->
  <appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <!-- 正在記錄的日志文檔的路徑及文檔名 -->
    <file>${log.path}/debug/debug.log</file>
    <!--日志文檔輸出格式-->
    <encoder>
      <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
      <charset>UTF-8</charset> <!-- 設(shè)置字符集 -->
    </encoder>
    <!-- 日志記錄器的滾動(dòng)策略,按日期,按大小記錄 -->
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
      <!-- 日志歸檔 -->
      <fileNamePattern>${log.path}/debug/debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
      <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
        <maxFileSize>100MB</maxFileSize>
      </timeBasedFileNamingAndTriggeringPolicy>
      <!--日志文檔保留天數(shù)-->
      <maxHistory>15</maxHistory>
    </rollingPolicy>
    <!-- 此日志文檔只記錄debug級別的 -->
    <filter class="ch.qos.logback.classic.filter.LevelFilter">
      <level>debug</level>
      <onMatch>ACCEPT</onMatch>
      <onMismatch>DENY</onMismatch>
    </filter>
  </appender>

  <!-- 2.2 level為 INFO 日志,時(shí)間滾動(dòng)輸出 -->
  <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <!-- 正在記錄的日志文檔的路徑及文檔名 -->
    <file>${log.path}/info/info.log</file>
    <!--日志文檔輸出格式-->
    <encoder>
      <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
      <charset>UTF-8</charset>
    </encoder>
    <!-- 日志記錄器的滾動(dòng)策略,按日期,按大小記錄 -->
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
      <!-- 每天日志歸檔路徑以及格式 -->
      <fileNamePattern>${log.path}/info/info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
      <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
        <maxFileSize>100MB</maxFileSize>
      </timeBasedFileNamingAndTriggeringPolicy>
      <!--日志文檔保留天數(shù)-->
      <maxHistory>15</maxHistory>
    </rollingPolicy>
    <!-- 此日志文檔只記錄info級別的 -->
    <filter class="ch.qos.logback.classic.filter.LevelFilter">
      <level>info</level>
      <onMatch>ACCEPT</onMatch>
      <onMismatch>DENY</onMismatch>
    </filter>
  </appender>

  <!-- 2.3 level為 WARN 日志,時(shí)間滾動(dòng)輸出 -->
  <appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <!-- 正在記錄的日志文檔的路徑及文檔名 -->
    <file>${log.path}/warn/warn.log</file>
    <!--日志文檔輸出格式-->
    <encoder>
      <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
      <charset>UTF-8</charset> <!-- 此處設(shè)置字符集 -->
    </encoder>
    <!-- 日志記錄器的滾動(dòng)策略,按日期,按大小記錄 -->
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
      <fileNamePattern>${log.path}/warn/warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
      <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
        <maxFileSize>100MB</maxFileSize>
      </timeBasedFileNamingAndTriggeringPolicy>
      <!--日志文檔保留天數(shù)-->
      <maxHistory>15</maxHistory>
    </rollingPolicy>
    <!-- 此日志文檔只記錄warn級別的 -->
    <filter class="ch.qos.logback.classic.filter.LevelFilter">
      <level>warn</level>
      <onMatch>ACCEPT</onMatch>
      <onMismatch>DENY</onMismatch>
    </filter>
  </appender>

  <!-- 2.4 level為 ERROR 日志,時(shí)間滾動(dòng)輸出 -->
  <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <!-- 正在記錄的日志文檔的路徑及文檔名 -->
    <file>${log.path}/error/error.log</file>
    <!--日志文檔輸出格式-->
    <encoder>
      <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
      <charset>UTF-8</charset> <!-- 此處設(shè)置字符集 -->
    </encoder>
    <!-- 日志記錄器的滾動(dòng)策略,按日期,按大小記錄 -->
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
      <fileNamePattern>${log.path}/error/error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
      <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
        <maxFileSize>100MB</maxFileSize>
      </timeBasedFileNamingAndTriggeringPolicy>
      <!--日志文檔保留天數(shù)-->
      <maxHistory>15</maxHistory>
    </rollingPolicy>
    <!-- 此日志文檔只記錄ERROR級別的 -->
    <filter class="ch.qos.logback.classic.filter.LevelFilter">
      <level>ERROR</level>
      <onMatch>ACCEPT</onMatch>
      <onMismatch>DENY</onMismatch>
    </filter>
  </appender>

  <springProfile name="dev">
    <root level="info">
      <appender-ref ref="CONSOLE" />
      <appender-ref ref="DEBUG_FILE" />
      <appender-ref ref="INFO_FILE" />
      <appender-ref ref="WARN_FILE" />
      <appender-ref ref="ERROR_FILE" />
    </root>
  </springProfile>

  <springProfile name="prod">
    <root level="info">
      <appender-ref ref="DEBUG_FILE" />
      <appender-ref ref="INFO_FILE" />
      <appender-ref ref="WARN_FILE" />
      <appender-ref ref="ERROR_FILE" />
    </root>
  </springProfile>

  <appender name="ControllerRequest" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>${log.path}/request/info.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
      <FileNamePattern>${log.path}/request/info.log.%d{yyyy-MM-dd}</FileNamePattern>
      <maxHistory>30</maxHistory>
    </rollingPolicy>
    <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
      <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
    </encoder>
  </appender>

  <logger name="ControllerRequest" level="DEBUG" additivity="false">
    <appender-ref ref="ControllerRequest"/>
  </logger>

</configuration>

3..實(shí)現(xiàn)

實(shí)現(xiàn)切面的注解

(1)類注解

A. @Aspect 將一個(gè)java類定義為切面類

B. @order(i) 標(biāo)記切面類的處理優(yōu)先級,i值越小,優(yōu)先級別越高。可以注解類,也能注解到方法上

(2)方法注解

A. @Pointcut 定義一個(gè)切入點(diǎn),可以是一個(gè)表達(dá)式

execution表達(dá)式,eg:

任意公共方法的執(zhí)行
execution(public * *(..)) 

任何一個(gè)以“set”開始的方法的執(zhí)行
execution(* set*(..)) 

定義在controller包里的任意方法的執(zhí)行
execution(public * com.example.demo.controller.*(..)) 

定義在controller包里的任意方法的執(zhí)行
execution(public * com.example.demo.controller.*.*(..)) 

定義在controller包和所有子包里的任意類的任意方法的執(zhí)行
execution(public * com.example.demo.controller..*.*(..))

B. 實(shí)現(xiàn)在不同的位置切入

  • @Before 在切點(diǎn)前執(zhí)行方法,內(nèi)容為指定的切點(diǎn)
  • @After 在切點(diǎn)后,return前執(zhí)行
  • @AfterReturning 切入點(diǎn)在 return內(nèi)容之后(可用作處理返回值)
  • @Around 切入點(diǎn)在前后切入內(nèi)容,并自己控制何時(shí)執(zhí)行切入的內(nèi)容
  • @AfterThrowing 處理當(dāng)切入部分拋出異常后的邏輯

C.@order(i) 標(biāo)記切點(diǎn)的優(yōu)先級,i越小,優(yōu)先級越高

@order(i)注解說明

注解類,i值是,值越小,優(yōu)先級越高

注解方法,分兩種情況

注解的是 @Before 是i值越小,優(yōu)先級越高

注解的是 @After或@AfterReturning 中,i值越大,優(yōu)先級越高

具體實(shí)現(xiàn)

package com.example.demo.configure;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.util.HashMap;
import java.util.Map;

@Aspect
@Component
public class WebRequestLogAspect {

  private final Logger loggerController = LoggerFactory.getLogger("ControllerRequest");
  private final Logger logger = LoggerFactory.getLogger(WebRequestLogAspect.class);
  ThreadLocal<Long> startTime = new ThreadLocal<>();
  ThreadLocal<String> beanName = new ThreadLocal<>();
  ThreadLocal<String> user = new ThreadLocal<>();
  ThreadLocal<String> methodName = new ThreadLocal<>();
  ThreadLocal<String> params = new ThreadLocal<>();
  ThreadLocal<String> remoteAddr = new ThreadLocal<>();
  ThreadLocal<String> uri = new ThreadLocal<>();

  private static Map<String, Object> getFieldsName(ProceedingJoinPoint joinPoint) {
    // 參數(shù)值
    Object[] args = joinPoint.getArgs();
    ParameterNameDiscoverer pnd = new DefaultParameterNameDiscoverer();
    MethodSignature signature = (MethodSignature) joinPoint.getSignature();
    Method method = signature.getMethod();
    String[] parameterNames = pnd.getParameterNames(method);
    Map<String, Object> paramMap = new HashMap<>(32);
    for (int i = 0; i < parameterNames.length; i++) {
      paramMap.put(parameterNames[i], args[i] + "(" + args[i].getClass().getSimpleName() + ")");
    }
    return paramMap;
  }

  @Pointcut("execution(public * com.example.demo.controller..*.*(..))")
  public void webRequestLog() {
  }

  /**
   * 前置通知,方法調(diào)用前被調(diào)用
   * @param joinPoint
   */
  @Before("webRequestLog()")
  public void doBefore(JoinPoint joinPoint) {
    try {
      startTime.set(System.currentTimeMillis());
      // 接收到請求,記錄請求內(nèi)容
      ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
      HttpServletRequest request = attributes.getRequest();
      beanName.set(joinPoint.getSignature().getDeclaringTypeName());
      methodName.set(joinPoint.getSignature().getName());
      uri.set(request.getRequestURI());
      remoteAddr.set(getIpAddr(request));
      user.set((String) request.getSession().getAttribute("user"));
    } catch (Exception e) {
      logger.error("***操作請求日志記錄失敗doBefore()***", e);
    }
  }

  /**
   * 環(huán)繞通知,環(huán)繞增強(qiáng),相當(dāng)于MethodInterceptor
   * @param thisJoinPoint
   */
  @Around("webRequestLog()")
  public Object proceed(ProceedingJoinPoint thisJoinPoint) throws Throwable {
    Object object = thisJoinPoint.proceed();
    Map<String, Object> fieldsName = getFieldsName(thisJoinPoint);
    params.set(fieldsName.toString());
    return object;
  }

  /**
   * 處理完請求返回內(nèi)容
   * @param result
   */
  @AfterReturning(returning = "result", pointcut = "webRequestLog()")
  public void doAfterReturning(Object result) {
    try {
      long requestTime = (System.currentTimeMillis() - startTime.get()) / 1000;
      loggerController.info("請求耗時(shí):" + requestTime + ", uri=" + uri.get() + "; beanName=" + beanName.get() + "; remoteAddr=" + remoteAddr.get() + "; user=" + user.get()
          + "; methodName=" + methodName.get() + "; params=" + params.get() + "; RESPONSE : " + result);

    } catch (Exception e) {
      logger.error("***操作請求日志記錄失敗doAfterReturning()***", e);
    }
  }

  /**
   * 獲取登錄用戶遠(yuǎn)程主機(jī)ip地址
   *
   * @param request
   * @return
   */
  private String getIpAddr(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();
      if (ip.equals("127.0.0.1") || ip.equals("0:0:0:0:0:0:0:1")) {
        //根據(jù)網(wǎng)卡取本機(jī)配置的IP
        InetAddress inet = null;
        try {
          inet = InetAddress.getLocalHost();
        } catch (Exception e) {
          e.printStackTrace();
        }
        ip = inet.getHostAddress();
      }
    }
    // 多個(gè)代理的情況,第一個(gè)IP為客戶端真實(shí)IP,多個(gè)IP按照','分割
    if (ip != null && ip.length() > 15) {
      if (ip.indexOf(",") > 0) {
        ip = ip.substring(0, ip.indexOf(","));
      }
    }
    return ip;
  }
}

4.測試類

package com.example.demo.controller;

import com.alibaba.fastjson.JSONObject;
import com.example.demo.dao.UserRepository;
import com.example.demo.domain.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
@RestController
public class Demo {
  @RequestMapping (value = "test1")
  public String test1(@RequestParam(defaultValue = "0") Integer id,@RequestParam(defaultValue = "0")String name){
    return id+name;
  }
  @RequestMapping("hello")
  public String hello() {
    return "Hello World!";
  }
  @PostMapping("/updateStatus")
  public Object updateStatus(@RequestBody JSONObject jsonParam) {

    return jsonParam;
  }
}

輸出到logs/request/info.log內(nèi)容

2019-09-11 13:31:45.729 [http-nio-8080-exec-4] INFO ControllerRequest - 請求耗時(shí):0, uri=/test1; beanName=com.example.demo.controller.Demo; remoteAddr=172.27.0.17; user=null; methodName=test1; params={name=abcdef(String), id=123(Integer)}; RESPONSE : 123abcdef
2019-09-11 13:32:16.692 [http-nio-8080-exec-5] INFO ControllerRequest - 請求耗時(shí):0, uri=/updateStatus; beanName=com.example.demo.controller.Demo; remoteAddr=172.27.0.17; user=null; methodName=updateStatus; params={jsonParam={"id":"17","type":3,"status":2}(JSONObject)}; RESPONSE : {"id":"17","type":3,"status":2}
2019-09-11 13:33:32.584 [http-nio-8080-exec-7] INFO ControllerRequest - 請求耗時(shí):0, uri=/hello; beanName=com.example.demo.controller.Demo; remoteAddr=172.27.0.17; user=null; methodName=hello; params={}; RESPONSE : Hello World!

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • SpringBoot2中使用@RequestHeader獲取請求頭的方法

    SpringBoot2中使用@RequestHeader獲取請求頭的方法

    springMVC/SpringBoot中提供了@RequestHeader注解用來獲取請求頭。本文就詳細(xì)的來介紹一下如何使用,感興趣的可以了解下
    2021-10-10
  • java 數(shù)據(jù)類型有哪些取值范圍多少

    java 數(shù)據(jù)類型有哪些取值范圍多少

    這篇文章主要介紹了java 數(shù)據(jù)類型有哪些取值范圍多少的相關(guān)資料,網(wǎng)上關(guān)于java 數(shù)據(jù)類型的資料有很多,不夠全面,這里就整理下,需要的朋友可以參考下
    2017-01-01
  • 淺談spring注解之@profile

    淺談spring注解之@profile

    這篇文章主要介紹了淺談spring注解之@profile,@profile通過配置來改變參數(shù),這里整理的詳細(xì)的用法,有興趣的可以了解一下
    2017-10-10
  • springboot對接微信支付的完整流程(附前后端代碼)

    springboot對接微信支付的完整流程(附前后端代碼)

    最近在做支付平臺的項(xiàng)目,承接公司業(yè)務(wù)系統(tǒng)與第三方支付平臺的對接任務(wù),主要涉及微信支付、支付寶支付以及理房通支付等第三方平臺,這篇文章主要給大家介紹了關(guān)于springboot對接微信支付的完整流程,需要的朋友可以參考下
    2021-08-08
  • java實(shí)現(xiàn)上傳文件到FTP

    java實(shí)現(xiàn)上傳文件到FTP

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)上傳文件到FTP,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • 如何實(shí)現(xiàn)Spring?Event(異步事件)

    如何實(shí)現(xiàn)Spring?Event(異步事件)

    這篇文章主要介紹了如何實(shí)現(xiàn)Spring?Event(異步事件)問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • MyBatis?和?jeesite多表查詢示例詳解

    MyBatis?和?jeesite多表查詢示例詳解

    這篇文章主要介紹了MyBatis?和?jeesite多表查詢,本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-04-04
  • Java9中接口的私有方法詳解

    Java9中接口的私有方法詳解

    印象中Java?接口就沒有論述私有方法這回事。既然?Java?9?添加了這項(xiàng)特性,那么,應(yīng)該就有它的用途,我們一起來看看?Java?9?中的接口的私有方法是什么樣的吧
    2023-04-04
  • 基于servlet實(shí)現(xiàn)統(tǒng)計(jì)網(wǎng)頁訪問次數(shù)

    基于servlet實(shí)現(xiàn)統(tǒng)計(jì)網(wǎng)頁訪問次數(shù)

    這篇文章主要為大家詳細(xì)介紹了基于servlet實(shí)現(xiàn)統(tǒng)計(jì)網(wǎng)頁訪問次數(shù),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • Java中的Feign深入分析

    Java中的Feign深入分析

    這篇文章主要介紹了Java中的Feign深入分析,Feign是一個(gè)用于發(fā)送HTTP請求的工具,它的主要作用是在不同的服務(wù)之間傳遞Token,為了使用Feign,你需要在項(xiàng)目中配置一個(gè)Feign的配置類,需要的朋友可以參考下
    2023-09-09

最新評論

墨玉县| 甘谷县| 宿州市| 望城县| 石泉县| 四平市| 南宁市| 新营市| 明水县| 团风县| 电白县| 乡城县| 玉山县| 石棉县| 西和县| 呼图壁县| 进贤县| 吴堡县| 峨边| 秦皇岛市| 大连市| 汪清县| 漳州市| 离岛区| 唐海县| 古浪县| 梁山县| 开原市| 扎兰屯市| 郎溪县| 寿阳县| 玉田县| 蕲春县| 延长县| 玉林市| 临安市| 安阳县| 商都县| 台南市| 咸宁市| 独山县|