day04-实现SpringBoot底层机制

打印 上一主题 下一主题

主题 511|帖子 511|积分 1533

实现SpringBoot底层机制

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

(1)创建一个Maven项目,修改pom.xml文件:我们需要自己创建Tomcat对象,因此在引入的场景启动器中排除SpringBoot内嵌的Tomcat,并引入tomcat依赖库
  1. <parent>
  2.     <artifactId>spring-boot-starter-parent</artifactId>
  3.     <groupId>org.springframework.boot</groupId>
  4.     <version>2.5.3</version>
  5. </parent>
  6. <dependencies>
  7.    
  8.     <dependency>
  9.         <groupId>org.springframework.boot</groupId>
  10.         <artifactId>spring-boot-starter-web</artifactId>
  11.         
  12.         <exclusions>
  13.             <exclusion>
  14.                 <groupId>org.springframework.boot</groupId>
  15.                 <artifactId>spring-boot-starter-tomcat</artifactId>
  16.             </exclusion>
  17.         </exclusions>
  18.     </dependency>
  19.    
  20.     <dependency>
  21.         <groupId>org.apache.tomcat.embed</groupId>
  22.         <artifactId>tomcat-embed-core</artifactId>
  23.         <version>8.5.75</version>
  24.     </dependency>
  25. </dependencies>
复制代码
(2)创建LiSpringApplication.java
  1. package com.li.lispringboot;
  2. import org.apache.catalina.startup.Tomcat;
  3. /**
  4. * @author 李
  5. * @version 1.0
  6. */
  7. public class LiSpringApplication {
  8.     //创建tomcat对象,并关联spring容器,然后启动tomcat
  9.     public static void run() {
  10.         try {
  11.             //创建tomcat对象
  12.             Tomcat tomcat = new Tomcat();
  13.             //设置默认端口-9090
  14.             tomcat.setPort(9090);
  15.             //启动,就会在指定端口监听
  16.             tomcat.start();
  17.             //等待请求接入
  18.             System.out.println("======9090端口等待请求接入======");
  19.             tomcat.getServer().await();
  20.         } catch (Exception e) {
  21.             e.printStackTrace();
  22.         }
  23.     }
  24. }
复制代码
(3)LiMainApp
  1. package com.li.lispringboot;
  2. /**
  3. * @author 李
  4. * @version 1.0
  5. */
  6. public class LiMainApp {
  7.     public static void main(String[] args) {
  8.         //启动LiSpringBoot项目/程序
  9.         LiSpringApplication.run();
  10.     }
  11. }
复制代码
(4)测试启动main方法,后台输出如下:
打开浏览器,访问9090端口,页面一片空白,因为这时候还没有接入其他组件。
2.任务2-创建Spring容器

(1)创建Monster.java,做一个测试bean
  1. package com.li.lispringboot.bean;
  2. /**
  3. * @author 李
  4. * @version 1.0
  5. */
  6. public class Monster {
  7. }
复制代码
(2)创建HelloController.java,做一个测试Controller
  1. package com.li.lispringboot.controller;
  2. import org.springframework.web.bind.annotation.RequestMapping;
  3. import org.springframework.web.bind.annotation.RestController;
  4. /**
  5. * @author 李
  6. * @version 1.0
  7. */
  8. @RestController
  9. public class HelloController {
  10.     @RequestMapping("/hello")
  11.     public String Hello() {
  12.         return "Hello,I'm HelloController!";
  13.     }
  14. }
复制代码
(3)创建LiConfig.java,作为Spring的配置文件
  1. package com.li.lispringboot.config;
  2. import com.li.lispringboot.bean.Monster;
  3. import org.springframework.context.annotation.Bean;
  4. import org.springframework.context.annotation.ComponentScan;
  5. import org.springframework.context.annotation.Configuration;
  6. /**
  7. * @author 李
  8. * @version 1.0
  9. * 配置类-作为Spring的配置文件
  10. * 这里有一个问题,容器怎么知道要扫描哪些包?
  11. */
  12. @Configuration
  13. @ComponentScan("com.li.lispringboot")//指定要配置类扫描哪些包
  14. public class LiConfig {
  15.     //注入Bean-Monster对象到Spring容器
  16.     @Bean
  17.     public Monster monster() {
  18.         return new Monster();
  19.     }
  20. }
复制代码
(4)LiWebApplicationInitializer.java
  1. package com.li.lispringboot;
  2. import org.springframework.web.WebApplicationInitializer;
  3. import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
  4. import org.springframework.web.servlet.DispatcherServlet;
  5. import javax.servlet.ServletContext;
  6. import javax.servlet.ServletException;
  7. import javax.servlet.ServletRegistration;
  8. /**
  9. * @author 李
  10. * @version 1.0
  11. * LiWebApplicationInitializer容器初始化类的任务:
  12. * 1.创建spring容器
  13. * 2.加载/关联spring容器的配置-按照注解方式
  14. * 3.完成spring容器配置的bean的创建,依赖注入
  15. * 4.创建前端控制器(DispatcherServlet),让其持有spring容器
  16. * 5.这的onStartup()方法是tomcat来调用,并把ServletContext对象传入
  17. */
  18. public class LiWebApplicationInitializer implements WebApplicationInitializer {
  19.     @Override
  20.     public void onStartup(ServletContext servletContext) throws ServletException {
  21.         System.out.println("onStartup ...");
  22.         //加载-Spring Web Application Configuration
  23.         AnnotationConfigWebApplicationContext ac =
  24.                 new AnnotationConfigWebApplicationContext();
  25.         //在ac中注册配置类LiConfig
  26.         ac.register(LiConfig.class);
  27.         ac.refresh();//完成bean的创建和配置
  28.         /*
  29.         创建注册非常重要的前端控制器-DispatchServlet
  30.         让 DispatchServlet持有spring容器-ac
  31.         这样就可以进行映射分发
  32.         */
  33.         DispatcherServlet dispatcherServlet = new DispatcherServlet(ac);
  34.         //返回ServletRegistration.Dynamic对象
  35.         ServletRegistration.Dynamic registration
  36.                 = servletContext.addServlet("app", dispatcherServlet);
  37.         //设置前端控制器的加载顺序(这里设置为当tomcat启动时,就加载)
  38.         registration.setLoadOnStartup(1);
  39.         //设置前端控制器拦截所有请求,并进行分发处理
  40.         registration.addMapping("/");
  41.     }
  42. }
复制代码
3.任务3-将Tomcat和Spring容器关联,并启动Spring容器

(1)修改LiSpringApplication,将tomcat和Spring容器关联
  1. package com.li.lispringboot;
  2. import org.apache.catalina.startup.Tomcat;
  3. /**
  4. * @author 李
  5. * @version 1.0
  6. */
  7. public class LiSpringApplication {
  8.     //创建tomcat对象,并关联spring容器,然后启动tomcat
  9.     public static void run() {
  10.         try {
  11.             //创建tomcat对象
  12.             Tomcat tomcat = new Tomcat();
  13.             /*
  14.               1.让tomcat能够将请求转发到SpringWeb容器,因此需要关联
  15.               2."/liboot" 就是我们的项目的 application context,即原来配置tomcat时的项目名称
  16.               3."D:\\IDEA-workspace\\li-springboot" 指定项目的路径
  17.              */
  18.             tomcat.addWebapp("/liboot", "D:\\IDEA-workspace\\li-springboot");
  19.             //设置默认端口-9090
  20.             tomcat.setPort(9090);
  21.             //启动,就会在指定端口监听
  22.             tomcat.start();
  23.             //等待请求接入
  24.             System.out.println("======9090端口等待请求接入======");
  25.             tomcat.getServer().await();
  26.         } catch (Exception e) {
  27.             e.printStackTrace();
  28.         }
  29.     }
  30. }
复制代码
(2)在LiMainApp.java中重新启动项目,在浏览器中访问测试Controller,访问成功:
3.1注意事项和细节

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

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

宝塔山

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表