成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

使用 Spring Boot 實(shí)現(xiàn)動(dòng)態(tài)加載 jar 包,動(dòng)態(tài)配置功能太贊了!

開發(fā) 前端
本文展示了一個(gè)使用 Spring Boot 實(shí)現(xiàn)動(dòng)態(tài)加載、卸載 JAR 包和動(dòng)態(tài)修改 YAML 配置信息的完整示例,包括項(xiàng)目配置的更新、相關(guān)類的實(shí)現(xiàn)以及使用 Thymeleaf 實(shí)現(xiàn)的前端頁(yè)面,為開發(fā)者提供了一個(gè)可參考的實(shí)現(xiàn)方案。

在當(dāng)今的軟件開發(fā)中,靈活性和可擴(kuò)展性是至關(guān)重要的。Spring Boot 框架為我們提供了強(qiáng)大的工具和機(jī)制,使得實(shí)現(xiàn)動(dòng)態(tài)加載 jar 包和動(dòng)態(tài)配置變得輕松而高效。這一特性在應(yīng)對(duì)不斷變化的業(yè)務(wù)需求和復(fù)雜的運(yùn)行環(huán)境時(shí)具有極大的優(yōu)勢(shì)。

動(dòng)態(tài)加載 jar 包的原理與優(yōu)勢(shì)

動(dòng)態(tài)加載 jar 包的實(shí)現(xiàn)基于 Java 的類加載機(jī)制。在 Java 中,類加載器負(fù)責(zé)將類的字節(jié)碼加載到 JVM 中,并創(chuàng)建對(duì)應(yīng)的類對(duì)象。通常,Java 應(yīng)用使用默認(rèn)的類加載器層次結(jié)構(gòu),包括啟動(dòng)類加載器、擴(kuò)展類加載器和應(yīng)用類加載器。然而,為了實(shí)現(xiàn)動(dòng)態(tài)加載 jar 包,我們需要?jiǎng)?chuàng)建自定義的類加載器。

自定義類加載器繼承自 java.lang.ClassLoader 類,并覆蓋其 findClass 或 loadClass 方法來實(shí)現(xiàn)自定義的類查找和加載邏輯。當(dāng)需要?jiǎng)討B(tài)加載 jar 包時(shí),自定義類加載器首先獲取 jar 包的文件路徑,然后讀取 jar 包中的字節(jié)碼數(shù)據(jù)。

通過解析字節(jié)碼數(shù)據(jù),找到其中定義的類信息,并將其加載到 JVM 中。在這個(gè)過程中,還需要處理類的依賴關(guān)系,確保所有相關(guān)的類都能正確加載。

動(dòng)態(tài)加載 jar 包帶來了諸多顯著的優(yōu)勢(shì)。

首先,它極大地提高了系統(tǒng)的靈活性。在傳統(tǒng)的應(yīng)用部署中,如果需要添加新的功能或修復(fù)缺陷,往往需要重新編譯、打包和部署整個(gè)應(yīng)用。而通過動(dòng)態(tài)加載 jar 包,可以在應(yīng)用運(yùn)行時(shí)直接加載新的功能模塊,無需中斷服務(wù),實(shí)現(xiàn)了無縫的功能擴(kuò)展和更新。

其次,它有助于降低系統(tǒng)的維護(hù)成本。對(duì)于一些頻繁變化的業(yè)務(wù)需求,不必因?yàn)樾〉墓δ苷{(diào)整而進(jìn)行大規(guī)模的應(yīng)用部署,減少了部署過程中的風(fēng)險(xiǎn)和人力投入。

再者,動(dòng)態(tài)加載 jar 包能夠提高開發(fā)效率。開發(fā)人員可以獨(dú)立開發(fā)和測(cè)試新的功能模塊,然后在需要時(shí)將其動(dòng)態(tài)加載到生產(chǎn)環(huán)境中,避免了與現(xiàn)有代碼的頻繁集成和沖突。

此外,它還為系統(tǒng)的模塊化設(shè)計(jì)提供了有力支持。不同的功能模塊可以封裝在獨(dú)立的 jar 包中,根據(jù)實(shí)際需求動(dòng)態(tài)加載,使系統(tǒng)的架構(gòu)更加清晰和易于管理。

項(xiàng)目依賴配置(pom.xml)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.10</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.icoderoad</groupId>
    <artifactId>dynamic-loading-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>dynamic-loading-demo</name>
    <description>Demo project for dynamic loading with Spring Boot</description>

    <properties>
        <java.version>11</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
      	<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

YAML 屬性文件配置(application.yml)

# 動(dòng)態(tài)配置相關(guān)屬性
dynamic:
  enabled: true
  # 其他動(dòng)態(tài)配置項(xiàng)

后端代碼示例

DynamicConfig 類:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.stereotype.Component;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

@Component
@ConfigurationProperties(prefix = "dynamic")
public class DynamicConfig {

    private String configProperty;

    @Autowired
    private String filePath;

    public String getConfigProperty() {
        return configProperty;
    }

    public void setConfigProperty(String configProperty) {
        this.configProperty = configProperty;
        // 同步修改 YAML 文件中的配置信息
        modifyYaml(filePath, "configProperty", configProperty);
    }

    public void modifyYaml(String filePath, String key, String value) {
        try (FileInputStream inputStream = new FileInputStream(new File(filePath))) {
            Yaml yaml = new Yaml();
            Map<String, Object> config = yaml.load(inputStream);

            config.put(key, value);

            DumperOptions options = new DumperOptions();
            options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);

            try (FileWriter writer = new FileWriter(new File(filePath))) {
                yaml.dump(config, writer, options);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

工具類 JarLoadingUtils:

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class JarLoadingUtils {

    private Map<String, ClassLoader> loadedJars = new HashMap<>();

    public void loadJars(List<String> jarPaths) throws IOException {
        for (String jarPath : jarPaths) {
            URL url = new URL(jarPath);
            CustomClassLoader classLoader = new CustomClassLoader();
            classLoader.loadJar(url.getFile());
            loadedJars.put(jarPath, classLoader);
            System.out.println("正在加載 JAR 包: " + jarPath);
        }
    }

    public void unloadJar(String jarPath) {
        ClassLoader classLoader = loadedJars.remove(jarPath);
        if (classLoader!= null) {
            // 執(zhí)行卸載相關(guān)的邏輯
            System.out.println("正在卸載 JAR 包: " + jarPath);
        }
    }

    class CustomClassLoader extends URLClassLoader {

        public CustomClassLoader() {
            super(new URL[0], getParentClassLoader());
        }

        public void loadJar(String jarPath) {
            try {
                URL url = new File(jarPath).toURI().toURL();
                addURL(url);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

DynamicLoadingController 類:

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

import java.io.IOException;
import java.util.List;
import java.util.Map;

public class DynamicLoadingController {

    private JarLoadingUtils jarLoadingUtils;
    private DynamicConfig dynamicConfig;

    public DynamicLoadingController(JarLoadingUtils jarLoadingUtils, DynamicConfig dynamicConfig) {
        this.jarLoadingUtils = jarLoadingUtils;
        this.dynamicConfig = dynamicConfig;
    }

    @PostMapping("/dynamic/load")
    public ResponseEntity<String> loadJars(@RequestBody List<String> jarPaths) {
        try {
            jarLoadingUtils.loadJars(jarPaths);
            return ResponseEntity.status(HttpStatus.OK).body("JAR 包加載成功");
        } catch (IOException e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("加載 JAR 包時(shí)出錯(cuò): " + e.getMessage());
        }
    }

    @PostMapping("/dynamic/unload")
    public ResponseEntity<String> unloadJar(@RequestBody String jarPath) {
        jarLoadingUtils.unloadJar(jarPath);
        return ResponseEntity.status(HttpStatus.OK).body("JAR 包卸載成功");
    }

    @PostMapping("/dynamic/config/update")
    public ResponseEntity<String> updateConfig(@RequestBody Map<String, String> configData) {
        String key = configData.get("key");
        String value = configData.get("value");
        dynamicConfig.setConfigProperty(value);
        return ResponseEntity.status(HttpStatus.OK).body("配置更新成功");
    }
}

核心的后端代碼實(shí)現(xiàn)如下:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DynamicLoadingApplication implements ApplicationRunner {

    @Autowired
    private DynamicConfig dynamicConfig;

    @Autowired
    private JarLoadingUtils jarLoadingUtils;

    public static void main(String[] args) {
        SpringApplication.run(DynamicLoadingApplication.class, args);
    }

    @Override
    public void run(ApplicationArguments args) throws Exception {
        // 模擬動(dòng)態(tài)加載 jar 包的邏輯
        List<String> jarPaths = new ArrayList<>();
        jarPaths.add("path/to/your/jar/file1.jar");
        jarPaths.add("path/to/your/jar/file2.jar");
        jarLoadingUtils.loadJars(jarPaths);
    }
}

使用 Thymeleaf 的前端頁(yè)面:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>動(dòng)態(tài)加載配置頁(yè)面</title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <script>
        $(document).ready(function() {
            $("#loadButton").click(function() {
                $.ajax({
                    url: "/dynamic/load",
                    type: "POST",
                    success: function(response) {
                        $("#loadResult").text(response);
                    },
                    error: function(xhr, status, error) {
                        $("#loadResult").text("加載出錯(cuò): " + error);
                    }
                });
            });

            $("#unloadButton").click(function() {
                var jarPath = $("#unloadPath").val();
                $.ajax({
                    url: "/dynamic/unload",
                    type: "POST",
                    data: JSON.stringify({ "jarPath": jarPath }),
                    contentType: "application/json",
                    success: function(response) {
                        $("#unloadResult").text(response);
                    },
                    error: function(xhr, status, error) {
                        $("#unloadResult").text("卸載出錯(cuò): " + error);
                    }
                });
            });

            $("#updateButton").click(function() {
                var key = $("#updateKey").val();
                var value = $("#updateValue").val();
                $.ajax({
                    url: "/dynamic/config/update",
                    type: "POST",
                    data: JSON.stringify({ "key": key, "value": value }),
                    contentType: "application/json",
                    success: function(response) {
                        $("#updateResult").text(response);
                    },
                    error: function(xhr, status, error) {
                        $("#updateResult").text("更新出錯(cuò): " + error);
                    }
                });
            });
        });
    </script>
</head>
<body>
    <h2>動(dòng)態(tài)操作</h2>
    <button id="loadButton">觸發(fā)動(dòng)態(tài)加載</button>
    <p id="loadResult"></p>
    <form>
        <input type="text" id="unloadPath" placeholder="輸入要卸載的 JAR 路徑" />
        <button id="unloadButton">觸發(fā)動(dòng)態(tài)卸載</button>
    </form>
    <p id="unloadResult"></p>
    <form>
        <input type="text" id="updateKey" placeholder="輸入配置鍵" />
        <input type="text" id="updateValue" placeholder="輸入配置值" />
        <button id="updateButton">觸發(fā)動(dòng)態(tài)配置更新</button>
    </form>
    <p id="updateResult"></p>
</body>
</html>

總結(jié)

本文展示了一個(gè)使用 Spring Boot 實(shí)現(xiàn)動(dòng)態(tài)加載、卸載 JAR 包和動(dòng)態(tài)修改 YAML 配置信息的完整示例,包括項(xiàng)目配置的更新、相關(guān)類的實(shí)現(xiàn)以及使用 Thymeleaf 實(shí)現(xiàn)的前端頁(yè)面,為開發(fā)者提供了一個(gè)可參考的實(shí)現(xiàn)方案。

責(zé)任編輯:武曉燕 來源: 路條編程
相關(guān)推薦

2021-10-18 10:36:31

Spring Boot插件Jar

2021-10-18 12:04:22

Spring BootJava開發(fā)

2025-06-18 07:32:16

SpringJar動(dòng)態(tài)加載

2024-09-05 09:35:58

CGLIBSpring動(dòng)態(tài)代理

2024-02-04 09:19:00

Nacos動(dòng)態(tài)化線程池

2024-11-08 14:11:09

2022-08-02 11:24:22

菜鳥Python網(wǎng)站自動(dòng)簽到

2022-07-14 10:38:39

動(dòng)態(tài)標(biāo)簽Spring

2023-12-08 14:37:51

接口jar包開發(fā)

2021-12-02 09:31:22

Python 代碼進(jìn)度條

2025-02-07 09:11:04

JSON對(duì)象策略

2022-02-08 17:07:54

Spring BooSpring Aop日志記錄

2021-09-01 10:07:43

開發(fā)零搭建Groovy

2009-06-22 15:10:00

java 編程AOP

2024-09-03 10:44:32

2025-01-17 09:11:51

2024-12-20 17:29:34

SpringBootAOP開發(fā)

2022-06-16 10:38:24

URL權(quán)限源代碼

2009-08-28 16:14:26

C#實(shí)現(xiàn)加載動(dòng)態(tài)庫(kù)

2014-12-04 10:30:04

Java
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 久久久精品一区 | 91在线免费观看网站 | av中文在线播放 | 国产高清精品一区二区三区 | 毛片网在线观看 | 免费一区二区 | 欧美在线 | 中国一级大毛片 | 黄色av网站在线免费观看 | 国产目拍亚洲精品99久久精品 | 91高清视频 | 中文在线亚洲 | 成人精品鲁一区一区二区 | 久久久成人免费一区二区 | 精品日韩一区二区 | 日韩一区二区在线免费观看 | 亚洲精品久久久久中文字幕欢迎你 | 日韩毛片免费看 | 在线播放国产视频 | 一级黄色片免费在线观看 | 国产在线观看网站 | 99久久中文字幕三级久久日本 | 性做久久久久久免费观看欧美 | 国产一级特黄视频 | 精品不卡 | 亚洲成人自拍 | 国产清纯白嫩初高生在线播放视频 | 国产精品美女久久久久久免费 | 涩涩视频网站在线观看 | 红桃视频一区二区三区免费 | 日韩播放| av中文在线观看 | 亚洲国产乱码 | 久久99精品久久久久久琪琪 | 欧美精品久久 | 久久久国产一区二区三区 | 亚洲高清在线 | 成人国产一区二区三区精品麻豆 | 中文字幕高清av | 日日操夜夜操天天操 | 国产福利精品一区 |