宝塔山 发表于 2023-3-15 21:05:20

day04-实现SpringBoot底层机制

实现SpringBoot底层机制

Tomcat底层启动分析+Spring容器初始化+Tomcat关联Spring容器
1.任务1-创建Tomcat,并启动

(1)创建一个Maven项目,修改pom.xml文件:我们需要自己创建Tomcat对象,因此在引入的场景启动器中排除SpringBoot内嵌的Tomcat,并引入tomcat依赖库
<parent>
    <artifactId>spring-boot-starter-parent</artifactId>
    <groupId>org.springframework.boot</groupId>
    <version>2.5.3</version>
</parent>
<dependencies>
   
    <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.apache.tomcat.embed</groupId>
      <artifactId>tomcat-embed-core</artifactId>
      <version>8.5.75</version>
    </dependency>
</dependencies>(2)创建LiSpringApplication.java
package com.li.lispringboot;

import org.apache.catalina.startup.Tomcat;

/**
* @author 李
* @version 1.0
*/
public class LiSpringApplication {
    //创建tomcat对象,并关联spring容器,然后启动tomcat
    public static void run() {
      try {
            //创建tomcat对象
            Tomcat tomcat = new Tomcat();
            //设置默认端口-9090
            tomcat.setPort(9090);
            //启动,就会在指定端口监听
            tomcat.start();
            //等待请求接入
            System.out.println("======9090端口等待请求接入======");
            tomcat.getServer().await();
      } catch (Exception e) {
            e.printStackTrace();
      }
    }
}(3)LiMainApp
package com.li.lispringboot;

/**
* @author 李
* @version 1.0
*/
public class LiMainApp {
    public static void main(String[] args) {
      //启动LiSpringBoot项目/程序
      LiSpringApplication.run();
    }
}(4)测试启动main方法,后台输出如下:
https://liyuelian.oss-cn-shenzhen.aliyuncs.com/imgs/image-20230315185127121.pnghttps://liyuelian.oss-cn-shenzhen.aliyuncs.com/imgs/image-20230315185616405.png打开浏览器,访问9090端口,页面一片空白,因为这时候还没有接入其他组件。
https://liyuelian.oss-cn-shenzhen.aliyuncs.com/imgs/image-20230315190021617.png2.任务2-创建Spring容器

(1)创建Monster.java,做一个测试bean
package com.li.lispringboot.bean;

/**
* @author 李
* @version 1.0
*/
public class Monster {
}(2)创建HelloController.java,做一个测试Controller
package com.li.lispringboot.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
* @author 李
* @version 1.0
*/
@RestController
public class HelloController {
    @RequestMapping("/hello")
    public String Hello() {
      return "Hello,I'm HelloController!";
    }
}(3)创建LiConfig.java,作为Spring的配置文件
package com.li.lispringboot.config;

import com.li.lispringboot.bean.Monster;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
* @author 李
* @version 1.0
* 配置类-作为Spring的配置文件
* 这里有一个问题,容器怎么知道要扫描哪些包?
*/
@Configuration
@ComponentScan("com.li.lispringboot")//指定要配置类扫描哪些包
public class LiConfig {
    //注入Bean-Monster对象到Spring容器
    @Bean
    public Monster monster() {
      return new Monster();
    }
}(4)LiWebApplicationInitializer.java
package com.li.lispringboot;

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;

/**
* @author 李
* @version 1.0
* LiWebApplicationInitializer容器初始化类的任务:
* 1.创建spring容器
* 2.加载/关联spring容器的配置-按照注解方式
* 3.完成spring容器配置的bean的创建,依赖注入
* 4.创建前端控制器(DispatcherServlet),让其持有spring容器
* 5.这的onStartup()方法是tomcat来调用,并把ServletContext对象传入
*/
public class LiWebApplicationInitializer implements WebApplicationInitializer {
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
      System.out.println("onStartup ...");
      //加载-Spring Web Application Configuration
      AnnotationConfigWebApplicationContext ac =
                new AnnotationConfigWebApplicationContext();

      //在ac中注册配置类LiConfig
      ac.register(LiConfig.class);
      ac.refresh();//完成bean的创建和配置

      /*
      创建注册非常重要的前端控制器-DispatchServlet
      让 DispatchServlet持有spring容器-ac
      这样就可以进行映射分发
      */
      DispatcherServlet dispatcherServlet = new DispatcherServlet(ac);
      //返回ServletRegistration.Dynamic对象
      ServletRegistration.Dynamic registration
                = servletContext.addServlet("app", dispatcherServlet);
      //设置前端控制器的加载顺序(这里设置为当tomcat启动时,就加载)
      registration.setLoadOnStartup(1);
      //设置前端控制器拦截所有请求,并进行分发处理
      registration.addMapping("/");
    }
}3.任务3-将Tomcat和Spring容器关联,并启动Spring容器

(1)修改LiSpringApplication,将tomcat和Spring容器关联
package com.li.lispringboot;

import org.apache.catalina.startup.Tomcat;

/**
* @author 李
* @version 1.0
*/
public class LiSpringApplication {
    //创建tomcat对象,并关联spring容器,然后启动tomcat
    public static void run() {
      try {
            //创建tomcat对象
            Tomcat tomcat = new Tomcat();
            /*
            1.让tomcat能够将请求转发到SpringWeb容器,因此需要关联
            2."/liboot" 就是我们的项目的 application context,即原来配置tomcat时的项目名称
            3."D:\\IDEA-workspace\\li-springboot" 指定项目的路径
             */
            tomcat.addWebapp("/liboot", "D:\\IDEA-workspace\\li-springboot");
            //设置默认端口-9090
            tomcat.setPort(9090);
            //启动,就会在指定端口监听
            tomcat.start();
            //等待请求接入
            System.out.println("======9090端口等待请求接入======");
            tomcat.getServer().await();
      } catch (Exception e) {
            e.printStackTrace();
      }
    }
}(2)在LiMainApp.java中重新启动项目,在浏览器中访问测试Controller,访问成功:
https://liyuelian.oss-cn-shenzhen.aliyuncs.com/imgs/image-20230315202158051.png3.1注意事项和细节

如果启动时报异常,如下:
严重: Servlet in web application threw load() exception java.lang.ClassNotFoundException: org.apache.jasper.servlet.JspServlet解决方案是:引入对应版本的 Jasper包即可。
<dependency>
    <groupId>org.apache.tomcat</groupId>
    <artifactId>tomcat-jasper</artifactId>
    <version>8.5.75</version>
</dependency>
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: day04-实现SpringBoot底层机制