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

Springboot 集成 SocketIO的示例代碼

 更新時(shí)間:2024年10月24日 15:40:32   作者:我只會(huì)發(fā)熱  
Socket.IO是實(shí)現(xiàn)瀏覽器與服務(wù)器之間實(shí)時(shí)、雙向和基于事件的通信的工具庫,本文主要介紹了Springboot 集成 SocketIO的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

1 前言

1.1 什么是 SocketIO ?

Socket.IO 是一個(gè)可以在瀏覽器與服務(wù)器之間實(shí)現(xiàn)實(shí)時(shí)、雙向、基于事件的通信的工具庫。 Socket.IO 能夠在任何平臺(tái)、瀏覽器或設(shè)備上運(yùn)行,可靠性和速度同樣出色。其本質(zhì)上是將 webSocket、Ajax 和其他通信方式再封裝了一層,更強(qiáng)大,適應(yīng)性和兼容性更好。

(這句話怎么理解呢?簡單的來說,就是客戶端可以給服務(wù)端發(fā)消息,服務(wù)端也可以給客戶端發(fā)消息,而鏈接它們之間的消息紐帶,就是“事件監(jiān)聽”。)

1.2 webSocket 的優(yōu)點(diǎn)

webSocket 和 socket.io 區(qū)別?

  • webSocketa:一種讓客戶端和服務(wù)器之間能進(jìn)行雙向?qū)崟r(shí)通信的技術(shù)
    b:使用時(shí),雖然主流瀏覽器都已經(jīng)支持,但仍然可能有不兼容的情況
    c:適合用于client和基于node搭建的服務(wù)端使用
  • socket.ioa:將 webSocket、Ajax 和其它的通信方式全部封裝成了統(tǒng)一的通信接口
    b:使用時(shí),不用擔(dān)心兼容問題,底層會(huì)自動(dòng)選用最佳的通信方式
    c:適合進(jìn)行服務(wù)端和客戶端雙向數(shù)據(jù)通信
    d:Socket.IO中文網(wǎng)地址:https://socket.nodejs.cn/docs/v4/

1.3 應(yīng)用及版本

  • spring-boot:2.5.14
  • socketio:2.0.3
  • jdk:java8
  • 本文是基于《若依前后端分離》版本的基礎(chǔ)上進(jìn)行代碼編寫和演示的

2 物料準(zhǔn)備(均為后端代碼)

2.1 添加 Socket 依賴包

<dependency>
    <groupId>com.corundumstudio.socketio</groupId>
    <artifactId>netty-socketio</artifactId>
    <version>2.0.3</version>
</dependency>

2.2 創(chuàng)建頻道常量類:SocketEventContants

我這個(gè)常量類是為了統(tǒng)一頻道所建,你們不一定需要這個(gè)類

package com.mss.common.constant;

/**
 * @Description: Socket 自定義事件名稱
 * @Author: zhanleai
 */
public class SocketEventContants {

    /**
     * 用戶頻道
     **/
    public static final String CHANNEL_USER = "channel_user";

    /**
     * 系統(tǒng)頻道
     **/
    public static final String CHANNEL_SYSTEM = "channel_system";

}

2.3 創(chuàng)建 Socket 連接類:SocketHandler

  • 用來監(jiān)聽 socket 客戶端上下線,以及服務(wù)端自動(dòng)關(guān)閉;
  • 有些博主把這個(gè)類的內(nèi)容跟工具類里監(jiān)聽事件方法放在一起,個(gè)人認(rèn)為需要解耦,特別是在分布式的項(xiàng)目中;
package com.mss.framework.handle;

import com.corundumstudio.socketio.SocketIOServer;
import com.mss.common.utils.socket.SocketUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.springframework.stereotype.Component;

/**
 * @Author: zhanleai
 * @Description: 客戶端自動(dòng)連接和斷開、服務(wù)端關(guān)閉
 */
@Component
@Slf4j
public class SocketHandler {

    @Autowired
    private SocketIOServer socketIoServer;

