实战:自定义简易版SpringBoot
实战:自定义简易版SpringBoot
一、功能要求
自定义简易版SpringBoot,实现SpringBoot MVC及内嵌Tomcat启动、DispatcherServlet注册和组件扫描功能
程序通过main方法启动,可以自动启动tomcat服务器可以自动创建和加载DispatcherServlet组件到ServletContext中可以自动通过@ComponentScan扫描Controller等组件Controller组件可以处理浏览器请求,返回响应结果
二、实现思路分析
传统SpringMVC框架web.xml的配置内容:
<web-app><!-- 初始化Spring上下文 --><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><!-- 指定Spring的配置文件 --><context-param><param-name>contextConfigLocation</param-name><param-value>/WEB-INF/app-context.xml</param-value></context-param><!-- 初始化DispatcherServlet --><servlet><servlet-name>app</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value></param-value></init-param><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>app</servlet-name><url-pattern>/app/*</url-pattern></servlet-mapping>
</web-app>
Spring官方文档中给出了基于Servlet3.0规范如何使用Java代码实现web.xml配置的example
public class MyWebApplicationInitializer implements WebApplicationInitializer {@Overridepublic void onStartup(ServletContext servletCxt) {// Load Spring web application configuration//通过注解的方式初始化Spring的上下文AnnotationConfigWebApplicationContext ac = new AnnotationConfigWebApplicationContext();//注册spring的配置类(替代传统项目中xml的configuration)ac.register(AppConfig.class);ac.refresh();// Create and register the DispatcherServlet//基于java代码的方式初始化DispatcherServletDispatcherServlet servlet = new DispatcherServlet(ac);ServletRegistration.Dynamic registration = servletContext.addServlet("app", servlet);registration.setLoadOnStartup(1);registration.addMapping("/app/*");}
}
- 当实现了Servlet3.0规范的容器(比如Tomcat7及以上版本)启动时
会通过SPI扩展机制自动扫描所有jar包里META-INF/services/javax.servlet.ServletContainerInitializer文件中指定的全路径类(该类需实现ServletContainerInitializer接口)
Servlet3.0+容器启动时将自动扫描类路径,以查找Spring的WebApplicationInitializer接口的所有实现类
将实现类放置到一个set集合中,提供给ServletContainerInitializer中onStartup的第一个参数使用
- 实例化ServletContainerInitializer实现类
- 回调类中的onStartup方法
- 在onStartup方法中(形参webAppInitializerClasses 已经封装了WebApplicationInitializer接口的所有实现类),可以回调WebApplicaitonInitializer的onStartup方法
- 在WebApplicaitonInitializer的onStartup方法中 进行传统SpringMVC框架web.xml的 内容配置
三、编码(实现方式一:使用框架的SpringServletContainerInitializer)
(1)创建maven工程,导入以下依赖:
<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId><version>5.0.8.RELEASE</version></dependency><dependency><groupId>org.apache.tomcat.embed</groupId><artifactId>tomcat-embed-core</artifactId><version>8.5.32</version></dependency><dependency><groupId>org.apache.tomcat.embed</groupId><artifactId>tomcat-embed-jasper</artifactId><version>8.5.32</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.0.8.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.0.8.RELEASE</version></dependency></dependencies>
(2)创建SpringApplication类,编写run方法(方法中要求完成tomcat的创建及启动)
public class SpringApplication {public static void run(){//创建tomcat实例Tomcat tomcat = new Tomcat();//设置tomcat端口tomcat.setPort(8888);try {//设置项目文件路径(完成一些自动配置,否则SpringServletContainerInitializer的onStartup方法可能不执行)tomcat.addWebapp("/", "G:\\");//启动tomcattomcat.start();// 监听关闭端口,阻塞式。没有这一句,方法执行完会直接结束tomcat.getServer().await();} catch (LifecycleException e) {e.printStackTrace();} catch (ServletException e) {e.printStackTrace();}}
}
(3)创建spring的配置类 AppConfig该类上要通过@ComponentScan来进行包扫描
@Configuration
@ComponentScan("com.dabing")
public class AppConfig {{System.out.println("ComponentScan...........");}
}
(4)创建MyWebApplicationInitializer实现WebApplicationInitializer接口,重写onstartup方法(WebApplicationInitializer实现web.xml的配置)
public class MyWebApplicationInitializer implements WebApplicationInitializer {public void onStartup(ServletContext servletContext) throws ServletException {System.out.println("初始化 MyWebApplicationInitializer");//通过注解的方式初始化Spring的上下文AnnotationConfigWebApplicationContext ac = new AnnotationConfigWebApplicationContext();//注册spring的配置类(替代传统项目中xml的configuration)ac.register(AppConfig.class);// Create and register the DispatcherServlet//基于java代码的方式初始化DispatcherServletDispatcherServlet servlet = new DispatcherServlet(ac);ServletRegistration.Dynamic registration = servletContext.addServlet("/", servlet);registration.setLoadOnStartup(1);registration.addMapping("/*");}
}
(5)编写一个Controller测试类及目标方法,响应输出“hello”即可
@RestController
public class TestController {@RequestMapping("/test/hello")public String test(){System.out.println("--- hello ---");return "hello";}}
(6)编写一个启动类Main,通过执行main方法启动服务
public class Main {public static void main(String[] args) {SpringApplication.run();}
}
(7)通过浏览器对目标方法进行方法
四、扩展:验证当实现了Servlet3.0规范的容器启动时 会通过SPI扩展机制 自动扫描 所有jar包里 META-INF/services/javax.servlet.ServletContainerInitializer 文件中指定的全路径类
自定义MySpringServletContainerInitializer 进行验证
(1)创建maven工程,导入以下依赖:
<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId><version>5.0.8.RELEASE</version></dependency><dependency><groupId>org.apache.tomcat.embed</groupId><artifactId>tomcat-embed-core</artifactId><version>8.5.32</version></dependency><dependency><groupId>org.apache.tomcat.embed</groupId><artifactId>tomcat-embed-jasper</artifactId><version>8.5.32</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.0.8.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.0.8.RELEASE</version></dependency></dependencies>
(2)创建SpringApplication 类,编写run方法(方法中要求完成tomcat的创建及启动)
public class SpringApplication {public static void run(){//创建tomcat实例Tomcat tomcat = new Tomcat();//设置tomcat端口tomcat.setPort(8888);try {//设置项目文件路径tomcat.addWebapp("/", "G:\\");//启动tomcattomcat.start();// 监听关闭端口,阻塞式。没有这一句,方法执行完会直接结束tomcat.getServer().await();} catch (LifecycleException e) {e.printStackTrace();} catch (ServletException e) {e.printStackTrace();}}
}
(3)创建spring的配置类 AppConfig该类上要通过@ComponentScan来进行包扫描
@Configuration
@ComponentScan("com.dabing")
public class AppConfig {{System.out.println("ComponentScan...........");}
}
(4)创建MySpringServletContainerInitializer,实现ServletContainerInitializer接口,重写onstartup方法,方法中调用第4步中MyWebApplicationInitializer的onstartup方法
@HandlesTypes(WebApplicationInitializer.class)
public class MySpringServletContainerInitializer implements ServletContainerInitializer {public void onStartup(Set<Class<?>> webAppInitializerClasses, ServletContext servletContext) throws ServletException {System.out.println("初始化 MySpringServletContainerInitializer");List<WebApplicationInitializer> initializers = new LinkedList<WebApplicationInitializer>();if (webAppInitializerClasses != null) {for (Class<?> waiClass : webAppInitializerClasses) {if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) &&WebApplicationInitializer.class.isAssignableFrom(waiClass)) {try {initializers.add((WebApplicationInitializer)ReflectionUtils.accessibleConstructor(waiClass).newInstance());} catch (Throwable ex) {throw new ServletException("Failed to instantiate WebApplicationInitializer class", ex);}}}}if (initializers.isEmpty()) {servletContext.log("No Spring WebApplicationInitializer types detected on classpath");return;}servletContext.log(initializers.size() + " Spring WebApplicationInitializers detected on classpath");AnnotationAwareOrderComparator.sort(initializers);for (WebApplicationInitializer initializer : initializers) {System.out.println("for--------------");initializer.onStartup(servletContext);}}
}
(5)创建文件:META-INF/services/javax.servlet.ServletContainerInitializer,在该文件中配置ServletContainerInitializer的实现类MySpringServletContainerInitializer
com.dabing.web.MySpringServletContainerInitializer
(6)创建MyWebApplicationInitializer实现WebApplicationInitializer接口,重写onstartup方法(WebApplicationInitializer实现web.xml的配置)
public class MyWebApplicationInitializer implements WebApplicationInitializer {public void onStartup(ServletContext servletContext) throws ServletException {System.out.println("初始化 MyWebApplicationInitializer");//通过注解的方式初始化Spring的上下文AnnotationConfigWebApplicationContext ac = new AnnotationConfigWebApplicationContext();//注册spring的配置类(替代传统项目中xml的configuration)ac.register(AppConfig.class);// Create and register the DispatcherServlet//基于java代码的方式初始化DispatcherServletDispatcherServlet servlet = new DispatcherServlet(ac);ServletRegistration.Dynamic registration = servletContext.addServlet("/", servlet);if(registration==null) return;registration.setLoadOnStartup(1);registration.addMapping("/*");}
}
(7)编写一个Controller测试类及目标方法,响应输出“hello”即可
@RestController
public class TestController {@RequestMapping("/test/hello")public String test(){System.out.println("--- hello ---");return "hello";}}
(8)编写一个启动类Main,通过执行main方法启动服务
public class Main {public static void main(String[] args) {SpringApplication.run();}
}
(9)通过浏览器对目标方法进行方法
项目地址
测试demo
实战:自定义简易版SpringBoot相关推荐
- 【Opencv实战】简易版“美颜”来啦—再见旧照片,Python一键美颜哦~
前言
- 手写简易版Vue源码之数据响应化的实现
当前,Vue和React已成为两大炙手可热的前端框架,这两个框架都算是业内一些最佳实践的集合体.其中,Vue最大的亮点和特色就是数据响应化,而React的特点则是单向数据流与jsx. 笔者近期正在研究 ...
- springboot整合websocket实现简易版单人聊天
websockt在作为即时通讯类的聊天方面有较多的应用,其主要的特点就是轻量,使用方便,容易快速上手,通过webscoket整合服务端,就可以实现简单的类似聊天的功能,下面说说springboot整合 ...
- Axure 9 实战案例,动态面板的应用 4.1,省市区三级联动下拉菜单(重制简易版)
前言 Hello!欢迎来到Axure 9 实战案例教程专栏. 本次课程我们继续来学习一下,动态面板的应用.本篇我们来讲解一下,如何绘制省市区联动下拉菜单(重新撰写简易版). 下拉菜单初稿 为了节省时间 ...
- 简易版电商推荐系统开发实战Hive
简易版电商推荐系统开发实战 数据来源 数据转换 Pandas->MySQL 用Sqoop把数据导入Hive 推荐算法 Mahout安装 itembase协同过滤算法 进行推荐 实验结果 这是从H ...
- c语言期中项目实战二—简易扫雷,思路分析加代码详细注释
c语言期中项目实战二-简易扫雷,思路分析+代码详细注释 游戏介绍 项目步骤 模块化编程 设置菜单 设置棋盘 打印棋盘 布置雷 排查雷 总结及总代码和详细注释 游戏介绍 扫雷这个经典游戏,直到现在仍有很 ...
- python项目开发实战网盘-python项目开发实战 第2版
python项目开发实战 第2版是一本Python项目开发流程实战手册,由日本BePROUD股份有限公司编著.本书的内容全部基于python开发事实,全部都是BeProud员工实际尝试.实践过的,可以 ...
- 5 拦截器拦截请求路由_手写简易版axios拦截器,实现微信小程序wx.request的封装与拦截...
前言: axios是一个功能强大的网络请求库,其中拦截器又是axios的精髓.在小程序的开发或者需要手动实现ajax的时候,没有实现对请求的拦截,开发的时候非常不方便,因此手写一个简易版的axios拦 ...
- HTML5 Canvas游戏开发实战 PDF扫描版
HTML5 Canvas游戏开发实战主要讲解使用HTML5 Canvas来开发和设计各类常见游戏的思路和技巧,在介绍HTML5 Canvas相关特性的同时,还通过游戏开发实例深入剖析了其内在原理,让读 ...
最新文章
- DeepSpeed超大规模模型训练工具
- vue的路由与es6的import, export
- REST service 化一个数据系统(REST Service 的最佳实践,第 2 部分)
- Docker 部署ELK 日志分析
- insert ... on duplicate key update产生death lock死锁原理
- 14.1178亿人 流动人口超3亿 “大国普查”这些数据很重要
- tree命令生成目录结构
- 3项目估算表_浮动油封生产项目可行性研究报告
- Task Parallel Library
- STM32库中自定义的数据类型
- snakeyaml操作yml文件中注释的处理
- 如何限定apt-get使用IPv4或IPv6协议下载
- html五线谱编辑器,​Notation Pad五线谱乐谱编辑器
- mysql routines是什么_MySQL入门:Stored Routines 的变数与流程 - Break易站
- 切换输入法半角全角(打开关闭输入法)
- 合肥辰工科技有限公司简介及公司产品介绍
- python中做为词云轮廓的图片,Python如何生成词云图片
- 音乐及游戏爱好者的福利,小鹏P7上新网易云及阴阳师,赶快看看吧
- c语言联机游戏,C/C++ 游戏 贪吃蛇双人对战版
- STM32CubeMx笔记--P2. LED亮晶晶