当前位置: 首页 > news >正文

用jq和ajax做能登陆注册的一个网站整站优化关键词排名

用jq和ajax做能登陆注册的一个网站,整站优化关键词排名,网站建设套定额,百度宣传广告要多少钱文章目录 前情提要发散探索从management.port开始确定否需要开启额外端口额外端口是如何开启的ManagementContextFactory的故事从哪儿来创建过程 management 相关API如何被注册 小结 前情提要 最近遇到一个需求,在单个服务进程上开启多网络端口,将API的…

文章目录

  • 前情提要
  • 发散探索
  • 从management.port开始
    • 确定否需要开启额外端口
    • 额外端口是如何开启的
    • ManagementContextFactory的故事
      • 从哪儿来
      • 创建过程
    • management 相关API如何被注册
  • 小结

前情提要

最近遇到一个需求,在单个服务进程上开启多网络端口,将API的访问通过端口强行隔离开。

发散探索

  1. SpringBoot自带的多端口配置,server.port和management.port,将常规的API与管理相关API通过端口拆分开;
  2. 1中的端口是基于HTTP/1.1通信的,如果需要基于HTTP/2.0(如gRPC)又会有些差别;
  3. 一般一个进程内SpringApplication对象只有1个,理论上搞多个自然就能开启多个端口,略显粗暴;
    本着探索的态度,我会逐个探讨上述3个方向,本文先关注在方向1上。如果你有更NB的问题或者建议,欢迎评论区留言。

从management.port开始

配置生效依赖SpringBoot的AutoConfiguration机制,management相关配置体现在ManagementContextAutoConfiguration中,完成ManagementContext的配置;其中涉及的问题如下。

确定否需要开启额外端口

@ConditionalOnManagementPort决定了是否开启新端口,该注解声明如下

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Documented
@Conditional(OnManagementPortCondition.class)
public @interface ConditionalOnManagementPort {/*** The {@link ManagementPortType} to match.* @return the port type*/ManagementPortType value();}

其依赖的OnManagementPortCondition会在配置过程中被处理,处理概要过程如下:

  1. 基于当前的Environment决定实际的ManagementPortType;
  2. 获得当前注解中value对应的设定ManagementPortType;
  3. 基于1和2决定被其注解的bean是否初始化,ManagementPortType的定义如下
public enum ManagementPortType {/*** The management port has been disabled.*/DISABLED,/*** The management port is the same as the server port.*/SAME,/*** The management port and server port are different.*/DIFFERENT;/*** Look at the given environment to determine if the {@link ManagementPortType} is* {@link #DISABLED}, {@link #SAME} or {@link #DIFFERENT}.* @param environment the Spring environment* @return {@link #DISABLED} if {@code management.server.port} is set to a negative* value, {@link #SAME} if {@code management.server.port} is not specified or equal to* {@code server.port} and {@link #DIFFERENT} otherwise.* @since 2.1.4*/public static ManagementPortType get(Environment environment) {Integer managementPort = getPortProperty(environment, "management.server.");if (managementPort != null && managementPort < 0) {return DISABLED;}Integer serverPort = getPortProperty(environment, "server.");return ((managementPort == null || (serverPort == null && managementPort.equals(8080))|| (managementPort != 0 && managementPort.equals(serverPort))) ? SAME : DIFFERENT);}private static Integer getPortProperty(Environment environment, String prefix) {return environment.getProperty(prefix + "port", Integer.class);}}

额外端口是如何开启的

