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

詳解Springboot工程中如何快速判斷web應(yīng)用服務(wù)器類型

 更新時(shí)間:2026年04月13日 09:31:38   作者:愛碼少年?00fly.online  
在?Spring?Boot?工程中快速判斷?Web?應(yīng)用服務(wù)器類型,可以從運(yùn)行時(shí)環(huán)境、Spring?Boot?特有?API、底層類加載器、HTTP?響應(yīng)和外部命令等多個(gè)層面入手,下面小編就和大家簡單介紹一下吧

在 Spring Boot 工程中快速判斷 Web 應(yīng)用服務(wù)器類型,可以從運(yùn)行時(shí)環(huán)境、Spring Boot 特有 API、底層類加載器、HTTP 響應(yīng)和外部命令等多個(gè)層面入手。下面是幾種常見方法的速覽表:

方法原理簡述代碼復(fù)雜度通用性推薦度
注入 ServletContext直接調(diào)用 getServerInfo() 獲取服務(wù)器信息★☆☆☆☆極高 (適用于所有 Servlet 容器)?????
檢查特定類是否存在通過 Class.forName() 加載特定服務(wù)器的關(guān)鍵類★★☆☆☆????
利用 Spring Boot 條件注解使用 @ConditionalOnClass 注解聲明 Bean★★☆☆☆一般 (適用于 Spring 環(huán)境)???
監(jiān)聽容器初始化事件在應(yīng)用啟動(dòng)時(shí)監(jiān)聽 ServletWebServerInitializedEvent 事件★★☆☆☆一般 (適用于 Spring Boot)???
查看啟動(dòng)日志直接觀察應(yīng)用啟動(dòng)時(shí)的控制臺日志輸出☆☆☆☆☆極高?????
使用 Actuator 端點(diǎn)訪問 /actuator/env 端點(diǎn)查看服務(wù)器相關(guān)配置★★☆☆☆一般???
檢查特定系統(tǒng)屬性或 JMX讀取 java.vm.vendor 或查詢 JMX MBean★★★☆☆??
通過外部命令或端口號推斷使用 netstat 或 ps 命令在操作系統(tǒng)層面查詢★★★☆☆低 (僅限手動(dòng)排查)?

方法一:通過 ServletContext 獲取服務(wù)器信息(推薦)

這是最直接、最可靠的方式。你可以在任何 Spring Bean 中注入 ServletContext 對象,并調(diào)用 getServerInfo() 方法。該方法會返回一個(gè)字符串,其中包含了當(dāng)前正在運(yùn)行的 Servlet 容器的名稱和版本信息。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.servlet.ServletContext;
@Service
public class ServerInfoService {
    @Autowired
    private ServletContext servletContext;
    public void printServerInfo() {
        String serverInfo = servletContext.getServerInfo();
        System.out.println("服務(wù)器信息: " + serverInfo);
        // 對于 Tomcat,輸出可能是 "Apache Tomcat/9.0.83" 
        // 對于 Jetty,輸出可能是 "Jetty/9.4.53.v20231009"
        // 對于 Undertow,輸出可能是 "Undertow - 2.2.24.Final"
    }
}

根據(jù) getServerInfo() 返回的內(nèi)容進(jìn)行判斷時(shí),注意對版本號部分進(jìn)行清理,避免因版本差異導(dǎo)致匹配失敗。

方法二:檢查特定類的存在性

通過 Class.forName() 方法檢測特定服務(wù)器的關(guān)鍵類是否存在于當(dāng)前應(yīng)用的 Classpath 中,從而判斷其類型。

import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@Component
public class ServerDetector {
    public enum ServerType {
        TOMCAT, JETTY, UNDERTOW, JBOSS, WEBLOGIC, WEBSPHERE, UNKNOWN
    }
    private static ServerType detectedServer;
    @PostConstruct
    public void detect() {
        detectedServer = determineServerType();
        System.out.println("檢測到服務(wù)器類型: " + detectedServer);
    }
    public static ServerType determineServerType() {
        if (isClassPresent("org.apache.catalina.startup.Tomcat")) return ServerType.TOMCAT;
        if (isClassPresent("org.eclipse.jetty.server.Server")) return ServerType.JETTY;
        if (isClassPresent("io.undertow.Undertow")) return ServerType.UNDERTOW;
        if (isClassPresent("org.jboss.Main")) return ServerType.JBOSS;
        if (isClassPresent("weblogic.Server")) return ServerType.WEBLOGIC;
        if (isClassPresent("com.ibm.websphere.product.VersionInfo")) return ServerType.WEBSPHERE;
        return ServerType.UNKNOWN;
    }
    private static boolean isClassPresent(String className) {
        try {
            Class.forName(className);
            return true;
        } catch (ClassNotFoundException e) {
            return false;
        }
    }
}

方法三:利用 Spring Boot 的條件注解

這種方式適合用于控制某些特定服務(wù)器下 Bean 的加載,是一種聲明式的判斷方法。

