現在系統之間的功能模塊,相互調用以及數據的傳遞,如果採用http模式通訊,很少有人用webservice了,大多都是使用Restful接口,因爲方便、簡單嘛。
先說說怎麼創建Restful接口吧,這個和普通的Controller的寫法感覺差不多,就是對外路徑稍微有所不同。直接看代碼。
package com.springboot.controller;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.springboot.entity.ProductOrder;
import com.springboot.entity.ReqData;
import net.sf.json.JSONObject;
@RestController
public class RestfulController {
@RequestMapping(value = "/api/data", method = RequestMethod.POST)
public ProductOrder postObject(@RequestBody ReqData data) {
if (data == null) {
return null;
}
return getone(data.requestType);
}
@RequestMapping(value = "/api/map", method = RequestMethod.POST)
public List<ProductOrder> postMap(@RequestBody Map<String, String> map) {
if (map == null || map.isEmpty()) {
return null;
}
return getData();
}
@RequestMapping(value = "/api/json", method = RequestMethod.POST)
public ProductOrder postJson(@RequestBody JSONObject jsonRequest) {
if (jsonRequest == null || jsonRequest.isEmpty()) {
return null;
}
return getone("json");
}
//
@GetMapping(value = "/api/product/{id}")
public ProductOrder findone(@PathVariable("id") String id){
if (id == null)
{
id = ".";
}
return getone(id);
}
/**
* 模擬數據
* */
private List<ProductOrder> getData(){
List<ProductOrder> list=new ArrayList<ProductOrder>();
ProductOrder m1 = new ProductOrder();
m1.setId("1");
m1.setName("admin1");
m1.setPrice(0.8553f);
m1.setPDate(new Date());
list.add(m1);
ProductOrder m2 = new ProductOrder();
m2.setId("2");
m2.setName("admin2");
m2.setPrice(0.633f);
m2.setPDate(new Date());
list.add(m2);
ProductOrder m3 = new ProductOrder();
m3.setId("3");
m3.setName("admin3");
m3.setPrice(0.344f);
m3.setPDate(new Date());
list.add(m3);
return list;
}
private ProductOrder getone(String id){
ProductOrder m1 = new ProductOrder();
m1.setId(id);
m1.setName("admin");
m1.setPrice(0.8553f);
m1.setPDate(new Date());
return m1;
}
}
就是前面三個方法,這個好像很簡單,注意每個方法都帶不同的參數,ReqData,map,JSONObject ,對應不同的調用方法,也不多說直接上代碼。這個test類因爲有main方法,直接右鍵 Debug as ---> Java Application就可以運行了。
package com.springboot.service;
import java.util.HashMap;
import java.util.Map;
import org.springframework.web.client.RestTemplate;
import com.springboot.entity.Body;
import com.springboot.entity.Pojo;
import com.springboot.entity.ReqData;
import net.sf.json.JSONObject;
public class test {
public static void main(String[] args) {
testModel();
testMap();
testJson();
}
private static void testModel()
{
String url = "http://localhost:8181/webapp/api/data";
RestTemplate client = new RestTemplate();
ReqData m = new ReqData("01","2020-03-24 22:29:00");
String result = client.postForObject(url, m, String.class);
System.out.println(result);
}
private static void testMap()
{
String url = "http://localhost:8181/webapp/api/map";
RestTemplate client = new RestTemplate();
Map<String, Object> hashMap = new HashMap<String, Object>();
hashMap.put("key1", 999);
hashMap.put("key2", "admin");
String result = client.postForObject(url, hashMap, String.class);
System.out.println(result);
}
private static void testJson()
{
String url = "http://localhost:8181/webapp/api/json";
RestTemplate client = new RestTemplate();
JSONObject json = new JSONObject();
json.put("key1", 999);
json.put("key2", "admin");
String result = client.postForObject(url, json, String.class);
System.out.println(result);
}
}
RestTemplate 這個就是springboot下專門用來調用restful接口,這個看起來好像很簡單,確實也簡單。實體類代碼也簡單。
package com.springboot.entity;
public class ReqData {
public ReqData(String requestType,String timestamp){
this.requestType = requestType;
this.timestamp = timestamp;
}
public String requestType;
public String timestamp;
}
如果你的代碼不需要JSONObject,json-lib節點可以刪除。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
<classifier>jdk15</classifier>
</dependency>
需要注意的是,這兩部分代碼理論上是放在兩個工程裏面下,現實場景中對外接口都是提供給別的第三方來調用。
用 RestTemplate 類調用Restful接口時,默認的情況下,GET方法是不可以傳遞body數據的。需要把 RestTemplate 類擴展一下。
RestTemplate restTemplate = new RestTemplate();
restTemplate.setRequestFactory(new HttpComponentsClientRestfulHttpRequestFactory());
HttpGetRequestWithEntity 類
package com.springboot.config;
import java.net.URI;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.springframework.http.HttpMethod;
public class HttpGetRequestWithEntity extends HttpEntityEnclosingRequestBase {
public HttpGetRequestWithEntity(final URI uri) {
super.setURI(uri);
}
@Override
public String getMethod() {
return HttpMethod.GET.name();
}
}
HttpComponentsClientRestfulHttpRequestFactory 類
package com.springboot.config;
import java.net.URI;
import org.apache.http.client.methods.HttpUriRequest;
import org.springframework.http.HttpMethod;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
public class HttpComponentsClientRestfulHttpRequestFactory extends HttpComponentsClientHttpRequestFactory {
@Override
protected HttpUriRequest createHttpUriRequest(HttpMethod httpMethod, URI uri) {
if (httpMethod == HttpMethod.GET) {
return new HttpGetRequestWithEntity(uri);
}
return super.createHttpUriRequest(httpMethod, uri);
}
}
調用代碼如下
String url = "http://127.0.0.1:8181/api/data";
RestTemplate restTemplate = new RestTemplate();
restTemplate.setRequestFactory(new HttpComponentsClientRestfulHttpRequestFactory());
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Type", "application/json");
headers.add("dataType", "json");
ReqData r = new ReqData("01","2020-03-24 22:29:00");
HttpEntity<ReqData> formEntity = new HttpEntity<ReqData>(r, headers);
ResponseEntity<String> exchange = restTemplate.exchange(url,HttpMethod.GET,formEntity, String.class);
String body = exchange.getBody();
System.out.println(body);
如果想測試代碼的話,restful接口最好是自己重新寫一個。 使用RestTemplate類還是比較方便,相對 httpclient 已經方便多了,尤其是在springboot下。
如果是真實業務場景,寫restful接口的時候,個人建議參數類型,不要實體類型,不要map,也不要JSONObject,儘量都用String,傳進去是String,返回的也是String 。當然,這個String往往是可以json組成的,這樣一來,數據類型簡單,而且還能應付複雜的業務場景。
這樣就是你好,我好,大家好。否則總會有各種各樣麻煩,搞個接口調試的人應該知道。這樣做似乎有點土,是笨辦法,迴避複雜的做法,但是,可以避免被人吐槽你寫的接口,甚至.......