mst*_*tzn 6 spring spring-mvc spring-boot spring-cloud spring-cloud-feign
Spring Cloud openFeign 无法创建动态查询参数。它抛出以下异常,因为 SpringMvcContract 试图找到不存在的 RequestParam 值属性。
java.lang.IllegalStateException: RequestParam.value() was empty on parameter 0
@RequestMapping(method = RequestMethod.GET, value = "/orders")
Pageable<Order> searchOrder2(@RequestParam CustomObject customObject);
Run Code Online (Sandbox Code Playgroud)
我尝试使用@QueryMap而不是@RequestParam但@QueryMap不生成查询参数。
顺便说一句,@RequestParam Map<String, Object> params方法参数可以很好地生成动态查询参数。
但我想使用一个自定义对象,其中 feign 客户端可以从对象的属性生成动态查询参数。
Spring Cloud OpenFeign 提供了一个等效的@SpringQueryMap 注解,用于将POJO 或Map 参数注解为查询参数映射
所以你的代码应该是:
@RequestMapping(method = RequestMethod.GET, value = "/orders")
Pageable<Order> searchOrder2(@SpringQueryMap @ModelAttribute CustomObject customObject);
Run Code Online (Sandbox Code Playgroud)
spring-cloud-starter-feign支持 pojo 对象作为请求参数有一个未解决的问题。因此,我使用了一个请求拦截器,它从 feign 方法获取对象并从其字段创建 url 的查询部分。感谢@charlesvhe
public class DynamicQueryRequestInterceptor implements RequestInterceptor {
private static final Logger LOGGER = LoggerFactory.getLogger(DynamicQueryRequestInterceptor.class);
private static final String EMPTY = "";
@Autowired
private ObjectMapper objectMapper;
@Override
public void apply(RequestTemplate template) {
if ("GET".equals(template.method()) && Objects.nonNull(template.body())) {
try {
JsonNode jsonNode = objectMapper.readTree(template.body());
template.body(null);
Map<String, Collection<String>> queries = new HashMap<>();
buildQuery(jsonNode, EMPTY, queries);
template.queries(queries);
} catch (IOException e) {
LOGGER.error("IOException occurred while try to create http query");
}
}
}
private void buildQuery(JsonNode jsonNode, String path, Map<String, Collection<String>> queries) {
if (!jsonNode.isContainerNode()) {
if (jsonNode.isNull()) {
return;
}
Collection<String> values = queries.computeIfAbsent(path, k -> new ArrayList<>());
values.add(jsonNode.asText());
return;
}
if (jsonNode.isArray()) {
Iterator<JsonNode> it = jsonNode.elements();
while (it.hasNext()) {
buildQuery(it.next(), path, queries);
}
} else {
Iterator<Map.Entry<String, JsonNode>> it = jsonNode.fields();
while (it.hasNext()) {
Map.Entry<String, JsonNode> entry = it.next();
if (StringUtils.hasText(path)) {
buildQuery(entry.getValue(), path + "." + entry.getKey(), queries);
} else {
buildQuery(entry.getValue(), entry.getKey(), queries);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
}
| 归档时间: |
|
| 查看次数: |
4470 次 |
| 最近记录: |