SpringBoot 之七:消费 REST 服务

  客户端与 Rest 资源交互涉及很多工作,通常都是单调的模板代码。如果使用较低层级的 HTTP 库,客户端就需要创建一个客户端实例和请求对象、执行请求、解析响应、将响应映射为领域对象,并且还要处理这个过程中可能会抛出的所有异常。

  Spring 提供了 RestTemplate 来避免样板代码,就像 JdbcTemplate 一样。

1、用法

  RestTemplate 拥有很多操作方法,主要分为以下几种形式:

形式 含义
...ForEntity() 发送一个 GET 或 POST 请求,返回的 ResponseEntity 包含了由响应体所映射成的对象,有 getForEntity()、postForEntity()
...ForObject() 发送一个 GET、POST 或 PATCH 请求,返回的响应体将映射为一个对象,支持方法有:getForObject()、postForObject()、patchForObject()
postForLocation() POST 数据到一个 URL,返回一个新创建资源的 URL
put() PUT 资源到特定的 URL,主要用于更新数据
execute() 在 URL 上执行特定的HTTP方法,返回一个从响应体映射得到的对象
exchange() 在 URL 上执行特定的HTTP方法,返回一个包含了由响应体所映射成的ResponseEntity 对象



2、获取资源

(1)获取 POJO


// 1、使用URL占位变量,并指定 POJO 类型和传参
public Ingredient getIngredientById(String ingredientId) {
    /**
     * "http://localhost:8080/ingredients/{id}": 要被调用的接口
     * Ingredient.class: 调用接口返回JSON要被反序列化为的对象类型
     * ingredientId: 传入接口的参数
     */
    try {
        return rest.getForObject("http://localhost:8080/api/ingredients/{id}",
                                Ingredient.class, 
                               ingredientId);       
    } catch (HttpClientErrorException e) {
        if (e.getRawStatusCode() == 404) {
            log.info("there not exists ingredient(" + ingredientId + ")");
        }
    } catch (Exception e) {
        e.printStackTrace();            
    }
    return null;
}

// 2、使用URL占位变量,并指定 POJO 类型和传入Map参数
public Ingredient getIngredientById2(String ingredientId) {
    Map<String, String> urlVariables = new HashMap<>();
    urlVariables.put("id", ingredientId);
    return rest.getForObject("http://localhost:8080/api/ingredients/{id}",
                             Ingredient.class, 
                             urlVariables);
}   

// 3、使用 URI 参数
public Ingredient getIngredientById3(String ingredientId) {
    Map<String, String> urlVariables = new HashMap<>();
    urlVariables.put("id", ingredientId);
    URI url = UriComponentsBuilder.fromHttpUrl("http://localhost:8080/api/ingredients/{id}")
                                .build(urlVariables);
    return rest.getForObject(url, Ingredient.class);
}

// 4、获取ResponseEntity对象,得到响应细节,并提取POJO
public Ingredient getIngredientById4(String ingredientId) {
    ResponseEntity<Ingredient> responseEntity = 
            rest.getForEntity("http://localhost:8080/api/ingredients/{id}",
                            Ingredient.class, 
                            ingredientId);          
    log.info("Fetched time: " + responseEntity.getHeaders().getDate());
    log.info("Response header: " + responseEntity.getHeaders());
    log.info("Response status: " + responseEntity.getStatusCode()); 
    return responseEntity.getBody();
}   

// 5、使用 URI 参数并获取 ResponseEntity
public Ingredient getIngredientById5(String ingredientId) {
    Map<String, String> urlVariables = new HashMap<>();
    urlVariables.put("id", ingredientId);
    URI url = UriComponentsBuilder.fromHttpUrl("http://localhost:8080/api/ingredients/{id}")
                                .build(urlVariables);
    ResponseEntity<Ingredient> responseEntity = rest.getForEntity(url, Ingredient.class);
    log.info("Fetched time: " + responseEntity.getHeaders().getDate());
    log.info("Response header: " + responseEntity.getHeaders());
    log.info("Response status: " + responseEntity.getStatusCode());
    return responseEntity.getBody();
}   

