上回我们了解了Spring Boot 项目的搭建和程序员入门Hello World 的一个体验,我们也引入了org.springframework.boot:spring-boot-starter-web 依赖,这个依赖就是我们这回要学习的重点基于Web开发。

嵌入式Web容器

说到Web开发,那么不得不说一个重重之中的东西,Web容器。我们回想下J2EE项目,额,已经改名叫Java EE项目了。它的部署是什么来着?把一个Java项目打包成war包,然后放入tomcat的webapps中,启动tomcat那么部署完成,然后就是浏览器访问了。那么,我们Spring Boot项目呢?

上回我们就聊到了fat jar的概念,就是说可执行jar文件,那么什么叫可执行jar文件呢?就是我们常说的java -jar直接启动的一个项目,我们做个简单的案例来说明fat jar。

首先我们创建一个Java世界里面的第一个文件Hello.java

package com.demo;

public class Hello{

	public static void main(String[] args){
		System.out.println("hello world");
	}
}

然后,我们编译javac -d . Hello.java,然后我们再运行java com.demo.Hello,控制台打印出了hello,world的字样,假如说我们要把这段代码发布到生产环境的话(这是不可能的),直接发布文件吗?当然没人会这么干,那么我们怎么办呢?jdk提供了一种命令行打成jar包的形式,我们试试。

我们先创建一个MANIFEST.MF文件,这个文件是引导文件,告诉我们默认执行那个类,源码如下:

Manifest-Version: 1.0
Created-By: 1.8.0_141 (Oracle Corporation)
Main-Class: com.demo.Hello

这个文件需要注意一下三点
1. 第一行之前,行与行之间不能有空行,第一行后面不能有空格
2. 最后一行后面一定要一个空行
3. key值后面一定要一个空格,如Main-Class:后面接了一个空格
我们根据这个引导文件打成jar包指令为jar cvfm hello.jar MANIFEST.MF com ,我们稍微分析下这个指令:
1. c 创建一个jar包
2. v 生成详细的信息并输出到控制台
3. f 指定的jar包文件名
4. m 指定manifest.mf文件
打好jar包后,我们执行javar -jar hello.jar,发现控制台也打印出了hello,world的字样,这就是fat jar了。

好了,说了fat jar后,我们再回到Spring Boot,看看Spring Boot 的fat jar又是什么样子呢?我们先看下引导文件吧。

Manifest-Version: 1.0
Implementation-Title: first-gui-application
Implementation-Version: 0.0.1-SNAPSHOT
Built-By: DELL
Implementation-Vendor-Id: com.zwq
Spring-Boot-Version: 2.1.4.RELEASE
Main-Class: org.springframework.boot.loader.JarLauncher
Start-Class: com.zwq.firstguiapplication.FirstGuiApplication
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Created-By: Apache Maven 3.5.2
Build-Jdk: 1.8.0_141
Implementation-URL: https://projects.spring.io/spring-boot/#/spring-bo
 ot-starter-parent/first-gui-application

无独有偶,和我们之前的hello-world版有相似之处,都有个Main-Class,这么说来,JarLauncher类就是我们的引导类了,这里先不深入探讨这个问题,我们回到标题,嵌入式容器吧,有点跑题了。

首先我们把项目导入到IDEA中(毕竟用记事本写代码效率还是比较低的),具体步骤不细说了。

说下Spring Boot 是如何嵌入式Tomcat容器的,我们使用maven查看下spring-boot-starter-web的依赖,idea里面有图形化界面可供查看,具体在maven>> dependencies 。我们也可以用命令行的形式查看,这里我们了解下命令行的形式查看依赖吧,图形化界面过于简单就不列出了。

输入命令mvn dependency:tree 我们可以知道项目的所有依赖,不过依赖太多了,我们筛选下我们感兴趣的mvn dependency:tree -Dincludes=org.springframework.* ,执行结果如下所示:

[INFO] --- maven-dependency-plugin:3.1.1:tree (default-cli) @ first-gui-application ---
[INFO] com.zwq:first-gui-application:jar:0.0.1-SNAPSHOT
[INFO] +- org.springframework.boot:spring-boot-starter-web:jar:2.1.4.RELEASE:compile
[INFO] |  +- org.springframework.boot:spring-boot-starter:jar:2.1.4.RELEASE:compile
[INFO] |  |  +- org.springframework.boot:spring-boot:jar:2.1.4.RELEASE:compile
[INFO] |  |  +- org.springframework.boot:spring-boot-autoconfigure:jar:2.1.4.RELEASE:compile
[INFO] |  |  \- org.springframework.boot:spring-boot-starter-logging:jar:2.1.4.RELEASE:compile
[INFO] |  +- org.springframework.boot:spring-boot-starter-json:jar:2.1.4.RELEASE:compile
[INFO] |  \- org.springframework.boot:spring-boot-starter-tomcat:jar:2.1.4.RELEASE:compile
[INFO] \- org.springframework.boot:spring-boot-starter-test:jar:2.1.4.RELEASE:test
[INFO]    +- org.springframework.boot:spring-boot-test:jar:2.1.4.RELEASE:test
[INFO]    \- org.springframework.boot:spring-boot-test-autoconfigure:jar:2.1.4.RELEASE:test
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS

原来Spring Boot 嵌入式Tomcat容器就是加入了org.springframework.boot:spring-boot-starter-tomcat:jar:2.1.4.RELEASE所致,那么如果我们想使用Undertow或者Jetty容器呢?是不是加入org.springframework.boot:spring-boot-starter-jetty即可?我们修改下pom.xml文件,如下:

<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
			<exclusions>
				<exclusion>
					<groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-jetty</artifactId>
		</dependency>

得到的结果就是我们猜想的(由于spring-boot-starter-web 默认使用tomcat,如果要使用jetty那么必须移出掉tomcat依赖)。

集成Thymeleaf

集成之前我们回顾下Spring Boot的一个特点Get started in seconds using Spring Initializr,那么,集成Thymeleaf是不是也能那么快呢?答案是肯定的。

首先,我们添加上Thymeleaf的依赖org.springframework.boot:spring-boot-starter-thymeleaf,看到这个依赖是不是很熟悉,和我没的web依赖几乎一模一样,那么,使用起来,应该也是很方便的,我们在templates目录(图形化界面创建的项目会自带该目录,如果没有刻意在resource目录下自己创建一个)下创建一个thymeleaf的html文件index.html,代码如下:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8" />
    <title>Title</title>
    <link th:href="@{bootstrap/css/bootstrap.css}" rel="stylesheet"/>
    <link th:href="@{bootstrap/css/bootstrap-theme.css}" rel="stylesheet"/>
</head>
<body>
    <div class="container">
        <div class="panel panel-primary">
            <h3 class="panel-heading">访问model</h3>
            <div class="panel-body">
                <span th:text="${word}"></span>
                <button class="btn btn-danger">提示按钮</button>
            </div>
        </div>

    </div>

<script th:src="@{js/jquery-1.12.4.min.js}" type="text/javascript"></script>
<script th:src="@{bootstrap/js/bootstrap.js}" type="text/javascript"></script>
</body>
</html>

这里面的一些具体语法和使用参考Thymeleaf和Bootstrap官网(相关静态代码放在static目录下),这不是这里关注的。

然后创建一个控制器,IndexController.java

@Controller
public class IndexController {
    @GetMapping({"/","/index"})
    public String index(Model model){
        model.addAttribute("word","spring boot word");
        return "index";
    }
}

接下来启动项目,直接访问http://localhost:8080会看到如下
Spring Boot 学习之Web开发(二)
这样,我们就算集成成功了。具体为什么这么方便,我们以后再探讨。

注册Servlet、Listener、Filter

使用web项目,常用的Servlet、Listener、Filter在Spring Boot中创建也会更为的方便,接下来,我们实践一下。

  1. 直接使用@WebServlet,@WebFilter,@WebListener 三大注解的形式创建,需要注意的是要在启动类上加上注解@ServletComponentScan 否则不会生效,篇幅有限,具体代码就不列出来了。
  2. Spring Boot 提供了另一种方式注册,需要借助ServletRegistrationBeanFilterRegistrationBeanServletListenerRegistrationBean三个类来达到注册的效果,类似于web.xml中配置。具体代码如下
@Bean
    public ServletRegistrationBean servletRegistrationBean(){
        ServletRegistrationBean servletRegistrationBean =
                new ServletRegistrationBean(new DemoServlet(),"/demoServlet");
        return servletRegistrationBean;
    }

    @Bean
    public FilterRegistrationBean filterRegistrationBean(){
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setFilter(new DemoFilter());
        filterRegistrationBean.setOrder(1);
        filterRegistrationBean.setUrlPatterns(Arrays.asList("/*"));
        return filterRegistrationBean;
    }
    @Bean
    public ServletListenerRegistrationBean listenerRegistrationBean(){
        ServletListenerRegistrationBean listenerRegistrationBean = new ServletListenerRegistrationBean();
        listenerRegistrationBean.setListener(new DemoListener());
        return listenerRegistrationBean;
    }

尾声

这回,我们初步理解了嵌入式容器,继承Thymeleaf以及Spring Boot 的Servlet,Filter,Listener如何注册,千里之行,基于跬步,我们只有一步一步的学习才能真正的成长起来。

相关文章:

  • 2021-04-16
  • 2021-05-02
  • 2021-06-10
  • 2021-12-09
  • 2021-12-02
  • 2021-10-10
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2021-07-07
  • 2021-09-28
  • 2021-05-17
  • 2021-12-01
  • 2022-12-23
相关资源
相似解决方案