Spring?Boot應用打WAR包后無法注冊到Nacos的問題及解決方法
在微服務架構中,服務注冊與發(fā)現(xiàn)是至關重要的一環(huán)。Nacos 作為阿里巴巴開源的注冊中心,能夠很好地滿足這一需求。然而,在將 Spring Boot 應用打包成 WAR 部署到外部服務器時,可能會遇到服務無法注冊到 Nacos 的問題。本文將詳細講解這一問題的解決方案。
問題描述
在開發(fā)過程中,通常使用 JAR 包運行 Spring Boot 應用,這種方式下,服務注冊到 Nacos 通常沒有問題。然而,當我們將 Spring Boot 應用打包成 WAR 并部署到外部 Tomcat 服務器時,可能會遇到服務無法注冊到 Nacos 的情況。其原因主要是應用獲取不到正確的服務器端口。
解決方案
為了在 WAR 包部署時正確地注冊服務到 Nacos,我們需要動態(tài)地獲取實際使用的服務器端口,并將其設置到 Nacos 的服務注冊中。以下是一個具體的實現(xiàn)代碼:
import com.alibaba.cloud.nacos.registry.NacosAutoServiceRegistration;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.management.Query;
import java.lang.management.ManagementFactory;
import java.util.Set;
/**
* 解決 Spring Boot 應用打 WAR 包后無法注冊到 Nacos 的問題
* 通過動態(tài)獲取服務器端口并注冊到 Nacos
*/
@Slf4j
@ConditionalOnProperty(prefix = "project.deploy", name = "mode", havingValue = "war")
@Component
public class NacosConfig implements ApplicationRunner {
@Autowired
private NacosAutoServiceRegistration registration;
@Value("${server.port:8080}")
Integer port;
@Override
public void run(ApplicationArguments args) {
if (registration != null && port != null) {
Integer serverPort = port;
try {
serverPort = new Integer(getServerPort());
} catch (Exception e) {
log.warn("getServerPort warn", e);
log.info("getServerPort fail, use the config-file's port {}", port);
}
registration.setPort(serverPort);
registration.start();
}
}
/**
* 獲取實際使用的服務器端口
*/
public String getServerPort() throws Exception {
MBeanServer beanServer = ManagementFactory.getPlatformMBeanServer();
Set<ObjectName> objectNames = beanServer.queryNames(new ObjectName("*:type=Connector,*"), Query.match(Query.attr("protocol"), Query.value("HTTP/1.1")));
String port = objectNames.iterator().next().getKeyProperty("port");
log.debug("getServerPort {}", port);
return port;
}
}代碼解析
1. 類與注解
@Slf4j
@ConditionalOnProperty(prefix = "project.deploy", name = "mode", havingValue = "war")
@Component
public class NacosConfig implements ApplicationRunner {@Slf4j:Lombok 提供的注解,用于生成日志記錄器。@ConditionalOnProperty:只有在project.deploy.mode屬性值為war時,才會創(chuàng)建這個NacosConfigbean。@Component:標記為 Spring 的組件,使其能夠被 Spring 掃描和管理。ApplicationRunner:實現(xiàn)該接口的run方法將在應用啟動時運行。
2. 自動注入與配置
@Autowired
private NacosAutoServiceRegistration registration;
@Value("${server.port:8080}")
Integer port;@Autowired:注入 Nacos 的服務注冊類NacosAutoServiceRegistration。@Value:注入配置文件中的端口號,如果未配置則默認使用 6888 端口。
3. 啟動時設置端口
@Override
public void run(ApplicationArguments args) {
if (registration != null && port != null) {
Integer serverPort = port;
try {
serverPort = new Integer(getServerPort());
} catch (Exception e) {
log.warn("getServerPort warn", e);
log.info("getServerPort fail, use the config-file's port {}", port);
}
registration.setPort(serverPort);
registration.start();
}
}- 在應用啟動時嘗試獲取實際使用的服務器端口,如果獲取失敗則使用配置文件中的端口。
- 將端口設置到 Nacos 的服務注冊中,并啟動服務注冊。
4. 獲取實際端口
public String getServerPort() throws Exception {
MBeanServer beanServer = ManagementFactory.getPlatformMBeanServer();
Set<ObjectName> objectNames = beanServer.queryNames(new ObjectName("*:type=Connector,*"), Query.match(Query.attr("protocol"), Query.value("HTTP/1.1")));
String port = objectNames.iterator().next().getKeyProperty("port");
log.debug("getServerPort {}", port);
return port;
}通過 JMX 管理接口獲取實際使用的 HTTP 端口。
總結
通過上述代碼,我們可以實現(xiàn)在 Spring Boot 應用啟動時,動態(tài)獲取并設置 Nacos 注冊的端口號。這對于在不同環(huán)境中部署應用非常有用,可以避免硬編碼端口號帶來的問題。同時,結合 Nacos 的服務注冊與發(fā)現(xiàn)功能,可以更加靈活地管理微服務架構中的各個服務。
到此這篇關于Spring Boot 應用打 WAR 包后無法注冊到 Nacos怎么辦的文章就介紹到這了,更多相關Spring Boot打 WAR 包無法注冊到 Nacos內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
SpringBoot使用thymeleaf實現(xiàn)前端表格
雖然現(xiàn)在流行前后端分離,但是后端模版在一些關鍵地方還是非常有用的,例如郵件模版、代碼模版等。當然也不排除一些古老的項目后端依然使用動態(tài)模版。Thymeleaf 簡潔漂亮、容易理解,并且完美支持 HTML5,可以直接打開靜態(tài)頁面,同時不新增標簽,只需增強屬性2022-10-10
Java 數(shù)據(jù)流之Broadcast State
這篇文章主要介紹了Java 數(shù)據(jù)流之Broadcast State,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-09-09
Mybatis實現(xiàn)Mapper動態(tài)代理方式詳解
這篇文章主要為大家詳細介紹了Mybatis實現(xiàn)Mapper動態(tài)代理方式,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-08-08
Jmeter解析返回參數(shù)以及解析并操作json方式
本文總結了Java或JMeter的BeanShell腳本中處理JSON字符串的常用操作,包括解析JSON數(shù)組、JSON對象和嵌套的JSON字符串,并提供了示例代碼和打印結果2025-02-02
java自動生成編號的實現(xiàn)(格式:yyMM+四位流水號)
這篇文章主要介紹了java自動生成編號的實現(xiàn)(格式:yyMM+四位流水號),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-10-10

