精华内容
下载资源
问答
  • 本文主要针对内嵌服务器的原理以及如何切换不同内嵌服务器进行介绍。 下面针对springBoot2.3.4版本进行简单的介绍。springBoot主要内嵌的服务器从官方文档可以看到: 由此可知,主要集成了jetty,netty,tomcat以及...

    SpringBoot 集成的服务器源码分析

    本文主要针对内嵌服务器的原理以及如何切换不同内嵌服务器进行介绍。
    下面针对springBoot2.3.4版本进行简单的介绍。springBoot主要内嵌的服务器从官方文档可以看到:
    在这里插入图片描述
    由此可知,主要集成了jetty(适合交互式消息),tomcat以及undertow(不支持JSP,并发性能较高)三种,spring-boot-starter-web默认使用的是tomcat服务器。我们在启动springboot的时候就会发现,不需要导入tomcat组件就可以直接运行,这就是内嵌服务器。这与传统的打war包不同,内嵌服务器直接将项目打包成jar包,使用 java -jar + jar包名 来直接部署,而打war包需将war包放入tomcat目录下的webapps,启动Tomcat才可以。

    如何修改这些内嵌服务器的配置

    查看ServerProperties.class类

    public class ServerProperties {
     private Integer port;
     private InetAddress address;
     @NestedConfigurationProperty
     private final ErrorProperties error = new ErrorProperties();
     private ServerProperties.ForwardHeadersStrategy forwardHeadersStrategy;
     private String serverHeader;
     private DataSize maxHttpHeaderSize = DataSize.ofKilobytes(8L);
     private Shutdown shutdown;
     @NestedConfigurationProperty
     private Ssl ssl;
     @NestedConfigurationProperty
     private final Compression compression;
     @NestedConfigurationProperty
     private final Http2 http2;
     private final ServerProperties.Servlet servlet;
     private final ServerProperties.Tomcat tomcat;
     private final ServerProperties.Jetty jetty;
     private final ServerProperties.Netty netty;
     private final ServerProperties.Undertow undertow;
    

    这些配置都可在application.yml/application-{profiles}.yml/application.properties等配置文件下配置,例如:

    server:
      port: 8089
      #开启压缩
      compression:
        enable: true
        #压缩文件类型
        # 触发压缩的最小内容长度
        min-response-size: 2048
        mime-types: /*
      servlet:
        # session 过期时间,注意单位是秒
        session:
          timeout: 3600
      undertow:
        threads:
          io: 8
          worker: 256
    

    如何切换内嵌服务器

    由于我们在引入spring-boot-starter-web模块的时候,默认会将tomcat作为servlet容器。因此,在pom.xml中更改如下:

    <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-web</artifactId>
             <exclusions>
                 <exclusion>
                     <groupId>org.springframework.boot</groupId>
                     <artifactId>spring-boot-starter-tomcat</artifactId>
                 </exclusion>
             </exclusions>
         </dependency>
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-undertow</artifactId>
         </dependency>
    

    内嵌服务器自动配置原理介绍(如何使用)

    在SpringBoot的自动配置类路径下找到:org\springframework\boot\spring-boot-autoconfigure\2.3.4.RELEASE\spring-boot-autoconfigure-2.3.4.RELEASE.jar!\org\springframework\boot\autoconfigure\web\servlet\ServletWebServerFactoryAutoConfiguration.class,

    @Configuration(
     proxyBeanMethods = false
    )
    @AutoConfigureOrder(-2147483648)
    @ConditionalOnClass({ServletRequest.class})
    @ConditionalOnWebApplication(
     type = Type.SERVLET
    )
    @EnableConfigurationProperties({ServerProperties.class})
    @Import({ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class, EmbeddedTomcat.class, EmbeddedJetty.class, EmbeddedUndertow.class})
    

    这里主要关注两个注解:
    @EnableConfigurationProperties({ServerProperties.class})//加载可配置的属性
    @Import({ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class, EmbeddedTomcat.class, EmbeddedJetty.class, EmbeddedUndertow.class})//导入内嵌服务器插件
    下面对具体实现进行分析:

    public class ServletWebServerFactoryAutoConfiguration {
        public ServletWebServerFactoryAutoConfiguration() {
        }
    
        @Bean
        public ServletWebServerFactoryCustomizer servletWebServerFactoryCustomizer(ServerProperties serverProperties) {
            return new ServletWebServerFactoryCustomizer(serverProperties);
        }
    
        @Bean
        @ConditionalOnClass(
            name = {"org.apache.catalina.startup.Tomcat"}
        )
        public TomcatServletWebServerFactoryCustomizer tomcatServletWebServerFactoryCustomizer(ServerProperties serverProperties) {
            return new TomcatServletWebServerFactoryCustomizer(serverProperties);
        }
    
        @Bean
        @ConditionalOnMissingFilterBean({ForwardedHeaderFilter.class})
        @ConditionalOnProperty(
            value = {"server.forward-headers-strategy"},
            havingValue = "framework"
        )
        public FilterRegistrationBean<ForwardedHeaderFilter> forwardedHeaderFilter() {
            ForwardedHeaderFilter filter = new ForwardedHeaderFilter();
            FilterRegistrationBean<ForwardedHeaderFilter> registration = new FilterRegistrationBean(filter, new ServletRegistrationBean[0]);
            registration.setDispatcherTypes(DispatcherType.REQUEST, new DispatcherType[]{DispatcherType.ASYNC, DispatcherType.ERROR});
            registration.setOrder(-2147483648);
            return registration;
        }
    //前面主要注册了三个Bean对象,分别为ServletWebServerFactoryCustomizer、TomcatServletWebServerFactoryCustomizer和FilterRegistrationBean。
    
        public static class BeanPostProcessorsRegistrar implements ImportBeanDefinitionRegistrar, BeanFactoryAware {
            private ConfigurableListableBeanFactory beanFactory;
    
            public BeanPostProcessorsRegistrar() {
            }
    
            public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
                if (beanFactory instanceof ConfigurableListableBeanFactory) {
                    this.beanFactory = (ConfigurableListableBeanFactory)beanFactory;
                }
    
            }
    
            public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
                if (this.beanFactory != null) {
                    this.registerSyntheticBeanIfMissing(registry, "webServerFactoryCustomizerBeanPostProcessor", WebServerFactoryCustomizerBeanPostProcessor.class);
                    this.registerSyntheticBeanIfMissing(registry, "errorPageRegistrarBeanPostProcessor", ErrorPageRegistrarBeanPostProcessor.class);
                }
            }
    
            private void registerSyntheticBeanIfMissing(BeanDefinitionRegistry registry, String name, Class<?> beanClass) {
                if (ObjectUtils.isEmpty(this.beanFactory.getBeanNamesForType(beanClass, true, false))) {
                    RootBeanDefinition beanDefinition = new RootBeanDefinition(beanClass);
                    beanDefinition.setSynthetic(true);
                    registry.registerBeanDefinition(name, beanDefinition);
                }
    
            }
        }
    }
    //后续三个函数主要注册了WebServerFactoryCustomizerBeanPostProcessor.class和ErrorPageRegistrarBeanPostProcessor.class两个类。
    

    分析:
    WebServerFactoryCustomizerBeanPostProcessor.class:后置处理器。bean初始化前后(创建完对象,还没赋值),执行初始化工作。
    //如果当前初始化的是一个webServerFactory对象,就执行postProcessBeforeInitialization
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    if (bean instanceof WebServerFactory) {
    this.postProcessBeforeInitialization((WebServerFactory)bean);
    }
    return bean;
    }
    //获取所有的定制器,调用每一个定制器的customize方法为其赋值。这里的customize方法就是为其做赋值处理的。
    private void postProcessBeforeInitialization(WebServerFactory webServerFactory) {
    ((Callbacks)LambdaSafe.callbacks(WebServerFactoryCustomizer.class, this.getCustomizers(), webServerFactory, new Object[0]).withLogger(WebServerFactoryCustomizerBeanPostProcessor.class)).invoke((customizer) -> {
    customizer.customize(webServerFactory);
    });
    }

    展开全文
  • Spring MVC 使用 Jetty 作为内嵌服务器

    千次阅读 2018-03-27 23:53:53
    在本文中,我们将使用 Spring Web MVC 技术来实现 REST 接口,并使用 使用 Jetty 作为内嵌服务器,方便测试。 接口设计 我们将会在系统中实现两个接口: GET http://localhost:8080/hello GET ...

    Jetty 是高性能的 Servlet 容器,经常会在开发环境中作为服务器来使用。在本文中,我们将使用 Spring Web MVC 技术来实现 REST 接口,并使用 使用 Jetty 作为内嵌服务器,方便测试。

    接口设计

    我们将会在系统中实现两个接口:

    其中,第一个接口“/hello”将会返回“Hello World!” 的字符串;而第二个接口“/hello/way”则会返回一个包含用户信息的JSON字符串。

    系统配置

    我们需要在应用中添加如下依赖:

    <properties>
        <spring.version>5.0.4.RELEASE</spring.version>
        <jetty.version>9.4.9.v20180320</jetty.version>
        <jackson.version>2.9.4</jackson.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-servlet</artifactId>
            <version>${jetty.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>${jackson.version}</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>${jackson.version}</version>
        </dependency>
    </dependencies>

    其中,

    • spring-webmvc 是为了使用 Spring MVC 的功能。
    • jetty-servlet是为了提供内嵌的 Servlet 容器,这样我们就无需依赖外部的容器,可以直接运行我们的应用。
    • jackson-corejackson-databind 为我们的应用提供 JSON 序列化的功能。

    后台编码实现

    领域模型

    创建一个 User 类,代表用户信息。

    public class User {
        private String username;
        private Integer age;
    
        public User(String username, Integer age) {
            this.username = username;
            this.age = age;
        }
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public Integer getAge() {
            return age;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    
    }

    控制器

    创建 HelloController 用于处理用户的请求。

    @RestController
    public class HelloController {
    
        @RequestMapping("/hello")
        public String hello() {
            return "Hello World! Welcome to visit waylau.com!";
        }
    
        @RequestMapping("/hello/way")
        public User helloWay() {
            return new User("Way Lau", 30);
        }
    }

    其中,映射到“/hello”的方法将会返回“Hello World!” 的字符串;而映射到“/hello/way”则会返回一个包含用户信息的JSON字符串。

    应用配置

    在本应用中,我们采用基于 Java 注解的配置。

    AppConfiguration 是我们的主应用配置:

    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Import;
    
    @Configuration
    @ComponentScan(basePackages = { "com.waylau.spring" })  
    @Import({ MvcConfiguration.class })
    public class AppConfiguration {
    
    }

    AppConfiguration 会扫描“com.waylau.spring”包下的文件,并自动将相关的 bean 进行注册。

    AppConfiguration 同时又引入了 MVC 的配置类 MvcConfiguration:

    @EnableWebMvc
    @Configuration
    public class MvcConfiguration implements WebMvcConfigurer {
    
        public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
            converters.add(new MappingJackson2HttpMessageConverter());
        }
    }

    MvcConfiguration 配置类一方面启用了 MVC 的功能,另一方面添加了 Jackson JSON 的转换器。

    最后,我们需要引入 Jetty 服务器 JettyServer:

    import org.eclipse.jetty.server.Server;
    import org.eclipse.jetty.servlet.ServletContextHandler;
    import org.eclipse.jetty.servlet.ServletHolder;
    import org.springframework.web.context.ContextLoaderListener;
    import org.springframework.web.context.WebApplicationContext;
    import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
    import org.springframework.web.servlet.DispatcherServlet;
    import com.waylau.spring.mvc.configuration.AppConfiguration;
    
    public class JettyServer {
        private static final int DEFAULT_PORT = 8080;
        private static final String CONTEXT_PATH = "/";
        private static final String MAPPING_URL = "/*";
    
        public void run() throws Exception {
            Server server = new Server(DEFAULT_PORT);
            server.setHandler(servletContextHandler(webApplicationContext()));
            server.start();
            server.join();
        }
    
        private ServletContextHandler servletContextHandler(WebApplicationContext context) {
            ServletContextHandler handler = new ServletContextHandler();
            handler.setContextPath(CONTEXT_PATH);
            handler.addServlet(new ServletHolder(new DispatcherServlet(context)), MAPPING_URL);
            handler.addEventListener(new ContextLoaderListener(context));
            return handler;
        }
    
        private WebApplicationContext webApplicationContext() {
            AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
            context.register(AppConfiguration.class);
            return context;
        }
    }

    JettyServer 将会在 Application 类中进行启动:

    public class Application {
    
        public static void main(String[] args) throws Exception {
            new JettyServer().run();;
        }
    
    }

    11.13.6 运行

    在编辑器中,直接运行 Application 类即可。启动之后,应能看到如下控制台信息:

    2018-03-21 23:14:52.665:INFO::main: Logging initialized @203ms to org.eclipse.jetty.util.log.StdErrLog
    2018-03-21 23:14:52.868:INFO:oejs.Server:main: jetty-9.4.9.v20180320; built: 2018-03-20T20:21:10+08:00; git: 1f8159b1e4a42d3f79997021ea1609f2fbac6de5; jvm 1.8.0_112-b15
    2018-03-21 23:14:52.902:INFO:oejshC.ROOT:main: Initializing Spring root WebApplicationContext
    三月 21, 2018 11:14:52 下午 org.springframework.web.context.ContextLoader initWebApplicationContext
    信息: Root WebApplicationContext: initialization started
    三月 21, 2018 11:14:52 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
    信息: Refreshing Root WebApplicationContext: startup date [Wed Mar 21 23:14:52 CST 2018]; root of context hierarchy
    三月 21, 2018 11:14:52 下午 org.springframework.web.context.support.AnnotationConfigWebApplicationContext loadBeanDefinitions
    信息: Registering annotated classes: [class com.waylau.spring.mvc.configuration.AppConfiguration]
    三月 21, 2018 11:14:53 下午 org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistry register
    信息: Mapped "{[/hello]}" onto public java.lang.String com.waylau.spring.mvc.controller.HelloController.hello()
    三月 21, 2018 11:14:53 下午 org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistry register
    信息: Mapped "{[/hello/way]}" onto public com.waylau.spring.mvc.vo.User com.waylau.spring.mvc.controller.HelloController.helloWay()
    三月 21, 2018 11:14:53 下午 org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter initControllerAdviceCache
    信息: Looking for @ControllerAdvice: Root WebApplicationContext: startup date [Wed Mar 21 23:14:52 CST 2018]; root of context hierarchy
    三月 21, 2018 11:14:53 下午 org.springframework.web.context.ContextLoader initWebApplicationContext
    信息: Root WebApplicationContext: initialization completed in 983 ms
    2018-03-21 23:14:53.893:INFO:oejshC.ROOT:main: Initializing Spring FrameworkServlet 'org.springframework.web.servlet.DispatcherServlet-6aaa5eb0'
    三月 21, 2018 11:14:53 下午 org.springframework.web.servlet.FrameworkServlet initServletBean
    信息: FrameworkServlet 'org.springframework.web.servlet.DispatcherServlet-6aaa5eb0': initialization started
    三月 21, 2018 11:14:53 下午 org.springframework.web.servlet.FrameworkServlet initServletBean
    信息: FrameworkServlet 'org.springframework.web.servlet.DispatcherServlet-6aaa5eb0': initialization completed in 15 ms
    2018-03-21 23:14:53.910:INFO:oejsh.ContextHandler:main: Started o.e.j.s.ServletContextHandler@2796aeae{/,null,AVAILABLE}
    2018-03-21 23:14:54.037:INFO:oejs.AbstractConnector:main: Started ServerConnector@42054532{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}
    2018-03-21 23:14:54.038:INFO:oejs.Server:main: Started @1578ms

    分别在浏览器中访问 “http://localhost:8080/hello” 和 “http://localhost:8080/hello/way” 地址进行测试,能看到图1和图2的响应效果。

    图1 “/hello”接口的返回内容

    图1 “/hello”接口的返回内容

    图2 “/hello/way”接口的返回内容

    图2 “/hello/way”接口的返回内容

    参考应用

    展开全文
  • 为什么Sprint Boot要内嵌服务器呢? 想象一下如果要部署一个Java应用都需要做些什么呢? 安装JDK 安装Web/Application服务器(Tomcat/Jetty etc) 部署war包 如果我们想要简化这个流程,并且只要拥有Java运行环境...

    为什么Sprint Boot要内嵌服务器呢?

    想象一下如果要部署一个Java应用都需要做些什么呢?

    1. 安装JDK
    2. 安装Web/Application服务器(Tomcat/Jetty etc)
    3. 部署war包

    如果我们想要简化这个流程,并且只要拥有Java运行环境就能够运行部署应用,要做些什么呢?

    在创建一个可部署的应用时,内嵌一个服务器,在Spring Boot创建一个应用时,会生产一个包含服务器的Jar包,这样就可以运行这个web application香java application 那样

    嵌入式服务器意味着我们的可部署单元包含服务器的二进制文件(例如tomcat.jar.

    展开全文
  • Jetty内嵌服务器实例

    2014-03-20 11:41:40
    jetty服务器内嵌实例,运行JettTest后即可访问
  • Tomcat7内嵌服务器

    2019-04-21 01:36:20
    NULL 博文链接:https://liuguxing.iteye.com/blog/1928161
  • 内嵌服务器?springboot优势初体验! 创建maven工厂,pom中添加依赖 编写main函数,类上标明@SpringBootApplication Controller层 使用@RestController注解 在resource目录下创建配置文件application.properties ...

    核心!

    场景starter - xxxxAutoConfiguration - 导入xxx组件 - 绑定xxxProperties – 绑定配置文件项

    开始

    内嵌服务器?springboot优势初体验!

    1. 创建maven工厂,pom中添加依赖
    2. 编写main函数,类上标明@SpringBootApplication
    3. Controller层 使用@RestController注解
    4. 在resource目录下创建配置文件application.properties
    5. 使用maven进行打包,通过命令行手动部署在Tomcat服务器中。cmd命令窗口下输入:
    java -jar  springboot-1.0-SNAPSHOT.jar
    

    springboot依赖管理与版本仲裁

    之所以只引入一个spring-boot-starter-parent这个jar包,在spring-boot-dependencies中springboot当前版本自动为开发者实现jar包导入管理。若开发者向更改当前依赖jar包版本号,只需在pom文件中就近原则声明properties自定义修改版本号,实现版本仲裁。

    包扫描

    使用@SpringBootApplication(scanBasePackages=“com.lwt”)或者不使用前者(前者包含后者)使用@ComponentScan

    自动配置原理

    spring-boot-starter-web-2.3.4.RELEASE.pom到spring-boot-starter-2.3.4.RELEASE.pom到spring-boot-autoconfigure-2.3.4.RELEASE.pom

    前期简单总结

    1. 引入依赖
    2. 查看自动配置 debug=true Negative/Positive
    3. application.properties配置参照
      https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-application-properties.html#common-application-properties 官网。

    开发技巧

    1. lombok @Data
    2. dev-tools
    <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>
    
    1. spring-Initailizr 初始化向导,返璞归真。
    展开全文
  • 我们知道spring 底层是servlet,而servlet必须运行在web容器中,而我们使用spring 并没有使用自己定义的tomcat,那为什么会有Tomcat给我们用呢? org.springframework.boot:spring-boot-starter-tomcat:2.4.3 ...
  • 为了完成web工程的测试,最近内嵌jetty也要搞起来.第一次搞还是挺焦头烂额的.直接上成果: package com.test.action; import java.io.File; import org.eclipse.jetty.server.Connector; import org.eclipse...
  • Embedding Jetty 创建简单的内嵌服务器

    千次阅读 2014-01-12 21:15:33
    创建内嵌的Jetty服务器主要有以下几个步骤: (1)创建一个Server实例 (2)添加或者配置一个Connectors (3)添加或者配置 Handler and/or Contexts and/or Servlet  (4)启动Server (5)等待服务,或者...
  • JavaWeb之Jetty和Tomcat内嵌服务器实现

    千次阅读 2017-10-22 13:33:55
    在开发Java web项目时候,可以在项目中嵌入tomcat和jetty服务器的方式来运行web程序。
  • 使用jetty作为内嵌服务器启动项目

    万次阅读 2012-05-11 13:47:32
    需求:把jetty作为内嵌的一个服务器,直接启动,web项目不用部署在应用服务器中。在网上搜索了一些资料,参照后,都没有成功,经过3天的研究,终于搞定了,记录在此,以备查询。 最开始用的jetty8.1,没成功,后又...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,122
精华内容 848
关键字:

内嵌服务器