// 6、查询获取数据列表
public List<Ingredient> getAllIngredients() {
    return rest.exchange("http://localhost:8080/ingredients", 
                        HttpMethod.GET, 
                        null,
                        new ParameterizedTypeReference<List<Ingredient>>() {})
              .getBody();
}


(2)获取 JSON

RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response
  = restTemplate.getForEntity("http://localhost:8080/ingredients/{id}", 
                              String.class,
                              ingredientId);
String json = response.getBody();


(3)获取 Header

public void retrieveHeaders() {
    HttpHeaders httpHeaders = rest.headForHeaders("http://localhost:8080/api/ingredients");
    log.info("Headers : " + httpHeaders);
}

测试:

Headers : [Vary:"Origin", "Access-Control-Request-Method", "Access-Control-Request-Headers", Link:"<http://localhost:8080/api/ingredients>;rel="self",<http://localhost:8080/api/profile/ingredients>;rel="profile"", X-Content-Type-Options:"nosniff", X-XSS-Protection:"1; mode=block", Cache-Control:"no-cache, no-store, max-age=0, must-revalidate", Pragma:"no-cache", Expires:"0", X-Frame-Options:"SAMEORIGIN", Date:"Wed, 26 Apr 2023 08:03:22 GMT", Keep-Alive:"timeout=60", Connection:"keep-alive"]



3、更新资源

RestTemplate rest = new RestTemplate();
// 1、URL 使用占位变量,传入参数
public void updateIngredient(Ingredient ingredient) {       
    rest.put("http://localhost:8080/api/ingredients/{id}", 
             ingredient, 
             ingredient.getId());       
}

// 2、URL 使用占位变量,传入Map参数
public void updateIngredient2(Ingredient ingredient) {
    Map<String, String> urlVariables = new HashMap<>();
    urlVariables.put("id", ingredient.getId());
    rest.put("http://localhost:8080/api/ingredients/{id}", 
             ingredient, 
             urlVariables);
}   

// 3、使用exchange(),指定请求方法为 POST
public void updateIngredient3(Ingredient ingredient) {   
    HttpEntity<Ingredient> entity = new HttpEntity<Ingredient>(ingredient);
    rest.exchange("http://localhost:8080/api/ingredients/{id}", 
                  HttpMethod.PUT, 
                  entity, 
                  Ingredient.class,
                  ingredient.getId());
}       



4、创建资源

RestTemplate rest = new RestTemplate();

// 1、使用 postForObject()
public Ingredient createIngredient(Ingredient ingredient) {
    return rest.postForObject("http://localhost:8080/api/ingredients", 
                              ingredient, 
                              Ingredient.class);
}

// 2、使用 postForLocation()
// 返回的URI是从响应的Location头信息派生出来的
public URI createIngredient2(Ingredient ingredient) {
    return rest.postForLocation("http://localhost:8080/api/ingredients", 
                              ingredient, 
                              Ingredient.class);
}   

// 3、使用 postForEntity()
public Ingredient createIngredient3(Ingredient ingredient) {
    ResponseEntity<Ingredient> responseEntity = 
            rest.postForEntity("http://localhost:8080/api/ingredients",
                              ingredient, 
                             Ingredient.class);     
    log.info("New resource created at " + responseEntity.getHeaders().getLocation());       
    return responseEntity.getBody();
}



5、删除资源

public void deleteIngredient(Ingredient ingredient) {
    rest.delete("http://localhost:8080/api/ingredients/{id}", 
                ingredient.getId());
}



6、提交表单数据

  首先,我们需要将 Content-Type 标头设置为 application/x-www-form-urlencoded。 这可确保可以将大型查询字符串发送到服务器,其中包含由 & 分隔的键值对。

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

// 将表单变量包装到 MultiValueMap 中
MultiValueMap<String, String> map= new LinkedMultiValueMap<>();
map.add("id", "1");

// 构建 HttpEntity 请求实例
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);

// 通过在端点上调用 restTemplate.postForEntity() 来连接到 REST 服务:/foos/form
ResponseEntity<String> response = restTemplate.postForEntity(fooResourceUrl+"/form", 
                                                             request , 
                                                             String.class);
Assertions.assertEquals(response.getStatusCode(), HttpStatus.CREATED);



