前言:
springboot是為了簡(jiǎn)化spring應(yīng)用的創(chuàng)建、運(yùn)行、調(diào)試、部署等而出現(xiàn)的,使用它可以做到專注于spring應(yīng)用的開發(fā),而無(wú)需過(guò)多關(guān)注xml的配置。
簡(jiǎn)單來(lái)說(shuō),它提供了一堆依賴打包,并已經(jīng)按照使用習(xí)慣解決了依賴問(wèn)題---習(xí)慣大于約定。
spring boot默認(rèn)使用tomcat作為服務(wù)器,使用logback提供日志記錄。
spring boot的主要優(yōu)點(diǎn):
- 為所有spring開發(fā)者更快的入門
- 開箱即用,提供各種默認(rèn)配置來(lái)簡(jiǎn)化項(xiàng)目配置
- 內(nèi)嵌式容器簡(jiǎn)化web項(xiàng)目
- 沒(méi)有冗余代碼生成和xml配置的要求
技術(shù)棧:
- java 8
- maven
- spring-boot
- mybatis
- redis
- lombok
- swagger2
- jenkins
- sonarquber
1、使用maven構(gòu)建項(xiàng)目
1.1 通過(guò) spring initializr 工具生產(chǎn)基礎(chǔ)項(xiàng)目
通過(guò)訪問(wèn):http://start.spring.io/ 快速創(chuàng)建spring-boot 的服務(wù)框架。
初始化相應(yīng)信息后,下載壓縮包。解壓完成后,用idea打開項(xiàng)目,項(xiàng)目的目錄結(jié)構(gòu):
總體流程:
- 訪問(wèn):http://start.spring.io/
- 選擇構(gòu)建工具maven project、spring boot版本1.3.2以及一些工程基本信息
- 點(diǎn)擊generate project下載項(xiàng)目壓縮包
解壓項(xiàng)目包,并用ide以maven項(xiàng)目導(dǎo)入,以intellij idea 14為例:
- 菜單中選擇file–>new–>project from existing sources...
- 選擇解壓后的項(xiàng)目文件夾,點(diǎn)擊ok
- 點(diǎn)擊import project from external model并選擇maven,點(diǎn)擊next到底為止。
- 若你的環(huán)境有多個(gè)版本的jdk,注意到選擇java sdk的時(shí)候請(qǐng)選擇java 7以上的版本
1.2 導(dǎo)入spring-boot 相關(guān)依賴
項(xiàng)目初始化時(shí),相關(guān)依賴如下:
- spring-boot-starters:核心模塊,包括自動(dòng)配置支持、日志和yaml
- spring-boot-starter-test:測(cè)試模塊,包括junit、hamcrest、mockito
- spring-boot-devtools:用于設(shè)置熱部署
1
2
3
4
5
6
7
8
9
10
11
12
|
<dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter</artifactid> </dependency> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-test</artifactid> <scope>test</scope> </dependency> <!--熱部署--> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-devtools</artifactid> <optional> true </optional> </dependency> |
這里我們需要引入web模塊,需要添加:
1
2
3
4
|
<dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-web</artifactid> </dependency> |
1.3 啟動(dòng)項(xiàng)目
添加首頁(yè)控制層:
1
2
3
4
5
6
7
8
|
@restcontroller public class indexcontroller { @requestmapping ( "index" ) public string index() { return "hello world!" ; } } |
運(yùn)行demoapplication中的main方法,啟動(dòng)服務(wù):
服務(wù)啟動(dòng)后, 訪問(wèn) http://localhost:8080/index ,可以看到頁(yè)面輸出hello world!。
2、整合mybatis
2.1 項(xiàng)目依賴
- 引入連接mysql的必要依賴mysql-connector-java
- 引入整合mybatis的核心依賴mybatis-spring-boot-starter
- 引入tk.mybatis 依賴,實(shí)現(xiàn)對(duì)實(shí)體類的增刪改查的代碼
- 引入pagerhelper 依賴,實(shí)現(xiàn)分頁(yè)功能
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
<dependency> <groupid>org.mybatis.spring.boot</groupid> <artifactid>mybatis-spring-boot-starter</artifactid> <version> 1.3 . 0 </version> </dependency> <dependency> <groupid>mysql</groupid> <artifactid>mysql-connector-java</artifactid> <version> 5.1 . 43 </version> </dependency> <dependency> <groupid>tk.mybatis</groupid> <artifactid>mapper-spring-boot-starter</artifactid> <version> 1.1 . 3 </version> </dependency> <!--pagehelper--> <dependency> <groupid>com.github.pagehelper</groupid> <artifactid>pagehelper-spring-boot-starter</artifactid> <version> 1.1 . 2 </version> </dependency> |
2.2 項(xiàng)目配置
修改resources 下的application.properties文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
spring.datasource.url=jdbc:mysql: //localhost:3306/test spring.datasource.username=root spring.datasource.password=root spring.datasource.driver- class -name=com.mysql.jdbc.driver #實(shí)體類掃描包 mybatis.type-aliases- package =com.jaycekon.demo.model #mapper.xml文件掃描目錄 mybatis.mapper-locations=classpath:mapper/*.xml #駝峰命名 mybatis.configuration.mapunderscoretocamelcase= true #tkmapper 工具類 mapper.mappers=com.jaycekon.demo.util.mymapper mapper.not-empty= false mapper.identity=mysql pagehelper.helperdialect=mysql pagehelper.reasonable= true pagehelper.supportmethodsarguments= true pagehelper.params=count=countsql |
2.3 單元測(cè)試
創(chuàng)建實(shí)體類,我們引入lombok相關(guān)依賴,用于避免數(shù)據(jù)get set方法的重復(fù)創(chuàng)建:
1
2
3
4
5
6
|
<dependency> <groupid>org.projectlombok</groupid> <artifactid>lombok</artifactid> <version> 1.16 . 18 </version> <scope>provided</scope> </dependency> |
實(shí)體類最終的代碼如下:
1
2
3
4
5
6
7
8
9
10
11
|
@data @noargsconstructor @allargsconstructor @accessors (chain = true ) public class user { private int id; private string username; private string idcard; private string phone; private string password; } |
可以看出,在添加了lombok 之后,我們的java 實(shí)體類代碼簡(jiǎn)潔了很多。
接下來(lái),我們需要?jiǎng)?chuàng)建usermapper 數(shù)據(jù)庫(kù)處理類。由于mymapper 已經(jīng)幫我們實(shí)現(xiàn)了基本的crud操作,因此我們這里并不需要再重寫操作,我可以先一個(gè)根據(jù)用戶名查找的方法:
1
2
3
4
5
6
7
8
|
@mapper public interface usermapper extends mymapper<user> { @select ( "select * from user where username=#{username}" ) user selectbyname(string username); } mymapper 類位于util 目錄下: public interface mymapper<t> extends mapper<t>, mysqlmapper<t> { } |
這里需要注意,mymapper 與我們的實(shí)體類mapper 不能放在同一個(gè)目錄。
測(cè)試類:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
@runwith (springrunner. class ) @springboottest @mapperscan ( "com.jaycekon.demo.mapper" ) public class usermappertest { @autowired private usermapper mapper; @test public void testinset() { user user = new user( 1 , "jaycekon" , "1234" , "1234" , "123" ); int i = mapper.insert(user); assert .assertnotequals( 0 , i); } @test public void testselect(){ user user = mapper.selectbyname( "jaycekon" ); assert .assertnotequals( null ,user); } } |
3、整合redis
3.1 相關(guān)依賴
spring boot提供的數(shù)據(jù)訪問(wèn)框架spring data redis基于jedis。可以通過(guò)引入 spring-boot-starter-redis 來(lái)配置依賴關(guān)系。
1
2
3
4
|
<dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-redis</artifactid> </dependency> |
3.2 redis 配置
1、spring-boot 連接單機(jī)版redis 的配置如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
# redis (redisproperties) # redis數(shù)據(jù)庫(kù)索引(默認(rèn)為 0 ) spring.redis.database= 0 # redis服務(wù)器地址 spring.redis.host=localhost # redis服務(wù)器連接端口 spring.redis.port= 6379 # redis服務(wù)器連接密碼(默認(rèn)為空) spring.redis.password= # 連接池最大連接數(shù)(使用負(fù)值表示沒(méi)有限制) spring.redis.pool.max-active= 8 # 連接池最大阻塞等待時(shí)間(使用負(fù)值表示沒(méi)有限制) spring.redis.pool.max-wait=- 1 # 連接池中的最大空閑連接 spring.redis.pool.max-idle= 8 # 連接池中的最小空閑連接 spring.redis.pool.min-idle= 0 # 連接超時(shí)時(shí)間(毫秒) spring.redis.timeout= 0 |
2、spriig-boot 連接sentinel 哨兵集群配置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
# redis (redisproperties) # redis數(shù)據(jù)庫(kù)索引(默認(rèn)為 0 ) spring.redis.database= 0 # redis服務(wù)器地址 #spring.redis.host=localhost # redis服務(wù)器連接端口 #spring.redis.port= 6379 # redis服務(wù)器連接密碼(默認(rèn)為空) spring.redis.password= # 連接池最大連接數(shù)(使用負(fù)值表示沒(méi)有限制) spring.redis.pool.max-active= 8 # 連接池最大阻塞等待時(shí)間(使用負(fù)值表示沒(méi)有限制) spring.redis.pool.max-wait=- 1 # 連接池中的最大空閑連接 spring.redis.pool.max-idle= 8 # 連接池中的最小空閑連接 spring.redis.pool.min-idle= 0 # 連接超時(shí)時(shí)間(毫秒) spring.redis.timeout= 0 #哨兵監(jiān)聽redis server名稱 spring.redis.sentinel.master=cn-test-master #哨兵的配置列表 spring.redis.sentinel.nodes=localhost: 26379 ,localhost: 36379 ,localhost: 46379 |
3.3 redis 操作工具類
1、stringredistemplate 工具類
stringredistemplate 工具類可以解決字符串級(jí)別的redis操作。在寫好配置后,可以直接通過(guò)autowried 就可以注入對(duì)象。
1
2
3
4
5
6
7
8
9
10
11
12
|
@runwith (springjunit4classrunner. class ) @springapplicationconfiguration (application. class ) public class applicationtests { @autowired private stringredistemplate stringredistemplate; @test public void test() throws exception { // 保存字符串 stringredistemplate.opsforvalue().set( "aaa" , "111" ); assert .assertequals( "111" , stringredistemplate.opsforvalue().get( "aaa" )); } } |
2、redistemplate<object,object> 工具類
可以處理大部分的序列化操作,在這里我封裝了一個(gè)簡(jiǎn)化redis工具類,后續(xù)可以繼續(xù)優(yōu)化。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
@component public class rediscomponent { @autowired //操作字符串的template,stringredistemplate是redistemplate的一個(gè)子集 private stringredistemplate stringredistemplate; private logger logger = loggerfactory.getlogger(rediscomponent. class ); @autowired // redistemplate,可以進(jìn)行所有的操作 private redistemplate<object, object> redistemplate; public void set(string key, string value) { valueoperations<string, string> ops = this .stringredistemplate.opsforvalue(); boolean bexistent = this .stringredistemplate.haskey(key); if (bexistent) { logger.info( "this key is bexistent!" ); } else { ops.set(key, value); } } public string get(string key) { return this .stringredistemplate.opsforvalue().get(key); } public void del(string key) { this .stringredistemplate.delete(key); } public void sentinelset(string key, object object) { redistemplate.opsforvalue().set(key, json.tojsonstring(object)); } public string sentinelget(string key) { return string.valueof(redistemplate.opsforvalue().get(key)); } } |
4、整合swagger2
4.1 添加swagger2 依賴:
1
2
3
4
5
6
7
8
9
10
|
<dependency> <groupid>io.springfox</groupid> <artifactid>springfox-swagger2</artifactid> <version> 2.7 . 0 </version> </dependency> <dependency> <groupid>io.springfox</groupid> <artifactid>springfox-swagger-ui</artifactid> <version> 2.7 . 0 </version> </dependency> |
4.2 創(chuàng)建swagger2 配置類:
在application.java 同級(jí)創(chuàng)建一個(gè)swagger2 的配置類:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
@configuration @enableswagger2 public class swagger2 { @bean public docket webapi() { return new docket(documentationtype.swagger_2) .groupname( "demoapi接口文檔" ) .apiinfo(apiinfo()) .select() .apis(requesthandlerselectors.basepackage( "com.jaycekon.demo.controller" )) .paths(pathselectors.any()).build(); } /** swagger2使用說(shuō)明: @api:用在類上,說(shuō)明該類的作用 @apioperation:用在方法上,說(shuō)明方法的作用 @apiignore:使用該注解忽略這個(gè)api @apiimplicitparams:用在方法上包含一組參數(shù)說(shuō)明 @apiimplicitparam:用在@apiimplicitparams注解中,指定一個(gè)請(qǐng)求參數(shù)的各個(gè)方面 paramtype:參數(shù)放在哪個(gè)地方 header-->請(qǐng)求參數(shù)的獲取:@requestheader query-->請(qǐng)求參數(shù)的獲取:@requestparam path(用于restful接口)-->請(qǐng)求參數(shù)的獲取:@pathvariable body(不常用) form(不常用) name:參數(shù)名 datatype:參數(shù)類型 required:參數(shù)是否必須傳 value:參數(shù)的意思 defaultvalue:參數(shù)的默認(rèn)值 @apiresponses:用于表示一組響應(yīng) @apiresponse:用在@apiresponses中,一般用于表達(dá)一個(gè)錯(cuò)誤的響應(yīng)信息 code:數(shù)字,例如400 message:信息,例如"請(qǐng)求參數(shù)沒(méi)填好" response:拋出異常的類 @apimodel:描述一個(gè)model的信息(這種一般用在post創(chuàng)建的時(shí)候,使用@requestbody這樣的場(chǎng)景,請(qǐng)求參數(shù)無(wú)法使用@apiimplicitparam注解進(jìn)行描述的時(shí)候) @apimodelproperty:描述一個(gè)model的屬性 */ private apiinfo apiinfo() { return new apiinfobuilder() .title( "demo使用swagger2構(gòu)建restful apis" ) .description( "微信打卡服務(wù)" ) .contact( new contact( "jaycekon" , "http://petstore.swagger.io/v2/swagger.json" , "[email protected]" )) .version( "1.0" ) .build(); } } |
4.3 在需要生成api 的接口添加注解:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
@api (tags = "測(cè)試用例" ) @restcontroller @requestmapping (value= "/users" ) // 通過(guò)這里配置使下面的映射都在/users下,可去除 public class usercontroller { @apioperation (value= "獲取用戶列表" , notes= "" ) @requestmapping (value={ "" }, method= requestmethod.get) public list<user> getuserlist() { return new arraylist<>(); } @apioperation (value= "創(chuàng)建用戶" , notes= "根據(jù)user對(duì)象創(chuàng)建用戶" ) @apiimplicitparam (name = "user" , value = "用戶詳細(xì)實(shí)體user" , required = true , datatype = "user" ) @requestmapping (value= "" , method=requestmethod.post) public string postuser( @requestbody user user) { return "success" ; } @apioperation (value= "獲取用戶詳細(xì)信息" , notes= "根據(jù)url的id來(lái)獲取用戶詳細(xì)信息" ) @apiimplicitparam (name = "id" , value = "用戶id" , required = true , datatype = "long" ) @requestmapping (value= "/{id}" , method=requestmethod.get) public user getuser( @pathvariable long id) { return new user(); } @apioperation (value= "更新用戶詳細(xì)信息" , notes= "根據(jù)url的id來(lái)指定更新對(duì)象,并根據(jù)傳過(guò)來(lái)的user信息來(lái)更新用戶詳細(xì)信息" ) @apiimplicitparams ({ @apiimplicitparam (name = "id" , value = "用戶id" , required = true , datatype = "long" ), @apiimplicitparam (name = "user" , value = "用戶詳細(xì)實(shí)體user" , required = true , datatype = "user" ) }) @requestmapping (value= "/{id}" , method=requestmethod.put) public string putuser( @pathvariable long id, @requestbody user user) { return "success" ; } @apioperation (value= "刪除用戶" , notes= "根據(jù)url的id來(lái)指定刪除對(duì)象" ) @apiimplicitparam (name = "id" , value = "用戶id" , required = true , datatype = "long" ) @requestmapping (value= "/{id}" , method=requestmethod.delete) public string deleteuser( @pathvariable long id) { return "success" ; } } |
完成上述代碼添加上,啟動(dòng)spring boot程序,訪問(wèn):http://localhost:8080/swagger-ui.html
。
就能看到前文所展示的restful api的頁(yè)面。我們可以再點(diǎn)開具體的api請(qǐng)求,以post類型的/users請(qǐng)求為例,可找到上述代碼中我們配置的notes信息以及參數(shù)user的描述信息,如下圖所示。
4、接入jenkins&sonarqube
項(xiàng)目框架搭建好后,我們可以通jenkins 進(jìn)行項(xiàng)目的自動(dòng)發(fā)版,以及sonarqube 進(jìn)行代碼質(zhì)量檢測(cè)。在接入錢,我們需要將項(xiàng)目打包成war包,需要進(jìn)行以下修改:
1、修改項(xiàng)目打包類型:
1
2
3
4
|
<groupid>com.jaycekon</groupid> <artifactid>demo</artifactid> <version> 0.0 . 1 -snapshot</version> <packaging>war</packaging> |
2、修改application.java 文件:
1
2
3
4
5
6
7
8
9
10
|
@springbootapplication public class demoapplication extends springbootservletinitializer { @override protected springapplicationbuilder configure(springapplicationbuilder application) { return application.sources(demoapplication. class ); } public static void main(string[] args) { springapplication.run(demoapplication. class , args); } } |
在我的上一篇博客,哆啦a夢(mèng)的傳送門,已經(jīng)講解了一些基本配置方法,這里為大家講解一下,接入sonarqube 進(jìn)行代碼質(zhì)量檢測(cè)的配置(需要本地安裝sonarqube服務(wù))。
首先需要在metadata 中,加入sonarqube 的項(xiàng)目名(新建的命名):
然后在post steps 中選擇添加 execute sonarqube scanner:
在配置好這兩項(xiàng)后,jenkins 在編譯文件時(shí),就會(huì)執(zhí)行sonarqube 代碼質(zhì)量檢測(cè)。
最后,我們可以設(shè)置項(xiàng)目在編譯完后,執(zhí)行shell 腳本,進(jìn)行項(xiàng)目的自動(dòng)發(fā)版:
項(xiàng)目編譯完后,會(huì)找到項(xiàng)目下的playbook,執(zhí)行里面的腳本,將我們的項(xiàng)目部署到設(shè)定的服務(wù)器中。
源碼地址:https://github.com/jaycekon/springbootdemo
總結(jié) :
本篇文章為大家?guī)?lái)了spring-boot 的架構(gòu)搭建,主要使用到了目前較為流行的技術(shù)。希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)服務(wù)器之家網(wǎng)站的支持!
原文鏈接:http://www.cnblogs.com/jaycekon/p/SpringBoot.html