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);
Я пробовал использовать @QueryMap вместо @RequestParam, но @QueryMap не генерирует параметры запроса.
Параметр метода Btw @RequestParam Map<String, Object> params отлично работает для создания параметра динамического запроса.
Но я хочу использовать настраиваемый объект, в котором воображаемый клиент может генерировать параметры динамического запроса из атрибутов объекта.
Спасибо за помощь @bhdrkn. Пожалуйста, посмотрите мой ответ.
spring-cloud-starter-feign имеет открытый вопрос для поддержки объекта pojo в качестве параметра запроса. Поэтому я использовал перехватчик запросов, который берет объект из метода симуляции и создает часть запроса 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);
}
}
}
}
}
От Документы Spring Cloud OpenFeign:
Spring Cloud OpenFeign provides an equivalent @SpringQueryMap annotation, which is used to annotate a POJO or Map parameter as a query parameter map
Итак, ваш код должен быть:
@RequestMapping(method = RequestMethod.GET, value = "/orders")
Pageable<Order> searchOrder2(@SpringQueryMap @ModelAttribute CustomObject customObject);
Это сработало, большое спасибо. Я удаляю @RequestParam, потому что он добавляет объект в url.
@mstzn, удалено
AFAIK, Spring не нуждается в аннотации RequestParam при привязке параметров запроса к настраиваемому DTO. (Ссылка). Вы пробовали без аннотации RequestParam? Этот контракт нормально работает на стороне сервера? Если этот интерфейс создавался только для генерации клиентов на стороне Feign, пробовали ли вы какой-либо другой формат? А что вы подразумеваете под динамическими параметрами запроса? AFAIK, в спецификации http нет такого понятия, как параметр динамического запроса.