    /**
     *  容器銷毀前,自動(dòng)調(diào)用此方法,關(guān)閉 socketIo 服務(wù)端
     *
     * @Param []
     * @return
     **/
    @PreDestroy
    private void destroy(){
        try {
            log.debug("關(guān)閉 socket 服務(wù)端");
            socketIoServer.stop();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @PostConstruct
    public void init() {
        log.debug("SocketEventListener initialized");

        //添加監(jiān)聽,客戶端自動(dòng)連接到 socket 服務(wù)端
        socketIoServer.addConnectListener(client -> {
            String userId = client.getHandshakeData().getSingleUrlParam("userId");
            SocketUtil.connectMap.put(userId, client);
            log.debug("客戶端userId: "+ userId+ "已連接,客戶端ID為:" + client.getSessionId());
        });

        //添加監(jiān)聽,客戶端跟 socket 服務(wù)端自動(dòng)斷開
        socketIoServer.addDisconnectListener(client -> {
            String userId = client.getHandshakeData().getSingleUrlParam("userId");
            SocketUtil.connectMap.remove(userId, client);
            log.debug("客戶端userId:" + userId + "斷開連接,客戶端ID為:" + client.getSessionId());
        });
    }

//    // 注釋說明:以下 onConnect和 onDisconnect 方法在某些場景下會(huì)失效,不建議使用,所以注釋掉
//    /**
//     *  客戶端自動(dòng)連接到 socket 服務(wù)端
//     *
//     * @Param [client]
//     * @return
//     **/
//    @OnConnect
//    public void onConnect(SocketIOClient client) {
//        String userId = client.getHandshakeData().getSingleUrlParam("userId");
//        SocketUtil.connectMap.put(userId, client);
//        log.debug("客戶端userId: "+ userId+ "已連接,客戶端ID為:" + client.getSessionId());
//    }
//
//    /**
//     *  客戶端跟 socket 服務(wù)端自動(dòng)斷開
//     *
//     * @Param [client]
//     * @return
//     **/
//    @OnDisconnect
//    public void onDisconnect(SocketIOClient client) {
//        String userId = client.getHandshakeData().getSingleUrlParam("userId");
//        log.debug("客戶端userId:" + userId + "斷開連接,客戶端ID為:" + client.getSessionId());
//        SocketUtil.connectMap.remove(userId, client);
//    }
}

2.4 Socket 配置文件和配置類

用來定義 socket 的一些配置

2.4.1 yml 配置

socketio:
    host: 127.0.0.1		//主機(jī)名,默認(rèn)是 0.0.0.0 (這個(gè)設(shè)不設(shè)置無所謂,因?yàn)楹竺娴?SocketConfig 類一般不用設(shè)置這個(gè))
    port: 33000			//監(jiān)聽端口
    maxFramePayloadLength: 1048576
    maxHttpContentLength: 1048576
    bossCount: 1
    workCount: 100
    allowCustomRequests: true
    upgradeTimeout: 1000000		//協(xié)議升級(jí)超時(shí)時(shí)間(毫秒),默認(rèn)10000。HTTP握手升級(jí)為ws協(xié)議超時(shí)時(shí)間
    pingTimeout: 6000000		//Ping消息超時(shí)時(shí)間(毫秒),默認(rèn)60000,這個(gè)時(shí)間間隔內(nèi)沒有接收到心跳消息就會(huì)發(fā)送超時(shí)事件
    pingInterval: 25000			//Ping消息間隔(毫秒),默認(rèn)25000??蛻舳讼蚍?wù)器發(fā)送一條心跳消息間隔

2.4.2 配置類:SocketConfig

package com.mss.framework.config;

import com.corundumstudio.socketio.SocketIOServer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

@Component
public class SocketConfig {

    @Value("${socketio.host}")
    private String host;

    @Value("${socketio.port}")
    private Integer port;

    @Value("${socketio.bossCount}")
    private int bossCount;

    @Value("${socketio.workCount}")
    private int workCount;

    @Value("${socketio.allowCustomRequests}")
    private boolean allowCustomRequests;

    @Value("${socketio.upgradeTimeout}")
    private int upgradeTimeout;

    @Value("${socketio.pingTimeout}")
    private int pingTimeout;

    @Value("${socketio.pingInterval}")
    private int pingInterval;

    @Bean
    public SocketIOServer socketIOServer() {
        com.corundumstudio.socketio.Configuration configuration = new com.corundumstudio.socketio.Configuration();
        configuration.setPort(port);
        com.corundumstudio.socketio.SocketConfig socketConfig=new com.corundumstudio.socketio.SocketConfig();
        socketConfig.setReuseAddress(true);
        configuration.setSocketConfig(socketConfig);
        configuration.setOrigin(null);
        configuration.setBossThreads(bossCount);
        configuration.setWorkerThreads(workCount);
        configuration.setAllowCustomRequests(allowCustomRequests);
        configuration.setUpgradeTimeout(upgradeTimeout);
        configuration.setPingTimeout(pingTimeout);
        configuration.setPingInterval(pingInterval);
        //設(shè)置 sessionId 隨機(jī)
        configuration.setRandomSession(true);

//         configuration.setKeyStorePassword("pi0yo93pqgrs");
//         configuration.setKeyStore(this.getClass().getResourceAsStream("www.ibms.club.jks"));
//         configuration.setAuthorizationListener(data -> {
//             String token = data.getSingleUrlParam("token");
//             return StrUtil.isNotBlank(token);
//         });

        //初始化 Socket 服務(wù)端配置
        return new SocketIOServer(configuration);
    }
    
    /**
     *  Spring加載 SocketIOServer
     * 
     * @Param [server]
     * @return 
     **/
	@Bean
    public SpringAnnotationScanner springAnnotationScanner(SocketIOServer socketIOServer ) {
        return new SpringAnnotationScanner(socketIOServer );
    }
	}

2.5 Socket 服務(wù)啟動(dòng)類:ServerRunner

實(shí)現(xiàn) CommandLineRunner 接口類,項(xiàng)目啟動(dòng)時(shí)自動(dòng)執(zhí)行 socketIOServer.start() 方法

package com.mss.framework.run;

import com.corundumstudio.socketio.SocketIOServer;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

@Slf4j
@Component
@AllArgsConstructor
public class ServerRunner implements CommandLineRunner {

    private final SocketIOServer socketIOServer;

    /**
     *  項(xiàng)目啟動(dòng)時(shí),自動(dòng)啟動(dòng) socket 服務(wù),服務(wù)端開始工作
     *
     * @Param [args]
     * @return
     **/
    @Override
    public void run(String... args)  {
        socketIOServer.start();
        log.info("socket.io server started !");
    }
}

2.6 Socket 工具類:SocketUtil

下列實(shí)例代碼中,是使用 userId 來當(dāng)做客戶端唯一標(biāo)識(shí),這個(gè)每個(gè)人可以根據(jù)自己項(xiàng)目里自行設(shè)置;

下列實(shí)例代碼的應(yīng)用場景,只有服務(wù)端向客戶端發(fā)送消息的需求,所以實(shí)際這個(gè)工具類只有 sendToOne() 方法是實(shí)際起作用的,其余的代碼都是為了本文額外寫的方法;

package com.mss.common.utils.socket;

import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.annotation.OnEvent;
import com.mss.common.constant.SocketEventContants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * @Author: zhanleai
 * @Description:
 */
@Component
@Slf4j
public class SocketUtil {

    //暫且把用戶&客戶端信息存在緩存
    public static ConcurrentMap<String, SocketIOClient> connectMap = new ConcurrentHashMap<>();

    /**
     *  單發(fā)消息(以 userId 為標(biāo)識(shí)符,給用戶發(fā)送消息)
     *
     * @Param [userId, message]
     * @return
     **/
    public static void sendToOne(String userId, Object message) {
        //拿出某個(gè)客戶端信息
        SocketIOClient socketClient = getSocketClient(userId);
        if (Objects.nonNull(socketClient) ){
            //單獨(dú)給他發(fā)消息
            socketClient.sendEvent(SocketEventContants.CHANNEL_USER,message);
        }else{
            log.info(userId + "已下線,暫不發(fā)送消息。");
        }
    }

    /**
     *  群發(fā)消息
     *
     * @Param
     * @return
     **/
    public static void sendToAll(Object message) {
        if (connectMap.isEmpty()){
            return;
        }
        //給在這個(gè)頻道的每個(gè)客戶端發(fā)消息
        for (Map.Entry<String, SocketIOClient> entry : connectMap.entrySet()) {
            entry.getValue().sendEvent(SocketEventContants.CHANNEL_SYSTEM, message);
        }
    }

    /**
     * 根據(jù) userId 識(shí)別出 socket 客戶端
     * @param userId
     * @return
     */
    public static SocketIOClient getSocketClient(String userId){
        SocketIOClient client = null;
        if (StringUtils.hasLength(userId) &&  !connectMap.isEmpty()){
            for (String key : connectMap.keySet()) {
                if (userId.equals(key)){
                    client = connectMap.get(key);
                }
            }
        }
        return client;
    }

    /**
     *  1)使用事件注解,服務(wù)端監(jiān)聽獲取客戶端消息;
     *  2)拿到客戶端發(fā)過來的消息之后,可以再根據(jù)業(yè)務(wù)邏輯發(fā)送給想要得到這個(gè)消息的人;
     *  3)channel_system 之所以會(huì)向全體客戶端發(fā)消息,是因?yàn)槲腋岸思s定好了,你們也可以自定定義;
     *
     * @Param message
     * @return
     **/
    @OnEvent(value = SocketEventContants.CHANNEL_SYSTEM)
    public void channelSystemListener(String message) {
        if (!StringUtils.hasLength(message)){
            return;
        }

        this.sendToAll(message);
    }
}

3 Socket 調(diào)用

3.1 實(shí)際項(xiàng)目的應(yīng)用場景:在需要發(fā)送消息通知的業(yè)務(wù)代碼中調(diào)用

這個(gè)方法里有幾個(gè)類:Message、DateUtils、IMessageService、MessageMapper,均為根據(jù)自身業(yè)務(wù)場景自定義的類,你們自己建吧。有需要再私信我要;

后端代碼寫到這里,實(shí)際上已經(jīng)寫完了。從 3.2 開始均為測試代碼;

package com.mss.message.service.impl;

import com.mss.common.utils.DateUtils;
import com.mss.common.utils.socket.SocketUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.mss.message.mapper.MessageMapper;
import com.mss.message.domain.entity.Message;
import com.mss.message.service.IMessageService;

/**
 * 消息Service業(yè)務(wù)層處理
 *
 * @author zhanleai
 */
@Service
@Slf4j
public class MessageServiceImpl implements IMessageService {

    @Autowired
    private MessageMapper messageMapper;

    /**
     * 新增消息
     *
     * @param message 消息
     * @return 結(jié)果
     */
    @Override
    public int insertMessage(Message message) {
        message.setSendTime(DateUtils.getNowDate());
        // 消息入庫,消息持久化
        int i = messageMapper.insertMessage(message);
        if(i > 0){
			// 新增消息之后,再向前端推送 Socket 消息
        	SocketUtil.sendToOne(message.getSendUserId().toString(),message);
		}
        return i;
    }

}

3.2 測試Controller

下文均為測試的代碼

package com.mss.message.controller;

import com.mss.common.utils.socket.SocketUtil;
import io.swagger.annotations.Api;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.mss.common.core.controller.BaseController;
import com.mss.common.core.domain.AjaxResult;

/**
 * 消息Controller
 *
 * @author zhanleai
 */
@RestController
@Api(tags="消息")
@RequestMapping("/message")
public class MessageController extends BaseController {

    /**
     *  給指定客戶端發(fā)送消息
     * 
     * @Param [userId, message]
     * @return 
     **/
    @GetMapping("/sendToOne")
    public AjaxResult sendToOne(String userId , String message){
        SocketUtil.sendToOne(userId,message);
        return AjaxResult.success("單獨(dú)發(fā)送消息成功。");
    }
}

4 前端調(diào)用代碼

  • 前端代碼監(jiān)聽了 channel_user 和 channel_system 兩個(gè)頻道,一個(gè)做了三個(gè)動(dòng)作:
  • 1)連接上服務(wù)端;
    2)監(jiān)聽并接收 channel_user 頻道的消息;
    3)給服務(wù)端發(fā)送一條消息,并廣播到所有客戶端;
  • postman 只做了一個(gè)動(dòng)作,給后端指定的 userId 發(fā)送一條 channel_user 頻道的消息,并被指定客戶端捕獲;

