SpringBoot系列之集成jsp模板引擎
SpringBoot系列之集成jsp模板引擎
1、模板引擎简介
引用百度百科的模板引擎解释:
模板引擎(这里特指用于Web开发的模板引擎)是为了使用户界面与业务数据(内容)分离而产生的,它可以生成特定格式的文档,用于网站的模板引擎就会生成一个标准的HTML文档。
在JavaEE领域有几中比较常用的模板引擎,分别是Jsp、Velocity、Freemarker、Thymeleaf,不过对于前端页面渲染效率来说,jsp其实还是最快的,Velocity次之。Thymeleaf虽然渲染效率不是很快,但是语法方面是比较轻巧的,Thymeleaf语法比Velocity轻巧,但是渲染效率不如Velocity
2、环境准备
ok,Springboot是一款javaee框架,使用非常简捷,创建工程也是默认打成jar包的,启动jar包就可以直接运行嵌入式的Servlet容器,比如Tomcat等等,不过Springboot要集成模板引擎的话,是默认不支持jsp的,但是并不表示不能使用,首先Springboot项目默认是jar方式运行的,而我们之前的jsp项目大部分都是war包方式,jar方式打包的项目默认就没有webapp等等这些文件,所以我们要创建jsp项目,就可以创建工程时候改成war包形式
ok,进行jsp实验,环境准备:
- 版本:
- Maven3.9+
- SpringBoot2.2.1
- IDE:
- IntelliJ IDEA
创建Springboot Initializer项目,打包方式选择war方式

创建好的项目,默认是没有webapp文件的,所以我们可以手动加上,或者在idea这样做:

新增web.xml,记得改下默认路径

创建好之后,我们可以看看自动生成的项目有什么特征:
- 首先是多了一个ServletInitializer类,这个类是干什么的?后面再详讲

- Pom文件,翻了一下,发现spring-boot-starter-tomcat的作用范围被改成provided的,这个是什么意思?需要补充一下maven的基础知识,maven中三种classpath 编译,测试,运行
- 1.compile:默认范围,编译测试运行都有效
- 2.provided:在编译和测试时有效
- 3.runtime:在测试和运行时有效
- 4.test:只在测试时有效
- 5.system:在编译和测试时有效,与本机系统关联,可移植性差
修改scope为provided,也就是在运行时不起效,也就是打成war包时候,就不引入对应的Tomcat jar包,不使用嵌入式的Tomcat容器,使用外部的Tomcat容器

3、外部Servlet容器
Springboot项目创建之后,其实就可以直接创建jsp应用了,然后从其自动生成的配置可以看出我们在创建war包时,是可以使用外部的Tomcat容器的,所以,我们引入一下外部Tomcat


部署时候,直接使用暴露的war即可,Application context可以写上也可以不管

直接创建一个jsp页面

进行页面跳转,写个Controller类:
@Controller
public class HelloController {
@RequestMapping(value = {"/success"})
public String toSuccess(){
return "success";
}
}
注意:还要向以前那样定义一下mvc的一下配置:
spring.mvc.view.prefix=/WEB-INF/
spring.mvc.view.suffix=.jsp
ok,我之前博客SpringBoot源码学习系列之嵌入式Servlet容器已经比较详细地介绍了Springboot嵌入式Servlet容器的知识,所以本博客有必要对比一下嵌入式的Servlet容器和本博客介绍的外部Servlet容器的区别
- 外部Servlet容器:maven打包是war形式,先启动Servlet容器,在创建ioc容器
- 嵌入式Servlet容器:maven打包是jar形式,启动时候先创建ioc容器,再启动嵌入式的Servlet容器,比如Tomcat、undertow等等
4、源码原理简介
尚硅谷视频介绍过Servlet的规范,翻下文档,找到如图章节,这个章节介绍了创建war包项目时候会自动创建ServletInitializer类,主要介绍共享库和运行时插件,里面介绍了ServletContainerInitializer,也就是Servlet容器的一个初始化类的使用,启动时候会通过配置在META-INF/services的文件找对应类,通过@HandlesTypes注解在启动时候将需要的类引进来

全局搜索,在Spring-web项目找到对应配置

