Thymeleaf、Web定制、容器定制
- 创建Spring Boot应用,选中我们需要的模块
- Spring Boot已经默认将这些场景配置好了,我们只需要在配置文件中指定少量配置就可以运行起来
- 编写业务代码
- 访问映射路径,会去对应的资源路径找资源
- 关于上表中常用前端框架的映射规则提到的webjars
webjars:以jar包的方式引入静态资源,参考网站,在参考网站中找到需要引入的webjars,通过maven或其他方式引入即可,以JQuery 3.5.1为例
在pom.xml中引入完成后的jar包结构如下:
此时,如果我们在浏览器中输入的地址是localhost:8080/webjars/jquery/3.5.1/dist/jquery.js,那么就会找当前这个jQuery jar包下的/META-INF/resources/webjars/jquery/3.5.1/dist/jquery.js - 对于自己的静态资源,如果没人处理,就会去对应的资源路径下找,而假如访问,还是会先去对应的资源路径下找。
- 配置自定义静态资源文件夹路径列表(自定义哪些路径是存放静态资源的路径):,多个路径以逗号分隔
- 查看源码的过程中遇到的System.arraycopy,用于复制数组的内容,用法如下
public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
src:源数组;
srcPos:源数组要复制的起始位置;
dest:目的数组;
destPos:目的数组放置的起始位置;
length:复制的长度.
pom.xml中引入Thymeleaf的场景启动器即可
参考网站
其中,Thymeleaf主程序和布局功能的扩展程序的版本是有对应关系的,主程序版本为Thymeleaf 3,布局功能的扩展程序的版本就要为 2以上版本,主程序版本为Thymeleaf 2,布局功能的扩展程序的版本就要为 1。
使用步骤
- 看 看自动配置规则
由此可知:只要把Html页面放在classpath:/templates/目录下,Thymeleaf就能自动渲染
2.使用:
1、导入Thymeleaf的名称空间,导入名称空间的好处是会有语法提示
2、简单使用Thymeleaf;
1)th:text;改变当前元素里面的文本内容;
th:任意html属性;来替换原生属性的值
Thymeleaf和JSP标签的对比如下(属性的优先级自上而下是由高到低的,优先级高的先生效)
th:insert th:replace th:incloud之间的对比
定义公共片段的两种方式:
- th:fragment属性进行定义,通过~{页面名 :: th:fragment属性值}或页面名 :: th:fragment属性值引入片段
- 定义id,通过~{页面名 :: #id值}或页面名 :: #id值引入片段
th:attr;设置属性值
设置单个属性值
设置多个属性值
以上两个的代替写法 th:xxxx
所有h5兼容的标签写法
https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#setting-value-to-specific-attributes
th:each;迭代
th:if、th:switch;条件运算
2)表达式?
表达式总结如下
hello.html
HelloController
https://docs.spring.io/spring-boot/docs/1.5.10.RELEASE/reference/htmlsingle/#boot-features-developing-web-applications
Ctrl + G 光标跳转到行
Spring Boot 自动配置好了SpringMVC
以下是SpringBoot对SpringMVC的默认配置:(WebMvcAutoConfiguration)
- Inclusion of and beans.
- 自动配置了ViewResolver(视图解析器:根据方法的返回值得到视图对象(View),视图对象决定如何渲染(转发?重定向?))
- ContentNegotiatingViewResolver:组合所有的视图解析器的;
- 如何定制:我们可以自己给容器中添加一个视图解析器;自动的将其组合进来;
- Support for serving static resources, including support for WebJars (see below).静态资源文件夹路径,webjars
- Static support. 静态首页访问
- Custom support (see below). favicon.ico
- 自动注册了 of , , beans.(页面过来的数据与要封装的类型不一致的情况)
- Converter:转换器; public String hello(User user):类型转换使用Converter
- 格式化器; 2017.12.17===Date;(日期字符串按指定格式转为日期类型)
自己添加的格式化器转换器,我们只需要放在容器中即可
- Support for (see below).
- HttpMessageConverter:SpringMVC用来转换Http请求和响应的;User---Json;(Controller中的方法返回JavaBean要以JSON的形式写回给浏览器就要用到HttpMessageConverter)
- 是从容器中确定;获取所有的HttpMessageConverter;
自己给容器中添加HttpMessageConverter,只需要将自己的组件注册容器中(@Bean,@Component)
- Automatic registration of (see below).定义错误代码生成规则
- Automatic use of a bean (see below).
我们可以配置一个ConfigurableWebBindingInitializer来替换默认的;(添加到容器)
org.springframework.boot.autoconfigure.web:web的所有自动配置场景(该包下的所有XXXAutoConfiguration);
If you want to keep Spring Boot MVC features, and you just want to add additional MVC configuration (interceptors, formatters, view controllers etc.) you can add your own class of type , but without . If you wish to provide custom instances of , or you can declare a instance providing such components.
If you want to take complete control of Spring MVC, you can add your own annotated with .
既保留了所有的自动配置,也能用我们扩展的配置
编写一个配置类(@Configuration),是WebMvcConfigurerAdapter类型(继承WebMvcConfigurerAdapter);不能标注@EnableWebMvc;
原理:
1)WebMvcAutoConfiguration是SpringMVC的自动配置类
2)WebMvcAutoConfiguration中的静态内部类WebMvcAutoConfigurationAdapter会导入;
3)容器中所有的WebMvcConfigurer都会一起起作用;
4)我们的配置类也会被调用;
效果:SpringMVC的自动配置和我们的扩展配置都会起作用;
SpringBoot对SpringMVC的自动配置不需要了,所有都是我们自己配置;所有的SpringMVC的自动配置(WebMvcAutoConfiguration)都失效了
我们需要在配置类中添加@EnableWebMvc即可;
原理:
为什么加了@EnableWebMvc,自动配置就失效了;
1)@EnableWebMvc的核心
2)、
3)、
4)、@EnableWebMvc将WebMvcConfigurationSupport组件导入进来;
5)、导入的DelegatingWebMvcConfiguration(WebMvcConfigurationSupport)只是SpringMVC最基本的功能;
模式:
1)SpringBoot在自动配置很多组件的时候,先看容器中有没有用户自己配置的(@Bean、@Component)如果有就用用户配置的,如果没有,才自动配置(@ConditionalOnMissingBean);如果有些组件可以有多个(ViewResolver),将用户配置的和自己默认的组合起来;
2)在SpringBoot中会有非常多的xxxConfigurer帮助我们进行扩展配置
3)在SpringBoot中会有很多的xxxCustomizer帮助我们进行定制配置
- Controller中定义方法
- WebMvcConfigurerAdapter(推荐)
Shift+F6:文件重命名
FAQ:
首先,classpath:/public目录下已经存在了index.html
我在WebMvcConfigurerAdapter中是这么写的
但是这样访问项目跳转到的页面是index.html,而不是login.html
而当我把WebMvcConfigurerAdapter中的/login.html改为index.html时,访问的就是login.html页面了
通过浏览器的语言信息动态显示首页的国际化效果(说白了就是切换浏览器语言,首页的语言也相应的改变)
SpringMVC配置国际化的步骤:
1)编写国际化资源文件(SpringBoot配置国际化仅需要这一步);
2)使用ResourceBundleMessageSource管理国际化资源文件
3)在JSP页面使用fmt:message取出国际化内容
SpringBoot配置国际化的步骤:
1)编写国际化资源文件(一定是properties文件),抽取页面需要显示的国际化消息,
login.properties:未指定浏览器语言信息情况下默认的资源文件
IDEA检测到国际化资源文件后会自动切换到国际化视图
2)SpringBoot自动配置好了管理国际化资源文件的组件;
由于我们没有用默认的基础名,所以需要进行设置
3)去页面获取国际化的值(#{}用来获取国际化信息);
运行后可能会出现乱码
解决方法是IDEA-File-Settings进行properties文件编码的设置
上述设置是临时生效的
效果:根据浏览器语言设置的信息切换了国际化;
在运行时也肯出现如图的问题
application.properties文件的内容改为如下即可
正常显示之后,还可能出现切换语言显示不成功的情况,像我,不管怎么切换英文,还是会显示中文╮(╯▽╰)╭
SpringMVC中的国际化原理:
国际化Locale(区域信息对象);LocaleResolver(获取区域信息对象);
4)点击链接切换国际化(在链接上携带区域信息实现)
RestAPI方式的注解
所有4开头的状态码表示客户端错误,400表示客户端提交的数据不对
设置开发期间模板引擎页面修改以后实时生效
1)禁用模板引擎的缓存
2)页面修改完成以后ctrl+f9:重新编译(手动编译的原因是IDEA在项目运行期间不会自动编译我们所做的页面修改);
登陆错误消息的显示
由于登录后是转发到成功页的,刷新页面,就会出现表单重复提交的问题,解决的方法是通过重定向跳转到成功页
首先增加一个到主页的视图映射
然后修改Controller中验证通过时的页面跳转为重定向
通过重定向的方式解决了表单重复提交的问题之后,可以直接访问/main.html跳转到主页从而绕过登录,为了解决这个问题,我们引入了拦截器
自定义的拦截器
注册拦截器
实验要求:
1)RestfulCRUD:CRUD满足Rest风格;
(1)Rest风格:
URI: /资源名称/资源标识(一般就是ID) HTTP请求方式区分对资源CRUD操作
(2)普通CRUD和RestfulCRUD的区别:
2)请求架构;
3)员工列表:
(1)thymeleaf公共页面元素抽取
三种引入公共片段的th属性:
th:insert:将公共片段整个插入到声明引入的元素(th:insert所在的标签)中
th:replace:将声明引入的元素替换为公共片段
th:include:将被引入的片段的内容包含进th:include所在的标签中
将公共内容单独放到一个目录中
分别在dashboard.html和list.html中引入公共元素片段
(2)链接高亮的动态效果显示
首先在公共元素片段中增加如下判断
然后在引入片段的时候传入参数,多个参数用逗号分隔:
上述传参引入片段的形式为:
在公共片段中直接使用类似于${activeURI}的形式使用参数,引入公共片段的时候通过commons/bar::#sidebar(参数名=参数值)的形式进行传参,这样的好处是在公共片段中不需要实现定义参数。
(3)遍历后台返回的Collection完成列表页显示
通过date工具对象格式化日期显示
添加页面
完成页面添加后需要发送/emps请求来到列表页面,这时是不能直接写路径的,可以通过重定向或请求转发的方式实现
- 直接写视图名,会交给Thymeleaf模板引擎进行解析,拼串查找页面
- 前缀为 :这样如果写Controller中的路径映射,就会找到对应的方法了
- 前缀为 :请求转发
提交的数据格式不对:生日(日期)
2017-12-12;2017/12/12;2017.12.12;
日期的格式化;SpringMVC将页面提交的值需要转换为指定的类型;
2017-12-12---Date; 类型转换,格式化;
默认日期是按照/的方式;
自定义日期填报格式
修改添加二合一表单
上述方式虽然也能实现删除,但由于是遍历生成的删除按钮,会导致页面中多很多个form表单,改进如下
默认效果:
1)浏览器,返回一个默认的错误页面
2)如果是其他客户端,默认响应一个json数据
通过请求头信息可以判断是相应PC端浏览器的页面还是其他客户端的JSON数据
PC端浏览器发送请求的请求头:
其他客户端发送请求的请求头:
原理:
可以参照;错误处理的自动配置;
1、DefaultErrorAttributes:
2、BasicErrorController:处理默认/error请求
3、ErrorPageCustomizer:
4、DefaultErrorViewResolver:
步骤:
一但系统出现4xx或者5xx之类的错误;ErrorPageCustomizer就会生效(定制错误的响应规则);就会来到/error请求;就会被BasicErrorController处理;
1)响应页面;去哪个页面是由DefaultErrorViewResolver解析得到的;
7.2.1 PC端浏览器:如何定制错误的页面
1)有模板引擎的情况下;error/状态码【将错误页面命名为 错误状态码.html 放在 templates/error文件夹下,templates为模板引擎文件夹】,发生此状态码的错误就会来到 对应的页面;
我们可以使用4xx和5xx作为错误页面的文件名来匹配这种类型的所有错误,;其中xx并不区分大小写
错误页面能获取的信息;
timestamp:时间戳
status:状态码
error:错误提示
exception:异常对象
message:异常消息
errors:JSR303数据校验的错误都在这里
错误页面中通过的方式可以获取这些信息。
2)没有模板引擎(模板引擎找不到这个错误页面),默认去静态资源文件夹下找;
3)以上都没有错误页面,就是默认来到SpringBoot默认的错误提示页面;
7.2.2 其他客户端:如何定制错误的json数据
1)自定义异常处理&返回定制json数据;
缺陷:没有自适应效果(PC端浏览器和其他客户端都会返回JSON数据)
2)转发到/error进行自适应响应效果处理
缺陷:没有显示出我们自定义的异常数据
3)将我们的定制数据携带出去;
出现错误以后,会来到/error请求,会被BasicErrorController处理,响应出去可以获取的数据是由getErrorAttributes(AbstractErrorController(ErrorController)规定的方法)得到的
1、完全来编写一个ErrorController的实现类【或者是编写AbstractErrorController的子类】,放在容器中;
2、页面上能用的数据,或者是json返回能用的数据都是通过errorAttributes.getErrorAttributes得到;
容器中DefaultErrorAttributes.getErrorAttributes();默认进行数据处理的;
自定义ErrorAttributes
异常处理器
最终的效果:响应是自适应的,可以通过定制ErrorAttributes改变需要返回的内容。
SpringBoot默认使用Tomcat作为嵌入式的Servlet容器;
嵌入式Servlet容器存在的问题:
- 如何定制和修改Servlet容器的相关配置
- SpringBoot能不能支持其他的Servlet容器
以下的讲解就是围绕这两个问题展开的
(对应外部Tomcat的配置文件)
1、修改和server有关的配置(ServerProperties【也是EmbeddedServletContainerCustomizer】);
2、编写一个EmbeddedServletContainerCustomizer:嵌入式的Servlet容器的定制器;来修改Servlet容器的配置
(对应原Web工程中web.xml中注册的三大组件)
由于SpringBoot默认是以jar包的方式启动嵌入式的Servlet容器来启动SpringBoot的web应用,没有web.xml文件。
注册三大组件用以下方式
ServletRegistrationBean
FilterRegistrationBean
ServletListenerRegistrationBean
SpringBoot帮我们自动配置SpringMVC的时候,自动的注册SpringMVC的前端控制器;DispatcherServlet;
DispatcherServletAutoConfiguration中:
默认支持:Tomcat、Jetty、Undertow
选中+Ctrl+H:打开继承树
Jetty:适合开发应用
Undertow:不支持JSP、但并发性能非常好
通过更换不同依赖就可以切换不同的Servlet容器
Tomcat(默认使用)
Jetty
Undertow
EmbeddedServletContainerAutoConfiguration:嵌入式的Servlet容器自动配置?
1)、EmbeddedServletContainerFactory(嵌入式Servlet容器工厂)
2)、EmbeddedServletContainer:(嵌入式的Servlet容器)
3)、以TomcatEmbeddedServletContainerFactory为例
4)、我们对嵌入式容器的配置修改是怎么生效?
EmbeddedServletContainerCustomizer:定制器帮我们修改了Servlet容器的配置?
怎么修改的原理?
5)、容器中导入了EmbeddedServletContainerCustomizerBeanPostProcessor
步骤:
1)SpringBoot根据导入的依赖情况,给容器中添加相应的EmbeddedServletContainerFactory【TomcatEmbeddedServletContainerFactory】
2)(容器中某个组件)EmbeddedServletContainerFactory要创建对象就会惊动后置处理器;EmbeddedServletContainerCustomizerBeanPostProcessor;
只要是嵌入式的Servlet容器工厂,后置处理器就工作;
3)后置处理器,从容器中获取所有的EmbeddedServletContainerCustomizer,调用定制器的定制方法
什么时候创建嵌入式的Servlet容器工厂?什么时候获取嵌入式的Servlet容器并启动Tomcat;
获取嵌入式的Servlet容器工厂:
1)SpringBoot应用启动运行run方法
2)refreshContext(context);SpringBoot刷新IOC容器【创建IOC容器对象并初始化容器(创建容器中的每一个组件)】;如果是web应用创建AnnotationConfigEmbeddedWebApplicationContext,否则:AnnotationConfigApplicationContext
3)refresh(context);刷新刚才创建好的ioc容器;
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容器
嵌入式Servlet容器:应用打成可执行的jar
优点:简单、便携;
缺点:默认不支持JSP、优化定制比较复杂(使用定制器【ServerProperties、自定义EmbeddedServletContainerCustomizer】,自己编写嵌入式Servlet容器的创建工厂【EmbeddedServletContainerFactory】);
外置的Servlet容器:外面安装Tomcat---应用war包的方式打包;
1)必须创建一个war项目;(利用idea创建好目录结构)
创建war项目后生成webapp目录
然后生成web.xml
配置Tomcat并部署项目
2)将嵌入式的Tomcat指定为provided(目标环境已经存在,打包时不需要打进这个包);
3)必须编写一个SpringBootServletInitializer的子类(类名随意),并调用configure方法
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)、orgspringframeworkspring-web4.3.14.RELEASEspring-web-4.3.14.RELEASE.jar!META-INFservicesjavax.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;创建容器
7)、Spring的应用启动并且创建IOC容器
首先启动Servlet容器,再启动SpringBoot应用
到此这篇springboot应用服务器(spring boot服务器)的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!版权声明:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权、违法违规、事实不符,请将相关资料发送至xkadmin@xkablog.com进行投诉反馈,一经查实,立即处理!
转载请注明出处,原文链接:https://www.xkablog.com/kjbd-yiny/74336.html