到这里,我们可以回到ManagementContextAutoConfiguration,针对性地关注@ConditionalOnManagementPort(ManagementPortType.DIFFERENT)相关类, 也就是下面这段

    @Configuration(proxyBeanMethods = false)@ConditionalOnManagementPort(ManagementPortType.DIFFERENT)static class DifferentManagementContextConfiguration implements ApplicationListener<WebServerInitializedEvent> {private final ApplicationContext applicationContext;private final ManagementContextFactory managementContextFactory;DifferentManagementContextConfiguration(ApplicationContext applicationContext,ManagementContextFactory managementContextFactory) {this.applicationContext = applicationContext;this.managementContextFactory = managementContextFactory;}@Overridepublic void onApplicationEvent(WebServerInitializedEvent event) {if (event.getApplicationContext().equals(this.applicationContext)) {ConfigurableWebServerApplicationContext managementContext = this.managementContextFactory.createManagementContext(this.applicationContext,EnableChildManagementContextConfiguration.class,PropertyPlaceholderAutoConfiguration.class);if (isLazyInitialization()) {managementContext.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());}managementContext.setServerNamespace("management");managementContext.setId(this.applicationContext.getId() + ":management");setClassLoaderIfPossible(managementContext);CloseManagementContextListener.addIfPossible(this.applicationContext, managementContext);managementContext.refresh();}}protected boolean isLazyInitialization() {AbstractApplicationContext context = (AbstractApplicationContext) this.applicationContext;List<BeanFactoryPostProcessor> postProcessors = context.getBeanFactoryPostProcessors();return postProcessors.stream().anyMatch(LazyInitializationBeanFactoryPostProcessor.class::isInstance);}private void setClassLoaderIfPossible(ConfigurableApplicationContext child) {if (child instanceof DefaultResourceLoader) {((DefaultResourceLoader) child).setClassLoader(this.applicationContext.getClassLoader());}}}

从中我们可以发现几个点:

  1. ManagementContext是在主WebApplicationContext发布事件WebServerInitializedEvent后开始初始化;
  2. ManagementContext全新的ConfigurableWebServerApplicationContext,这意味着最终启动后,内存中存在至少两个ApplicationContext;如果说开启两个SpringApplication对象是表象的话,那么创建两个WebApplicationContext应该说就是底层的本质了;
  3. 整个处理过程就是创建ConfigurableWebServerApplicationContext,后续做必要的配置,最后refresh。如果你分析过SpringApplication.run(),那想必你看到了熟悉的味道。

ManagementContextFactory的故事

从哪儿来

对应的子类有两个,ReactiveManagementContextFactory和ServletManagementContextFactory,具体初始化则由xxxManagementContextFactoryAutoConfiguration影响,更进一步的细节藏在
@ConditionalOnWebApplication(type=xxx)中。

创建过程

以ReactiveManagementContextFactory为例

