Java 企业级开发,经历了从 SSH (Spring + Struts2 + Hibernate)到 SSM(Spring + StringMVC + MyBatis)再到 Spring 全家桶(Spring + Spring Boot + SpringData + Spring Cloud 等)的过程。总之,代码的封装程度越来越高,开发的复杂度也在越来越低。
Spring 全家桶的底层基础都是 Spring 框架,通常可以分为两类:
- Java 企业级开发:Spring Boot
- Java 分布式应用:Spring Cloud
Spring Boot 概述
Spring Boot 可以一站式实现 J2EE 企业级开发。
Spring Boot 用来简化 Spring 应用的开发,采用“约定大于配置”的原则,省去了大量复杂的配置,可以方便快速的创建一个企业级应用。
Spring Boot 本身是基于 Spring 的,类似于前端框架 Vue 所使用的 vue-cli,快速创建独立的企业级应用。
Spring Boot 的特点:
- 嵌入了 Servlet 容器,应用无需打包
- 提前封装好了各种依赖对应的 starter
- 默认配置,简化开发,配置可以修改
- 不用配置 XML,不会生成代码,各种写好的 API 开箱即用
- 运行时的应用监控,可以监控服务状态
因为 Spring Boot 是基于 Spring 框架的二次封装,如果你不了解 Spring 框架的一些底层原理,则在轻松入门后,难以精通。
单体应用和微服务
Spring Boot 的诞生背景就是微服务的大潮流,这里先大概提一下微服务这个概念。
微服务概念流行之前,大部分应用都是单体应用。单体应用将所有代码耦合到一个项目中,通过命名空间或直接引入类文件实现类的调用。在项目初期比较小的时候,这种开发方式效率高、部署容易、测试方便、易于实现负载均衡(水平扩容)。但是发展到一定规模后,会出现牵一发而动全身的问题,各种依赖关系耦合复杂,难以实现新需求,难以修改。
微服务将应用的每一个模块独立为一个服务,服务之间通过 RPC 或 HTTP 方式实现相互调用,从而实现解耦,方便实现各个微服务的独立扩容。通常会有一个网关对外提供统一的服务入口。
Spring Boot 的 HelloWorld 项目(基于 IDEA)
在 Spring 官网 http://spring.io/ 可以找到各种相关的资源。HelloWorld 示例可以参考:http://spring.io/guides/gs/actuator-service/
创建 Maven 工程
在 Intellij IDEA 中选择 File-》New Project-》Maven,创建 Maven 类型的项目,选择合适的SDK 版本后,点击下一步,输入 GroupId(例如com.baid)和 ArtifactId(例如 spring_boot_demo,IDEA 不支持中横线),点击下一步选择项目的位置(默认在 C 盘),然后 Finish 完成即可。
项目初始化完成后,IDEA 右下角会弹出“Maven project need to be imported”弹出,选择“Enable Auto-Import” 即可。这样当你更新了 Maven 项目的 pom.xml 文件时,IDEA 会自动获取依赖。
导入 Spring Boot 的依赖
到这里,Maven 项目就创建完成了,接下来只需要添加 Spring Boot 依赖即可,复制下面的文本到项目根目录中的 pom.xml 文件的 project 标签下即可:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.5.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
编写 Java 代码
编写主程序启动 Spring Boot 应用
在 IDEA 中展开刚才创建的项目的代码目录,在 /src/main/java 目录右击,创建新的 Java class,输入“com.kikakika.SpringBootApplication”这种方式,可以自动创建包和类,然后编辑类:
package com.kikakika;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* 通过注解标注这是一个 Spring Boot 主程序类
*/
@SpringBootApplication
public class HelloWorldMainApplication {
// 启动 Spring Boot 应用程序
public static void main(String[] args) {
SpringApplication.run(HelloWorldMainApplication.class, args);
}
}
编写 Controller
右击 com.kikakika 包名,创建新的 Java class,输入 controller.HelloController,在 com.kikakika.controller 包下面创建 HelloController 类:
package com.kikakika.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class HelloController {
@ResponseBody
@RequestMapping
public String Hello() {
return "Hello World!!";
}
}
启动 Spring Boot
回到 SpringBootApplication 文件,右击,运行即可启动这个 Java 应用。控制台会打印启动日志,注意看对应的 Tomcat 端口,一般是 8080:
2019-01-01 12:27:20.100 INFO 12380 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup
2019-01-01 12:27:20.154 INFO 12380 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2019-01-01 12:27:20.160 INFO 12380 --- [ main] com.kikakika.HelloWorldMainApplication : Started HelloWorldMainApplication in 5.598 seconds (JVM running for 8.007)
在浏览器中访问localhost:8080/hello
查看效果。
打包部署 Spring Boot 应用
参考:https://docs.spring.io/spring-boot/docs/current/reference/html/build-tool-plugins-maven-plugin.html
首先将 Spring Boot 的用于创建可执行 Jar 文件的 Maven 插件导入项目中:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.1.1.RELEASE</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
然后,打包。
打包完成后,整个项目,包括 Tomcat 都会被打到一个 Jar 包中,一般放在项目根目录下的 target 目录中,可以直接通过 java -jar
命令运行即可。
C:UserskikaDesktop>java -jar spring_boot_demo-1.0-SNAPSHOT.jar
. ____ _ __ _ _
/\ / ___'_ __ _ _(_)_ __ __ _
( ( )\___ | '_ | '_| | '_ / _` |
\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.0.5.RELEASE)
2019-01-01 12:50:36.293 INFO 10096 --- [ main] com.kikakika.HelloWorldMainApplication : Starting HelloWorldMainApplication v1.0-SNAPSHOT on DESKTOP-QDO2CMR with PID 10096 (C:UserskikaDesktopspring_boot_demo-1.0-SNAPSHOT.jar started by kika in C:UserskikaDesktop)
2019-01-01 12:50:36.301 INFO 10096 --- [ main] com.kikakika.HelloWorldMainApplication : No active profile set, falling back to default profiles: default
2019-01-01 12:50:36.447 INFO 10096 --- [ main] ConfigServletWebServerApplicationContext : Refreshing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@6d1e7682: startup date [Tue Jan 01 12:50:36 CST 2019]; root of context hierarchy
通过浏览器访问即可,效果跟在 IDEA 中启动应用一样。
Spring Boot 的一点点原理
启动器
在项目根目录下的 pom.xml 文件中,可以看到 artifactId 以 spring-boot-starter-
开头的各种项目,不管是在 parent 父项目标签还是 dependencies 依赖标签中。这些项目,就是各种场景下的启动器,每个启动器都内置了完整的依赖。
Spring 提前为我们封装了各种场景下的启动器,例如针对 ActiveMQ 的 spring-boot-starter-activemq,针对 AOP 的 spring-boot-starter-aop,针对使用 Hibernate 的 Spring Data JPA 的 spring-boot-starter-data-jpa,针对 Redis 的 spring-boot-starter-data-redis,针对邮件的 spring-boot-starter-mail 等。使用的时候,只需要当做依赖导入即可。
例如 web 开发所用到的 spring-boot-starter-web 项目的依赖关系如下:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.0.5.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-json</artifactId>
<version>2.0.5.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<version>2.0.5.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.12.Final</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.0.9.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.9.RELEASE</version>
<scope>compile</scope>
</dependency>
</dependencies>
@SpringBootApplication 注解及相关注解
所有的 Spring Boot 入口类必须添加 @SpringBootApplication
注解,表示这是一个 Spring Boot 应用程序。
按住 Ctrl 后点击 SpringBootApplication 注解,可以查看注解的定义。可以看到这个注解有引入了一堆其他注解,其中有个 EnableAutoConfiguration 注解,继续深入可以发现 EnableAutoConfiguration 注解又引入了另一堆注解,其中有 @AutoConfigurationPackage
和 @Import({AutoConfigurationImportSelector.class})
。
@AutoConfigurationPackage 注解
查看这个注解的定义时,可以发现其引入了 @Import({Registrar.class})
注解,进入到 Registrar 类对应代码,在下面这一行加断点:
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
AutoConfigurationPackages.register(registry, (new AutoConfigurationPackages.PackageImport(metadata)).getPackageName());
}
在 getPackageName 方法上右击,选择“Evaluate Expression”,查看对应信息,这里会显示加 @SpringBootApplication
的类所在的包:
综上,Spring Boot 将主配置类(即使用 @SpringBootApplication
注解标注的类)所在的包及其子包下的所有组件都扫描到 Spring 容器。
@Import({AutoConfigurationImportSelector.class})
注解
EnableAutoConfiguration 注解中,还引入了 @Import({AutoConfigurationImportSelector.class})
这个注解。
自定义依赖
最终,所有自动加载的依赖,都来自 Maven 仓库中的 Jar 包指定,如果需要修改,可以直接改这里:repository/org/springframework/boot/spring-boot-autoconfigure/2.0.5.RELEASE/spring-boot-autoconfigure-2.0.5.RELEASE.jar!/META-INF/spring.factories
用 IDEA 快速创建 Spring Boot 项目
Spring Boot 太流行了,所以各个版本的 IDE 都内置了创建 Spring Boot 项目的快速方式。对于 IDEA,在创建项目 project 时,可以选择创建 “Spring Initialize” 项目,IDEA 会在创建项目时提示你导入各种 Starter 启动器,之后便自动导入依赖。