zoukankan      html  css  js  c++  java
  • 20、springboot——使用外置的tomcat服务器

    嵌入式Servlet容器:应用打成可执行的j ar
    优点:简单、便携;
    缺点:默认不支持JSP、优化定制比较复杂
            使用定制器【ServerProperties、自定义
            EmbeddedServletContainerCustomizer】,
            自己编写嵌入式Servlet容器的创建工厂
            EmbeddedServletContainerFactory】
     
    外置的Servlet容器:外面安装Tomcat---应用war包的方式打包
     
    创建工程的时候使用war包

     添加xml配置文件

     

     

     
     添加外部的服务器:

     

     完成hello.jsp页面的跳转

     

    hello.jsp

     

    test.jsp

     test.java

     

     测试:

     

    总结:
    1)、必须创建一个war项目;(利用idea创建好目录结构
    2)、将嵌入式的Tomcat指定为provided
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
        <scope>provided</scope>
    </dependency>

     3)、必须编写一个SpringBootServletInitializer的子类,并调用configure方法(IDEA创建的时候回自带)

    4)、启动服务器就可以使用

    原理:

    jar包:执行SpringBoot主类的main方法,启动ioc容器,创建嵌入式的Servlet容器
     
    war包:启动服务器,服务器启动SpringBoot应用【SpringBootServletInitializer】,启动ioc容器
     
     
    servlet3.0(Spring注解版)
    章节:8.2.4 Shared libraries / runtimes pluggability
    规则:
    1)、服务器启动(web应用启动)会创建当前web应用里面每一个jar包里面ServletContainerInitializer实例:
    2)、ServletContainerInitializer的实现放在jar包的META-INF/services文件夹下,有一个名为
            javax.servlet.ServletContainerInitializer的全类名
    3)、还可以使用@HandlesTypes,在应用启动的时候加载我们感兴趣

    流程:

    1)、启动Tomcat
    2)、orgspringframeworkspring-web4.3.14.RELEASEspring-web-         5.1.3.RELEASE.jar!METAINFservicesjavax.servlet.ServletContainerInitializer:
      Spring的web模块里面有这个文件:

     

    3)、SpringServletContainerInitializer将@HandlesTypes(WebApplicationInitializer.class)标注的所
      有这个类型的类都传入到onStartup方法的Set>;为这些WebApplicationInitializer类型的类创建实例;
    复制代码
    @HandlesTypes({WebApplicationInitializer.class})
    public class SpringServletContainerInitializer implements ServletContainerInitializer {
        public SpringServletContainerInitializer() {
        }
    
        public void onStartup(@Nullable Set<Class<?>> webAppInitializerClasses, ServletContext servletContext) throws ServletException {
            List<WebApplicationInitializer> initializers = new LinkedList();
            Iterator var4;
            if (webAppInitializerClasses != null) {
                var4 = webAppInitializerClasses.iterator();
    
                while(var4.hasNext()) {
                    Class<?> waiClass = (Class)var4.next();
                    if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) && WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
                        try {
                            initializers.add((WebApplicationInitializer)ReflectionUtils.accessibleConstructor(waiClass, new Class[0]).newInstance());
                        } catch (Throwable var7) {
                            throw new ServletException("Failed to instantiate WebApplicationInitializer class", var7);
                        }
                    }
                }
            }
    
            if (initializers.isEmpty()) {
                servletContext.log("No Spring WebApplicationInitializer types detected on classpath");
            } else {
                servletContext.log(initializers.size() + " Spring WebApplicationInitializers detected on classpath");
                AnnotationAwareOrderComparator.sort(initializers);
                var4 = initializers.iterator();
    
                while(var4.hasNext()) {
                    WebApplicationInitializer initializer = (WebApplicationInitializer)var4.next();
                    initializer.onStartup(servletContext);
    }}}}
    复制代码
    4)、每一个WebApplicationInitializer都调用自己的onStartup;
    WebApplicationInitializer的实现

     

    是我们自己的Servletinitializer类
    5)、相当于我们的SpringBootServletInitializer的类会被创建对象,并执行onStartup方法
    6)、SpringBootServletInitializer实例执行onStartup的时候会createRootApplicationContext;创建容器
    public class ServletInitializer extends SpringBootServletInitializer {
        @Override
        protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
            return application.sources(WebJspApplication.class);
        }
    }

     SpringBootServletInitializer.java

    复制代码
    public void onStartup(ServletContext servletContext) throws ServletException {
        this.logger = LogFactory.getLog(this.getClass());
        WebApplicationContext rootAppContext = this.createRootApplicationContext(servletContext);
        if (rootAppContext != null) {
            servletContext.addListener(new ContextLoaderListener(rootAppContext) {
                public void contextInitialized(ServletContextEvent event) {
                }
            });
        } else {
            this.logger.debug("No ContextLoaderListener registered, as createRootApplicationContext() did not return an application context");
        }
    }
    
    .....
    复制代码
    复制代码
    protected WebApplicationContext createRootApplicationContext(
          ServletContext servletContext) {
        //1、创建SpringApplicationBuilder
       SpringApplicationBuilder builder = createSpringApplicationBuilder();
       StandardServletEnvironment environment = new StandardServletEnvironment();
       environment.initPropertySources(servletContext, null);
       builder.environment(environment);
       builder.main(getClass());
       ApplicationContext parent = getExistingRootWebApplicationContext(servletContext);
       if (parent != null) {
          this.logger.info("Root context already created (using as parent).");
          servletContext.setAttribute(
                WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, null);
          builder.initializers(new ParentContextApplicationContextInitializer(parent));
       }
       builder.initializers(
             new ServletContextApplicationContextInitializer(servletContext));
       builder.contextClass(AnnotationConfigEmbeddedWebApplicationContext.class);
        
        //调用configure方法,子类重写了这个方法,将SpringBoot的主程序类传入了进来
       builder = configure(builder);
        
        //使用builder创建一个Spring应用
       SpringApplication application = builder.build();
       if (application.getSources().isEmpty() && AnnotationUtils
             .findAnnotation(getClass(), Configuration.class) != null) {
          application.getSources().add(getClass());
       }
       Assert.state(!application.getSources().isEmpty(),
             "No SpringApplication sources have been defined. Either override the "
                   + "configure method or add an @Configuration annotation");
       // Ensure error pages are registered
       if (this.registerErrorPageFilter) {
          application.getSources().add(ErrorPageFilterConfiguration.class);
       }
        //启动Spring应用
       return run(application);
    }
    复制代码
    7)、Spring的应用就启动并且创建IOC容器

    复制代码
    public ConfigurableApplicationContext run(String... args) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        ConfigurableApplicationContext context = null;
        Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
        this.configureHeadlessProperty();
        SpringApplicationRunListeners listeners = this.getRunListeners(args);
        listeners.starting();
    
        Collection exceptionReporters;
        try {
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
            this.configureIgnoreBeanInfo(environment);
            Banner printedBanner = this.printBanner(environment);
            context = this.createApplicationContext();
            exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
            this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
           
    //刷新容器的初始化
     this.refreshContext(context);
            this.afterRefresh(context, applicationArguments);
            stopWatch.stop();
            if (this.logStartupInfo) {
                (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
            }
    
            listeners.started(context);
            this.callRunners(context, applicationArguments);
        } catch (Throwable var10) {
            this.handleRunFailure(context, var10, exceptionReporters, listeners);
            throw new IllegalStateException(var10);
        }
    
        try {
            listeners.running(context);
            return context;
        } catch (Throwable var9) {
            this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);
            throw new IllegalStateException(var9);
        }
    }
    复制代码
  • 相关阅读:
    python实现七段数码管显示
    词频统计实例
    分形几何中科赫雪花的绘制
    脚本实现自动化绘制
    Android查看数据库方法及工具(转)
    2011年度总结
    Bad NPObject as private data 解决方案
    LINQ学习之旅——LINQ TO SQL继承支持(转载)
    我记录开源系统1.6源码解析(一)
    2011年度总结
  • 原文地址:https://www.cnblogs.com/lyh233/p/12541552.html
Copyright © 2011-2022 走看看