解决springboot application.properties server.port配置问题

 更新时间:2021年08月13日 10:19:03   作者:quentinschuman  
这篇文章主要介绍了解决springboot application.properties server.port配置问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

springboot application.properties server.port配置的问题

近年来,springboot以其快速构建方便便捷,开箱即用,约定优于配置(Convention Over Configuration)的特性深受广大开发者喜爱。

springboot已经集成配置好了一套web开发的默认配置,开发者可以无需修改任何配置即可开始一个web工程,但是实际情况中有时候开发者还是需要修改部分默认配置项来使其更加契合自己的项目需求。

下面就其中一个小问题做个记录

在配置服务启动的端口时,springboot默认在application.properties配置文件中提供了server.port配置项来

让开发者自行配置服务启动端口号,**但是注意:**

#服务启动端口号
server.port=8889

该配置项要想生效其实是依赖于项目中内嵌的tomcat容器,如下图:

内嵌tomcat的jar包依赖包含在pom中

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

如果pom中不引人上述依赖,那么项目中不会导入内嵌tomcat的jar包,相应的application.properties配置文件中server.port配置项也将无法生效,因为该配置项实际上修改的就是内嵌tomcat的web端口号。

Spring Boot server.port配置原理

我们经常配置server.port=xxx,但其实这是一个比较复杂的过程才生效的,这次讲讲生效的过程。

1. autoConfigure

本质来源于自动配置

org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryConfiguration

TomcatServletWebServerFactory

为什么是这个类,核心是beanPostProcess原理

@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)
public class ServerProperties {
 
	/**
	 * Server HTTP port.
	 */
	private Integer port;

beanPostProcess

public class WebServerFactoryCustomizerBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware {
 
	private ListableBeanFactory beanFactory; 
	private List<WebServerFactoryCustomizer<?>> customizers;  
	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		if (bean instanceof WebServerFactory) {
			postProcessBeforeInitialization((WebServerFactory) bean);
		}
		return bean;
	} 
	
	@SuppressWarnings("unchecked")
	private void postProcessBeforeInitialization(WebServerFactory webServerFactory) {
		LambdaSafe.callbacks(WebServerFactoryCustomizer.class, getCustomizers(), webServerFactory)
				.withLogger(WebServerFactoryCustomizerBeanPostProcessor.class)
				.invoke((customizer) -> customizer.customize(webServerFactory));
	}
 
    private Collection<WebServerFactoryCustomizer<?>> getCustomizers() {
		if (this.customizers == null) {
			// Look up does not include the parent context
			this.customizers = new ArrayList<>(getWebServerFactoryCustomizerBeans());
			this.customizers.sort(AnnotationAwareOrderComparator.INSTANCE);
			this.customizers = Collections.unmodifiableList(this.customizers);
		}
		return this.customizers;
	}
 
	@SuppressWarnings({ "unchecked", "rawtypes" })
	private Collection<WebServerFactoryCustomizer<?>> getWebServerFactoryCustomizerBeans() {
		return (Collection) this.beanFactory.getBeansOfType(WebServerFactoryCustomizer.class, false, false).values();
	}

最终

beanFactory.getBeansOfType(WebServerFactoryCustomizer.class, false, false).values()

WebServerFactoryCustomizer对象.customize(webServerFactory)

@Configuration
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@ConditionalOnClass(ServletRequest.class)
@ConditionalOnWebApplication(type = Type.SERVLET)
@EnableConfigurationProperties(ServerProperties.class)
@Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class,
		ServletWebServerFactoryConfiguration.EmbeddedTomcat.class,
		ServletWebServerFactoryConfiguration.EmbeddedJetty.class,
		ServletWebServerFactoryConfiguration.EmbeddedUndertow.class })
public class ServletWebServerFactoryAutoConfiguration {
 
	@Bean
	public ServletWebServerFactoryCustomizer servletWebServerFactoryCustomizer(ServerProperties serverProperties) {
		return new ServletWebServerFactoryCustomizer(serverProperties);
	}

这里就将port设置好了。

这里使用函数式编程,lambda表达式,将port的值设置进了

ConfigurableServletWebServerFactory ,即TomcatServletWebServerFactory对象

2. embed tomcat如何使用

tomcat创建时,会通过getBean方式获取工厂

就是 TomcatServletWebServerFactory

然后设置connector,从TomcatServletWebServerFactory读取port,设置connector,设置结束

总结

Spring Boot在解耦的时候绕了很多弯,先@Bean factory对象,然后BeanPostProcess,然后启动embed tomcat 在factory 中new Tomcat 然后设置Connector,设置port。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Java实现模拟机器人对话的示例代码

    Java实现模拟机器人对话的示例代码

    本文主要介绍了Java实现模拟机器人对话的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-06-06
  • Java实现线程同步方法及原理详解

    Java实现线程同步方法及原理详解

    这篇文章主要介绍了Java实现线程同步方法及原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-06-06
  • java中的DTO的使用示例

    java中的DTO的使用示例

    在Java中,DTO代表数据传输对象,本文主要介绍了java中的DTO的使用示例,具有一定的参考价值,感兴趣的可以了解一下
    2023-09-09
  • java类访问权限与成员访问权限解析

    java类访问权限与成员访问权限解析

    这篇文章主要针对java类访问权限与成员访问权限进行解析,对类与成员访问权限进行验证,感兴趣的小伙伴们可以参考一下
    2016-02-02
  • Java SpringBoot自动装配原理详解

    Java SpringBoot自动装配原理详解

    这篇文章主要介绍了详解Spring Boot自动装配的原理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-09-09
  • Spring Data JPA 设置字段默认值方式

    Spring Data JPA 设置字段默认值方式

    这篇文章主要介绍了Spring Data JPA设置字段默认值方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-11-11
  • redis发布订阅Java代码实现过程解析

    redis发布订阅Java代码实现过程解析

    这篇文章主要介绍了redis发布订阅Java代码实现过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-09-09
  • mybatis中#{}和${}的区别详解

    mybatis中#{}和${}的区别详解

    本文主要介绍了mybatis中#{}和${}的区别详解,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-01-01
  • 密码系统AES私钥RSA公钥的加解密示例

    密码系统AES私钥RSA公钥的加解密示例

    这篇文章主要为大家诠释并介绍了AES私钥RSA公钥的加解密系统示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步
    2022-03-03
  • java 实现线程同步的方式有哪些

    java 实现线程同步的方式有哪些

    当使用多个线程来访问同一个数据时,非常容易出现线程安全问题,所以我们用同步机制来解决这些问题,本文将详细介绍,需要的朋友可以参考下
    2012-11-11

最新评论