拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。
IMG-LOGO
主页 文章列表 Spring RestTemplate异常:“Not enough variables available to expand”

Spring RestTemplate异常:“Not enough variables available to expand”

白鹭 - 2021-11-24 712 0 0

1.概述

在这个简短的教程中,我们将仔细研究Spring的RestTemplate异常IllegalArgumentException :没有足够的变量可扩展。

首先,我们将详细讨论此异常背后的主要原因。然后,我们将展示如何产生它,最后是如何解决它。

2.原因

简而言之,当我们尝试在GET request中发送JSON数据时,通常会发生异常。

简而言之, RestTemplate提供了getForObject方法来通过在指定的URL上执行GET请求来获取表示。

造成此异常的主要原因是**RestTemplate将封装在花括号中的JSON数据视为URI变量的占位符**。

由于我们没有为预期的URI变量提供任何值,因此getForObject方法将引发异常。

例如,尝试发送{“name”:”HP EliteBook”}作为值:

String url = "http://products.api.com/get?key=a123456789z&criterion={\"name\":\"HP EliteBook\"}";

 Product product = restTemplate.getForObject(url, Product.class);

只会导致RestTemplate引发异常:

java.lang.IllegalArgumentException: Not enough variable values available to expand 'name'

3.示例应用

现在,让我们看一个示例,说明如何使用RestTemplate产生此IllegalArgumentException

为简单起见,我们将使用单个GET端点创建用于产品管理的基本REST API。

首先,让我们创建模型类Product

public class Product {



 private int id;

 private String name;

 private double price;



 // default constructor + all args constructor + getters + setters

 }

接下来,我们将定义一个spring控制器来封装REST API的逻辑:

@RestController

 @RequestMapping("/api")

 public class ProductApi {



 private List<Product> productList = new ArrayList<>(Arrays.asList(

 new Product(1, "Acer Aspire 5", 437),

 new Product(2, "ASUS VivoBook", 650),

 new Product(3, "Lenovo Legion", 990)

 ));



 @GetMapping("/get")

 public Product get(@RequestParam String criterion) throws JsonMappingException, JsonProcessingException {

 ObjectMapper objectMapper = new ObjectMapper();

 Criterion crt = objectMapper.readValue(criterion, Criterion.class);

 if (crt.getProp().equals("name")) {

 return findByName(crt.getValue());

 }



 // Search by other properties (id,price)



 return null;

 }



 private Product findByName(String name) {

 for (Product product : this.productList) {

 if (product.getName().equals(name)) {

 return product;

 }

 }

 return null;

 }



 // Other methods

 }

4.解释示例应用程序

处理程序方法get()的基本思想是根据特定条件检索产品对象.

该条件可以表示为具有两个键的JSON字符串: propvalue

prop键指的是产品属性,因此它可以是一个ID,名称或价格。

如上所示,该条件作为字符串参数传递给处理程序方法。我们使用ObjectMapper类将JSON字符串转换为Criterion对象。

这是我们的Criterion类的外观:

public class Criterion {



 private String prop;

 private String value;



 // default constructor + getters + setters

 }

最后,让我们尝试将GET请求发送到映射到处理程序方法get()的URL。

@RunWith(SpringRunner.class)

 @SpringBootTest(classes = { RestTemplate.class, RestTemplateExceptionApplication.class })

 public class RestTemplateExceptionLiveTest {



 @Autowired

 RestTemplate restTemplate;



 @Test(expected = IllegalArgumentException.class)

 public void givenGetUrl_whenJsonIsPassed_thenThrowException() {

 String url = "http://localhost:8080/spring-rest/api/get?criterion={\"prop\":\"name\",\"value\":\"ASUS VivoBook\"}";

 Product product = restTemplate.getForObject(url, Product.class);

 }

 }

确实,单元测试引发IllegalArgumentException因为我们试图将{“prop”:”name”,”value”:”ASUS VivoBook”}作为URL的一部分{“prop”:”name”,”value”:”ASUS VivoBook”}

5.解决方案

根据经验,我们应该始终使用POST请求发送JSON数据

但是,尽管不建议这样做,但使用GET的可能解决方案可能是定义一个包含我们标准的String对象,并在URL中提供真实的URI变量

@Test

 public void givenGetUrl_whenJsonIsPassed_thenGetProduct() {

 String criterion = "{\"prop\":\"name\",\"value\":\"ASUS VivoBook\"}";

 String url = "http://localhost:8080/spring-rest/api/get?criterion={criterion}";

 Product product = restTemplate.getForObject(url, Product.class, criterion);



 assertEquals(product.getPrice(), 650, 0);

 }

让我们看看使用UriComponentsBuilder类的另一个解决方案:

@Test

 public void givenGetUrl_whenJsonIsPassed_thenReturnProduct() {

 String criterion = "{\"prop\":\"name\",\"value\":\"Acer Aspire 5\"}";

 String url = "http://localhost:8080/spring-rest/api/get";



 UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(url).queryParam("criterion", criterion);

 Product product = restTemplate.getForObject(builder.build().toUri(), Product.class);



 assertEquals(product.getId(), 1, 0);

 }

如我们所见,在将其传递给getForObject方法之前,我们使用UriComponentsBuilder类构造了具有查询参数criterion URI .

六,结论

在这篇快速文章中,我们讨论了导致RestTemplate引发IllegalArgumentException: “原因IllegalArgumentException: “没有足够的变量可扩展”。

在此过程中,我们遍历了一个实际示例,展示了如何产生异常并解决异常。

标签:

0 评论

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *