Spring Cloud Alibaba - RestTemplate

Spring Cloud Alibaba - RestTemplate

Controller导入依赖和相关属性

@SuppressWarnings("all")
@RestController
public class TemplateController {
    @Autowired
    private RestTemplate restTemplate;

    @Autowired(required = false)
    private LoadBalancerClient loadBalancerClient;

    final String serviceName = "http://nacos-discovery-provider";  //可以通过配置文件远程获取
    
}

Get请求,无参数,返回String

 //GET请求,无参数,返回String
@RequestMapping("/getstring")
public String get(){
    // ResponseEntity中包含关于这个请求返回的许多信息,不光是结果
    ResponseEntity<String> responseEntity = restTemplate.getForEntity(serviceName+"/get",String.class);
    //String.class 指定返回类型为String
    //====================================================
    //开始获取 ResponseEntity中的详细信息
    int statusCodeValue = responseEntity.getStatusCodeValue();  //状态码的值
    HttpStatus httpStatus = responseEntity.getStatusCode();     //状态码
    HttpHeaders httpHeaders = responseEntity.getHeaders();      //头部信息
    String body = responseEntity.getBody();                     //返回内容体
    //====================================================
    System.out.println(statusCodeValue);
    System.out.println(httpStatus);
    System.out.println(httpHeaders);
    System.out.println(body);
    //返回其中的内容体 , 等同于返回上面的 String body
    return restTemplate.getForEntity(serviceName+"/get",String.class).getBody();
}

因为此处没有使用LoadBalancerClient做负载均衡,所以在启动类中需要添加注解@LoadBalanced

结果为:Spring Cloud Alibaba - RestTemplate

其中statusCodeValue = 200 httpStatus = 200 OK httpHeaders = [Content-Type:"text/plain;charset=UTF-8", Date:"Fri, 23 Jul 2021 09:02:34 GMT", Keep-Alive:"timeout=60", Connection:"keep-alive", Content-Length:"22"] =[Content-Type:"text/plain;charset=UTF-8", Date:"Fri, 23 Jul 2021 09:02:34 GMT", Keep-Alive:"timeout=60", Connection:"keep-alive", Content-Length:"22"] body = this is a get response

restTemplate.getForEntity(); 方法获取的是状态码、头部信息、结果体


Get请求,有参数,返回一个实体对象

首先在消费者和服务提供者的工程项目中都必须要含有同样的实体类

@Component
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private String name;
    private String age;
    private String msg;
}

在服务提供者中存在对应的调用接口:

@RestController
public class RestTemplateController {
    @RequestMapping("/getUser")
    public User getUser(@RequestParam("name")String name,
                        @RequestParam("age")String age,
                        @RequestParam("msg")String msg){
        return new User(name,age,msg);
    }
}

在消费者中调用:

@RequestMapping("/getEntity")
public String getUser(){
    String[] data = {"yangchen","18","from array"};
    //调用服务,获取对象的statusCodeValue,httpStatus,httpHeaders,body
    ResponseEntity<User> responseEntity =
            restTemplate.getForEntity(serviceName+"/getUser?name={0}&age={1}&msg={2}",User.class,data);
    //通过将数组中的参数放入请求链接中请求结果。通过{0} = data[0] 这样的方式一一对应

    //getForObject仅返回该请求的内容体
    User user_array = restTemplate.getForObject(serviceName+"/getUser?name={0}&age={1}&msg={2}",User.class,data);
    //输出信息
    System.out.println("user_array = "+user_array);
    //============ 第二种方法 ================================
    Map<String,Object> param = new ConcurrentHashMap<String, Object>();
    param.put("name","yangchen");
    param.put("age","21");
    param.put("msg","from map");
    //调用服务,获取对象的statusCodeValue,httpStatus,httpHeaders,body
    ResponseEntity<User> responseEntity1 =
            restTemplate.getForEntity(serviceName+"/getUser?name={name}&age={age}&msg={msg}",User.class,param);
    //通过将数组中的参数放入请求链接中请求结果。通过{name} = map中的{name} 这个key的value 这样的方式一一对应

    //getForObject仅返回该请求的内容体
    User user_map = restTemplate.getForObject(serviceName+"/getUser?name={name}&age={age}&msg={msg}",User.class,param);
    //输出信息
    System.out.println("user_map = "+user_map);

    return "success";
}

因为有两种方法,暂且返回String类型,在控制台将两种方法获得的User对象输出:

Spring Cloud Alibaba - RestTemplate

tips:restTemplate.getForObject( )方法仅返回该请求的内容体


Post请求,有参数,返回实体对象

消费者中编写接口:

//Post请求,有参数,返回实体对象
@RequestMapping("/postEntity")
public User postUser(){
    //Post请求的数据必须存放在这种类型的Map中
    MultiValueMap<String,Object> data = new LinkedMultiValueMap<String, Object>();
    data.add("name","yangchen");
    data.add("age","21");
    data.add("msg","from post map");
    //调用换成服务,注意这里用的是postForEntity,其中的传参位置有所变化!!!
    ResponseEntity<User> responseEntity =
            restTemplate.postForEntity(serviceName+"/getUser",data,User.class);

    //也可以通过postForObject直接返回请求的body
    User user_postForObject = restTemplate.postForObject(serviceName+"/getUser",data,User.class);
    System.out.println("user = "+user_postForObject);
    return restTemplate.postForEntity(serviceName+"/getUser",data,User.class).getBody();
}

结果为:

![image-20210723183459508](E:\software\JAVA\springcloud-alibaba\document\动力节点spring cloud alibaba\image-20210723183459508.png)

Spring Cloud Alibaba - RestTemplate

tips:注意参数存放只能存放在MultiValueMap接口实现类为LinkedMultiValueMap的map中,其次调用restTemplate.postForObject( )或者是restTemplate.postForEntity( )方法中的传参顺序与get不同,并且传入的url中不需要带有参数


从此以后,restTemplate.xxxForObject( ) 和 restTemplate.xxxForEntity( )两种方法只选择一种方法进行演示


Post请求,传输实体对象,返回实体对象

服务端提供相应的服务,通过@RequestBody注解来接收消费者端传进来的对象:

@RequestMapping("/responseUser")
public User responseUser(@RequestBody User user){
    return user;
}

消费者端提供接口:

//Post请求,传输实体对象,返回实体对象
@RequestMapping("/postUser")
public User post(){
    User user = new User("yangchen","21","from user entity");
    User user_response = restTemplate.postForObject(serviceName+"/responseUser",user,User.class);
    return user_response;
}

将原先的数据集合替换为实体对象进行传值。

结果为:

Spring Cloud Alibaba - RestTemplate


restTemplate调用传输JSON

消费者端:

​ 传输JSON格式的字符串时,需要使用HttpEntity 对JSON

进行包装才可以传输。

//restTemplate调用传输JSON
@RequestMapping("/postJson")
public User postJson(){
    //定义JSON字符串
    String json = "{\"name\": \"yangchen\",\"age\": \"21\",\"msg\": \"from json\"}";
    HttpHeaders headers = new HttpHeaders();
    //设定格式为JSON格式
    headers.setContentType(MediaType.APPLICATION_JSON);
    //将http头和json字符串使用HttpEntity进行包装然后传输
    HttpEntity<String> entity = new HttpEntity<String>(json,headers);
    User user_json=restTemplate.postForObject(serviceName+"/responseUser",entity,User.class);
    return user_json;
}

服务者端:

同样使用注解@RequestBody 进行接收:

@RequestMapping("/responseUser")
public User responseUser(@RequestBody User user){
    return user;
}

结果如下:

Spring Cloud Alibaba - RestTemplate


tips:如果restTemplate.postForObject( )方法中除了传输的对象还存在另外需要传的值,如:token,只需在后面继续添加,逗号隔开即可。因为在底层这边维护的是一个可变数组

Spring Cloud Alibaba - RestTemplate

服务端可以通过@RequestParam注解的方式进行获取:

Spring Cloud Alibaba - RestTemplate


Put请求--一般作为修改使用

同样修改时的相关参数需要存在MultiValueMap<String,Object> dataMap = new LinkedMultiValueMap<String,Object>( );中。因为Put请求和Post请求类似,甚至可以使用Post请求去代替Put请求。

服务端:

@RequestMapping("/getUser")
public User getUser(@RequestParam("name")String name,
                    @RequestParam("age")String age,
                    @RequestParam("msg")String msg){
    return new User(name,age,msg);
}

不能使用@RequestBody【User user】 方法接收。

消费者端:

//PUT请求
@RequestMapping("/put")
public String put(){
    //只能使用MultiValueMap存,和Post一样
    MultiValueMap<String,Object> multiValueMap = new LinkedMultiValueMap<String, Object>();
    multiValueMap.add("name","yangchen");
    multiValueMap.add("age","21");
    multiValueMap.add("msg","from put");
    //调用远程服务,put方法没有返回值
    restTemplate.put(serviceName+"/getUser",multiValueMap);
    return "success";
}

Delete请求

delete请求可以使用get请求代替。参数绑定方式和get请求类似:

消费端接口:

//delete请求
@RequestMapping("/delete")
public String delete(){
    //数组存取参数
    String[] param_array = {"yangchen","21","from delete array"};
    //远程调用服务
    restTemplate.delete(serviceName+"/getUser?name={0}&age={1}&msg={2}",param_array);
    //====================================================
    //Map存参数
    Map<String,Object> paramMap = new ConcurrentHashMap<String, Object>();
    paramMap.put("name","yangchen");
    paramMap.put("age","21");
    paramMap.put("msg","from param map");
    restTemplate.delete(serviceName+"/getUser?name={name}&age={age}&msg={msg}",paramMap);

    return "success";
}

与GET请求类似,但是restTemplate.delete( )方法没有返回值。


RestTemplate+Ribbon实现负载均衡

Ribbon

Spring Cloud Alibaba - RestTemplate

Spring Cloud Alibaba - RestTemplate

Spring Cloud Alibaba - RestTemplate

Spring Cloud Alibaba - RestTemplate

Spring Cloud Alibaba - RestTemplate

Spring Cloud Alibaba - RestTemplate

ribbon是客户端负载均衡

使用Ribbon需要添加依赖(客户端):
<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>

Spring Cloud Alibaba - RestTemplate

我们在启动类中进行添加:

@EnableDiscoveryClient
@EnableFeignClients
@SpringBootApplication
public class NacosConsumerApplication {

   public static void main(String[] args) {
      SpringApplication.run(NacosConsumerApplication.class, args);
   }

   @LoadBalanced //如果使用了loadBalancerClient进行了代理,则已经做过一次负载均衡,此处的注解不能加
   @Bean
   public RestTemplate restTemplate(){
      return new RestTemplate();
   }
}
上一篇:RestTemplate控制台打印请求响应日志


下一篇:springboot中RestTemplate的测试