项目端口号
背景
在实际项目中有时会一个项目代码启动多个实例。这时获取项目端口号可以防止重复执行一些定时任务,限定定时任务仅能在对应端口执行。防止多个实例时重复执行定时任务。
环境
- jdk:12
- tomcat: 9
- spring-boot:2.2.1.RELEASE
- ide: Eclipse
- 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