7、测试

客户端代码:

package tacos.restclient;

import java.net.URI;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.core.ParameterizedTypeReference;
import org.springframework.hateoas.CollectionModel;
import org.springframework.hateoas.client.Traverson;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import lombok.extern.slf4j.Slf4j;
import tacos.Ingredient;
import tacos.Order;
import tacos.Taco;

@Service
@Slf4j
public class TacoCloudClient {

    private RestTemplate rest;
    private Traverson traverson;

    public TacoCloudClient(RestTemplate rest, Traverson traverson) {        
        this.rest = rest;
        this.traverson = traverson;
    }
    
    
    /**
     * Get Example
     */
    
    // 将参数指定为可变参数
    public Ingredient getIngredientById(String ingredientId) {
        /**
         * "http://localhost:8080/ingredients/{id}": 要被调用的接口
         * Ingredient.class: 调用接口返回JSON要被反序列化为的对象类型
         * ingredientId: 传入接口的参数
         */
        try {
            return rest.getForObject("http://localhost:8080/api/ingredients/{id}",
                 Ingredient.class, 
                 ingredientId);     
        } catch (HttpClientErrorException e) {
            if (e.getRawStatusCode() == 404) {
                log.info("there not exists ingredient(" + ingredientId + ")");
            }
        } catch (Exception e) {
            e.printStackTrace();            
        }
        return null;
    }
    
    // 使用Map传参
    public Ingredient getIngredientById2(String ingredientId) {
        Map<String, String> urlVariables = new HashMap<>();
        urlVariables.put("id", ingredientId);
        return rest.getForObject("http://localhost:8080/api/ingredients/{id}",
                                 Ingredient.class, 
                                 urlVariables);
    }   
    
    // 使用URL参数、Map传参
    public Ingredient getIngredientById3(String ingredientId) {
        Map<String, String> urlVariables = new HashMap<>();
        urlVariables.put("id", ingredientId);
        URI url = UriComponentsBuilder.fromHttpUrl("http://localhost:8080/api/ingredients/{id}")
                                      .build(urlVariables);
        return rest.getForObject(url, Ingredient.class);
    }
    
    // 使用getForEntity返回的是一个ResponseEntity对象,可以获取响应细节比如响应头信息
    public Ingredient getIngredientById4(String ingredientId) {
        ResponseEntity<Ingredient> responseEntity = rest.getForEntity("http://localhost:8080/api/ingredients/{id}",
                                                                      Ingredient.class, 
                                                                      ingredientId);
                
        log.info("Fetched time: " + responseEntity.getHeaders().getDate());
        log.info("Response header: " + responseEntity.getHeaders());
        log.info("Response status: " + responseEntity.getStatusCode());
        
        return responseEntity.getBody();
    }   
    
    public Ingredient getIngredientById5(String ingredientId) {
        Map<String, String> urlVariables = new HashMap<>();
        urlVariables.put("id", ingredientId);
        URI url = UriComponentsBuilder.fromHttpUrl("http://localhost:8080/api/ingredients/{id}")
                                      .build(urlVariables);
        ResponseEntity<Ingredient> responseEntity = rest.getForEntity(url, Ingredient.class);
        
        log.info("Fetched time: " + responseEntity.getHeaders().getDate());
        log.info("Response header: " + responseEntity.getHeaders());
        log.info("Response status: " + responseEntity.getStatusCode());
        
        return responseEntity.getBody();
    }       
    
    public List<Ingredient> getAllIngredients() {
        return rest.exchange("http://localhost:8080/ingredients", 
                             HttpMethod.GET, 
                             null,
                             new ParameterizedTypeReference<List<Ingredient>>() {}).getBody();
    }
    
    public Order getOrderById(int orderId) {
        return rest.getForObject("http://localhost:8080/api/orders/{id}",
                                 Order.class, 
                                 orderId);      
    }   
    
    public void updateOrder(Order order) {
        rest.put("http://localhost:8080/api/orders/{id}", 
                  order, 
                  order.getId());           
    }
    
    /**
     * Put Example
     */
    
    public void updateIngredient(Ingredient ingredient) {       
        rest.put("http://localhost:8080/api/ingredients/{id}", 
                 ingredient, 
                 ingredient.getId());       
    }
    
    public void updateIngredient2(Ingredient ingredient) {
        Map<String, String> urlVariables = new HashMap<>();
        urlVariables.put("id", ingredient.getId());
        rest.put("http://localhost:8080/api/ingredients/{id}", 
                 ingredient, 
                 urlVariables);
    }   
    
    public void updateIngredient3(Ingredient ingredient) {   
        HttpEntity<Ingredient> entity = new HttpEntity<Ingredient>(ingredient);
        rest.exchange("http://localhost:8080/api/ingredients/{id}", 
                      HttpMethod.PUT, 
                      entity, 
                      Ingredient.class,
                      ingredient.getId());
    }       
    
    
    // Delete Example
    public void deleteIngredient(Ingredient ingredient) {
        rest.delete("http://localhost:8080/api/ingredients/{id}", 
                    ingredient.getId());
    }
    
    
    // Post Example
    public Ingredient createIngredient(Ingredient ingredient) {
        return rest.postForObject("http://localhost:8080/api/ingredients", 
                                  ingredient, 
                                  Ingredient.class);
    }
    // 返回的URI是从响应的Location头信息派生出来的
    public URI createIngredient2(Ingredient ingredient) {
        return rest.postForLocation("http://localhost:8080/api/ingredients", 
                                  ingredient, 
                                  Ingredient.class);
    }   
    
    public Ingredient createIngredient3(Ingredient ingredient) {
        ResponseEntity<Ingredient> responseEntity = rest.postForEntity("http://localhost:8080/api/ingredients",
                                                                       ingredient, 
                                                                       Ingredient.class);       
        log.info("New resource created at " + responseEntity.getHeaders().getLocation());       
        return responseEntity.getBody();
    }   
    
    
    public void retrieveHeaders() {
        HttpHeaders httpHeaders = rest.headForHeaders("http://localhost:8080/api/ingredients");
        log.info("Headers : " + httpHeaders);
    }
    
    //
    // Traverson with RestTemplate examples
    //
    public Iterable<Ingredient> getAllIngredientsWithTraverson() {      
        ParameterizedTypeReference<CollectionModel<Ingredient>> ingredientType = new ParameterizedTypeReference<CollectionModel<Ingredient>>() {
        };

        CollectionModel<Ingredient> ingredientRes = traverson.follow("ingredients").toObject(ingredientType);
        //Resources<Ingredient> ingredientRes = traverson.follow("ingredients").toObject(ingredientType);

        Collection<Ingredient> ingredients = ingredientRes.getContent();

        return ingredients;
    }
    
    public Ingredient addIngredient(Ingredient ingredient) {
        String ingredientsUrl = traverson.follow("ingredients").asLink().getHref();
        return rest.postForObject(ingredientsUrl, ingredient, Ingredient.class);
    }
    
    public Iterable<Taco> getRecentTacosWithTraverson() {
        ParameterizedTypeReference<CollectionModel<Taco>> tacoType = new ParameterizedTypeReference<CollectionModel<Taco>>() {
        };

        CollectionModel<Taco> tacoRes = traverson.follow("tacos").follow("recent").toObject(tacoType);

        return tacoRes.getContent();
    }
    
}

测试代码:

package tacos.restclient;

import java.net.URI;
import java.util.List;

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.hateoas.MediaTypes;
import org.springframework.hateoas.client.Traverson;
import org.springframework.web.client.RestTemplate;

import lombok.extern.slf4j.Slf4j;
import tacos.Ingredient;
import tacos.Order;
import tacos.Taco;

