Spring MVC: как указать, требуется ли переменная пути или нет?

Я делаю веб-сайт Spring. Для метода контроллера я могу использовать RequestParam, чтобы указать, требуется ли параметр или нет. Например:

@RequestMapping({"customer"}) 
public String surveys(HttpServletRequest request, 
@RequestParam(value="id", required = false) Long id,            
Map<String, Object> map)

Я хотел бы использовать PathVariable, например следующее:

@RequestMapping({"customer/{id}"}) 
public String surveys(HttpServletRequest request, 
@PathVariable("id") Long id,            
Map<String, Object> map) 

Как я могу указать, требуется ли переменная пути или нет? Мне нужно сделать его необязательным, потому что при создании нового объекта связанный идентификатор недоступен, пока он не будет сохранен.

Спасибо за помощь!


person curious1    schedule 23.07.2013    source источник
comment
Я думаю, вы спрашиваете о том же, что и этот вопрос variable" title="с помощью Spring 3 0 могу ли я сделать необязательную переменную пути"> stackoverflow.com/questions/4904092/   -  person TravJenkins    schedule 24.07.2013
comment
Возможный дубликат С Spring 3.0, могу ли я сделать необязательная переменная пути?   -  person Oleg Estekhin    schedule 03.08.2017


Ответы (6)


Невозможно сделать его необязательным, но вы можете создать два метода, один из которых имеет аннотацию @RequestMapping({"customer"}), а другой — @RequestMapping({"customer/{id}"}), а затем действовать соответствующим образом в каждом из них.

person Tristan    schedule 23.07.2013
comment
Тристан, я выбрал пост VTTom в качестве ответа, чтобы помочь всем, кто читает этот вопрос. Ты был прав. - person curious1; 18.12.2015
comment
Возможно, посмотрите некоторые другие ответы (@curious1, не стесняйтесь принять один из других ответов). - person rogerdpack; 16.04.2019
comment
можно использовать так: @PatchMapping(path = {"/{procurementInitId}/updateLinkedPurchase/{purchaseId}", "/{procurementInitId}/updateLinkedPurchase"}, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) public HttpEntity<?> updateLinkedPurchase( @PathVariable(name = "procurementInitId") Integer procurementInitId, @PathVariable(name = "purchaseId", required = false) Integer purchaseId) { - person Michael Gaev; 03.07.2020

Решение VTTom верное, просто измените переменную "value" на массив и перечислите все возможные URL-адреса: value={"/ ", "/{я бы}"}

@RequestMapping(method=GET, value={"/", "/{id}"})
public void get(@PathVariable Optional<Integer> id) {
  if (id.isPresent()) {
    id.get()   //returns the id
  }
}
person Martin Cmarko    schedule 18.12.2015
comment
Обратите внимание, что для этого требуются Spring 4.1+ и Java 1.8. - person Aniket Thakur; 08.01.2016
comment
Когда вы используете "/", вы получите 404 для адреса http://.../foo/bar и ответ для http://.../foo/bar/. Я использовал пустую строку "" в качестве первого значения. - person csharpfolk; 06.11.2016
comment
Обратите внимание, что начиная с Spring 4.3.3 вы также можете использовать @PathVariable(required = false) и получить значение null, если переменная отсутствует. - person Nicolai Ehemann; 05.10.2017
comment
@NicolaiEhemann, спасибо за информацию, которая верна. Но это только не работает. Это может быть как @RequestMapping(value = {"foo", "foo/{bar}"}) и @PathVariable(required = false) - person Ram; 04.11.2017
comment
Мой комментарий является лишь дополнением к ответу (который должен быть принятым ответом), поскольку он предоставляет альтернативу тому, чтобы сделать идентификатор необязательным. - person Nicolai Ehemann; 06.03.2018

Я знаю, что это старый вопрос, но поиск «необязательная переменная пути» ставит этот ответ высоко, поэтому я подумал, что стоит указать, что, поскольку Spring 4.1 использует Java 1.8, это возможно с использованием класса java.util.Optional.

примером может быть (обратите внимание, что значение должно перечислять все потенциальные маршруты, которые должны совпадать, т. е. с переменной пути id и без нее. Реквизит @martin-cmarko для указания на это)

@RequestMapping(method=GET, value={"/", "/{id}"})
public void get(@PathVariable Optional<Integer> id) {
  if (id.isPresent()) {
    id.get()   //returns the id
  }
}
person VTTom    schedule 27.08.2015
comment
Кто-нибудь может проверить, что это работает? Я получаю 404, когда пытаюсь получить доступ к этому пути без идентификатора (Spring MVC 4.1.4, Java 1.8.0_66). - person Wonko; 03.12.2015
comment
Да, это не сработает, так как путь без идентификатора не будет соответствовать этому контроллеру. - person Aniket Thakur; 08.01.2016
comment
Спасибо за упоминание имени пакета для дополнительного класса. - person Binita Bharati; 17.10.2016
comment
Эта часть value={"/", "/{id}"} заставляет его работать на маршрутах с идентификатором и без него. - person sr9yar; 09.05.2019

Ответ VTToms не будет работать, так как без идентификатора в пути он не будет сопоставлен (т.е. не будет найден соответствующий HandlerMapping) и, следовательно, контроллер не будет поражен. Скорее вы можете сделать -

@RequestMapping({"customer/{id}","customer"}) 
public String surveys(HttpServletRequest request, @PathVariable Map<String, String> pathVariablesMap, Map<String, Object> map) {
    if (pathVariablesMap.containsKey("id")) {
        //corresponds to path "customer/{id}"
    }
    else {
        //corresponds to path "customer"
    }
}

Вы также можете использовать java.util.Optional, о котором упоминали другие, но для этого требуется Spring 4.1+ и Java 1.8..

person Aniket Thakur    schedule 08.01.2016

Существует проблема с использованием 'Optional'(@PathVariable Optional id) или Map (@PathVariable Map pathVariables) в том, что если вы затем попытаетесь создать ссылку HATEOAS, вызвав метод контроллера, это не удастся, потому что Spring-hateoas кажется предварительным. java8 и не поддерживает «Необязательно». Также не удается вызвать какой-либо метод с аннотацией @PathVariable Map.

Вот пример, демонстрирующий отказ Map

   @RequestMapping(value={"/subs","/masterclient/{masterclient}/subs"}, method = RequestMethod.GET)
   public List<Jobs>  getJobListTest(
         @PathVariable  Map<String, String> pathVariables,
         @RequestParam(value="count", required = false, defaultValue = defaultCount) int count) 
   {

      if (pathVariables.containsKey("masterclient")) 
      {
         System.out.println("Master Client = " + pathVariables.get("masterclient"));
      } 
      else 
      {
         System.out.println("No Master Client");
      }




  //Add a Link to the self here.
  List list = new ArrayList<Jobs>();
  list.add(linkTo(methodOn(ControllerJobs.class).getJobListTest(pathVariables, count)).withSelfRel());

  return list;

}

person Ashutosh    schedule 25.10.2016

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

Поскольку В Spring MVC 4.3.3 представлен Веб-улучшения,

@PathVariable(required = false) //true is default value

законно и возможно.

person Giorgi Tsiklauri    schedule 05.02.2021