2018年3月初,Spring Boot发生了重大版本更替,正式更新到了2.x的正式(GA)版本。在学习Spring Boot的过程中使用的参考书籍《深入浅出Spring Boot 2.x》使用的Spring Boot的版本是2.0.0.RELEASE版本。但在本地IDE中的联系项目使用的版本为2.1.6.RELEASE。这里需要注意的是Spring Boot 2.x和Spring Boot 1.x在使用上有很多地方存在不同,并且只能支持JDK 8或者以上的版本。
在之前的系列博客《Spring使用篇系列博客传送门》中,我们曾经讨论过在Spring框架中何时使用注解,何时使用XML的问题,在这里我觉得有必要再次将它提出来做一下明确。
对于自己编写的业务类使用注解。例如,对于MVC开发,控制器使用@Controller注解,业务层使用@Service注解,持久层使用@Repository注解。
对于一些公用的Bean,例如对于数据库、第三方资源等则使用XML进行配置。
这已经是一个不成文的共识,直至今日这样的配置方式还在企业中广泛使用着。
随着Spring的版本不断更新,在Spring 4.x时注解功能越来越强大,对于XML的依赖越来越少。与此同时,Pivotal团地在原有Spring的基础上主要通过注解的方式继续简化了Spring框架的开发,他们基于Spring框架开发了Spring Boot,所以Spring Boot并非是代替Spring框架,而是让Spring框架更加容易得到快速的使用。
随着近年来微服务的流行,越来越多的企业需要快速的开发,而Spring Boot除了以注解为主的开发,还有其他的绑定,例如,对服务器进行了绑定和默认对Spring的最大化配置,所以开发者能够尽快进行代码开发、发布和测试自己的项目。这符合了现金微服务快速开发、测试和部署的需要,于是越来越多的企业选择Spring Boot作为开发的选型,进而使得Spring Boot更加兴旺流行起来。
在之前的系列博客《Spring MVC使用篇系列博客传送门》中,详细介绍了如何使用Spring MVC框架开发一个MVC的Web项目,这里便不再赘述,如感兴趣请查看博看《Spring MVC使用篇(二)—— 环境搭建》。其核心是需要配置DispatcherServlet,也需要配置Spring IoC的容器。而对于这些配置可以选择使用web.xml的配置来实现,当然如果使用的是Servlet 3.1规范,也可以继承又Spring MVC提供的AbstractAnnotationConfigDispatcherServletInitializer来配置Spring MVC项目。
传统的Spring MVC开发需要配置的内容还是比较多的,而且对设计人员要求较高。在开发完成后,开发者还需要找到对应的服务器去运行,例如Tomcat或者Jetty等,这样既要进行开发,又要进行配置和部署,工作量不小。
而使用Spring Boot开发后,我们可以通过Maven引入多个相关的Spring Boot的starter,具体依赖如下所示。Spring Boot会将对应的jar包加载到工程中,而且它还会把绑定的服务器也加载到工程中,这些都不需要你再进行处理。正如Spring Boot承诺的那样,绑定服务器,并且实现Spring的尽可能配置,采用约定优于配置的原则。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.1.6.RELEASEversion>
<relativePath/>
parent>
<groupId>com.ccff.springboot.demogroupId>
<artifactId>chapter1artifactId>
<version>0.0.1-SNAPSHOTversion>
<name>chapter1name>
<packaging>warpackaging>
<description>Demo project for Spring Bootdescription>
<properties>
<java.version>1.8java.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-aopartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
project>
根据官网的文档,Spring Boot具有以下优点:
通过上面官网文档的描述,我们可以看出:首先,Spring Boot是一个基于Spring框架搭建起来的应用,其次它会嵌入Tomcat、Jetty或者Undertow等服务器;同时提供通过Maven(或者Grandle)依赖的starter,这些starter可以直接获取开发所需的相关包,通过这些starter项目就能以Java Application的形式运行Spring Boot项目,而无须其他服务器配置;对于配置,Spring Boot提供Spring框架的最大自动化配置,大量使用自动化配置,使得开发者对Spring的配置尽量减少;此外还提供了一些监测、自动检测的功能和外部配置,与此同时没有附加代码和XML的配置要求。
约定优于配置,这是Spring Boot的主导思想。 对于Spring Boot而言,大部分情况下存在默认配置,你甚至可以在没有任何定义的情况下使用Spring框架,如果需要自定义也只需要在配置文件中配置一些属性便可, 十分便捷。而对于部署这些项目必需的功能,Spring Boot提供starter的依赖,这样使得开发者能够尽可能快地搭建开发环境,快速进行开发和部署,这就是Spring Boot的特色。
使用Spring Boot配置Spring MVC,开发控制器类的示例代码如下所示:
package com.ccff.springboot.demo.chapter1;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@SpringBootApplication
public class Chapter1Application {
@GetMapping("/index")
public String index() {
return "Hello Spring Boot 2.x!
";
}
public static void main(String[] args) {
SpringApplication.run(Chapter1Application.class, args);
}
}
直接运行上面的启动类,在控制台出现如下信息则说明Spring Boot已经启动成功。
启动成功后,在浏览器内打开相应url查看输出信息如下:
由此可见,Spring Boot允许直接进行开发,这就是它的优势。在传统所需要配置的地方,Spring Boot都进行了约定,也就是你可以直接以Spring Boot约定的方式进行开发和运行你的项目。
当你需要修改配置的时候,它也提供了一些快速配置的约定,尽可能地配置好Spring项目和绑定对应的服务器,使得开发人员的配置更少,更加直接地开发项目。
首先启动IntelliJ IDEA开发环境,然后选择Create New Project,在弹出的窗口中选择Spring Initializr,将JDK版本设置为1.8,并选择创建服务的URL后点击Next进入下一步。具体如下图所示:
其次,对我们创建的项目进行相应的配置后点击Next,进入下一步,需要注意的是这里我们仍然选择了War的打包形式。具体如下:
然后,在新窗口中需要选择Spring Boot的版本为2.1.6,并根据自己的需要选择对应的starter进行依赖,IntelliJ IDEA也会为你建好工程。这里我们先选择Web进行初始项目的创建,点击Next进入下一步。具体如下图所示:
最后,输入项目名称、项目保存位置,点击Finish,完成Spring Boot项目的创建。
在本小节中,我们利用之前创建的Spring Boot项目,在IntelliJ IDEA中搭建一个由多个模块相互组成并形成依赖的Spring Boot项目。
首先,将父项目中的.idea文件夹、.mvn文件夹、src文件夹、.gitignore文件、mvnw文件、mvnw.cmd文件、Help.md文件全部删除。
其次,创建两个子module,分别为"chapter1"与"chapter2"。两个子module的创建方式与创建父项目的方法一致。
然后,修改父项目中的pom.xml文件中的打包方式,将之前的打包成War包的形式修改为打包成pom的形式。具体如下所示:
<groupId>com.ccff.springboot.demogroupId>
<artifactId>springboot-learning-demoartifactId>
<version>0.0.1-SNAPSHOTversion>
<packaging>pompackaging>
接着,在父项目中的pom.xml文件中添加modules标签,声明其子module,具体配置如下:
<modules>
<module>chapter1module>
<module>chapter2module>
modules>
最后,分别修改chapter1和chapter2的子module中的pom.xml文件。将其中依赖的父项目修改为当前父项目,修改后的配置如下:
<parent>
<groupId>com.ccff.springboot.demogroupId>
<artifactId>springboot-learning-demoartifactId>
<version>0.0.1-SNAPSHOTversion>
<relativePath>../pom.xmlrelativePath>
parent>
在最后一步中有一个坑,这里需要特殊说明一下: 在修改子module依赖的父项目时,如果不指定relativePath的值,可能会出现如下错误提示:
maven报错:Non-resolvable parent POM
这说明了子module中的relativePath属性指向的路径不对,需要手动修改,使其指向父项目的pom.xml文件
我们以最常用的Spring MVC为例说明Spring Boot为什么在很少的配置下就能够运行。
打开本地Maven仓库,找到Spring Boot的文件夹:org.springframework.boot下的spring-boot-start-web,进入后发现有一个名为"2.0.0.RELEASE"的文件夹,进入后打开名为"spring-boot-starter-web-2.0.0.RELEASE.pom"的文件,如下所示:
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-startersartifactId>
<version>2.0.0.RELEASEversion>
parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
<version>2.0.0.RELEASEversion>
<name>Spring Boot Web Startername>
<description>Starter for building web, including RESTful, applications using Spring
MVC. Uses Tomcat as the default embedded containerdescription>
<url>https://projects.spring.io/spring-boot/#/spring-boot-parent/spring-boot-starters/spring-boot-starter-weburl>
<organization>
<name>Pivotal Software, Inc.name>
<url>https://spring.iourl>
organization>
<licenses>
<license>
<name>Apache License, Version 2.0name>
<url>http://www.apache.org/licenses/LICENSE-2.0url>
license>
licenses>
<developers>
<developer>
<name>Pivotalname>
<email>[email protected]email>
<organization>Pivotal Software, Inc.organization>
<organizationUrl>http://www.spring.ioorganizationUrl>
developer>
developers>
<scm>
<connection>scm:git:git://github.com/spring-projects/spring-boot.git/spring-boot-starters/spring-boot-starter-webconnection>
<developerConnection>scm:git:ssh://[email protected]/spring-projects/spring-boot.git/spring-boot-starters/spring-boot-starter-webdeveloperConnection>
<url>http://github.com/spring-projects/spring-boot/spring-boot-starters/spring-boot-starter-weburl>
scm>
<issueManagement>
<system>Githubsystem>
<url>https://github.com/spring-projects/spring-boot/issuesurl>
issueManagement>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starterartifactId>
<version>2.1.6.RELEASEversion>
<scope>compilescope>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-jsonartifactId>
<version>2.1.6.RELEASEversion>
<scope>compilescope>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-tomcatartifactId>
<version>2.1.6.RELEASEversion>
<scope>compilescope>
dependency>
<dependency>
<groupId>org.hibernate.validatorgroupId>
<artifactId>hibernate-validatorartifactId>
<version>6.0.7.Finalversion>
<scope>compilescope>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webartifactId>
<version>5.0.4.RELEASEversion>
<scope>compilescope>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>5.0.4.RELEASEversion>
<scope>compilescope>
dependency>
dependencies>
project>
从上面的文件中可以看出,当加入spring-boot-starter-web后,它会通过Maven将对应的资源加载到我们的工程中,这样便能够形成依赖。
但这样还不足以运行Spring MVC项目,要运行它还需要对Spring MVC进行配置,让它能够生产Spring MVC所需的对象,才能启用Spring MVC。
为了探讨Spring MVC在Spring Boot自动配置的问题,我们还需要在本地Maven仓库中找到spring-boot-autoconfigure目录下的名为"2.1.6.RELEASE"的文件夹下的名为"spring-boot-autoconfigure-2.1.6.RELEASE.jar"的源码包。将其解压缩出来,打开它目录下的子目录:/org/springframework/boot/autoconfigtre/web.servlet后,我们可以看到很多配置类。其中DispatcherServletAutoConfiguration就是一个对DispatcherServlet进行自动配置的类,其源码中的一个内部类DispatcherServletConfiguration对Spring Boot的自动配置做最基本的配置。
通过上一小节,我们知道在几乎没有任何配置下就能用Spring Boot启动Spring MVC项目,是因为Spring Boot通过Maven依赖找到对应的jar包和嵌入的服务器,然后使用默认自动配置类来创建默认的开发环境。
但有的时候,我们需要对这些默认的环境进行修改以适应个性化的要求,这些在Spring Boot中也是非常简单的。正如@EnableConfigurationProperties注解那样,它允许读入配置文件的内容来自定义自动初始化所需的内容。
在使用IntelliJ IDEA创建Spring Boot项目时,会在src/main/resources路径下创建一个名为"application.properties"的属性文件。它是一个默认的配置文件,通过它可以根据自己的需要实现自定义。
假设当前8080端口已经被占用,因此我们希望使用8090端口号启动Tomcat,那么只需要在application.properties属性文件中添加如下属性配置:
server.port=8090
事实上,在平时的日常开发中,除了使用properties文件外,yml文件也是一种十分常见的格式。yml文件的配置与properties文件只是简写和缩进的差别,因此差异并不大。
在2.4小节中,我们修改了服务器的端口号,除此之外有时我们还需要修改Spring MVC的视图解析器。在开发中较为常用的视图之一为JSP。
例如,现在控制器中返回一个字符串"index",那么我们希望它对应的是开发项目的/WEN-INF/jsp/index.jsp文件。
首先,我们需要在chapter2 module中的pom.xml文件中添加该模块特有的JSP和JSTL依赖包,具体如下:
<dependency>
<groupId>org.apache.tomcat.embedgroupId>
<artifactId>tomcat-embed-jasperartifactId>
<scope>providedscope>
dependency>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>jstlartifactId>
<scope>providedscope>
dependency>
其次,修改application.properties属性文件,设置Spring MVC视图解析器的前缀后后缀,具体属性配置如下:
server.port=8090
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
然后,在com.ccff.springboot.demo.chapter2.controller包下创建名为"IndexController"的控制器,具体代码如下所示:
package com.ccff.springboot.demo.chapter2.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* Created by wangzhefeng01 on 2019/8/2.
*/
@RestController
@RequestMapping("/Index")
public class IndexController {
@GetMapping("/index")
public String index(){
return "index";
}
}
接着,在src/main下创建webapp/WEB-INF/jsp/index.jsp,具体代码如下所示:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Spring boot 视图解析器title>
head>
<body>
<h1>测试视图解析器h1>
body>
html>
最后,运行Spring Boot启动类Chapter2Application,项目启动后在浏览器内输入url:,结果如下图所示:
这里有一个很深的坑需要大家注意:在IndexController控制器中使用@Controller注解时会出现404的问题,报错信息如下:
spring boot整合jsp的时候访问页面错误日志:Path with "WEB-INF" or "META-INF":
问题解析戳这里: