动态获取项目运行的端口号

背景

在实际项目中有时会一个项目代码启动多个实例。这时获取项目端口号可以防止重复执行一些定时任务,限定定时任务仅能在对应端口执行。防止多个实例时重复执行定时任务。

环境

  1. jdk:12
  2. tomcat: 9
  3. spring-boot:2.2.1.RELEASE
  4. ide: Eclipse
  5. pc:windows10

代码

pom依赖

<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 http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.llc</groupId>
	<artifactId>boot-port</artifactId>
	<packaging>war</packaging>
	<version>0.0.1-SNAPSHOT</version>
	<name>boot-port Maven Webapp</name>
	<url>http://maven.apache.org</url>
	
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.2.1.RELEASE</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>12</java.version>
	</properties>


	<dependencies>
		<!-- 测试依赖 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<!-- tomcat -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-tomcat</artifactId>
			<scope>provided</scope>
		</dependency>
		<!-- web -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

	</dependencies>
	<build>
		<finalName>port</finalName>
	</build>
</project>

yml

配置Spring-boot直接启动参数

server: 
  tomcat: 
        uri-encoding: UTF-8
        max-threads: 1000
        min-spare-threads: 30
  port: 8080
  servlet:
    context-path: /port
    
spring:
  jmx: 
    default-domain: ${server.servlet.context-path}

Spring-boot项目入口

package com.llc.port;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.scheduling.annotation.EnableScheduling;

/**
 * 	当要运行在tomcat等三方插件是,要实现SpringBootServletInitializer,不然认不到项目
 * @author linlvcao
 * @email 1013573731@qq.com
 * @time 2019年12月16日 下午4:43:58
 *
 */
@SpringBootApplication		//	标注程序为Spring-boot项目
@EnableScheduling			//	开启定时功能
public class PortApplication extends SpringBootServletInitializer {
	
	public static void main(String[] args) {
		SpringApplication.run(PortApplication.class, args);
	}
	
	@Override
	protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
		return application.sources(PortApplication.class);
	}

}

配置获取端口号

tomcat

运行在tomcat等三方插件时,获取端口

package com.llc.port.config;

import java.util.Iterator;
import java.util.Set;

import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.ObjectName;
import javax.management.Query;

import org.springframework.context.annotation.Configuration;

/**
 * 	运行在tomcat等三方插件时,获取端口
 * @author linlvcao
 * @email 1013573731@qq.com
 * @time 2019年12月16日 下午4:40:18
 *
 */
@Configuration
public class GetPort {

    public int getPort() {
    	try {
            MBeanServer server;
            if (MBeanServerFactory.findMBeanServer(null).size() > 0) {
                server = MBeanServerFactory.findMBeanServer(null).get(0);
            } else {
                return -1;
            }
     
            Set<ObjectName> names = server.queryNames(new ObjectName("Catalina:type=Connector,*"),
                    Query.match(Query.attr("protocol"), Query.value("HTTP/1.1")));
     
            Iterator<ObjectName> iterator = names.iterator();
            if (iterator.hasNext()) {
                ObjectName name = iterator.next();
                return Integer.parseInt(server.getAttribute(name, "port").toString());
            }
        } catch (Exception e) {
        	e.printStackTrace();
        }
        return -1;

    }

    
}

Spring-boot启动

package com.llc.port.config;

import org.springframework.boot.web.context.WebServerInitializedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

/**
 *	这个配置文件仅在直接通过PortApplication.java运行启动才会生效
 * @author linlvcao
 * @email 1013573731@qq.com
 * @time 2019年12月16日 下午4:40:06
 *
 */
@Component
public class SpringPortConfig implements ApplicationListener<WebServerInitializedEvent> {

    private int serverPort;

    @Override
    public void onApplicationEvent(WebServerInitializedEvent event) {
        this.serverPort = event.getWebServer().getPort();
        System.err.println("init…………");
    }

    public int getPort() {
        return this.serverPort;
    }
}

前两者整合

package com.llc.port.config;

import java.util.Iterator;
import java.util.Set;

import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.ObjectName;
import javax.management.Query;

import org.springframework.boot.web.context.WebServerInitializedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

/**
 *	 获取当前项目运行端口号---整合
 * @author linlvcao
 * @email 1013573731@qq.com
 * @time 2019年12月16日 下午4:39:51
 *
 */
@Component
public class PortConfig implements ApplicationListener<WebServerInitializedEvent> {
	
	private Integer port = 0;
	
	/**
	 * 	对外获取当前项目端口
	 * @return
	 */
	public Integer getProPort() {
		if (this.port == 0) {	//	表明当前项目运行在第三方插件(如tomcat)
			this.port = getPort();
		}
		return this.port;
	}

	@Override
	public void onApplicationEvent(WebServerInitializedEvent event) {
		this.port = event.getWebServer().getPort();
	}
	
	/**
	 * 	第三方获取项目端口
	 * @return
	 */
	private int getPort() {
    	try {
            MBeanServer server;
            if (MBeanServerFactory.findMBeanServer(null).size() > 0) {
                server = MBeanServerFactory.findMBeanServer(null).get(0);
            } else {
                return -1;
            }
     
            Set<ObjectName> names = server.queryNames(new ObjectName("Catalina:type=Connector,*"),
                    Query.match(Query.attr("protocol"), Query.value("HTTP/1.1")));
     
            Iterator<ObjectName> iterator = names.iterator();
            if (iterator.hasNext()) {
                ObjectName name = iterator.next();
                return Integer.parseInt(server.getAttribute(name, "port").toString());
            }
        } catch (Exception e) {
        	e.printStackTrace();
        }
        return -1;

    }

}

定时器

package com.llc.port.schduled;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import com.llc.port.config.GetPort;
import com.llc.port.config.PortConfig;
import com.llc.port.config.SpringPortConfig;

/**
 * 	获取当前项目运行端口测试----定时
 * @author linlvcao
 * @email 1013573731@qq.com
 * @time 2019年12月16日 下午4:40:29
 *
 */
@Component
public class ScheduledTask {

	/**
	 * 	运行在tomcat环境下
	 */
	@Autowired
	private GetPort tomcatPort;
	
	/**
	 * 	直接启动项目
	 */
	@Autowired
	private SpringPortConfig springPort;
	
	/**
	 * 	上面两个功能整合
	 */
	@Autowired
	private PortConfig portConfig;

	/**
	 * 	每三秒执行一次,便于测试
	 */
	@Scheduled(cron = "0/3 * * * * *")
	public void reportCurrentTimeCron() {
		System.err.println("=======tomcat========");
		System.err.println(tomcatPort.getPort());
		
		
		System.err.println("========spring-boot=======");
		System.err.println(springPort.getPort());
		
		
		System.err.println("============整合===============");
		System.err.println(portConfig.getProPort());
	}
	
}

效果测试

直接Spring-boot运行

在这里插入图片描述

运行在tomcat

在这里插入图片描述

项目地址

https://gitee.com/llc-Spring/boot-port

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值