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

如何使用java agent修改字節(jié)碼并在springboot啟動(dòng)時(shí)自動(dòng)生效

 更新時(shí)間:2024年10月26日 14:07:09   作者:gyx_ruarua  
本文介紹了JavaAgent的使用方法和在SpringBoot中的應(yīng)用,JavaAgent可以通過(guò)修改類的字節(jié)碼,實(shí)現(xiàn)對(duì)非Spring容器管理對(duì)象的AOP處理,演示了如何定義切面邏輯,實(shí)現(xiàn)接口mock,感興趣的朋友跟隨小編一起看看吧

       在java開(kāi)發(fā)的過(guò)程中,我們經(jīng)常遇到一些需要對(duì)某個(gè)方法做切面的需求,通常做法是使用spring提供的AOP功能,對(duì)方法做切面,例如方法出入?yún)⒋蛴。涌趍ock等等。但很多時(shí)候,需要切面的方法是非spring容器管理的類,例如需要對(duì)okhttp、apacheHttpClient請(qǐng)求做mock,判斷http請(qǐng)求的參數(shù)、url為某個(gè)值時(shí),返回測(cè)試結(jié)果,例如請(qǐng)求參數(shù)中包含userName=tester,返回code=200。這種使用可以使用java Agent,通過(guò)java agent修改類的字節(jié)碼,實(shí)現(xiàn)對(duì)非spring容器管理對(duì)象的aop處理。但是使用javaAgent后,啟動(dòng)時(shí)需要添加參數(shù)-javaagent:xxx.jar,使用方還需要下載對(duì)象的jar到本地,使用起來(lái)略顯麻煩。proxy-sdk就是為了解決這個(gè)問(wèn)題,通過(guò)maven、gradle依賴工具直接引入jar依賴即可,然后添加你的切面邏輯,springboot服務(wù)啟動(dòng)即可生效。

GitHub - YingXinGuo95/proxy-agent: java agent with springboot

按照github上的README的指引我們引入jar包,從maven的中央倉(cāng)庫(kù)下載依賴。

<dependency>
  <groupId>io.github.yingxinguo95</groupId>
  <artifactId>proxy-sdk</artifactId>
  <version>0.0.1</version>
  <!-- 0.0.1拉取不到可以試試0.0.1-RELEASE -->
  <!--<version>0.0.1-RELEASE</version>-->
</dependency>

配置需要代理方法配置和定義我們自己的需要重寫(xiě)邏輯,例如我們需要apache httpclient的請(qǐng)求方法,實(shí)現(xiàn)接口mock,判斷當(dāng)請(qǐng)求某個(gè)地址時(shí)返回測(cè)試數(shù)據(jù),而不是真的請(qǐng)求對(duì)方。

 例如以下代碼,前置重寫(xiě)httpClient的execute方法,當(dāng)請(qǐng)求baidu.com時(shí)就返回測(cè)試的json數(shù)據(jù){\"code\":\"200\", \"msg\":\"mock data\"}

import io.github.proxy.annotation.ProxyRecodeCfg;
import io.github.proxy.annotation.ReCodeType;
import io.github.proxy.service.ProxyReCode;
import lombok.SneakyThrows;
import org.apache.http.*;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.entity.BasicHttpEntity;
import org.apache.http.message.BasicHttpResponse;
import org.apache.http.message.BasicStatusLine;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Component;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Locale;
/**
 * 重寫(xiě)apacheHttp請(qǐng)求處理邏輯,實(shí)現(xiàn)mock功能
 */
@Component
public class MockApacheHttpReCoder implements ProxyReCode {
    @SneakyThrows
    @ProxyRecodeCfg(proxyClassName="org.apache.http.impl.client.CloseableHttpClient", method="execute", type = ReCodeType.BEFORE)
    public static CloseableHttpResponse executeProxy1(HttpUriRequest request, HttpContext context) {
        String path = request.getURI().toString();
        if (request instanceof HttpEntityEnclosingRequestBase) {
            //post請(qǐng)求讀取body
            HttpEntity entity = ((HttpEntityEnclosingRequestBase)request).getEntity();
            if (entity == null) {
                return null;
            }
            String reqBody = EntityUtils.toString(entity, StandardCharsets.UTF_8);
        }
        if (path.startsWith("http://baidu.com")) {
            return buildMockResponse("{\"code\":\"200\", \"msg\":\"mock data\"}", null);
        }
        return null;
    }
    @SneakyThrows
    @ProxyRecodeCfg(proxyClassName="org.apache.http.impl.client.CloseableHttpClient", method="execute", type = ReCodeType.BEFORE)
    public static CloseableHttpResponse executeProxy2(HttpHost target, HttpRequest request, HttpContext context) {
        String path = request.getRequestLine().getUri();
        if (request instanceof HttpEntityEnclosingRequestBase) {
            //post請(qǐng)求讀取body
            HttpEntity entity = ((HttpEntityEnclosingRequestBase)request).getEntity();
            if (entity == null) {
                return null;
            }
            String reqBody = EntityUtils.toString(entity, StandardCharsets.UTF_8);
        }
        if (path.startsWith("http://baidu.com")) {
            return buildMockResponse("{\"code\":\"200\", \"msg\":\"mock返回\"}", null);
        }
        return null;
    }
    public static CloseableHttpResponse buildMockResponse(String mockValue, Header[] headers) {
        ProtocolVersion protocolVersion = new ProtocolVersion("HTTP", 1, 1);
        String reasonPhrase = "OK";
        StatusLine statusline = new BasicStatusLine(protocolVersion, HttpStatus.SC_OK, reasonPhrase);
        MockCloseableHttpResponse mockResponse = new MockCloseableHttpResponse(statusline);
        BasicHttpEntity entity = new BasicHttpEntity();
        InputStream inputStream = new ByteArrayInputStream(mockValue.getBytes());
        entity.setContent(inputStream);
        entity.setContentLength(mockValue.length());
        entity.setChunked(false);
        mockResponse.setEntity(entity);
        if (headers != null) {
            mockResponse.setHeaders(headers);
        }
        return mockResponse;
    }
    public static class MockCloseableHttpResponse extends BasicHttpResponse implements CloseableHttpResponse {
        public MockCloseableHttpResponse(StatusLine statusline, ReasonPhraseCatalog catalog, Locale locale) {
            super(statusline, catalog, locale);
        }
        public MockCloseableHttpResponse(StatusLine statusline) {
            super(statusline);
        }
        public MockCloseableHttpResponse(ProtocolVersion ver, int code, String reason) {
            super(ver, code, reason);
        }
        @Override
        public void close() throws IOException {
        }
    }
}

我們?cè)趕pringBoot啟動(dòng)后請(qǐng)求試試