import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ServerSpecificConfig {
    @Bean
    @ConditionalOnClass(name = "org.apache.catalina.startup.Tomcat")
    public String tomcatOnlyBean() {
        return "僅當(dāng)應(yīng)用運(yùn)行在 Tomcat 服務(wù)器上時(shí),此 Bean 才會被創(chuàng)建";
    }
}

這個(gè)例子也可以作為快速判斷的依據(jù),當(dāng)你看到 tomcatOnlyBean 在應(yīng)用上下文中被創(chuàng)建,就可以認(rèn)為當(dāng)前運(yùn)行的是 Tomcat 容器。

方法四:監(jiān)聽容器初始化事件

通過實(shí)現(xiàn) ApplicationListener<ServletWebServerInitializedEvent> 接口,可以在 Servlet 容器完成初始化后獲取 WebServer 實(shí)例,從而獲取服務(wù)器的具體實(shí)現(xiàn)類,反推出其類型。

import org.springframework.boot.web.context.WebServerInitializedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
@Component
public class WebServerListener implements ApplicationListener<WebServerInitializedEvent> {
    @Override
    public void onApplicationEvent(WebServerInitializedEvent event) {
        // 獲取 WebServer 實(shí)例,其實(shí)現(xiàn)類通常是 TomcatWebServer、JettyWebServer、UndertowWebServer 等
        Class<?> webServerClass = event.getWebServer().getClass();
        System.out.println("WebServer 實(shí)現(xiàn)類: " + webServerClass.getName());
        // 可根據(jù)實(shí)現(xiàn)類名判斷服務(wù)器類型
        if (webServerClass.getName().contains("Tomcat")) {
            System.out.println("當(dāng)前運(yùn)行在 Tomcat 服務(wù)器上");
        }
    }
}

補(bǔ)充說明

通用性與準(zhǔn)確性ServletContext.getServerInfo() 是標(biāo)準(zhǔn) Java Servlet 規(guī)范的一部分,在所有支持 Servlet 規(guī)范的容器中均可使用,且直接提供官方定義的服務(wù)器名稱,是最可靠的方法。

為什么可能有“多種判斷”:在某些特殊場景下(例如需要與不支持 Servlet API 的老舊代碼集成),可能需要采用其他方式。另外,getServerInfo() 返回的字符串版本號格式因服務(wù)器而異,有時(shí)需要自行解析。

方法選擇建議:對絕大多數(shù) Spring Boot 應(yīng)用,最推薦 ServletContext.getServerInfo()。若無法獲取 ServletContext,可使用“檢查類是否存在”的方法作為替代。若要根據(jù)服務(wù)器類型選擇性加載 Bean,應(yīng)優(yōu)先使用 Spring 的條件注解。

方法補(bǔ)充

該代碼片段通過檢查Spring應(yīng)用上下文中的Bean定義來判斷當(dāng)前使用的是Tomcat還是Jetty容器。使用@PostConstruct注解在初始化時(shí)執(zhí)行檢測邏輯,通過掃描Bean名稱是否包含EmbeddedTomcat或EmbeddedJetty來設(shè)置相應(yīng)的布爾標(biāo)志,并輸出日志記錄檢測結(jié)果。這種動(dòng)態(tài)識別方式適用于需要針對不同嵌入式容器做差異化處理的場景。

核心源碼

    boolean isTomcat;
    
    boolean isJetty;
    
    @Autowired
    ApplicationContext applicationContext;
    
    @PostConstruct
    private void init()
    {
        isTomcat = Stream.of(applicationContext.getBeanDefinitionNames()).anyMatch(name -> StringUtils.containsIgnoreCase(name, "EmbeddedTomcat"));
        isJetty = Stream.of(applicationContext.getBeanDefinitionNames()).anyMatch(name -> StringUtils.containsIgnoreCase(name, "EmbeddedJetty"));
        log.info("#### isTomcat: {}", isTomcat);
        log.info("#### isJetty: {}", isJetty);
    }

典型應(yīng)用

import java.io.File;
import java.io.IOException;
import java.util.stream.Stream;

import javax.annotation.PostConstruct;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.fly.demo.common.JsonResult;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Api(tags = "文件上傳(simple)")
@RestController
@RequestMapping("/simple/file")
public class SimpleFileController
{
    boolean isTomcat;
    
    boolean isJetty;
    
    @Autowired
    ApplicationContext applicationContext;
    
    @PostConstruct
    private void init()
    {
        isTomcat = Stream.of(applicationContext.getBeanDefinitionNames()).anyMatch(name -> StringUtils.containsIgnoreCase(name, "EmbeddedTomcat"));
        isJetty = Stream.of(applicationContext.getBeanDefinitionNames()).anyMatch(name -> StringUtils.containsIgnoreCase(name, "EmbeddedJetty"));
        log.info("#### isTomcat: {}", isTomcat);
        log.info("#### isJetty: {}", isJetty);
    }
    
