天天看点

springboot学习,如何使用RestTemplate调用Restful接口

      现在系统之间的功能模块,相互调用以及数据的传递,如果采用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组成的,这样一来,数据类型简单,而且还能应付复杂的业务场景。

    这样就是你好,我好,大家好。否则总会有各种各样麻烦,搞个接口调试的人应该知道。这样做似乎有点土,是笨办法,回避复杂的做法,但是,可以避免被人吐槽你写的接口,甚至.......