Множественное значение присваивания запроса с переменными пути

@RequestMapping(value = {"/abcd", "/employees/{value}/{id}"})
public String getEmployees(
      @PathVariable(value = "value") String val, 
      @PathVariable(value = "id") String id,
      @RequestParam(value = "param", required = false) String value) {
        // ********

}

Для одного URL-адреса я передаю переменную пути, а для одного - нет. Но я хочу, чтобы оба URL-адреса попадали в один и тот же API. Как я могу это достичь?

Ответ 1

Теперь вы можете иметь необязательные переменные пути через поддержку Java 8 Необязательно. Требуется как минимум версия Spring 4.x.

@RequestMapping({"/abcd", "/employees/{value}/{id}"})
public String getEmployees(
    @PathVariable("value") Optional<String> val, 
    @PathVariable("id") Optional<String> id,
    @RequestParam("param") Optional<String> value
) {
    // ********
}

Примечание: это не работает с необязательными примитивами (OptionalInt и т.д.).

Ответ 2

У нас не может быть optional path variables, у вас могут быть два метода контроллера, которые могут вызывать одну и ту же службу.

Первый метод

@RequestMapping("/abcd")
public String getEmployees(@RequestParam(value="param", required=false)String value){}

Второй метод

@RequestMapping("/employees/{value}/{id}")
public String getEmployees(@PathVariable(value="value") String val, @PathVariable(value="id") String id, @RequestParam(value="param", required=false) String value){}

Для @RequestParam мы можем использовать

@RequestParam(value="somevalue",required=false)

для необязательного params, а не pathVariable

Ответ 3

Просто нашел способ сделать это, не используя несколько методов.

Сначала создайте простой класс для хранения переменных пути:

public class EmployeesRequest {
  private String value;
  private String id;

  public String getValue() {
    return this.value;
  }

  public void setValue(String value) {
    this.value = value;
  }

  public String getId() {
    return this.id;
  }

  public void setId(String id) {
    this.id = id;
  }
}

Затем определите свой метод контроллера следующим образом:

@RequestMapping(value={
  "/abcd",
  "/employees/{value}/{id}"
})
public String getEmployees(@RequestParam(value="param", required=false) String param,
                           EmployeesRequest request) {
  if (request.getValue() != null) {
    // do something
  } else {
    // do something else
  }
}

Spring автоматически сопоставляет любые переменные пути, доступные для класса EmployeesRequest. Spring также сделает это для любых параметров запроса, чтобы вы могли упростить ситуацию, добавив параметр запроса в EmployeesRequest:

public class EmployeesRequest {
  private String value;
  private String id;
  private String param;

  public String getValue() {
    return this.value;
  }

  public void setValue(String value) {
    this.value = value;
  }

  public String getId() {
    return this.id;
  }

  public void setId(String id) {
    this.id = id;
  }

  public String getParam() {
    return this.param;
  }

  public void setParam(String param) {
    this.param = param;
  }
}

И наконец:

@RequestMapping(value={
  "/abcd",
  "/employees/{value}/{id}"
})
public String getEmployees(EmployeesRequest request) {
  if (request.getValue() != null) {
    // do something
  } else {
    // do something else
  }
}

Дополнительным преимуществом этого решения является то, что теперь вы можете поддерживать как переменные, так и параметры запроса. Значение всех из них было бы правильным:

  • /abcd
  • /abcd?param=123
  • /abcd?value=123&id=456&param=789
  • /employees/123/456
  • /employees/123/456?param=123

Ответ 4

У вас не может быть необязательного PathVariables в Spring Mvc. Просто создайте 2 метода для двух Request mappings.

@RequestMapping("/abcd")
public String getEmployees(@RequestParam(value="param", required=false)String value){}


@RequestMapping("/employees/{value}/{id}")
public String getEmployees(@PathVariable(value="value") String val,PathVariable(value="id")String id,@RequestParam(value="param", required=false)String value){}

Ответ 5

У меня была похожая проблема, и я нашел это решение:

@GetMapping(value = {"/clients/page", "/clients/page/{page}"})
public Page<Client> index(@PathVariable Optional<Integer> page) {
   PageRequest pageRequest = page.map(integer -> PageRequest.of(integer, 4))
   .orElseGet(() -> PageRequest.of(0, 4));
      return clientService.showAll(pageRequest);
}

Intellij помог мне получить такой компактный результат. Хотя Intellij выкинуть это сообщение:

'' Сообщает о любом использовании java.util.Optional, java.util.OptionalDouble, java.util.OptionalInt, java.util.OptionalLong или com.google.common.base.Optional в качестве типа для поля или параметра. Необязательный был разработан, чтобы обеспечить ограниченный механизм для возвращаемых типов библиотечного метода, где должен был быть ясный способ представить "нет результата". Использование поля с типом java.util.Optional также проблематично, если класс должен быть Serializable, а java.util.Optional - нет. ''

Если честно, я новичок в этом бизнесе и не совсем понимаю, что говорит мне IDE. Если кто-то с большим опытом может помочь прояснить это сообщение было бы здорово.