@SpringBootApplication
public class AppMain {
    @SneakyThrows
    public static void main(String[] args) {
        SpringApplication.run(AppMain.class, args);
        //創(chuàng)建HttpClient對(duì)象
        CloseableHttpClient httpClient = HttpClients.createDefault();
        //創(chuàng)建請(qǐng)求對(duì)象
        HttpGet httpGet = new HttpGet("http://baidu.com");
        //發(fā)送請(qǐng)求,請(qǐng)求響應(yīng)結(jié)果
        CloseableHttpResponse response = httpClient.execute(httpGet);
        //獲取服務(wù)器返回的狀態(tài)碼
        int statusCode = response.getStatusLine().getStatusCode();
        System.out.println(">>>>>>>>>服務(wù)端返回成功的狀態(tài)碼為:"+statusCode);
        HttpEntity entity = response.getEntity();
        String body = EntityUtils.toString(entity);
        System.out.println(">>>>>>>>>服務(wù)端返回的數(shù)據(jù)為:"+body);
        //關(guān)閉資源
        response.close();
        httpClient.close();
    }
}

啟動(dòng)服務(wù),在控制臺(tái)可以看到打印了對(duì)org.apache.http.impl.client.CloseableHttpClient類做字節(jié)碼重寫(xiě)

[Attach Listener] INFO  i.g.p.transformer.ReCoderTransformer -[proxy-agent] rewrite class:[org.apache.http.impl.client.CloseableHttpClient]
[Attach Listener] INFO  io.github.proxy.AgentMain -[proxy-agent] redefine loaded class complete, cost:171ms

springboot啟動(dòng)后請(qǐng)求baidu.com,得到結(jié)果,順利得到了我們需要的測(cè)試數(shù)據(jù)

我們調(diào)整下代碼,new HttpGet("http://zhihu.com"),換一個(gè)請(qǐng)求地址,然后發(fā)起請(qǐng)求

執(zhí)行了httpClient的原始邏輯,請(qǐng)求zhihu.com拿到了響應(yīng)。

簡(jiǎn)單試驗(yàn)就到這里了,其他用法可以按照github上readme指引試驗(yàn)一下。覺(jué)的這個(gè)小工具不錯(cuò)小伙伴可以點(diǎn)個(gè)star~