@SpringBootConfiguration
@ComponentScan
@Slf4j
public class RestExamples {
    
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }   
    
    public static void main(String[] args) {
        SpringApplication.run(RestExamples.class, args);
    }

    // 根据id获取单个配料,获取所有的配料列表
    @Bean
    public CommandLineRunner fetchIngredients(TacoCloudClient tacoCloudClient) {
        return args -> {
            log.info("----------------------- GET -------------------------");
            log.info("GETTING INGREDIENT BY IDE");
            log.info("Ingredient:  " + tacoCloudClient.getIngredientById("CHED"));
            log.info("GETTING ALL INGREDIENTS");
            List<Ingredient> ingredients = tacoCloudClient.getAllIngredients();
            log.info("All ingredients:");
            for (Ingredient ingredient : ingredients) {
                log.info("   - " + ingredient);
            }
            log.info("");
        };      
    }
    
    @Bean
    public CommandLineRunner fetchIngredients2(TacoCloudClient tacoCloudClient) {
        return args -> {
            log.info("----------------------- GET(Map variables) -------------------------");
            log.info("GETTING INGREDIENT BY IDE");
            log.info("Ingredient:  " + tacoCloudClient.getIngredientById2("CHED"));
            log.info("GETTING ALL INGREDIENTS");
            List<Ingredient> ingredients = tacoCloudClient.getAllIngredients();
            log.info("All ingredients:");
            for (Ingredient ingredient : ingredients) {
                log.info("   - " + ingredient);
            }
            log.info("");
        };
    }   
    
    @Bean
    public CommandLineRunner fetchIngredients3(TacoCloudClient tacoCloudClient) {
        return args -> {
            log.info("----------------------- GET(URL & Map variables) -------------------------");
            log.info("GETTING INGREDIENT BY IDE");
            log.info("Ingredient:  " + tacoCloudClient.getIngredientById3("CHED"));
            log.info("GETTING ALL INGREDIENTS");
            List<Ingredient> ingredients = tacoCloudClient.getAllIngredients();
            log.info("All ingredients:");
            for (Ingredient ingredient : ingredients) {
                log.info("   - " + ingredient);
            }
            log.info("");
        };
    }       
    
    @Bean
    public CommandLineRunner fetchIngredientsResponseEntity(TacoCloudClient tacoCloudClient) {
        return args -> {
            log.info("----------------------- GET(ResponseEntity) -------------------------");
            log.info("GETTING INGREDIENT BY IDE");
            log.info("Ingredient:  " + tacoCloudClient.getIngredientById4("CHED"));
            log.info("GETTING ALL INGREDIENTS");
            List<Ingredient> ingredients = tacoCloudClient.getAllIngredients();
            log.info("All ingredients:");
            for (Ingredient ingredient : ingredients) {
                log.info("   - " + ingredient);
            }
            log.info("");
        };
    }   
    
    @Bean
    public CommandLineRunner fetchIngredientsResponseEntity2(TacoCloudClient tacoCloudClient) {
        return args -> {
            log.info("----------------------- GET(ResponseEntity2) -------------------------");
            log.info("GETTING INGREDIENT BY IDE");
            log.info("Ingredient:  " + tacoCloudClient.getIngredientById5("CHED"));
            log.info("GETTING ALL INGREDIENTS");
            List<Ingredient> ingredients = tacoCloudClient.getAllIngredients();
            log.info("All ingredients:");
            for (Ingredient ingredient : ingredients) {
                log.info("   - " + ingredient);
            }
            log.info("");
        };
    }   
    
    // 获取并更新一条配料数据
    //@Bean
    public CommandLineRunner putAnIngredient(TacoCloudClient tacoCloudClient) {
        return args -> {
            log.info("----------------------- PUT -------------------------");
            Ingredient before = tacoCloudClient.getIngredientById("LETC");
            log.info("BEFORE:  " + before);
            tacoCloudClient.updateIngredient(new Ingredient("LETC", "Lettuce", Ingredient.Type.VEGGIES));
            Ingredient after = tacoCloudClient.getIngredientById("LETC");
            log.info("AFTER:  " + after);   
            log.info("");
        };
    }
    
    //@Bean
    public CommandLineRunner putAnIngredient2(TacoCloudClient tacoCloudClient) {
        return args -> {
            log.info("----------------------- PUT -------------------------");
            Ingredient before = tacoCloudClient.getIngredientById("LETC");
            log.info("BEFORE:  " + before);
            tacoCloudClient.updateIngredient2(new Ingredient("LETC", "VEGGIES", Ingredient.Type.VEGGIES));
            Ingredient after = tacoCloudClient.getIngredientById("LETC");
            log.info("AFTER:  " + after);
            log.info("");
        };
    }   
    
    //@Bean
    public CommandLineRunner putAnIngredient3(TacoCloudClient tacoCloudClient) {
        return args -> {
            log.info("----------------------- PUT(Call exchange) -------------------------");
            Ingredient before = tacoCloudClient.getIngredientById("LETC");
            log.info("BEFORE:  " + before);
            tacoCloudClient.updateIngredient3(new Ingredient("LETC", "Lettuce", Ingredient.Type.VEGGIES));
            Ingredient after = tacoCloudClient.getIngredientById("LETC");
            log.info("AFTER:  " + after);
            log.info("");
        };
    }       
    
    // 删除一条配料数据
    //@Bean
    public CommandLineRunner deleteAnIngredient(TacoCloudClient tacoCloudClient) {
        return args -> {
            log.info("----------------------- DELETE -------------------------");
            Ingredient before = tacoCloudClient.getIngredientById("CHIX");
            log.info("BEFORE DELETE:  " + before);
            Ingredient chix = new Ingredient("CHIX", "Shredded Chicken", Ingredient.Type.PROTEIN);
            tacoCloudClient.deleteIngredient(chix);
            Ingredient after = tacoCloudClient.getIngredientById("CHIX");
            log.info("AFTER DELETE:  " + after);
            log.info("");
            
            Ingredient before2 = tacoCloudClient.getIngredientById("CHIY");
            log.info("BEFORE DELETE:  " + before2);
            Ingredient chix2 = new Ingredient("CHIY", "Shredded Chicken", Ingredient.Type.PROTEIN);
            tacoCloudClient.deleteIngredient(chix2);
            Ingredient after2 = tacoCloudClient.getIngredientById("CHIY");
            log.info("AFTER DELETE:  " + after2);           
            log.info("");
            
            Ingredient before3 = tacoCloudClient.getIngredientById("CHIZ");
            log.info("BEFORE DELETE:  " + before3);
            Ingredient chix3 = new Ingredient("CHIZ", "Shredded Chicken", Ingredient.Type.PROTEIN);
            tacoCloudClient.deleteIngredient(chix3);
            Ingredient after3 = tacoCloudClient.getIngredientById("CHIZ");
            log.info("AFTER DELETE:  " + after3);           
            log.info("");           
        };
    }   
    
    // 添加一条配料数据
    //@Bean
    public CommandLineRunner addAnIngredient(TacoCloudClient tacoCloudClient) {
        return args -> {
            log.info("----------------------- POST -------------------------");
            Ingredient chix = new Ingredient("CHIX", "Shredded Chicken", Ingredient.Type.PROTEIN);
            Ingredient chixAfter = tacoCloudClient.createIngredient(chix);
            log.info("AFTER=1:  " + chixAfter); 
            log.info("");
        };
    }
    
    //@Bean
    public CommandLineRunner addAnIngredient2(TacoCloudClient tacoCloudClient) {
        return args -> {
            log.info("----------------------- POST(RETURN URI) -------------------------");
            Ingredient chix = new Ingredient("CHIY", "Shredded Chicken", Ingredient.Type.PROTEIN);
            URI uri = tacoCloudClient.createIngredient2(chix);
            log.info("ADD URI:  " + uri);   
            log.info("");
        };
    }   
    
    //@Bean
    public CommandLineRunner addAnIngredient3(TacoCloudClient tacoCloudClient) {
        return args -> {
            log.info("----------------------- POST(RETURN ResponseEntity) -------------------------");
            Ingredient chiz = new Ingredient("CHIZ", "Shredded Chicken", Ingredient.Type.PROTEIN);
            Ingredient chizAdd = tacoCloudClient.createIngredient3(chiz);
            log.info("AFTER=1:  " + chizAdd);   
            log.info("");
        };
    }   
    
    // 删除一条配料数据
    //@Bean
    public CommandLineRunner deleteAnIngredient2(TacoCloudClient tacoCloudClient) {
        return args -> {
            log.info("----------------------- DELETE -------------------------");
            // start by adding a few ingredients so that we can delete them later...
            Ingredient beefFajita = new Ingredient("BFFJ", "Beef Fajita", Ingredient.Type.PROTEIN);
            tacoCloudClient.createIngredient(beefFajita);
            Ingredient shrimp = new Ingredient("SHMP", "Shrimp", Ingredient.Type.PROTEIN);
            tacoCloudClient.createIngredient(shrimp);

            Ingredient before = tacoCloudClient.getIngredientById("CHIX");
            log.info("BEFORE:  " + before);
            before.setId("CHIX");
            tacoCloudClient.deleteIngredient(before);           
            Ingredient after = tacoCloudClient.getIngredientById("CHIX");
            log.info("AFTER:  " + after);
            
            before = tacoCloudClient.getIngredientById("BFFJ");
            log.info("BEFORE:  " + before);
            before.setId("BFFJ");
            tacoCloudClient.deleteIngredient(before);
            after = tacoCloudClient.getIngredientById("BFFJ");
            log.info("AFTER:  " + after);
            
            before = tacoCloudClient.getIngredientById("SHMP");
            log.info("BEFORE:  " + before);
            before.setId("SHMP");
            tacoCloudClient.deleteIngredient(before);
            after = tacoCloudClient.getIngredientById("SHMP");
            log.info("AFTER:  " + after);
        };
    }
    
    //@Bean
    public CommandLineRunner putOrder(TacoCloudClient tacoCloudClient) {
        return args -> {
            log.info("----------------------- PUT(GET -> UPDATE -> GET) -------------------------");
            // 因为hateoas返回单个数据对象时不带id,所以下面要重新set一下
            Order before = tacoCloudClient.getOrderById(1);
            log.info("BEFORE:  " + before);
            before.setDeliveryName("胡奕豪");
            before.setId(1L);
            tacoCloudClient.updateOrder(before);
            Order after = tacoCloudClient.getOrderById(1);
            log.info("AFTER:  " + after);
            log.info("");
        };
    }
    
    //@Bean
    public CommandLineRunner headers(TacoCloudClient tacoCloudClient) {
        return args -> {
            log.info("----------------------- Headers -------------------------");
            tacoCloudClient.retrieveHeaders();
            log.info("");
        };
    }
    
    /**
     * 参数1:指定基础URL
     * 参数2:指定API生成JSON格式的响应,并且具有HAL风格的超链接
     */
    @Bean
    public Traverson traverson() {
        Traverson traverson = new Traverson(URI.create("http://localhost:8080/api"), MediaTypes.HAL_JSON);
        return traverson;
    }
    
    //@Bean
    public CommandLineRunner traversonGetIngredients(TacoCloudClient tacoCloudClient) {
        return args -> {
            Iterable<Ingredient> ingredients = tacoCloudClient.getAllIngredientsWithTraverson();
            log.info("----------------------- GET INGREDIENTS WITH TRAVERSON -------------------------");
            for (Ingredient ingredient : ingredients) {
                log.info("   -  " + ingredient);
            }
        };
    }
    
    //@Bean
    public CommandLineRunner traversonSaveIngredient(TacoCloudClient tacoCloudClient) {
        
        return args -> {
            Ingredient pico = tacoCloudClient
                    .addIngredient(new Ingredient("PICO", "Pico de Gallo", Ingredient.Type.SAUCE));
            List<Ingredient> allIngredients = tacoCloudClient.getAllIngredients();
            log.info("----------------------- ALL INGREDIENTS AFTER SAVING PICO -------------------------");
            for (Ingredient ingredient : allIngredients) {
                log.info("   -  " + ingredient);
            }
            tacoCloudClient.deleteIngredient(pico);
            log.info("");
        };
    }

    //@Bean
    public CommandLineRunner traversonRecentTacos(TacoCloudClient tacoCloudClient) {
        return args -> {
            Iterable<Taco> recentTacos = tacoCloudClient.getRecentTacosWithTraverson();
            log.info("----------------------- GET RECENT TACOS WITH TRAVERSON -------------------------");
            for (Taco taco : recentTacos) {
                log.info("   -  " + taco);
            }
            log.info("");
        };
    }
    
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,922评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,591评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,546评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,467评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,553评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,580评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,588评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,334评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,780评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,092评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,270评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,925评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,573评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,194评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,437评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,154评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352

推荐阅读更多精彩内容