Один из распространённых способов передачи параметров запроса — в виде частей адреса запроса. Например, у нас есть страница с контактными данными человека, её адрес выглядит следующим образом:
http://example.com/person/contacts?personId=42
Но, если передать идентификатор человека не параметром personId, а частью адреса запроса, то получится что-то вроде
http://example.com/person/42/contacts
Что выглядит намного понятнее и удобнее.
Для работы с параметрами, передаваемыми через адрес запроса в Spring WebMVC используется аннотация @PathVariable.
Передача одного параметра через адрес
Допустим, у нас есть следующий контроллер:
1 2 3 4 5 6 7 8 |
@RequestMapping("example") @RestController public ExampleController { @GetMapping("{name}") public String greeting(@PathVariable String name) { return "Hello, " + name + "!"; } } |
Из Результатом обращения к http://localhost:8080/example/Alex будет строка «Hello, Alex!». В качестве аргумента аннотации @PathVariable можно передать имя части адреса, который будет извлечён в помеченный аттрибут:
1 2 3 4 |
@GetMapping("{name}") public String greeting(@PathVariable("name") String name) { return "Hello, " + name + "!"; } |
Но, если вы собираете проект с отладочной информацией или флагом -parameters, в этом необходимости нет.
Передача нескольких параметров через адрес
Так же можно передавать в метод сколько угодно параметров:
1 2 3 4 |
@GetMapping("{firstname}/{lastname}") public String greeting(@PathVariable String firstname, @PathVariable String lastname) { return "Hello, " + firstname + " " + lastname + "!"; } |
Альтернативный вариант — передача параметров в виде Map:
1 2 3 4 |
@GetMapping("{firstname}/{lastname}") public String greeting(@PathVariable Map<String, String> pathVars) { return "Hello, " + pathVars.get("firstname") + " " + pathVars.get("lastname") + "!"; } |
Регулярные выражения
Допустим, у вас есть маппинги /person/create и /person/{id}, где id — integer. Объявление таких маппингов приведёт к их конфликту, так как как create может быть воспринято как значение id. Данную проблему можно решить при помощи регулярных выражений. В таком случае в шаблоне адреса после идентификатора параметра ставится двоеточие и после него — желаемое регулярное выражение, например:
1 2 3 4 5 6 7 8 9 |
@GetMapping("{id:\\d+}") public ModelAndView view(@PathVariable int id) { //... } @GetMapping("create") public ModelAndView create() { //... } |
Интеграция с Spring Data
Интеграция Spring Data и Spring WebMVC позволяет упростить работу с репозиториями в контроллерах, предоставляя возможность в качестве атрибута, помеченного @PathVariable получать экземпляр класса-сущности. Допустим, у вас есть метод, возвращающий по запросу какую-нибудь сущность:
1 2 3 4 5 6 |
private PersonRepository personRepository; @GetMapping("{person:\\d+}") public ResponseEntity get(@PathVariable("person") int id) { return ResponseEntity.ok(personRepository.findOne(id)); } |
Этот метод легко можно упростить до
1 2 3 4 |
@GetMapping("{person:\\d+}") public ResponseEntity get(@PathVariable Person person) { return ResponseEntity.ok(person); } |
Spring Data за нас
- Находит в шаблоне адреса параметр person
- Определяет, что помеченный аннотацией @PathVariable атрибут person имеет тип Person
- Ищет репозиторий, работающий с типом Person
- У найденного репозитория вызывает метод findOne с запрашиваемым идентификатором
- Передаёт результат в атрибут person