到此這篇關(guān)于使用java agent修改字節(jié)碼,并在springboot啟動(dòng)時(shí)自動(dòng)生效的文章就介紹到這了,更多相關(guān)java agent修改字節(jié)碼內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 淺談Java8 的foreach跳出循環(huán)break/return

    淺談Java8 的foreach跳出循環(huán)break/return

    這篇文章主要介紹了Java8 的foreach跳出循環(huán)break/return,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Java基礎(chǔ)之構(gòu)造器、代碼塊、類加載時(shí)機(jī)的用法詳解

    Java基礎(chǔ)之構(gòu)造器、代碼塊、類加載時(shí)機(jī)的用法詳解

    這篇文章主要介紹了Java基礎(chǔ)之構(gòu)造器、代碼塊、類加載時(shí)機(jī)的用法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-05-05
  • 如何使用ActiveMQ中間件方式發(fā)送郵件

    如何使用ActiveMQ中間件方式發(fā)送郵件

    這篇文章主要介紹了如何使用ActiveMQ中間件方式發(fā)送郵件的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Spring初始化與銷毀順序案例演示詳解

    Spring初始化與銷毀順序案例演示詳解

    這篇文章主要介紹了SpringBoot中的Bean的初始化與銷毀順序,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • MyBatis詳解如何實(shí)現(xiàn)Dao層接口

    MyBatis詳解如何實(shí)現(xiàn)Dao層接口

    MyBatis允許只聲明一個(gè)dao接口,而無(wú)需寫(xiě)dao實(shí)現(xiàn)類的方式實(shí)現(xiàn)數(shù)據(jù)庫(kù)操作。前提是必須保證Mapper文件中的<mapper>標(biāo)簽的namespace屬性值必須要和dao接口的類路徑一致,MyBatis容器會(huì)自動(dòng)通過(guò)動(dòng)態(tài)代理生成接口的實(shí)現(xiàn)類
    2022-04-04
  • hadoop是什么語(yǔ)言

    hadoop是什么語(yǔ)言

    Hadoop是一個(gè)由Apache基金會(huì)所開(kāi)發(fā)的分布式系統(tǒng)基礎(chǔ)架構(gòu)。 用戶可以在不了解分布式底層細(xì)節(jié)的情況下,開(kāi)發(fā)分布式程序。充分利用集群的威力進(jìn)行高速運(yùn)算和存儲(chǔ)
    2017-09-09
  • SpringBoot整合FTP實(shí)現(xiàn)文件傳輸?shù)牟襟E

    SpringBoot整合FTP實(shí)現(xiàn)文件傳輸?shù)牟襟E

    這篇文章主要給大家介紹了SpringBoot整合FTP實(shí)現(xiàn)文件傳輸?shù)牟襟E,文中的流程步驟和代碼示例介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2023-11-11
  • Java將集合元素轉(zhuǎn)換為數(shù)組的三種方式

    Java將集合元素轉(zhuǎn)換為數(shù)組的三種方式

    在實(shí)際開(kāi)發(fā)中,雖然用集合來(lái)存儲(chǔ)元素通常更靈活,但有些場(chǎng)景下,我們?nèi)匀恍枰獙⒓限D(zhuǎn)換成數(shù)組,下面就來(lái)介紹一下Java將集合元素轉(zhuǎn)換為數(shù)組的三種方式,感興趣的可以了解一下
    2025-11-11
  • Mybatis特殊字符轉(zhuǎn)義查詢實(shí)現(xiàn)

    Mybatis特殊字符轉(zhuǎn)義查詢實(shí)現(xiàn)

    本文主要介紹了Mybatis特殊字符轉(zhuǎn)義查詢實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-02-02
  • SpringMVC ViewResolver視圖解析器組件

    SpringMVC ViewResolver視圖解析器組件

    這篇文章主要介紹了SpringMVC ViewResolver視圖解析器組件,Spring MVC的視圖解析器 ViewResolver 是框架中一個(gè)重要的組件,用于將控制器返回的邏輯視圖名稱解析為具體的視圖實(shí)現(xiàn)對(duì)象,最終呈現(xiàn)給用戶的是具體的視圖實(shí)現(xiàn)
    2023-04-04

最新評(píng)論

汉阴县| 黄骅市| 哈巴河县| 商河县| 光泽县| 屯门区| 浦城县| 兴隆县| 开封县| 洛扎县| 彰化市| 垦利县| 枝江市| 会东县| 白朗县| 漠河县| 福州市| 嵊州市| 济宁市| 开平市| 台前县| 南阳市| 阿克陶县| 双城市| 宁海县| 尖扎县| 巴楚县| 武山县| 广宁县| 宁德市| 封开县| 台南市| 曲靖市| 永定县| 平南县| 安吉县| 佛山市| 米易县| 萍乡市| 油尖旺区| 依兰县|