文章寫于2017.11月,作者已長時間沒有再接觸 SpringBoot 了。
目前更推薦 nestjs,這里附上一個代碼倉庫,不同的 commits 增加了不同的功能,供感興趣的同學參考。nest-starter
從一開始只有一個IDEA,到上線一個外網可訪問的API。最后的效果是這樣的:
開發環境:Win10
+ IDEA
+ Gradle
主要技術:SpringBoot框架
+ Kotlin語言
+ MySQL數據庫
內容提要:
- 創建一個基于
Gradle
的項目 - 初始化
SpringBoot
- 安裝、配置、關聯
MySQL
- 構建一個簡單的API
- 打包一個可執行文件
- 使用
ngrok
做外網訪問
創建一個新項目
先用IDEA創建一個Gradle項目
注意:
- 基于Gradle
- 使用Kotlin
- IDEA對JDK做了一些改進,比如把原來的
Logging
換成了SLF4J
,在使用時有時會導致重復導包。為了避免麻煩,我們使用原生的JDK。
接下來一路Next。
如果你網絡沒問題的話,最后會是這樣一個項目結構:
初始化SpringBoot
修改自動生成的build.gradle
如下:
代碼如下:
buildscript {
ext.kotlin_version = '1.1.51'
ext.spring_boot_version = '1.5.8.RELEASE'
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.springframework.boot:spring-boot-gradle-plugin:$spring_boot_version"
}
}
apply plugin: 'kotlin'
apply plugin: 'org.springframework.boot'
repositories {
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
compile 'org.springframework.boot:spring-boot-starter-web'
}
compileKotlin {
kotlinOptions.jvmTarget = "1.8"
}
compileTestKotlin {
kotlinOptions.jvmTarget = "1.8"
}
對上邊四個標注解釋:
- 上邊三條,主要是添加了一個
SpringBoot
的gradle
插件,作用如下:- 整合類路徑上所有的
jar
,并建立一個單一的,可運行的"über-jar"。(不用管,就是一個名字。) - 它搜索
public static void main()
方法來標記為可運行的類。 - 它提供了一個內建的依賴解析器,設置了版本號,以匹配
SpringBoot
的依賴。您可以覆蓋任何你想要的版本,但它會默認引導的選擇版本的集合。可以注意到下邊對spring-boot-starter-web
的依賴沒有設置版本。SpringBoot
有很多組件,之后依賴的組件多了,就很很方便的管理版本了。
- 整合類路徑上所有的
- 最后一條,真正的引用。
SpringBoot
的Web基礎包。
接下來,我們創建一個入口文件添加一些簡單代碼并運行。注意:一定要創建包!
@Controller //表明這是一個Controller,控制路由的東西
@EnableAutoConfiguration //告訴SpringBoot開始依據依賴路徑等添加Beans。
class SampleController {
@RequestMapping("/") //映射最基礎的URL
@ResponseBody //表明這是一個Resopnse,而不是一個視圖名稱
internal fun home(): String {
return "Hello World!" //為請求返回一個字符串。
}
}
fun main(args: Array<String>) {
SpringApplication.run(SampleController::class.java, *args)
}
不出錯的話,這時候訪問localhost:8080
(默認的),會看到我們剛才設置的Hello World!
:
表明SpringBoot
運行正常。繼續下一步。
接入MySQL
首先,修改依賴,添加下面的依賴:
compile 'org.springframework.boot:spring-boot-starter-data-jpa'
compile 'mysql:mysql-connector-java'
結果如圖:
然后,需要連接到MySQL
服務器。我們去下載一個MySQL
。
我是Windows的系統,所以按照Windows大致說下流程,很簡單的東西。推薦使用MySQL Installer
,Windows下載地址,只有32位的包,但是安裝的時候可選安裝64位的組件。
選擇要安裝的組件,我選了Custom
和下面5個。不想安裝多的話,可以只安裝Server
組件就可以了。自己決定選什么。
這個之后的配置,我只設置了root的密碼。(也可以不設置,一路next)。
接下來,配置一下數據庫:
先進入MySQL Server的目錄下面,我的是C:\Program Files\MySQL\MySQL Server 5.7\bin
,用的頻繁的話可以加到環境變量里去,輸入命令mysql -u root -p
并輸入密碼進入數據庫,然后執行下邊的數據庫命令:
mysql> create database db_example; -- 創建一個數據庫,名字自己設置。
mysql> create user 'springuser'@'localhost' identified by 'ThePassword'; -- 創建一個用戶,專門管理這個數據庫。也可以不創建用戶,等下直接使用root用戶。
mysql> grant all on db_example.* to 'springuser'@'localhost'; -- 把新建數據庫的所有權限都給到新建用戶
我的配置如下:
然后在項目里關聯上數據庫:
在resources
目錄下,創建一個文件application.properties
,內容如下:
spring.jpa.hibernate.ddl-auto=create
spring.datasource.url=jdbc:mysql://localhost:3306/(數據庫名字)
spring.datasource.username=(用戶名,比如我的是springuser或者root)
spring.datasource.password=(密碼,沒有就空著)
另外關于spring.jpa.hibernate.ddl-auto
:
- 幾個選項
-
none
MySQL默認選項,不改變數據庫結構。 -
update
根據給定的實體結構改變數據庫。 -
create
每次都創建數據庫,但關閉的時候不刪除數據庫。 -
create-drop
創建數據庫,在SessionFactory關閉時刪除數據庫。
-
- 在這里,我們使用create是因為我們現在還沒有數據庫結構。第一次運行之后,我們可以根據需求切換到update或none。要改變數據庫結構時使用update。
- H2和其他嵌入式數據庫默認是create-drop,但對于其他類似MySQL的是none
- 數據庫處于生產狀態時使用
none
是很好的安全做法,你設置none,并移除連接到Spring應用程序的MySQL用戶的所有特權,然后只給增刪查改的權限。
開始構建一個簡單的服務
我們要做的:
- 有一個
User
的表 - 可以通過請求增加一個
User
,也可以查找所有的User
信息
先創建一個User
類
package hello
import javax.persistence.Entity
import javax.persistence.GeneratedValue
import javax.persistence.GenerationType
import javax.persistence.Id
@Entity // 告訴Hibernate依據這個類創建一個表
class User {
@Id //主鍵
@GeneratedValue(strategy = GenerationType.AUTO) //自增長
var id: Int? = null
var name: String? = null
var email: String? = null
}
再創建一個操作數據的接口
// Spring會自動生成一個名為userRepository(注意是首字母小寫)Bean用來操作增刪改查
interface UserRepository : CrudRepository<User, Long>
再創建一個Controller
處理請求
@Controller // 申明這是一個Controller
@RequestMapping(path = arrayOf("/demo")) // 匹配路徑以/demo開頭的URL
class MainController(@Autowired private val userRepository: UserRepository) {//@Autowired 使用該注解可自動找到之前Spring自動創建的名為userRepository的Bean來填充數據
val allUsers: Iterable<User>
@GetMapping(path = arrayOf("/all"))
@ResponseBody
get() = userRepository.findAll()
@GetMapping(path = arrayOf("/add"))
@ResponseBody
fun addNewUser(@RequestParam name: String, @RequestParam email: String): String {
// @RequestParam 請求參數
val n = User()
n.name = name
n.email = email
userRepository.save(n)
return "Saved"
}
}
注意:@GetMapping
只匹配Get請求,是@RequestMapping(method=GET)
的簡寫。同理還有@PostMapping
等。如果只寫@RequestMapping
不指明請求方式表示匹配所有類型的請求。
最后,修改一下我們的入口類App.kt
:
@SpringBootApplication
open class Application
fun main(args: Array<String>) {
SpringApplication.run(Application::class.java, *args)
}
注意:
- 不加
open
修飾符會報錯。kotlin中不加open
修飾符類默認為final
類,而SpringBootApplication
不能是final
類。 - 關于
@SpringBootApplication
,其實是以下幾個注解的簡便寫法。-
@Configuration
標記類為bean定義的應用程序上下文的來源 -
@EnableAutoConfiguration
之前已經提到過了告訴SpringBoot開始依據依賴路徑等添加Beans。 - 通常你會添加
@EnableWebMvc
一個Spring MVC的應用程序,但是當它看到春天開機自動將其添加彈簧webmvc在classpath。此標志的應用程序作為Web應用程序和激活密鑰的行為,如設立DispatcherServlet。 -
@ComponentScan
告訴Spring在hello包自動尋找其他組件,配置,控制器。
-
這時候我們再運行一下:
用Get方法傳遞一個User
信息,它會執行保存操作,并返回結果:
獲取所有User
信息:
奇怪的是一個請求會執行兩次,在隱身模式下就不會這樣,我還在找原因。
好了,現在一個基本的Api已經搭建好了,在本地已經能訪問了。接下來,我們看如何打包運行,以及連接外網。
打包運行
由于SpringBoot
的特性,使用Gradle
可以方便的生成jar文件。
生成的文件在這里:
把生成的文件復制到桌面上并運行,為了方便我給它改了一個簡單點的名字:
和之前的效果一模一樣的。
使用ngrok連接外網
我使用的ngrok.cc
,因為可以免費綁定自己的域名。
流程如下:
- 注冊賬戶
- 開通一個隧道,選第三個免費的。
- 選http
- 隧道名稱隨便起
- 前置域名[***.free.ngrok.cc]
- 本地端口,比如我們使用的
127.0.0.1:8080
- http用戶名密碼,先不用管
- 添加
- 照簡單教程下載對應版本的軟件,啟動。
- 開啟你的
SpringBoot
服務,把之前的localhost:8080
換成***.free.ngrok.cc
即可訪問。***換自己起的前置域名。
如果你有一個域名,可以來替換掉這個免費域名:
點擊隧道管理 -> 選中隧道 -> 修改
按規定設置域名解析,比如我的是阿里云的域名:
設置好等一會即可。另外注意,ngrok.cc
目前還不支持https訪問,所以使用自己的域名時也要注意使用http進行訪問。
除了上邊提到的錯誤,我還遇到了另外一個錯誤,顯示端口占用。解決方法如下。
先打開CMD
命令行命令netstat ?ano
,找到占用8080端口的進程的PID
:
去進程詳情里找到該進程,結束掉,重新啟動SpringBoot
服務。
相關文檔
本文內容主要來自:
最后,SpringBoot
能做的東西還很多,本文只是和你一起搭了一個很基本的框架,你可以不斷的去添加新的內容進去,去嘗試構造你自己的優雅的API,做更多的事。