如需转载,请根据 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 许可,附上本文作者及链接。
本文作者: Alice
作者昵称: 沉。
本文链接: http://example.com/2020/11/17/SpringBoot-Web%E5%BC%80%E5%8F%91%E5%92%8C%E9%A1%B5%E9%9D%A2%E5%9B%BD%E9%99%85%E5%8C%96/
六、SpringBoot Web开发
核心:自动装配
- 创建应用,选择模块
springboot到底帮我们配置了什么?我们能不能进行修改?能修改哪些东西?能不能拓展?
- xxxAutoConfiguration:自动配置类,香容器中自动配置组件
- xxxProperties:自动配置类,装配配置文件中自定义的一些内容!
要解决问题:
- 导入静态资源
- 定制首页
- jsp,模板引擎Thymeleaf
- 装配扩展SpringMVC
- 增删改查
- 拦截器
- 国际化!
6.1、导入静态资源
SpringBoot中,SpringMVC的web配置都WebMvcAutoConfiguration 这个配置类里面;
我们可以去看看 WebMvcAutoConfigurationAdapter 中有很多配置方法;
有一个方法:addResourceHandlers 添加资源处理
1 | public void addResourceHandlers(ResourceHandlerRegistry registry) { |
读一下源代码:比如所有的 /webjars/** , 都需要去 classpath:/META-INF/resources/webjars/ 找对应的资源;
6.2、什么是webjars 呢?
Webjars本质就是以jar包的方式引入我们的静态资源 , 我们以前要导入一个静态资源文件,直接导入即可。
使用SpringBoot需要使用Webjars,我们可以去搜索一下:
要使用jQuery,我们只要要引入jQuery对应版本的pom依赖即可!
1 | <dependency> |
6.3、第二种静态资源映射规则
那我们项目中要是使用自己的静态资源该怎么导入呢?我们看下一行代码;
我们去找staticPathPattern发现第二种映射规则 :/** , 访问当前的项目任意资源,它会去找 resourceProperties 这个类,我们可以点进去看一下分析:
1 | // 进入方法 |
ResourceProperties 可以设置和我们静态资源有关的参数;这里面指向了它会去寻找资源的文件夹,即上面数组的内容。
所以得出结论,以下四个目录存放的静态资源可以被我们识别:
1 | /META-INF/resources/" : |
我们可以在resources根目录下新建对应的文件夹,都可以存放我们的静态文件;
比如我们访问 http://localhost:8080/1.js , 他就会去这些文件夹中寻找对应的静态资源文件;
自定义静态资源路径
我们也可以自己通过配置文件来指定一下,哪些文件夹是需要我们放静态资源文件的,在application.properties中配置;
1 | spring.resources.static-locations=classpath:/coding/,classpath:/chen/ |
一旦自己定义了静态文件夹的路径,原来的自动配置就都会失效了!
6.4、定制首页
关于首页的定制
1 |
|
点进去继续看
1 | private Optional<Resource> getWelcomePage() { |
欢迎页,静态资源文件夹下的所有 index.html 页面;被 /** 映射。
新建一个 index.html ,在我们上面的3个目录中任意一个;然后访问测试 http://localhost:8080/ 看结果!
关于网站图标说明:
与其他静态资源一样,Spring Boot在配置的静态内容位置中查找 favicon.ico。如果存在这样的文件,它将自动用作应用程序的favicon。
1、关闭SpringBoot默认图标
1 | #关闭默认图标 |
2、自己放一个图标在静态资源目录下,我放在 public 目录下
3、清除浏览器缓存!刷新网页,发现图标已经变成自己的了!
6.5、Thymleaf模板引擎
前端交给我们的页面,是html页面。如果是我们以前开发,我们需要把他们转成jsp页面,jsp好处就是当我们查出一些数据转发到JSP页面以后,我们可以用jsp轻松实现数据的显示,及交互等。
jsp支持非常强大的功能,包括能写Java代码,但是呢,我们现在的这种情况,SpringBoot这个项目首先是以jar的方式,不是war,像第二,我们用的还是嵌入式的Tomcat,所以呢,他现在默认是不支持jsp的。
那不支持jsp,如果我们直接用纯静态页面的方式,那给我们开发会带来非常大的麻烦,那怎么办呢?
SpringBoot推荐你可以来使用模板引擎:
模板引擎,我们其实大家听到很多,其实jsp就是一个模板引擎,还有用的比较多的freemarker,包括SpringBoot给我们推荐的Thymeleaf,模板引擎有非常多,但再多的模板引擎,他们的思想都是一样的,什么样一个思想呢我们来看一下这张图:
模板引擎的作用就是我们来写一个页面模板,比如有些值呢,是动态的,我们写一些表达式。而这些值,从哪来呢,就是我们在后台封装一些数据。然后把这个模板和这个数据交给我们模板引擎,模板引擎按照我们这个数据帮你把这表达式解析、填充到我们指定的位置,然后把这个数据最终生成一个我们想要的内容给我们写出去,这就是我们这个模板引擎,不管是jsp还是其他模板引擎,都是这个思想。只不过呢,就是说不同模板引擎之间,他们可能这个语法有点不一样。其他的我就不介绍了,我主要来介绍一下SpringBoot给我们推荐的Thymeleaf模板引擎,这模板引擎呢,是一个高级语言的模板引擎,他的这个语法更简单。而且呢,功能更强大。
我们呢,就来看一下这个模板引擎,那既然要看这个模板引擎。首先,我们来看SpringBoot里边怎么用。
引入Thymeleaf:
Thymeleaf 官网:https://www.thymeleaf.org/
Thymeleaf 在Github 的主页:https://github.com/thymeleaf/thymeleaf
Spring官方文档:找到我们对应的版本
https://docs.spring.io/spring-boot/docs/2.2.5.RELEASE/reference/htmlsingle/#using-boot-starter
找到对应的pom依赖:可以适当点进源码看下本来的包!
1 | <!--thymeleaf--> |
Thymeleaf的自动配置类:ThymeleafProperties:
1 |
|
我们可以在其中看到默认的前缀和后缀!
我们只需要把我们的html页面放在类路径下的templates下,thymeleaf就可以帮我们自动渲染了。
使用thymeleaf什么都不需要配置,只需要将他放在指定的文件夹下即可!
测试:
1、编写一个TestController
1 |
|
2、编写一个测试页面 test.html 放在 templates 目录下
1 | <!DOCTYPE html> |
简单的练习 :我们需要查出一些数据,在页面中展示
1、修改测试请求,增加数据传输;
1 |
|
2、我们要使用thymeleaf,需要在html文件中导入命名空间的约束,方便提示。
我们可以去官方文档的#3中看一下命名空间拿来过来:
1 | xmlns:th="http://www.thymeleaf.org" |
3、我们去编写下前端页面
1 |
|
1、我们可以使用任意的 th:attr 来替换Html中原生属性的值
1 | Simple expressions:(表达式语法) |
练习测试:
1、 我们编写一个Controller,放一些数据
1 | package com.chen.controller; |
2、测试页面取出数据
1 |
|
3、启动项目测试!
七、SpringMVC自动装配
7.1、关于官方文档
在进行项目编写前,我们还需要知道一个东西,就是SpringBoot对我们的SpringMVC还做了哪些配置,包括如何扩展,如何定制。
只有把这些都搞清楚了,我们在之后使用才会更加得心应手。途径一:源码分析,途径二:官方文档!
1 | Spring MVC Auto-configuration |
7.2、关于源码
ContentNegotiatingViewResolver 内容协商视图解析器
自动配置了ViewResolver,就是我们之前学习的SpringMVC的视图解析器;
即根据方法的返回值取得视图对象(View),然后由视图对象决定如何渲染(转发,重定向)。
我们去看看这里的源码:我们找到 WebMvcAutoConfiguration , 然后搜索ContentNegotiatingViewResolver。找到如下方法!
1 | // 注解说明:@Nullable 即参数可为null |
我们继续点进去看,他是怎么获得候选的视图的呢?
getCandidateViews中看到他是把所有的视图解析器拿来,进行while循环,挨个解析!
1 | Iterator var5 = this.viewResolvers.iterator(); |
所以得出结论:ContentNegotiatingViewResolver 这个视图解析器就是用来组合所有的视图解析器的
我们再去研究下他的组合逻辑,看到有个属性viewResolvers,看看它是在哪里进行赋值的!
1 | protected void initServletContext(ServletContext servletContext) { |
既然它是在容器中去找视图解析器,我们是否可以猜想,我们就可以去实现一个视图解析器了呢?
我们可以自己给容器中去添加一个视图解析器;这个类就会帮我们自动的将它组合进来;我们去实现一下
1、我们在我们的主程序中去写一个视图解析器来试试;
1 | //放到bean中 |
我们如果想要使用自己定制化的东西,我们只需要给容器中添加这个组件就好了!剩下的事情SpringBoot就会帮我们做了!
7.3、转换器和格式化器
找到格式化转换器:
1 |
|
点击去:
1 | public String getDateFormat() { |
可以看到在我们的Properties文件中,我们可以进行自动配置它!
如果配置了自己的格式化方式,就会注册到Bean中生效,我们可以在配置文件中配置日期格式化的规则:
1 | ##自定义的配置日期格式化 |
7.4、修改SpringBoot的默认配置
这么多的自动配置,原理都是一样的,通过这个WebMVC的自动配置原理分析,我们要学会一种学习方式,通过源码探究,得出结论;这个结论一定是属于自己的,而且一通百通。
SpringBoot的底层,大量用到了这些设计细节思想,所以,没事需要多阅读源码!得出结论;
SpringBoot在自动配置很多组件的时候,先看容器中有没有用户自己配置的(如果用户自己配置@bean),如果有就用用户配置的,如果没有就用自动配置的;
如果有些组件可以存在多个,比如我们的视图解析器,就将用户配置的和自己默认的组合起来!
我们要做的就是编写一个@Configuration注解类,并且类型要为WebMvcConfigurer,还不能标注@EnableWebMvc注解;我们去自己写一个;我们新建一个包叫config,写一个类MyMvcConfig;
1 | package com.chen.config; |
我们要扩展SpringMVC,官方就推荐我们这么去使用,既保SpringBoot留所有的自动配置,也能用我们扩展的配置!
我们可以去分析一下原理:
1、WebMvcAutoConfiguration 是 SpringMVC的自动配置类,里面有一个类WebMvcAutoConfigurationAdapter
2、这个类上有一个注解,在做其他自动配置时会导入:@Import(EnableWebMvcConfiguration.class)
3、我们点进EnableWebMvcConfiguration这个类看一下,它继承了一个父类:DelegatingWebMvcConfiguration
这个父类中有这样一段代码:
1 | public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport { |
4、我们可以在这个类中去寻找一个我们刚才设置的viewController当做参考,发现它调用了一个
1 | protected void addViewControllers(ViewControllerRegistry registry) { |
5、我们点进去看一下
1 | public void addViewControllers(ViewControllerRegistry registry) { |
所以得出结论:所有的WebMvcConfiguration都会被作用,不止Spring自己的配置类,我们自己的配置类当然也会被调用;
7.5、全面接管SpringMVC
官方文档:
1 | If you want to take complete control of Spring MVC |
全面接管即:SpringBoot对SpringMVC的自动配置不需要了,所有都是我们自己去配置!
只需在我们的配置类中要加一个@EnableWebMvc。
我们看下如果我们全面接管了SpringMVC了,我们之前SpringBoot给我们配置的静态资源映射一定会无效,我们可以去测试一下;
不加注解之前,访问首页:成功
给配置类加上注解:@EnableWebMvc:错误,errorpage
我们发现所有的SpringMVC自动配置都失效了!回归到了最初的样子;
当然,我们开发中,不推荐使用全面接管SpringMVC
为什么加了一个注解,自动配置就失效了!我们看下源码:
1、这里发现它是导入了一个类,我们可以继续进去看
1 |
|
2、它继承了一个父类 WebMvcConfigurationSupport
1 | public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport { |
3、我们来回顾一下Webmvc自动配置类
1 |
|
总结一句话:@EnableWebMvc将WebMvcConfigurationSupport组件导入进来了;
而导入的WebMvcConfigurationSupport只是SpringMVC最基本的功能!
八、页面国际化
8.1、准备工作
先在IDEA中统一设置properties的编码问题!
可能出现的错误:
IDEA Error:java: Compilation failed: internal java compiler error
解决办法很简单:File–>Setting…–>Build,Execution,Deployment–>Compiler–>Java Compiler 设置相应Module的target bytecode version的合适版本(跟你jkd版本一致),这里我改成1.8版本的。
编写国际化配置文件,抽取页面需要显示的国际化页面消息。我们可以去登录页面查看一下,哪些内容我们需要编写国际化的配置!
8.2、配置文件编写
1、我们在resources资源文件下新建一个i18n目录,存放国际化配置文件
2、建立一个login.properties文件,还有一个login_zh_CN.properties;发现IDEA自动识别了我们要做国际化操作;文件夹变了!
login.properties :默认
1 | 登录 = |
英文:
1 | Sign in = |
中文:
1 | 登录 = |
配置文件生效探究
我们去看一下SpringBoot对国际化的自动配置!这里又涉及到一个类:MessageSourceAutoConfiguration
里面有一个方法,这里发现SpringBoot已经自动配置好了管理我们国际化资源文件的组件 ResourceBundleMessageSource;
1 | // 获取 properties 传递过来的值进行判断 |
我们真实 的情况是放在了i18n目录下,所以我们要去配置这个messages的路径;
1 | i18n.login = |
8.3、配置国际化解析
在Spring中有一个国际化的Locale (区域信息对象);里面有一个叫做LocaleResolver (获取区域信息对象)的解析器!
我们去我们webmvc自动配置文件,寻找一下!看到SpringBoot默认配置:
1 |
|
AcceptHeaderLocaleResolver 这个类中有一个方法
1 | public Locale resolveLocale(HttpServletRequest request) { |
那假如我们现在想点击链接让我们的国际化资源生效,就需要让我们自己的Locale生效!
我们去自己写一个自己的LocaleResolver,可以在链接上携带区域信息!
修改一下前端页面的跳转连接:
1 | <!-- 这里传入参数不需要使用 ?使用 (key=value)--> |
我们去写一个处理的组件类!
1 | import org.springframework.util.StringUtils; |
为了让我们的区域化信息能够生效,我们需要再配置一下这个组件!在我们自己的MvcConofig下添加bean;
1 |
|
九、简单网站的开发
导入静态页面
9.1、默认访问首页
1 | //使用WebMvcConfigurerAdapter可以来扩展SpringMVC的功能 |
9.2、SpringBoot自动配置好了管理国际化资源文件的组件;
1 |
|
9.3、去页面获取国际化的值
1 |
|
效果:根据浏览器语言设置的信息切换了国际化;
原理:
国际化Locale(区域信息对象);LocaleResolver(获取区域信息对象);
1 |
|
9.4、点击链接切换国际化
1 | /** |
9.5、登陆
开发期间模板引擎页面修改以后,要实时生效
- 禁用模板引擎的缓存
1 | # 禁用缓存 |
页面修改完成以后ctrl+f9:重新编译;
登陆错误消息的显示
1 | <p style="color: red" th:text="${msg}" th:if="${not #strings.isEmpty(msg)}"></p> |
9.6、拦截器进行登陆检查
拦截器
1 | /** |
注册拦截器
1 | //所有的WebMvcConfigurerAdapter组件都会一起起作用 |
9.7、CRUD-员工列表
实验要求:
1)、RestfulCRUD:CRUD满足Rest风格;
URI: /资源名称/资源标识 HTTP请求方式区分对资源CRUD操作
普通CRUD(uri来区分操作) | RestfulCRUD | |
---|---|---|
查询 | getEmp | emp—GET |
添加 | addEmp?xxx | emp—POST |
修改 | updateEmp?id=xxx&xxx=xx | emp/{id}—PUT |
删除 | deleteEmp?id=1 | emp/{id}—DELETE |
2)、实验的请求架构;
实验功能 | 请求URI | 请求方式 |
---|---|---|
查询所有员工 | emps | GET |
查询某个员工(来到修改页面) | emp/1 | GET |
来到添加页面 | emp | GET |
添加员工 | emp | POST |
来到修改页面(查出员工进行信息回显) | emp/1 | GET |
修改员工 | emp | PUT |
删除员工 | emp/1 | DELETE |
3)、员工列表:
thymeleaf公共页面元素抽取
1 | 1、抽取公共片段 |
三种引入公共片段的th属性:
th:insert:将公共片段整个插入到声明引入的元素中
th:replace:将声明引入的元素替换为公共片段
th:include:将被引入的片段的内容包含进这个标签中
1 | <footer th:fragment="copy"> |
引入片段的时候传入参数:
1 | <nav class="col-md-2 d-none d-md-block bg-light sidebar" id="sidebar"> |
9.8、CRUD-员工添加
添加页面
1 | <form> |
提交的数据格式不对:生日:日期;
2017-12-12;2017/12/12;2017.12.12;
日期的格式化;SpringMVC将页面提交的值需要转换为指定的类型;
2017-12-12—Date; 类型转换,格式化;
默认日期是按照/的方式;
9.8、CRUD-员工修改
修改添加二合一表单
1 | <!--需要区分是员工修改还是添加;--> |
9.9、CRUD-员工删除
1 | <tr th:each="emp:${emps}"> |
9.10、错误处理机制
1)、SpringBoot默认的错误处理机制
默认效果:
1)、浏览器,返回一个默认的错误页面
浏览器发送请求的请求头:
2)、如果是其他客户端,默认响应一个json数据
原理:
可以参照ErrorMvcAutoConfiguration;错误处理的自动配置;
给容器中添加了以下组件
1、DefaultErrorAttributes:
1 | 帮我们在页面共享信息; |
2、BasicErrorController:处理默认/error请求
1 |
|
3、ErrorPageCustomizer:
1 |
|
4、DefaultErrorViewResolver:
1 |
|
步骤:
一但系统出现4xx或者5xx之类的错误;ErrorPageCustomizer就会生效(定制错误的响应规则);就会来到/error请求;就会被BasicErrorController处理;
1)响应页面;去哪个页面是由DefaultErrorViewResolver解析得到的;
1 | protected ModelAndView resolveErrorView(HttpServletRequest request, |
2)、如果定制错误响应:
1)、如何定制错误的页面;
1)、有模板引擎的情况下;error/状态码; 【将错误页面命名为 错误状态码.html 放在模板引擎文件夹里面的 error文件夹下】,发生此状态码的错误就会来到 对应的页面;
我们可以使用4xx和5xx作为错误页面的文件名来匹配这种类型的所有错误,精确优先(优先寻找精确的状态码.html);
页面能获取的信息;
timestamp:时间戳
status:状态码
error:错误提示
exception:异常对象
message:异常消息
errors:JSR303数据校验的错误都在这里
2)、没有模板引擎(模板引擎找不到这个错误页面),静态资源文件夹下找;
3)、以上都没有错误页面,就是默认来到SpringBoot默认的错误提示页面;
2)、如何定制错误的json数据;
1)、自定义异常处理&返回定制json数据;
1 |
|
2)、转发到/error进行自适应响应效果处理
1 |
|
3)、将我们的定制数据携带出去;
出现错误以后,会来到/error请求,会被BasicErrorController处理,响应出去可以获取的数据是由getErrorAttributes得到的(是AbstractErrorController(ErrorController)规定的方法);
1、完全来编写一个ErrorController的实现类【或者是编写AbstractErrorController的子类】,放在容器中;
2、页面上能用的数据,或者是json返回能用的数据都是通过errorAttributes.getErrorAttributes得到;
容器中DefaultErrorAttributes.getErrorAttributes();默认进行数据处理的;
自定义ErrorAttributes
1 | //给容器中加入我们自己定义的ErrorAttributes |
最终的效果:响应是自适应的,可以通过定制ErrorAttributes改变需要返回的内容,
9.11、配置嵌入式Servlet容器
SpringBoot默认使用Tomcat作为嵌入式的Servlet容器;
问题?
1)、如何定制和修改Servlet容器的相关配置;
1、修改和server有关的配置(ServerProperties【也是EmbeddedServletContainerCustomizer】);
1 | 8081 = |
2、编写一个EmbeddedServletContainerCustomizer:嵌入式的Servlet容器的定制器;来修改Servlet容器的配置
1 | //一定要将这个定制器加入到容器中 |
2)、注册Servlet三大组件【Servlet、Filter、Listener】
由于SpringBoot默认是以jar包的方式启动嵌入式的Servlet容器来启动SpringBoot的web应用,没有web.xml文件。
注册三大组件用以下方式
ServletRegistrationBean
1 | //注册三大组件 |
FilterRegistrationBean
1 |
|
ServletListenerRegistrationBean
1 |
|
SpringBoot帮我们自动SpringMVC的时候,自动的注册SpringMVC的前端控制器;DIspatcherServlet;
DispatcherServletAutoConfiguration中:
1 |
|
2)、SpringBoot能不能支持其他的Servlet容器;
3)、替换为其他嵌入式Servlet容器
默认支持:
Tomcat(默认使用)
1 | <dependency> |
Jetty
1 | <!-- 引入web模块 --> |
Undertow
1 | <!-- 引入web模块 --> |
4)、嵌入式Servlet容器自动配置原理;
EmbeddedServletContainerAutoConfiguration:嵌入式的Servlet容器自动配置?
1 |
|
1)、EmbeddedServletContainerFactory(嵌入式Servlet容器工厂)
1 | public interface EmbeddedServletContainerFactory { |
2)、EmbeddedServletContainer:(嵌入式的Servlet容器)
3)、以TomcatEmbeddedServletContainerFactory为例
1 |
|
4)、我们对嵌入式容器的配置修改是怎么生效?
1 | ServerProperties、EmbeddedServletContainerCustomizer |
EmbeddedServletContainerCustomizer:定制器帮我们修改了Servlet容器的配置?
怎么修改的原理?
5)、容器中导入了EmbeddedServletContainerCustomizerBeanPostProcessor
1 | //初始化之前 |
步骤:
1)、SpringBoot根据导入的依赖情况,给容器中添加相应的EmbeddedServletContainerFactory【TomcatEmbeddedServletContainerFactory】
2)、容器中某个组件要创建对象就会惊动后置处理器;EmbeddedServletContainerCustomizerBeanPostProcessor;
只要是嵌入式的Servlet容器工厂,后置处理器就工作;
3)、后置处理器,从容器中获取所有的EmbeddedServletContainerCustomizer,调用定制器的定制方法
###5)、嵌入式Servlet容器启动原理;
什么时候创建嵌入式的Servlet容器工厂?什么时候获取嵌入式的Servlet容器并启动Tomcat;
获取嵌入式的Servlet容器工厂:
1)、SpringBoot应用启动运行run方法
2)、refreshContext(context);SpringBoot刷新IOC容器【创建IOC容器对象,并初始化容器,创建容器中的每一个组件】;如果是web应用创建AnnotationConfigEmbeddedWebApplicationContext,否则:AnnotationConfigApplicationContext
3)、refresh(context);刷新刚才创建好的ioc容器;
1 | public void refresh() throws BeansException, IllegalStateException { |
4)、 onRefresh(); web的ioc容器重写了onRefresh方法
5)、webioc容器会创建嵌入式的Servlet容器;createEmbeddedServletContainer();
6)、获取嵌入式的Servlet容器工厂:
EmbeddedServletContainerFactory containerFactory = getEmbeddedServletContainerFactory();
从ioc容器中获取EmbeddedServletContainerFactory 组件;TomcatEmbeddedServletContainerFactory创建对象,后置处理器一看是这个对象,就获取所有的定制器来先定制Servlet容器的相关配置;
7)、使用容器工厂获取嵌入式的Servlet容器:this.embeddedServletContainer = containerFactory .getEmbeddedServletContainer(getSelfInitializer());
8)、嵌入式的Servlet容器创建对象并启动Servlet容器;
先启动嵌入式的Servlet容器,再将ioc容器中剩下没有创建出的对象获取出来;
==IOC容器启动创建嵌入式的Servlet容器==
9.12、使用外置的Servlet容器
嵌入式Servlet容器:应用打成可执行的jar
优点:简单、便携;
缺点:默认不支持JSP、优化定制比较复杂(使用定制器【ServerProperties、自定义EmbeddedServletContainerCustomizer】,自己编写嵌入式Servlet容器的创建工厂【EmbeddedServletContainerFactory】);
外置的Servlet容器:外面安装Tomcat—应用war包的方式打包;
步骤
1)、必须创建一个war项目;(利用idea创建好目录结构)
2)、将嵌入式的Tomcat指定为provided;
1 | <dependency> |
3)、必须编写一个SpringBootServletInitializer的子类,并调用configure方法
1 | public class ServletInitializer extends SpringBootServletInitializer { |
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的文件,内容就是ServletContainerInitializer的实现类的全类名
3)、还可以使用@HandlesTypes,在应用启动的时候加载我们感兴趣的类;
流程:
1)、启动Tomcat
2)、org\springframework\spring-web\4.3.14.RELEASE\spring-web-4.3.14.RELEASE.jar!\META-INF\services\javax.servlet.ServletContainerInitializer:
Spring的web模块里面有这个文件:org.springframework.web.SpringServletContainerInitializer
3)、SpringServletContainerInitializer将@HandlesTypes(WebApplicationInitializer.class)标注的所有这个类型的类都传入到onStartup方法的Set<Class<?>>;为这些WebApplicationInitializer类型的类创建实例;
4)、每一个WebApplicationInitializer都调用自己的onStartup;
5)、相当于我们的SpringBootServletInitializer的类会被创建对象,并执行onStartup方法
6)、SpringBootServletInitializer实例执行onStartup的时候会createRootApplicationContext;创建容器
1 | protected WebApplicationContext createRootApplicationContext( |
7)、Spring的应用就启动并且创建IOC容器
1 | public ConfigurableApplicationContext run(String... args) { |
==启动Servlet容器,再启动SpringBoot应用==
-------------本文结束感谢您的阅读-------------
本文链接: http://example.com/2020/11/17/SpringBoot-Web%E5%BC%80%E5%8F%91%E5%92%8C%E9%A1%B5%E9%9D%A2%E5%9B%BD%E9%99%85%E5%8C%96/
版权声明: 本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。转载请注明出处!