    @ApiOperation("文件上傳")
    @PostMapping("/upload")
    public JsonResult<?> upload(@RequestParam MultipartFile file)
        throws IOException
    {
        File rootDir = new File("upload");
        File dest;
        if (isTomcat)
        {
            if (RandomUtils.nextBoolean())
            {
                log.info("### transferTo");
                dest = new File(rootDir.getCanonicalPath() + File.separator + file.getOriginalFilename());
                file.transferTo(dest);
            }
            else
            {
                log.info("### copyInputStreamToFile");
                dest = new File(rootDir, file.getOriginalFilename());
                FileUtils.copyInputStreamToFile(file.getInputStream(), dest);
            }
        }
        else
        {
            log.info("### copyInputStreamToFile");
            dest = new File(rootDir, file.getOriginalFilename());
            FileUtils.copyInputStreamToFile(file.getInputStream(), dest);
        } 
        return JsonResult.success(dest.getName());
    }
}

到此這篇關(guān)于詳解Springboot工程中如何快速判斷web應(yīng)用服務(wù)器類型的文章就介紹到這了,更多相關(guān)Springboot判斷web應(yīng)用服務(wù)器類型內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Nacos配置動(dòng)態(tài)刷新全過程

    Nacos配置動(dòng)態(tài)刷新全過程

    該技術(shù)方案通過使用nacos動(dòng)態(tài)刷新配置,解決了原系統(tǒng)在修改配置時(shí)需重啟的問題,通過在類上添加@RefreshScope注解和修改bootstrap.yml文件,確保配置修改后可以即時(shí)生效而無需重啟服務(wù),測試表明,修改配置后服務(wù)能夠立即讀取到新的配置內(nèi)容
    2025-10-10
  • springcloud?feign集成hystrix方式

    springcloud?feign集成hystrix方式

    這篇文章主要介紹了springcloud?feign集成hystrix方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • Java之MyBatis入門詳解

    Java之MyBatis入門詳解

    這篇文章主要介紹了Java之MyBatis入門詳解,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • Spring Boot 日志配置方法(超詳細(xì))

    Spring Boot 日志配置方法(超詳細(xì))

    默認(rèn)情況下,Spring Boot會用Logback來記錄日志,并用INFO級別輸出到控制臺。下面通過本文給大家介紹Spring Boot 日志配置方法詳解,感興趣的朋友參考下吧
    2017-07-07
  • Java圖形界面之JFrame,JLabel,JButton詳解

    Java圖形界面之JFrame,JLabel,JButton詳解

    這篇文章主要介紹了Java圖形界面之JFrame、JLabel、JButton詳解,文中有非常詳細(xì)的代碼示例,對正在學(xué)習(xí)java的小伙伴們有非常好的幫助,需要的朋友可以參考下
    2021-04-04
  • SpringBoot整合screw實(shí)現(xiàn)自動(dòng)生成數(shù)據(jù)庫設(shè)計(jì)文檔

    SpringBoot整合screw實(shí)現(xiàn)自動(dòng)生成數(shù)據(jù)庫設(shè)計(jì)文檔

    使用navicat工作的話,導(dǎo)出的格式是excel不符合格式,還得自己整理。所以本文將用screw工具包,整合到springboot的項(xiàng)目中便可以自動(dòng)生成數(shù)據(jù)庫設(shè)計(jì)文檔,非常方便,下面就分享一下教程
    2022-11-11
  • idea maven編譯報(bào)錯(cuò)Java heap space的解決方法

    idea maven編譯報(bào)錯(cuò)Java heap space的解決方法

    這篇文章主要為大家詳細(xì)介紹了idea maven編譯報(bào)錯(cuò)Java heap space的相關(guān)解決方法,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-04-04
  • 使用@PathVariable接收兩個(gè)參數(shù)

    使用@PathVariable接收兩個(gè)參數(shù)

    這篇文章主要介紹了使用@PathVariable接收兩個(gè)參數(shù)的操作,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • java面試常見問題之Hibernate總結(jié)

    java面試常見問題之Hibernate總結(jié)

    這篇文章主要介紹了在java面試過程中hibernate比較常見的問題,包括Hibernate的檢索方式,Hibernate中對象的狀態(tài),Hibernate的3種檢索策略是什么,Session的find()方法以及Query接口的區(qū)別等方面問題的總結(jié),需要的朋友可以參考下
    2015-07-07
  • Java利用泛型實(shí)現(xiàn)折半查找法

    Java利用泛型實(shí)現(xiàn)折半查找法

    泛型是JAVA重要的特性,使用泛型編程,可以使代碼復(fù)用率提高。查找作為泛型的一個(gè)簡單應(yīng)用,本文將使用泛型實(shí)現(xiàn)折半查找法,感興趣的可以了解一下
    2022-08-08

最新評論

渑池县| 通海县| 通州区| 新泰市| 陇南市| 怀安县| 霍州市| 伊金霍洛旗| 太和县| 营山县| 龙泉市| 合江县| 连江县| 射阳县| 徐水县| 洱源县| 德阳市| 长岭县| 南皮县| 泸定县| 辽宁省| 南宁市| 徐汇区| 清新县| 沧源| 深圳市| 游戏| 霞浦县| 景洪市| 张北县| 抚远县| 嵩明县| 新竹市| 安福县| 铅山县| 内乡县| 新化县| 秭归县| 衡南县| 汝阳县| 广昌县|