@HandlesTypes(WebApplicationInitializer.class)//SpringServletContainerInitializer 容器类启动时候会一起创建WebApplicationInitializer类
public class SpringServletContainerInitializer implements ServletContainerInitializer {
@Override
public void onStartup(@Nullable Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)
throws ServletException {
List<WebApplicationInitializer> initializers = new LinkedList<>();
if (webAppInitializerClasses != null) {
for (Class<?> waiClass : webAppInitializerClasses) {
// Be defensive: Some servlet containers provide us with invalid classes,
// no matter what @HandlesTypes says...
//检验WebApplicationInitializer不是一个接口、抽象类就进行实例
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);
//遍历获取到的WebApplicationInitializer 类,调用其对应的onStartup方法
for (WebApplicationInitializer initializer : initializers) {
initializer.onStartup(servletContext);
}
}
}
WebApplicationInitializer 其实就是一个接口类,所以打开其实现类,可以看到SpringBootServletInitializer类

SpringBootServletInitializer类implements WebApplicationInitializer接口,所以在Servlet容器启动时候也会被创建,同时执行onStartup方法,如图,找关键点:

createRootApplicationContext方法是创建根据的容器,看看源码:
protected WebApplicationContext createRootApplicationContext(ServletContext servletContext) {
//创建SpringApplication的构建器
SpringApplicationBuilder builder = createSpringApplicationBuilder();
builder.main(getClass());//设置main方法
ApplicationContext parent = getExistingRootWebApplicationContext(servletContext);
if (parent != null) {
this.logger.info("Root context already created (using as parent).");
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, null);
//构建器初始化
builder.initializers(new ParentContextApplicationContextInitializer(parent));
}
builder.initializers(new ServletContextApplicationContextInitializer(servletContext));
builder.contextClass(AnnotationConfigServletWebServerApplicationContext.class);
//关键点,调用configure方法
builder = configure(builder);
builder.listeners(new WebEnvironmentPropertySourceInitializer(servletContext));
SpringApplication application = builder.build();
if (application.getAllSources().isEmpty()
&& MergedAnnotations.from(getClass(), SearchStrategy.TYPE_HIERARCHY).isPresent(Configuration.class)) {
application.addPrimarySources(Collections.singleton(getClass()));
}
Assert.state(!application.getAllSources().isEmpty(),
"No SpringApplication sources have been defined. Either override the "
+ "configure method or add an @Configuration annotation");
// Ensure error pages are registered
if (this.registerErrorPageFilter) {
application.addPrimarySources(Collections.singleton(ErrorPageFilterConfiguration.class));
}
//启动Application类
return run(application);
}
从这个源码找到关键点configure方法,继续跟一下这个方法,基类的方法很简单,只是返回构造器

所以,在idea里ctrl+alt+B打开其实现方法,如图看到关键点,这个不就是自动创建的ServletInitializer类?而且重写了configure方法,而且将Springboot的Application类传给构造器类,所以跟到这里就明白了,为什么Servlet容器启动时候就会触发Springboot的ioc容器创建

