寫在前面
本文由markdown格式寫成,為本人第一次這么寫,排版可能會有點(diǎn)亂,還望各位海涵。
主要寫的是使用ribbon進(jìn)行restful請求,測試各個方法的使用,代碼冗余較高,比較適合初學(xué)者,介意輕噴謝謝。
前提
- 一個可用的eureka注冊中心(文中以之前博客中雙節(jié)點(diǎn)注冊中心,不重要)
- 一個連接到這個注冊中心的服務(wù)提供者
- 一個ribbon的消費(fèi)者
注意:文中使用@getmapping、@postmapping、@putmapping、@deletemapping等注解需要升級 spring-boot-starter-parent版本到1.5.9.realease以上(1.3.7.release版本沒有這些注解)
建議:每個微服務(wù)應(yīng)用都有自己的spring-boot-maven-plugin和maven-compiler-plugin并指定jdk編譯版本為1.8 ,指定方式如下,pom.xml中添加
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
<build> <plugins> <plugin> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-maven-plugin</artifactid> </plugin> <plugin> <groupid>org.apache.maven.plugins</groupid> <artifactid>maven-compiler-plugin</artifactid> <configuration> <source> 1.8 </source> <target> 1.8 </target> </configuration> </plugin> </plugins> </build> |
測試項目構(gòu)建
Eureka注冊中心:參考注冊中心的搭建
服務(wù)提供者:參考注冊服務(wù)提供者
ribbon消費(fèi)者:參考服務(wù)發(fā)現(xiàn)與消費(fèi)
項目搭建完后,記得按照這幾個教程中提到的配置hosts文件
為了防止項目中的requestmapping相同,這里就刪除所有的controller類(服務(wù)提供者和消費(fèi)者),接下來我會將每個restful方法都封裝成一個類,方便大家查看
get請求
getforentity:此方法有三種重載形式,分別為:
- getforentity(string url, class<t> responsetype)
- getforentity(string url, class<t> responsetype, object... urivariables)
- getforentity(string url, class<t> responsetype, map<string, ?> urivariables)
- getforentity(uri url, class<t> responsetype)
注意:此方法返回的是一個包裝對象responseentity<t>其中t為responsetype傳入類型,想拿到返回類型需要使用這個包裝類對象的getbody()方法
getforobject:此方法也有三種重載形式,這點(diǎn)與getforentity方法相同:
- getforobject(string url, class<t> responsetype)
- getforobject(string url, class<t> responsetype, object... urivariables)
- getforobject(string url, class<t> responsetype, map<string, ?> urivariables)
- getforobject(uri url, class<t> responsetype)
注意:此方法返回的對象類型為responsetype傳入類型
為了方便測試,這里分別在服務(wù)提供者和服務(wù)消費(fèi)者中提供相同的user類,用于方便測試
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
48
49
|
package com.cnblogs.hellxz; /** * 用于測試的pojo */ public class user { private string name; private string sex; private string phone; public user(){} public user(string name, string sex, string phone) { this .name = name; this .sex = sex; this .phone = phone; } public string tostring(){ return "user:{" + "name: " + name + ", " + "sex: " + sex + ", " + "phone: " + phone + " }" ; } public string getname() { return name; } public void setname(string name) { this .name = name; } public string getsex() { return sex; } public void setsex(string sex) { this .sex = sex; } public string getphone() { return phone; } public void setphone(string phone) { this .phone = phone; } } |
下邊我們在服務(wù)提供者處創(chuàng)建一個getrequestcontroller
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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
package com.cnblogs.hellxz; import org.apache.log4j.logger; import org.springframework.beans.factory.annotation.autowired; import org.springframework.cloud.client.serviceinstance; import org.springframework.cloud.client.discovery.discoveryclient; import org.springframework.web.bind.annotation.*; /** * @author : hellxz * @description: 服務(wù)提供者 * @date : 2018/4/18 11:36 */ @restcontroller public class getrequestcontroller { @autowired private discoveryclient client; //注入發(fā)現(xiàn)客戶端 private final logger logger = logger.getlogger(getrequestcontroller. class ); /** * go straight test */ @getmapping (value = "/hello" ) public string hello(){ //獲取服務(wù)實(shí)例,作用為之后console顯示效果 serviceinstance serviceinstance = client.getlocalserviceinstance(); logger.info( "/hello host:" +serviceinstance.gethost()+ " service_id:" +serviceinstance.getserviceid()); return "hello" ; } /** * parameter test */ @getmapping (value = "/greet/{dd}" ) public string greet( @pathvariable string dd){ serviceinstance serviceinstance = client.getlocalserviceinstance(); logger.info( "/hello host:" +serviceinstance.gethost()+ " service_id:" +serviceinstance.getserviceid()); return "hello " +dd; } /** * 返回測試對象 */ @getmapping ( "/user" ) public user getuser(){ serviceinstance serviceinstance = client.getlocalserviceinstance(); logger.info( "/user " +serviceinstance.gethost()+ " port:" +serviceinstance.getport()+ " serviceinstanceid:" +serviceinstance.getserviceid()); return new user( "hellxz" , "male" , "123456789" ); } /** * 根據(jù)名稱返回對象,這里模擬查數(shù)據(jù)庫操作 */ @getmapping ( "/user/{name}" ) public user getuserselect( @pathvariable string name){ serviceinstance serviceinstance = client.getlocalserviceinstance(); logger.info( "/user " +serviceinstance.gethost()+ " port:" +serviceinstance.getport()+ " serviceinstanceid:" +serviceinstance.getserviceid()); if (name.isempty()){ return new user(); } else if (name.equals( "hellxz" )){ return new user( "hellxz" , "male" , "123456789" ); } else { return new user( "隨機(jī)用戶" , "male" , "987654321" ); } } } |
接下來我們在服務(wù)消費(fèi)者項目中創(chuàng)建getrequestcontroller
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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
package com.cnblogs.hellxz; import org.apache.log4j.logger; import org.springframework.beans.factory.annotation.autowired; import org.springframework.http.responseentity; import org.springframework.web.bind.annotation.*; import org.springframework.web.client.resttemplate; import org.springframework.web.util.uricomponents; import org.springframework.web.util.uricomponentsbuilder; import java.net.uri; import java.util.hashmap; import java.util.map; /** * @author : hellxz * @description: ribbon消費(fèi)者應(yīng)用controller,get請求 * @date : 2018/4/16 15:54 */ @restcontroller public class getrequestcontroller { private logger logger = logger.getlogger(getrequestcontroller. class ); @autowired //注入resttemplate private resttemplate resttemplate; /** * responseentity<t> getforentity(string url, class<t> responsetype) * t getbody() 以下此方法相同 */ @getmapping (value= "/entity/noparam" ) public string noparamgetforentity(){ //這里注釋掉,因?yàn)橹跋氘?dāng)然使用了直鏈訪問服務(wù)提供者的接口,這樣是不會返回結(jié)果的,而且會報錯 //return resttemplate.getforentity("http://localhost:8080/hello",string.class).getbody(); //使用resttemplate調(diào)用微服務(wù)接口 return resttemplate.getforentity( "http://hello-service/hello" , string. class ).getbody(); } /** * responseentity<t> getforentity(string url, class<t> responsetype, object... urivariables) */ @getmapping ( "/entity/type" ) public user getforentityidentifybytype(){ //不傳參返回指定類型結(jié)果 responseentity<user> entity = resttemplate.getforentity( "http://hello-service/user" , user. class ); user body = entity.getbody(); logger.info( "user:" +body); return body; //以上可簡寫為 // return resttemplate.getforentity("http://hello-service/user", user.class).getbody(); } /** * responseentity<t> getforentity(string url, class<t> responsetype, object... urivariables) * 使用占位符對參數(shù)進(jìn)行替換,內(nèi)部使用string.format方法實(shí)現(xiàn) */ @getmapping (value= "/entity" ) //如果接收的參數(shù)是使用參數(shù)沒有使用?有則使用@pathvariable,否則用@requestparam public string getforentitybyquestionmarkparam( @requestparam ( "name" ) string name){ //主要測試getentity方法,這里測試直接傳參 return resttemplate.getforentity( "http://hello-service/greet/{1}" , string. class , name).getbody(); } /** * getforentity方法內(nèi)部會提取map中,以占位符為key的值作為參數(shù)回填入url中 * responseentity<t> getforentity(string url, class<t> responsetype, map<string, ?> urivariables) */ @getmapping (value= "/entity/map/{name}" ) //如果接收的參數(shù)是使用參數(shù)沒有使用?有則使用@pathvariable,否則用@requestparam public string getforentitybymap( @pathvariable ( "name" ) string name){ //主要測試getentity方法,這里測試map傳參 map<string, string> reqmap = new hashmap(); reqmap.put( "name" ,name); return resttemplate.getforentity( "http://hello-service/greet/{name}" , string. class ,reqmap).getbody(); } /** * responseentity<t> getforobject(uri url, class<t> responsetype) */ @getmapping ( "/entity/uri" ) public string getforentitybyuri(){ //使用uri進(jìn)行傳參并訪問 uricomponents uricomponents = uricomponentsbuilder.fromuristring( "http://hello-service/greet/{name}" ).build().expand( "laozhang" ).encode(); uri uri = uricomponents.touri(); return resttemplate.getforentity(uri, string. class ).getbody(); } /** * t getforobject(string url, class<t> responsetype) */ @getmapping ( "/object" ) public user getforobjectwithnoparam(){ //相比getforentity方法,獲取對象可以省去調(diào)用getbody return resttemplate.getforobject( "http://hello-service/user" , user. class ); } /** * t getforobject(string url, class<t> responsetype, map<string, ?> urivariables) */ @getmapping ( "/object/map" ) public user getforobjectbymap(){ //使用map傳參 map<string, string> parammap = new hashmap<>(); parammap.put( "name" , "hellxz" ); return resttemplate.getforobject( "http://hello-service/user" , user. class , parammap); } /** * t getforobject(string url, class<t> responsetype, object... urivariables) */ @getmapping ( "/object/param/{name}" ) public user getforobjectbyparam( @pathvariable string name){ return resttemplate.getforobject( "http://hello-service/user/{name}" ,user. class , name); } /** * t getforobject(uri url, class<t> responsetype) */ @getmapping ( "/object/uri/{name}" ) public user getforobjectbyuri( @pathvariable string name){ uricomponents uricomponents = uricomponentsbuilder.fromuristring( "http://hello-service/user/{name}" ) .build().expand(name).encode(); uri uri = uricomponents.touri(); return resttemplate.getforobject(uri,user. class ); } } |
先啟動注冊中心,然后通過訪問消費(fèi)者對外提供的接口進(jìn)行測試,這些都是本人實(shí)際操作過的了,這里就不寫測試了
post請求
post請求和get請求都有*forentity和*forobject方法,其中參數(shù)列表有些不同,除了這兩個方法外,還有一個postforlocation方法,其中postforlocation以post請求提交資源,并返回新資源的uri
postforentity:此方法有三種重載形式,分別為:
- postforentity(string url, object request, class<t> responsetype, object... urivariables)
- postforentity(string url, object request, class<t> responsetype, map<string, ?> urivariables)
- postforentity(uri url, object request, class<t> responsetype)
注意:此方法返回的是一個包裝對象responseentity<t>其中t為responsetype傳入類型,想拿到返回類型需要使用這個包裝類對象的getbody()方法
postforobject:此方法也有三種重載形式,這點(diǎn)與postforentity方法相同:
- postforobject(string url, object request, class<t> responsetype, object... urivariables)
- postforobject(string url, object request, class<t> responsetype, map<string, ?> urivariables)
- postforobject(uri url, object request, class<t> responsetype)
注意:此方法返回的對象類型為responsetype傳入類型
postforlocation:此方法中同樣有三種重載形式,分別為:
- postforlocation(string url, object request, object... urivariables)
- postforlocation(string url, object request, map<string, ?> urivariables)
- postforlocation(uri url, object request)
注意:此方法返回的是新資源的uri,相比getforentity、getforobject、postforentity、postforobject方法不同的是這個方法中無需指定返回類型,因?yàn)榉祷仡愋途褪莡ri,通過object... urivariables、map<string, ?> urivariables進(jìn)行傳參依舊需要占位符,參看postforentity部分代碼
按照之前的方式,我們分別在提供服務(wù)者和消費(fèi)者的項目中分別創(chuàng)建postrequestcontroller
如下服務(wù)者postrequestcontroller代碼如下:
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
48
49
|
package com.shunneng.springcloudhelloworld; import org.apache.log4j.logger; import org.springframework.web.bind.annotation.*; import org.springframework.web.util.uricomponents; import org.springframework.web.util.uricomponentsbuilder; import java.net.uri; /** * @author : hellxz * @description: * @date : 2018/4/18 10:21 */ @restcontroller public class postrequestcontroller { private logger logger = logger.getlogger(postrequestcontroller. class ); /** * 接收一個對象再返回回去,postforentity/postforobject方法通用 */ @postmapping ( "/user" ) public user returnuserbypost( @requestbody user user){ logger.info( "/use接口 " +user); if (user == null ) return new user( "這是一個空對象" , "" , "" ); return user; } /** * 測試postforentity方法的參數(shù),可以直接看輸出判斷結(jié)果了 */ @postmapping ( "/user/{str}" ) public user returnuserbypost( @pathvariable string str, @requestbody user user){ logger.info( "/user/someparam 接口傳參 name:" +str + " " +user); if (user == null ) return new user( "這是一個空對象" , "" , "" ); return user; } /** * 為postforlocation方法返回uri */ @postmapping ( "/location" ) public uri returnuri( @requestbody user user){ //這里模擬一個url,真實(shí)資源位置不一定是這里 uricomponents uricomponents = uricomponentsbuilder.fromuristring( "http://hello-service/location" ) .build().expand(user).encode(); uri touri = uricomponents.touri(); //這里不知道是什么問題,明明生成uri了,返回之后好像并沒有被獲取到 logger.info( "/location uri:" +touri); return touri; } } |
消費(fèi)端postrequestcontroller代碼:
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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
package com.cnblogs.hellxz; import org.apache.log4j.logger; import org.springframework.beans.factory.annotation.autowired; import org.springframework.http.responseentity; import org.springframework.web.bind.annotation.postmapping; import org.springframework.web.bind.annotation.restcontroller; import org.springframework.web.client.resttemplate; import org.springframework.web.util.uricomponents; import org.springframework.web.util.uricomponentsbuilder; import java.net.uri; /** * @author : hellxz * @description: ribbon消費(fèi)者post請求controller * @date : 2018/4/18 9:47 */ @restcontroller public class postrequestcontroller { private logger logger = logger.getlogger(postrequestcontroller. class ); @autowired private resttemplate resttemplate; /** * responseentity<t> postforentity(string url, object request, class<t> responsetype) * 其中參數(shù)url不多說,object request如果是不是一個httpentity對象,會自動轉(zhuǎn)換為httpentity對象,視作完整的body來處理; * 如果是httpentity對象,那么會被直接當(dāng)做body處理并且包含header內(nèi)容。 * 以下對于重寫的方法就不多說了,使用方法大體同getforentity,如果僅是簡單post對象,那么使用不帶object...variables或map variables的方法即可。 * postforentity(string url, object request, class<t> responsetype, object... urivariables) * postforentity(string url, object request, class<t> responsetype, map<string, ?> urivariables) * * 這里詳細(xì)說下我遇到的坑: * 1、其他幾個重載方法的最后邊的object...variables和map variables都是對之前的url進(jìn)行操作的, * 也就是說,在post請求的url中使用占位符進(jìn)行傳參,而如果在url中沒有使用占位符,那么這些最后傳的參數(shù)是無效的! * 2、方法中object request這個對象如果和服務(wù)提供者的接收參數(shù)類型相同,那么服務(wù)提供者僅需使用@requestbody接收參數(shù)即可。 * 3、如果二者都使用了,這就比較有趣了,需要一邊通過@pathvariable注解接收uri中的參數(shù),一邊還需要@requestbody接收對象或requestparam按字段接收參數(shù)! * 4、如果報錯了,請仔細(xì)看看我上邊寫的三條,并注意服務(wù)提供者的參數(shù)接收注解的使用等。 */ @postmapping ( "/entity" ) public user postforentity(){ user user = new user( "hellxz1" , "1" , "678912345" ); responseentity<user> entity = resttemplate.postforentity( "http://hello-service/user/{str}" , user, user. class , "測試參數(shù)" ); user body = entity.getbody(); //所有resttemplate.*forentity方法都是包裝類,body為返回類型對象 return body; } /** * 使用uri傳參,測試結(jié)果會顯示在服務(wù)提供者的終端中 * responseentity<t> postforentity(uri url, object request, class<t> responsetype) */ @postmapping ( "/entity/uri" ) public user postforentitybyuri(){ user user = new user( "老張" , "1" , "678912345" ); //這里只是將url轉(zhuǎn)成uri,并沒有添加參數(shù) uricomponents uricomponents = uricomponentsbuilder.fromuristring( "http://hello-service/user" ) .build().encode(); uri touri = uricomponents.touri(); //使用user傳參 user object = resttemplate.postforobject(touri, user, user. class ); return object; } /** * 這里測試postforobject方法,需要注意的參數(shù)如上述方法的描述,區(qū)別只是不需要getbody了,這里就不再累述了 * postforobject(string url, object request, class<t> responsetype, object... urivariables) * postforobject(string url, object request, class<t> responsetype, map<string, ?> urivariables) */ @postmapping ( "/object" ) public user postforobject(){ user user = new user( "hellxz2" , "1" , "123654987" ); //這里url傳1是為了調(diào)用服務(wù)者項目中的一個接口 user responsebody = resttemplate.postforobject( "http://hello-service/user/1" , user, user. class ); return responsebody; } /** * post請求還有一種:postforlocation,這里也同樣有三種重載,除了無需指定返回類型外,用法相同,返回類型均為uri,也就不累述了 * postforlocation(string url, object request, object... urivariables) * postforlocation(string url, object request, map<string, ?> urivariables) * postforlocation(uri url, object request) */ @postmapping ( "/location" ) public uri postforlocation(){ user user = new user( "hellxz3" , "1" , "987654321" ); uri uri = resttemplate.postforlocation( "http://hello-service/location" , user); //不知道為什么返回來是空,這個方法僅供參考吧,如果知道是什么情況,我會回來改的 logger.info( "/location uri:" +uri); return uri; } } |
put請求&&delete請求
put請求相對于get和post請求方法來的更為簡單,其中無需指定put請求的返回類型,當(dāng)然也沒有返回值,也是三種重載,和之前寫的基本一致,這里就不想多說了,delete請求和put請求都是沒有返回值的,這里再特地重復(fù)寫也沒什么意思,這里先分別列出這兩個請求的方法,代碼寫在一個類中了
put請求方法如下:
- put(string url, object request, object... urivariables)
- put(string url, object request, map<string, ?> urivariables)
- put(uri url, object request)
delete請求方法如下:
- delete(string url, object... urivariables)
- delete(string url, map<string, ?> urivariables)
- delete(uri url)
在提供服務(wù)者項目中添加putanddeleterequestcontroller,代碼如下
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
|
package com.cnblogs.hellxz; import org.apache.log4j.logger; import org.springframework.web.bind.annotation.*; /** * @author : hellxz * @description: 服務(wù)提供者 put&delete請求controller * @date : 2018/4/19 14:11 */ @restcontroller public class putanddeleterequestcontroller { private logger logger = logger.getlogger(putanddeleterequestcontroller. class ); @putmapping ( "/put" ) public void put( @requestbody user user){ logger.info( "/put " +user); } @deletemapping ( "/delete/{id}" ) public void delete( @pathvariable long id){ logger.info( "/delete id:" +id); } } |
在提供服務(wù)者項目中添加putanddeleterequestcontroller,代碼如下
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
|
package com.cnblogs.hellxz; import org.apache.log4j.logger; import org.springframework.beans.factory.annotation.autowired; import org.springframework.web.bind.annotation.*; import org.springframework.web.client.resttemplate; /** * @author : hellxz * @description: put請求、delete請求,重載的參數(shù)與上述demo基本相同,不予列出 * @date : 2018/4/19 13:43 */ @restcontroller public class putrequestcontroller { private logger logger = logger.getlogger(postrequestcontroller. class ); @autowired private resttemplate resttemplate; /** * put請求示例,一般put請求多用作修改 */ @putmapping ( "/put" ) public void put( @requestbody user user){ resttemplate.put( "http://hello-service/put" ,user); } /** * delete請求示例 */ @deletemapping ( "/del/{id}" ) public void delete( @pathvariable long id){ resttemplate.delete( "http://hello-service/delete/{1}" , id); } } |
結(jié)語
這篇博文使用markdown寫成,第一次寫不知道如何將代碼塊中加入序號以及折疊代碼功能,這可能不是一篇好文章,但是寫這篇博文寫了快兩天,有什么好的建議歡迎評論交流,
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。
原文鏈接:http://www.cnblogs.com/hellxz/p/8875452.html