@Overridepublic ConfigurableWebServerApplicationContext createManagementContext(ApplicationContext parent,Class<?>... configClasses) {// 复用EnvironmentEnvironment parentEnvironment = parent.getEnvironment();ConfigurableEnvironment childEnvironment = ApplicationContextFactory.DEFAULT.createEnvironment(WebApplicationType.REACTIVE);if (parentEnvironment instanceof ConfigurableEnvironment) {// 复用ConversionServicechildEnvironment.setConversionService(((ConfigurableEnvironment) parentEnvironment).getConversionService());}AnnotationConfigReactiveWebServerApplicationContext child = new AnnotationConfigReactiveWebServerApplicationContext();child.setEnvironment(childEnvironment);// 这里可以看到最终会是parent和child关系child.setParent(parent);/*
这里以编程的方式完成BeanDefinition注册, 这里的configClass =     {EnableChildManagementContextConfiguration.class,PropertyPlaceholderAutoConfiguration.class}		*/Class<?>[] combinedClasses = ObjectUtils.addObjectToArray(configClasses,ReactiveWebServerFactoryAutoConfiguration.class);child.register(combinedClasses);// 最后保持parent和child的WebFactory一致, 直接复用parent的BeanDefinitionregisterReactiveWebServerFactory(parent, child);return child;}

management 相关API如何被注册

经过前面一波分析,我们已经看到了创建ApplicationContext,注册必要的Class,而后refresh整个容器就要启动,但没有看到management相关API,其实就藏在EnableChildManagementContextConfiguration.class这里, 从这里出发最终找到配置文件ManagementContextConfiguration.imports,链路如下

EnableManagementContext -> ManagementContextConfigurationImportSelector -> META-INFO/spring/org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration.imports

ManagementContextConfiguration.imports的内容如下:

org.springframework.boot.actuate.autoconfigure.endpoint.web.ServletEndpointManagementContextConfiguration
org.springframework.boot.actuate.autoconfigure.endpoint.web.reactive.WebFluxEndpointManagementContextConfiguration
org.springframework.boot.actuate.autoconfigure.endpoint.web.servlet.WebMvcEndpointManagementContextConfiguration
org.springframework.boot.actuate.autoconfigure.endpoint.web.jersey.JerseyWebEndpointManagementContextConfiguration
org.springframework.boot.actuate.autoconfigure.security.servlet.SecurityRequestMatchersManagementContextConfiguration
org.springframework.boot.actuate.autoconfigure.web.jersey.JerseySameManagementContextConfiguration
org.springframework.boot.actuate.autoconfigure.web.jersey.JerseyChildManagementContextConfiguration
org.springframework.boot.actuate.autoconfigure.web.reactive.ReactiveManagementChildContextConfiguration
org.springframework.boot.actuate.autoconfigure.web.servlet.ServletManagementChildContextConfiguration
org.springframework.boot.actuate.autoconfigure.web.servlet.WebMvcEndpointChildContextConfiguration

这些Configuration最终受如下2个注解的解决决定是否初始化
@ManagementContextConfiguration(value = ManagementContextType.xxx, proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.xxx)
最终不同的EndPoint由不同的EndPointDiscover对整个ApplicationContext中的类进行扫描并提取出来,组装为EndPointHandlerMapping。

到这里可以解释一个现象,就是在manage端口上,无法访问到应用端口上的API,因为两者各自关联了一个独立的HandlerMapping。虽然通常child context可以访问到parent context中的所有bean实例,但是各自可见的API被各自的RequestHandlerMapping限制而隔离。

小结

以上是针对mangement API开放独立端口的探究,从中有几个点值得借鉴:

  1. 独立的ApplicationContext可以作为资源隔离的一种方式,同时又不完全失去与parent的联系;
  2. 条件初始化在SpringBoot自动配置中的广泛应用;
  3. WebApplicationContext与ApplicationContext的区别在于WebServerFactory是否存在,以及RequestHandlerMapping+必要的注解识别,有了这点发现,做API隔离可用的方案也会更加丰富;
    后续会对另外2种实现方式做探讨,感谢你的阅读。
http://www.hengruixuexiao.com/news/27810.html

相关文章:

  • 邢台路桥建设总公司没有网站吗新浪体育nba
  • 北海做网站百度域名
  • 网站怎么做qq登录西安seo培训
  • 龙岩网站推广软件nba球队排名
  • 深圳龙华区高峰社区搜索引擎优化的重要性
  • 重庆市建设工程招投标信息网苏州搜索引擎优化
  • 锐奇智能手机网站建设免费网站在线客服软件
  • 黄岛网站建设公司企业邮箱登录入口
  • 莱州网站建设百度搜索推广平台
  • 外贸做零售的网站上海网络营销公司
  • 苏州吴中区建设局工程网站天天seo伪原创工具
  • 江阴市建设局网站管理通道电商推广平台有哪些
  • 2345网址大全历史版本seo网络推广培训班
  • 网站开发业务规划怎么自己刷推广链接
  • 苏州网站建设自助建站模板网页设计用什么软件
  • 东莞网站建设价格武汉seo优化分析
  • 什么网站不能备案网络营销的有哪些特点
  • 网站建设公司下载网络营销内容
  • 专门做网站的公司 南阳企业推广宣传文案
  • 电子商务网站建设 市场分析今日国内新闻10则
  • 云阳网站建设站长之家域名查询官网
  • 做视频网站需要多大带宽关键词快速排名seo怎么优化
  • 微软手机做网站服务器吗手机网址大全123客户端下载
  • 免费服务器试用站长工具seo
  • 幼儿园网站建设方案成人短期技能培训学校
  • 企业营销网站案例火锅店营销方案
  • 一站式建设最新战争新闻事件今天
  • 网站首页制作代码网站换了域名怎么查
  • 福州网站网页设计西安网站排名优化培训
  • 工信部网站手机备案查询google中文搜索引擎入口