4.1 html 測試代碼以及說明

詳細(xì)的 html 測試代碼

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title>TestConnect</title>
    <base>
    <script src="https://cdn.bootcss.com/jquery/3.4.0/jquery.min.js"></script>
    <script src="https://cdn.bootcss.com/socket.io/2.0.3/socket.io.js"></script>
    <style>
        body {
            padding: 20px;
        }
        #console {
            height: 450px;
            overflow: auto;
        }
        .msg-color {
            color: green;
        }
    </style>
</head>
 
<body>
<div id="console" class="well"></div>
 
</body>
<script type="text/javascript">
    var socket;
    connect();
 
    function connect() {
        var userId = 'zhanleai';
        var opts = {
            query: 'userId=' + userId
        };
        socket = io.connect('http://127.0.0.1:33000', opts);
        socket.on('connect', function () {
            console.log("連接成功");
            output('當(dāng)前用戶是:' + userId );
            output('<span class="msg-color">連接成功了。</span>');
        });
        socket.on('disconnect', function () {
            output('<span class="msg-color">下線了。 </span>');
        });
 
        socket.on('channel_user', function (data) {
            let msg= JSON.stringify(data)
            output('收到 channel_user 頻道消息了:' + msg );
            console.log(data);
 
        });
 
    }
 
    function output(message) {
        var element = $("<div>" + message + "</div>");
        $('#console').prepend(element);
    }
 
