Spring Boot 永遠(yuǎn)滴神!10分鐘快速入門
為什么是 SpringBoot
因?yàn)槟壳伴_發(fā) WEB 應(yīng)用,Spring Boot 是啟動(dòng) Spring 項(xiàng)目最快最流行的方式了。無論我們要構(gòu)建一個(gè)什么樣的應(yīng)用,它都可以讓我們盡可能快的啟動(dòng)運(yùn)行起來。前期基本上無需配置啥東西,而且內(nèi)置應(yīng)用服務(wù)器,讓我們兩三下就可以搞一個(gè) 生產(chǎn)級(jí)別應(yīng)用出來,這對(duì)于 Java 程序員來說,只能用倆字來形容了,那就是幸福!
SpringBoot 和 Spring 的關(guān)系
可能因?yàn)?SpringBoot 實(shí)在是太驚艷了,網(wǎng)上有很多言論可能對(duì)很多小伙伴造成了一些誤解。這里我列舉幾個(gè),看看你中了沒?
1. SpringBoot不是應(yīng)用服務(wù)器;
之所以有這個(gè)誤解,是因?yàn)?SpringBoot 可以將Web應(yīng)用程序打包成可執(zhí)行的 jar 文件,不用部署到我們傳統(tǒng)的Java應(yīng)用服務(wù)器就可以運(yùn)行。這是因?yàn)?SpringBoot 內(nèi)置了一個(gè)Servlet容器(Tomcat、Jetty等),所以這個(gè)功能并不是 SpringBoot 本身的而是內(nèi)嵌的 Servlet容器提供的。
2. SpringBoot 沒有實(shí)現(xiàn) JPA 或者 JMS(Java消息服務(wù))等企業(yè)級(jí) Java 規(guī)范。
只不過是自動(dòng)配置了支持這些特性的 Bean,比如自動(dòng)配置了 Hibernate ,這些都是之前已經(jīng)有的技術(shù),并不是SpringBoot新實(shí)現(xiàn)的;
SpringBoot 就是 Spring,它做了那些沒有它我們也會(huì)自己去做的 Spring Bean 配置。
它利用的是 Spring4 的條件化配置特性,以及 Maven 和 Gradle 提供的傳遞依賴。
Spring Boot 相比于 Spring 主要包含了以下四個(gè)核心功能:
- 自動(dòng)配置;
- 起步依賴:告訴 Spring Boot 需要什么功能,它就能引入需要的庫(kù)。
- 命令行界面:這個(gè)可以讓我們無須構(gòu)建項(xiàng)目只寫代碼就可以完成完整的應(yīng)用程序;
- Actuator:應(yīng)用監(jiān)測(cè)和監(jiān)控;
搞清楚了 Spring Boot 其實(shí)就是一種開發(fā) Spring 應(yīng)用程序的快捷方式,那接下來,讓我們一起來感受疾風(fēng)吧,看看它到底有多便捷。
創(chuàng)建 SpringBoot 應(yīng)用
這里先說一下,本文我使用的 Spring Boot 版本是 2.5.2 ,要求你本地安裝的 JDK 至少是 1.8 或者更高的版本,Spring Boot 2.x 以上的版本最低要求就是 JDK 1.8 了。官方推薦的版本目前是 jdk8 和 jdk11,因?yàn)檫@倆版本目前是長(zhǎng)期維護(hù)的。構(gòu)建打包工具 Gradle 4+ or Maven 3.2+,最后就是宇宙最強(qiáng) IDE,IntellJ IDEA,沒有之一。
既然是入門,我們今天就以 Spring5 開始支持的響應(yīng)式編程為例,讓大家感受下使用 Spring Boot 是如何開發(fā)響應(yīng)式項(xiàng)目的。
1. 打開 https://start.spring.io/, 選擇語(yǔ)言和構(gòu)建工具以及依賴項(xiàng),點(diǎn)擊如下圖所示;
2. 點(diǎn)擊 Generate 下載;
3. 解壓下載的壓縮包,進(jìn)入到項(xiàng)目根目錄,然后使用 IDEA 打開 pom.xml ;
需要注意的是,上面一步,需要先設(shè)置 pom.xml 的默認(rèn)打開應(yīng)用程序?yàn)?IDEA,或者你可以選擇 File --> New --> Project from Existing Sources... 然后選擇 pom.xml 效果也是一樣的,如下圖所示。
4. 打開后,刷新 Maven 依賴(第一次會(huì)有點(diǎn)慢,耐心等待),我們就可以得到下圖項(xiàng)目結(jié)構(gòu)了;
訪問數(shù)據(jù)庫(kù)
Spring Boot 無縫集成了 關(guān)系型數(shù)據(jù)庫(kù) 和 NOSQL 數(shù)據(jù)庫(kù) 。并且 Spring Boot 也提供了響應(yīng)式的數(shù)據(jù)庫(kù)訪問支持。
那我們?nèi)绻胧褂?Spring Boot 訪問數(shù)據(jù)庫(kù),都需要做什么呢?穩(wěn)住,你可能會(huì)震驚的。
下面給大家看下我寫的響應(yīng)式編程數(shù)據(jù)庫(kù)訪問的測(cè)試代碼,為了不依賴任何環(huán)境,讓大家可以快速、直觀的感受,我使用的是內(nèi)存數(shù)據(jù)庫(kù) h2。
- 將下面的代碼,放到你的 Spring Boot 專屬啟動(dòng)類中。
- @SpringBootApplication
- public class Springroad01Application {
- public static void main(String[] args) {
- SpringApplication.run(Springroad01Application.class, args);
- }
- }
- // 測(cè)試數(shù)據(jù)庫(kù)訪問,容器啟動(dòng)后會(huì)執(zhí)行run方法
- @Component
- class DataWriter implements ApplicationRunner {
- private Logger log = LoggerFactory.getLogger(DataWriter.class);
- private DatabaseClient client;
- private UsersDao usersDao;
- public DataWriter(DatabaseClient client, UsersDao usersDao) {
- this.client = client;
- this.usersDao = usersDao;
- }
- @Override
- public void run(ApplicationArguments args) {
- List<String> statements = Arrays.asList(
- "DROP TABLE IF EXISTS USERS;",
- "CREATE TABLE IF NOT EXISTS USERS ( id SERIAL PRIMARY KEY, name VARCHAR(100) NOT NULL);");
- statements.forEach(sql -> client.sql(sql).fetch().rowsUpdated()
- .doOnSuccess(count -> log.info("Schema created, rows updated: {}", count))
- .doOnError(error -> log.error("got error : {}",error.getMessage(),error))
- .subscribe()
- );
- Flux.just("sevenluo","tonyzhu","jameschen").flatMap(name -> usersDao.save(new Users(null,name))).subscribe(user -> log.info("User saved: {}",user));
- }
- }
- // DAO 接口,不需要加注解,繼承了 ReactiveCrudRepository 會(huì)自動(dòng)生成實(shí)例的
- interface UsersDao extends ReactiveCrudRepository<Users, String> {
- }
- @Data
- @AllArgsConstructor
- @NoArgsConstructor
- class Users {
- @Id
- private Integer id;
- private String name;
- }
- 執(zhí)行 main 方法,輸入結(jié)果;
就是這么赤雞,結(jié)束了,啥配置沒有,直接寫了幾行代碼就可以訪問數(shù)據(jù)庫(kù)了。
REST 接口開發(fā)
你應(yīng)該還關(guān)心 Spring Boot 如何開發(fā)一個(gè) REST 風(fēng)格的 WEB 接口吧?別慌,我們直接用 Spring 支持的響應(yīng)式編程來搞一個(gè) REST 應(yīng)用服務(wù)。但是對(duì)于 WEB 訪問用戶來說是看不出來我們使用了非阻塞的響應(yīng)式編程的,來一手潤(rùn)物細(xì)無聲。
- 將下面的代碼放到啟動(dòng)類中,就是一個(gè)響應(yīng)式的 REST 接口就開發(fā)好了。
- 測(cè)試一下,打開命令行,curl 測(cè)試一下(不是非要裝逼不用瀏覽器訪問,公司的大佬說程序員要多用shell環(huán)境,嗯!從小事開始練);
溫馨提示,在 mac 上安裝 jq,直接使用 brew install jq 就會(huì)自動(dòng)幫你安裝好了。
好了,打完手工,沒啥搞頭,Spring Boot 永遠(yuǎn)滴神!
監(jiān)控和管理應(yīng)用
我們的應(yīng)用上線后,那肯定都是要上監(jiān)控的,不然哪一天神不知鬼不覺死翹翹了,麻煩就大了。這個(gè) Spring Boot 它就天生帶了可以替我們監(jiān)控和管理的 Spring 應(yīng)用的模塊工具:spring-boot-actuator 。
像什么 健康檢查、審計(jì)、統(tǒng)計(jì)和HTTP追蹤等該有的它都有。值得一提的是 spring-boot-actuator 它還很 open ,支持與其它外部監(jiān)控系統(tǒng)做整合。補(bǔ)充了它自身沒有一些好看的儀表盤、圖表、分析、告警等 酷炫吊炸天的能力。
那怎么玩呢?
確認(rèn)你的應(yīng)用添加了對(duì)應(yīng)的模塊依賴;
假如你使用的 maven,那看你的 pom.xml 中下面的依賴:
- <dependencies>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-actuator</artifactId>
- </dependency>
- </dependencies>
那如果你使用的 gradle,對(duì)應(yīng)的 build.gradle 文件中有下面的依賴:
- dependencies {
- compile("org.springframework.boot:spring-boot-starter-actuator")
- }
Actuator 通過 endpoint 來暴露 HTTP 請(qǐng)求 來監(jiān)控和管理應(yīng)用;
應(yīng)用啟動(dòng)后,http://localhost:8080/actuator 會(huì)展示出所有通過 HTTP 暴露的 endpoint。
因?yàn)樘L(zhǎng)了,我這里列出的只是一部分 endpoint,你自己一定要?jiǎng)邮衷囅隆?/p>
就比如,/health 這個(gè) endpoint,提供了關(guān)于應(yīng)用健康的基礎(chǔ)信息。
/metrics endpoint 展示了幾個(gè)非常有用的度量信息,比如 JVM內(nèi)存使用情況、系統(tǒng) CPU 使用情況、打開的文件等等。
/loggers endpoint 展示了應(yīng)用的日志和可以讓你在運(yùn)行時(shí)改變?nèi)罩镜燃?jí)。
還有好多,下去都自己玩玩,動(dòng)手就會(huì)了。
友情提示,如果你的 http://localhost:8080/actuator 展示的 開放端點(diǎn)很少,那是因?yàn)?actuator 的 endpoint 可以顯式的被打開和關(guān)閉,明白了吧!
默認(rèn)情況下很多 endpoint 是被關(guān)閉掉了,你只需要在 application.properties 配置文件中增加如下配置即可。
- management.endpoint.health.show-details=always //顯示詳細(xì)的健康信息
- management.endpoints.web.exposure.include=* //粗暴的全部打開,反正自己玩,任性
這里我們就不多說這些 endpoint 每個(gè)的作用了, 如果你感興趣,可以給我留言,我會(huì)根據(jù)大家需求看下是否在出一期教程詳細(xì)介紹一下。
當(dāng)然除了上面默認(rèn)顯示的應(yīng)用健康信息,我們也可以自定義一個(gè)健康指標(biāo);
我們可以選擇實(shí)現(xiàn) HealthIndicator 接口來實(shí)現(xiàn)我們的目標(biāo);
- @SpringBootApplication
- public class Springroad01Application {
- // 加上這個(gè)Bean就可以了
- @Bean
- HealthIndicator healthIndicator() {
- return () -> Health.up().withDetail("app", "i am so good").
- withDetail("error","開什么玩笑,老夫怎么可能有錯(cuò)!").build();
- }
- @Bean
- RouterFunction<ServerResponse> routes (UsersDao usersDao) {
- return RouterFunctions.route(GET("/users"),serverRequest -> ok().body(usersDao.findAll(),Users.class));
- }
- public static void main(String[] args) {
- SpringApplication.run(Springroad01Application.class, args);
- }
- }
一旦你加上我們上面自定義的健康指標(biāo),重啟應(yīng)用,就會(huì)看到 health 這個(gè) endpoint 將展示出我們?cè)黾拥倪@些信息:
安全控制
對(duì)于應(yīng)用安全的支持,那就繞不開 Spring Security 了。
它可以輕松完成應(yīng)用的鑒權(quán)、授權(quán)功能,同時(shí)也提供了對(duì)響應(yīng)式編程的支持。
接下來就展示下如果讓你的應(yīng)用快速帶上安全套。
- 加入 Spring-Security 依賴包;
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-security</artifactId>
- </dependency>
- 內(nèi)存中配置一個(gè)用戶,設(shè)置用戶名和密碼;
- @Bean
- // 內(nèi)存中配置用戶名、密碼為 admin/admin,用戶角色為 USER
- MapReactiveUserDetailsService users() {
- return new MapReactiveUserDetailsService(User.withUsername("admin").password(PasswordEncoderFactories.createDelegatingPasswordEncoder().encode("admin")).roles("USER").build());
- }
- 驗(yàn)證
直接訪問,提示 401 錯(cuò)誤,這個(gè)錯(cuò)誤碼應(yīng)該了然于心了吧。沒錯(cuò)就是沒有權(quán)限的意思。
加上用戶名、密碼我們?cè)僭囋嚕?nbsp;
- curl -vu admin:admin http://localhost:8080/actuator/health | jq
加上用戶名和密碼令人期待的結(jié)果就返回了,是不是瞬間心情大好呢。
上面我們僅僅是引入了 Spring-Security 包,然后加了兩三行代碼,沒有寫任何的攔截器驗(yàn)證邏輯,我們的應(yīng)用就具備了安全驗(yàn)證功能,這也太 啊妹子ing 了吧。
江湖再見
此章節(jié)我們就完成了 Spring-Boot 的入門開發(fā)介紹。
用10分鐘完成了包含 創(chuàng)建應(yīng)用、訪問數(shù)據(jù)庫(kù)、REST接口開發(fā)、監(jiān)控和管理、安全控制 的開發(fā)。
章節(jié)中并沒有對(duì)具體的技術(shù)細(xì)節(jié)做講解,比如 Demo 中使用響應(yīng)式編程、Spring Boot Actuator 端點(diǎn)的詳細(xì)講解等。
僅僅是為了讓小伙伴們了解到 Spring Boot 的強(qiáng)大和便利,感受下 Spring 對(duì)我們程序員的友好。