代码例子下载:github下载链接
SpringBoot系列之集成jsp模板引擎的更多相关文章
- springboot系列四、配置模板引擎、配置热部署
一.配置模板引擎 在之前所见到的信息显示发现都是以 Rest 风格进行显示,但是很明显在实际的开发之中,所有数据的显示最终都应该交由页面完成,但是这个页面并不是*.jsp 页面,而是普通的*.html ...
- springboot同时使用thymeleaf和jsp模板
语言:javaEE 框架:springboot+thymeleaf.jsp模板引擎 背景:学习springboot过程中想同时使用thymeleaf和jsp访问(官方不建议) 步骤: 1) 在pom ...
- SpringBoot系列之集成Druid配置数据源监控
SpringBoot系列之集成Druid配置数据源监控 继上一篇博客SpringBoot系列之JDBC数据访问之后,本博客再介绍数据库连接池框架Druid的使用 实验环境准备: Maven Intel ...
- SpringBoot系列之集成Mybatis教程
SpringBoot系列之集成Mybatis教程 环境准备:IDEA + maven 本博客通过例子的方式,介绍Springboot集成Mybatis的两种方法,一种是通过注解实现,一种是通过xml的 ...
- SpringBoot系列之集成logback实现日志打印(篇二)
SpringBoot系列之集成logback实现日志打印(篇二) 基于上篇博客SpringBoot系列之集成logback实现日志打印(篇一)之后,再写一篇博客进行补充 logback是一款开源的日志 ...
- SpringBoot系列之集成Dubbo的方式
SpringBoot系列之集成Dubbo的方式 本博客介绍Springboot框架集成Dubbo实现微服务的3种常用方式,对于Dubbo知识不是很熟悉的,请先学习我上一篇博客:SpringBoot系列 ...
- 九、SpringBoot集成Thymeleaf模板引擎
Thymeleaf咋读!??? 呵呵,是不是一脸懵逼...哥用我的大学四级英文知识告诉你吧:[θaimlif]. 啥玩意?不会音标?...那你就这样叫它吧:“赛母李府”,大部分中国人是听不出破绽的.. ...
- SpringBoot集成Thymeleaf模板引擎
简单介绍 目前在JavaEE领域有几中比较常用的模板引擎,分别是Jsp.Velocity.Freemarker.Thymeleaf,对Freemark语法不是特别熟悉,不过对于前端页面渲染效率来说,j ...
- SpringBoot系列之集成Thymeleaf用法手册
目录 1.模板引擎 2.Thymeleaf简介 2.1).Thymeleaf定义 2.2).适用模板 3.重要知识点 3.1).th:text和th:utext 3.2).标准表达式 3.3).Thy ...
随机推荐
- 学习笔记27_Action方法技巧
*在Action方法中,会存在重载问题,名字冲突就会报错,使用 [HttpPost]//只接受Post请求,且级别较高 public ActionResult Edit(..){} *在Action方 ...
- Android开发中常用的设计模式
首先需要说明的是,这篇博文灵感来自于 http://www.cnblogs.com/qianxudetianxia/archive/2011/07/29/2121547.html ,在这里,博主已经很 ...
- day 2 DP专场
上午讲了一上午背包,从01背包到完全背包到多重背包,感觉也没说什么,旁边的大佬一直在飞鸽里说让老师讲快点,然而最后也没人敢跟老师说.... 例题真的各个都是神仙题, 挂饰 好像就是一上午最简单的... ...
- Java Part 001( 01_01_Java概述 )
Java作为编程语言, 甚至超出了语言的范畴, 成为一种开发平台, 一种开发规范. Java语言相关的JavaEE规范里, 包含了时下最流行的各种软件工程理念, 学习Java相当于系统的学习了软件开发 ...
- MySQL系列:Windows 下 MySQL 8.X 的安装
之前一直使用的是MySQL5.7,但由于MySQL增加了一些新特性,所以选择了更新. 下载MySQL 进入MySQL官网下载地址,选择Windows (x86, 64-bit), ZIP Archiv ...
- C++中对C的扩展学习新增语法——强制类型转换
类型转换:主要进行指针类型转换,因为在C++中,不同类型指针不允许隐式转换,任何一个程序中如果出现了大量的类型转换,说明该程序不是太好的程序. 注意事项: 不同类型指针不允许隐式转换: void* 类 ...
- deepin 、 windows10,双系统安装
deepin . windows10,双系统安装: 首先,最好专门分一个盘用来存放deepin操作系统的安装位置(我这里分给它60个G). 1.在 http://rsync.deepin.com/de ...
- nyoj 67-三角形面积 (海伦公式, 叉积)
67-三角形面积 内存限制:64MB 时间限制:3000ms 特判: No 通过数:8 提交数:13 难度:2 题目描述: 给你三个点,表示一个三角形的三个顶点,现你的任务是求出该三角形的面积 输入描 ...
- PhpStudy BackDoor2019 深度分析
笔者<Qftm>原文发布<合天>:https://mp.weixin.qq.com/s?__biz=MjM5MTYxNjQxOA==&mid=2652852661&am ...
- 软件测试的原则,软件测试计划:5W1H
1.测试应该尽早介入. 2.所有的测试都应追溯到用户需求. 3.程序员应该避免检查自己的程序.除了单元测试.因为程序员对于自己的作品,思维具有局限性.无法保证测试质量.交给 ...