</script>
</html>

4.2 瀏覽器打開 html 文件,然后查看后端服務(wù)日志

(socket 服務(wù)端啟動(dòng),端口號(hào)為 33000,客戶端 zhanleai 連接上來了)

瀏覽器截圖

在這里插入圖片描述

后端服務(wù)日志截圖

在這里插入圖片描述

4.3 postman 工具測試

postman 截圖

在這里插入圖片描述

瀏覽器收到消息截圖

在這里插入圖片描述

到此這篇關(guān)于Springboot 集成 SocketIO的示例代碼的文章就介紹到這了,更多相關(guān)Springboot 集成 SocketIO內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家! 

相關(guān)文章

  • 淺談常用字符串與集合類轉(zhuǎn)換的工具類

    淺談常用字符串與集合類轉(zhuǎn)換的工具類

    下面小編就為大家?guī)硪黄獪\談常用字符串與集合類轉(zhuǎn)換的工具類。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-08-08
  • javaweb購物車案列學(xué)習(xí)開發(fā)

    javaweb購物車案列學(xué)習(xí)開發(fā)

    這篇文章主要為大家詳細(xì)介紹了javaweb購物車案列學(xué)習(xí)開發(fā)的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-05-05
  • 詳解如何在SpringBoot項(xiàng)目中使用全局異常處理

    詳解如何在SpringBoot項(xiàng)目中使用全局異常處理

    在完整的項(xiàng)目開發(fā)中,異常的出現(xiàn)幾乎是無法避免的;如果凡是有可能出現(xiàn)異常的地方,我們都手動(dòng)的使用try-catch將其捕獲的話,會(huì)使得代碼顯得十分臃腫并且后期不好維護(hù)。本文介紹了pringBoot項(xiàng)目中使用全局異常處理的方法,需要的可以參考一下
    2022-10-10
  • Java枚舉Enum從入門到實(shí)踐指南

    Java枚舉Enum從入門到實(shí)踐指南

    枚舉是Java中一個(gè)強(qiáng)大而實(shí)用的特性,它不僅可以用來定義常量,還可以實(shí)現(xiàn)復(fù)雜的業(yè)務(wù)邏輯,本文給大家介紹Java枚舉Enum從入門到實(shí)踐指南,感興趣的朋友跟隨小編一起看看吧
    2026-01-01
  • java教學(xué)筆記之對(duì)象的創(chuàng)建與銷毀

    java教學(xué)筆記之對(duì)象的創(chuàng)建與銷毀

    面向?qū)ο蟮木幊陶Z言使程序能夠直觀的反應(yīng)客觀世界的本來面目,并且使軟件開發(fā)人員能夠運(yùn)用人類認(rèn)識(shí)事物所采用的一般思維方法進(jìn)行軟件開發(fā),是當(dāng)今計(jì)算機(jī)領(lǐng)域中軟件開發(fā)和應(yīng)用的主流技術(shù)。
    2016-01-01
  • WIN10系統(tǒng)中添加bat腳本重啟jar服務(wù)

    WIN10系統(tǒng)中添加bat腳本重啟jar服務(wù)

    在bat腳本中執(zhí)行java服務(wù),命令與cmd中類似,下面這篇文章主要給大家介紹了關(guān)于WIN10系統(tǒng)中添加bat腳本重啟jar服務(wù)的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2023-12-12
  • 詳解Java中Comparable和Comparator接口的區(qū)別

    詳解Java中Comparable和Comparator接口的區(qū)別

    這篇文章主要介紹了詳解Java中Comparable和Comparator接口的區(qū)別的相關(guān)資料,希望通過本文大家能徹底掌握這部分內(nèi)容,需要的朋友可以參考下
    2017-09-09
  • Java中StringBuilder超詳細(xì)講解(附實(shí)例代碼)

    Java中StringBuilder超詳細(xì)講解(附實(shí)例代碼)

    在Java中StringBuilder是一個(gè)非常有用的類,用于高效操作可變字符串,這篇文章主要介紹了Java中StringBuilder超詳細(xì)講解的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2026-03-03
  • SpringBoot項(xiàng)目集成第三方CAS-client jar包的方法

    SpringBoot項(xiàng)目集成第三方CAS-client jar包的方法

    本文介紹了SpringBoot中集成第三方CAS-clientjar包的兩種核心方式,涵蓋了從背景原理到實(shí)操步驟、依賴沖突解決、打包配置及常見問題排查的全面內(nèi)容,通過對(duì)比兩種集成方式,提出了選型建議,并強(qiáng)調(diào)了依賴管理的規(guī)范性,為實(shí)際項(xiàng)目開發(fā)提供了全面指導(dǎo),感興趣的朋友一起看看吧
    2025-12-12
  • 對(duì)SpringBoot項(xiàng)目Jar包進(jìn)行加密防止反編譯

    對(duì)SpringBoot項(xiàng)目Jar包進(jìn)行加密防止反編譯

    最近項(xiàng)目要求部署到其他公司的服務(wù)器上,但是又不想將源碼泄露出去,要求對(duì)正式環(huán)境的啟動(dòng)包進(jìn)行安全性處理,防止客戶直接通過反編譯工具將代碼反編譯出來,本文介紹了如何對(duì)SpringBoot項(xiàng)目Jar包進(jìn)行加密防止反編譯,需要的朋友可以參考下
    2023-10-10

最新評(píng)論

琼中| 灵川县| 昌图县| 茶陵县| 年辖:市辖区| 曲周县| 格尔木市| 惠安县| 若羌县| 茶陵县| 双流县| 深州市| 汶川县| 麻阳| 大足县| 三河市| 东安县| 三江| 镇远县| 潮州市| 元江| 汉阴县| 平谷区| 类乌齐县| 滁州市| 曲阜市| 晋州市| 崇明县| 惠水县| 通渭县| 安化县| 京山县| 额尔古纳市| 昌宁县| 山西省| 盘山县| 宁南县| 玛曲县| 白河县| 安远县| 唐山市|