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

青岛信息网官网南宁seo网站排名优化公司

青岛信息网官网,南宁seo网站排名优化公司,全国最大的招商平台,p2p网站建设制作实现Tomcat和Jetty的切换 前言 上一篇文章我们聊到,SpringBoot中内置了web服务器,包括Tomcat、Jetty,并且实现了SpringBoot启动Tomcat的流程。 那么SpringBoot怎样自动切换成Jetty服务器呢? 接下来我们继续学习如何实现Tomcat…

实现Tomcat和Jetty的切换

前言

上一篇文章我们聊到,SpringBoot中内置了web服务器,包括Tomcat、Jetty,并且实现了SpringBoot启动Tomcat的流程。

那么SpringBoot怎样自动切换成Jetty服务器呢?

接下来我们继续学习如何实现Tomcat和Jetty的自动切换。

定义WebServer接口并实现

package com.ber.springboot;  import org.springframework.web.context.WebApplicationContext;  /**  * @Author 鳄鱼儿  * @Description TODO  * @date 2023/8/19 19:44  * @Version 1.0  */public interface WebServer {  void start(WebApplicationContext applicationContext);  
}

将BerSpringApplication类中startTomcat写到TomcatWebServer实现类中。

package com.ber.springboot;  import org.apache.catalina.*;  
import org.apache.catalina.connector.Connector;  
import org.apache.catalina.core.StandardContext;  
import org.apache.catalina.core.StandardEngine;  
import org.apache.catalina.core.StandardHost;  
import org.apache.catalina.startup.Tomcat;  
import org.springframework.web.context.WebApplicationContext;  
import org.springframework.web.servlet.DispatcherServlet;  /**  * @Author 鳄鱼儿  * @Description TODO  * @date 2023/8/19 19:45  * @Version 1.0  */  
public class TomcatWebServer implements WebServer{  @Override  public void start(WebApplicationContext applicationContext) {  System.out.println("启动Tomcat");  Tomcat tomcat = new Tomcat();  Server server = tomcat.getServer();  Service service = server.findService("Tomcat");  Connector connector = new Connector();  connector.setPort(8023);  Engine engine = new StandardEngine();  engine.setDefaultHost("localhost");  Host host = new StandardHost();  host.setName("localhost");  String contextPath = "";  Context context = new StandardContext();  context.setPath(contextPath);  context.addLifecycleListener(new Tomcat.FixContextListener());  host.addChild(context);  engine.addChild(host);  service.setContainer(engine);  service.addConnector(connector);  tomcat.addServlet(contextPath, "dispatcher", new DispatcherServlet(applicationContext));  context.addServletMappingDecoded("/*", "dispatcher");  try {  tomcat.start();  } catch (LifecycleException e) {  e.printStackTrace();  }  }  
}

JettyWebServer类同样实现WebServer接口,不过具体启动Jetty代码省略,不在本文探讨范围内。

package com.ber.springboot;  /**  * @Author 鳄鱼儿  * @Description TODO  * @date 2023/8/19 19:46  * @Version 1.0  */  
public class JettyWebServer implements WebServer{  @Override  public void start() {  System.out.println("启动Jetty");  }  
}

修改BerSpringApplication类

package com.ber.springboot;  import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;  import java.util.Map;  /**  * @Author 鳄鱼儿  * @Description TODO  * @date 2023/8/19 14:08  * @Version 1.0  */  
public class BerSpringApplication {  public static void run(Class clazz) {  // 1. 创建Spring 容器  AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();  applicationContext.register(clazz);  applicationContext.refresh();  // 2. 获取特定WebServer类型的Bean  WebServer webServer = getWebServer(applicationContext);  // 3. 调用start方法  webServer.start(applicationContext);  }  private static WebServer getWebServer(AnnotationConfigWebApplicationContext applicationContext) {  // key为beanName, value为Bean对象  Map<String, WebServer> webServers = applicationContext.getBeansOfType(WebServer.class);  if (webServers.isEmpty()) {  throw new NullPointerException();  }  if (webServers.size() > 1) {  throw new IllegalStateException();  }  return webServers.values().stream().findFirst().get();  }  
}

在run方法中,获取到特定的web服务器,并通过start方法进行 启动。

getWebServer方法实现判断web服务器,并处理特殊情况——没有web服务器或者出现多个web服务器。

条件注解

package com.ber.springboot;  import org.springframework.context.annotation.Conditional;  import java.lang.annotation.ElementType;  
import java.lang.annotation.Retention;  
import java.lang.annotation.RetentionPolicy;  
import java.lang.annotation.Target;  /**  * @Author 鳄鱼儿  * @Description TODO  * @date 2023/8/19 20:06  * @Version 1.0  */  
@Target({ElementType.TYPE, ElementType.METHOD})  
@Retention(RetentionPolicy.RUNTIME)  
@Conditional(BerOnClassConsition.class)  
public @interface BerConditionalOnClass {  String value() default "";  
}

具体步骤为:

  1. 拿到@BerConditionalOnClass中的value属性
  2. 类加载器进行加载,加载到了特定的类名,则符合条件;否则不符合条件
package com.ber.springboot;  import org.springframework.context.annotation.Condition;  
import org.springframework.context.annotation.ConditionContext;  
import org.springframework.core.type.AnnotatedTypeMetadata;  import java.util.Map;  /**  * @Author 鳄鱼儿  * @Description TODO  * @date 2023/8/19 20:08  * @Version 1.0  */  
public class BerOnClassConsition implements Condition {  @Override  public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {  Map<String, Object> annotationAttributes =  metadata.getAnnotationAttributes(BerConditionalOnClass.class.getName());  // 1. 拿到@BerConditionalOnClass中的value属性  String className = (String) annotationAttributes.get("value");  // 2. 类加载器进行加载  try {  // 2.1 加载到了特定的类名,则符合条件 true            context.getClassLoader().loadClass(className);  return true;  } catch (ClassNotFoundException e) {  // 2.2 加载不到,则不符合条件 false            return false;  }  }  
}

自动配置类

package com.ber.springboot;  import org.springframework.context.annotation.Bean;  
import org.springframework.context.annotation.Configuration;  /**  * @Author 鳄鱼儿  * @Description TODO  * @date 2023/8/19 20:34  * @Version 1.0  */  
@Configuration  
public class WebServiceAutoConfiguration implements AutoConfiguration{  @Bean  @BerConditionalOnClass("org.apache.catalina.startup.Tomcat")  public TomcatWebServer tomcatWebServer() {  return new TomcatWebServer();  }  @Bean  @BerConditionalOnClass("org.eclipse.jetty.server.Server")  public JettyWebServer jettyWebServer() {  return new JettyWebServer();  }  
}

自动配置类在Spring Boot应用程序中起着关键的作用,它们是实现自动化配置的核心组件。

这里定义满足各自条件的Bean,当org.apache.catalina.startup.Tomcat类存在时,TomcatWebServer的Bean才存在,另一个亦是如此。

当spring容器存在Bean时,就可以通过BerSpringApplication类getWebServer方法中的applicationContext.getBeansOfType(WebServer.class)获取到,并由此可以进行对web服务器是否存在的判断。

SPI机制发现WebServiceAutoConfiguration

刚刚我们定义了自动配置类,但运行user模块的Userapplication启动类时,发现是无法发现WebServiceAutoConfiguration配置类的。

这是因为我们传入了Userapplication作为配置类,扫描路径为Userapplication所在的包路径,是无法扫描到WebServiceAutoConfiguration类的。

在springboot中实现了类似SPI的思想,就是项目中的spring.factories文件,提供了一种可插拔的扩展机制,使开发人员能够轻松地定制应用程序的行为和功能,同时又能保持主应用程序的稳定性。

这里我们可以借助JDK的SPI机制实现发现WebServiceAutoConfiguration类。

在springboot模块中增加resources/META-INF/services/com.ber.springboot.AutoConfiguration文件,具体路径如图所示:

JDK的SPI.png

com.ber.springboot.WebServiceAutoConfiguration

增加AutoConfiguration接口类和实现类。

package com.ber.springboot;  /**  * @Author 鳄鱼儿  * @Description TODO  * @date 2023/8/19 21:08  * @Version 1.0  */  
public interface AutoConfiguration {  
}
package com.ber.springboot;  import org.springframework.context.annotation.Bean;  
import org.springframework.context.annotation.Configuration;  /**  * @Author 鳄鱼儿  * @Description TODO  * @date 2023/8/19 20:34  * @Version 1.0  */  
@Configuration  
public class WebServiceAutoConfiguration implements AutoConfiguration{  @Bean  @BerConditionalOnClass("org.apache.catalina.startup.Tomcat")  public TomcatWebServer tomcatWebServer() {  return new TomcatWebServer();  }  @Bean  @BerConditionalOnClass("org.eclipse.jetty.server.Server")  public JettyWebServer jettyWebServer() {  return new JettyWebServer();  }  
}

并在注解类@BerSpringBootApplication上增加@Import(BerImportSelect.class)注解,BerImportSelect类从com.ber.springboot.AutoConfiguration文件中获取类名,然后添加到spring容器。

package com.ber.springboot;  import org.springframework.context.annotation.DeferredImportSelector;  
import org.springframework.core.type.AnnotationMetadata;  import java.util.ArrayList;  
import java.util.List;  
import java.util.ServiceLoader;  /**  * @Author 鳄鱼儿  * @Description * @date 2023/8/19 21:15  * @Version 1.0  */  
public class BerImportSelect implements DeferredImportSelector {  @Override  public String[] selectImports(AnnotationMetadata importingClassMetadata) {  /** 使用Java的ServiceLoader机制加载实现了AutoConfiguration接口的类  * AutoConfiguration是Spring Boot中用于自动配置的接口  * AutoConfiguration的实现类通常包含了一些配置信息,帮助应用程序在不需要显式配置的情况下自动完成一些功能  */  ServiceLoader<AutoConfiguration> serviceLoader = ServiceLoader.load(AutoConfiguration.class);  List<String> list = new ArrayList<>();  for (AutoConfiguration autoConfiguration : serviceLoader) {  list.add(autoConfiguration.getClass().getName());  }  // 返回包含所有加载的AutoConfiguration实现类名的字符串数组  return list.toArray(new String[0]);  }  
}

添加Jetty依赖

修改user模块的依赖如下:

<?xml version="1.0" encoding="UTF-8"?>  
<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/xsd/maven-4.0.0.xsd">  <parent>  <artifactId>simulate-springboot</artifactId>  <groupId>org.example</groupId>  <version>1.0-SNAPSHOT</version>  </parent>  <modelVersion>4.0.0</modelVersion>  <artifactId>user</artifactId>  <properties>  <maven.compiler.source>8</maven.compiler.source>  <maven.compiler.target>8</maven.compiler.target>  </properties>  <dependencies>  <dependency>  <groupId>org.example</groupId>  <artifactId>springboot</artifactId>  <version>1.0-SNAPSHOT</version>  <exclusions>  <exclusion>  <groupId>org.apache.tomcat.embed</groupId>  <artifactId>tomcat-embed-core</artifactId>  </exclusion>  </exclusions>  </dependency>  <dependency>  <groupId>org.eclipse.jetty</groupId>  <artifactId>jetty-server</artifactId>  <version>9.4.43.v20210629</version>  </dependency>  </dependencies>  </project>

这里需要排除tomcat依赖,因为springboot中已经添加了tomcat的依赖。

不排除就会出来既有tomcat又有Jetty,就会出现IllegalStateException异常。

到此运行user模块的UserApplication类就可以啦。

http://www.r43.cn/news/150220.html

相关文章:

  • 从网站栏目看网站功能小程序开发流程
  • 做网站需要会什么条件seo自学网app
  • asp.net做的网站模板seo外包方案
  • 比较好的网站空间策划推广
  • 备案接入阿里云后原网站还能访问吗关键词优化排名的步骤
  • 快速做网站费用贵州网站seo
  • 株洲网站搜索优化关键词搜索
  • 广告公司管理制度优化防控举措
  • 学校网站 功能南宁seo平台标准
  • 江苏网站建设机构百度推广账号登陆入口
  • 江苏州 网站制作精准营销及推广
  • wordpress 页面宽度游戏优化大师下载安装
  • 去哪个网站做兼职0元入驻的电商平台
  • 外贸做哪个网站平台全网营销整合营销
  • 手机网站开发软件seo推广案例
  • 精品网站建设费用磐石网络免费网站大全
  • 工厂的网站在哪里做的网站友情链接的好处
  • 找人做网站要准备什么软件百度怎么推广自己的信息
  • 龙岩网站制作公司seo查询seo优化
  • 深圳做微信商城网站搜索引擎排名影响因素有哪些
  • it网上做笔记的网站网站关键词如何优化
  • 苏宁推客如何做网站北京做网站推广
  • 新加坡网站建设公司百度推广一个关键词多少钱
  • 沈阳微网站seo关键词是什么意思
  • 柳州中小企业网站建设网页设计页面
  • 重庆做网站建设哪家好上海网站排名推广
  • 网站制作一般要几天云南网站建设公司哪家好
  • 唐山网站建设最好的微信怎么推广引流客户
  • dede网站移动端怎么做app推广方案
  • 登不上学校的网站该怎么做微信运营方案