Рубрики
Без рубрики

Весенние аннотации: @RequestMapping и его варианты

Автор оригинала: David Landup.

Вступление

Если вы читали что-нибудь о Spring , разрабатывали проект или даже отдаленно интересовались тем, как он работает, вы ознакомились с аннотацией @RequestMapping .

Это одна из основных аннотаций в Spring, которая сопоставляет HTTP-запросы (URL-адреса) с методами:

@RequestMapping("/")
public void helloWorld() {
    return "Hello World!";
}

Это позволяет нам запускать методы и фрагменты кода каждый раз, когда конечный пользователь обращается к конечной точке с HTTP-запросом. В этом случае это простое корневое сопоставление, которое возвращает строку “Привет, мир!” при попадании в корневую конечную точку.

Аннотация @RequestMapping

Сама аннотация @RequestMapping предлагает больше, чем показано в предыдущем примере. Давайте кратко рассмотрим некоторые из основных вариантов использования аннотации.

@Области сопоставления запросов

Сопоставление может быть назначено на уровне класса или на уровне метода:

@RequestMapping("/admin")
public class AdminController() {
    @RequestMapping("/adminPanel")
    public String adminPanel() {
        return "adminPanel.html";
    }

    @RequestMapping("/statistics")
    public String statistics() {
        return "statistics.html";
    }
}

Здесь сопоставление /admin назначается на уровне класса, тогда как сопоставления /Панели администратора и /статистики назначаются методам. Сопоставление на уровне классов будет использоваться в качестве префикса для всех этих сопоставлений на уровне методов: /администратор/Панель администратора и /администратор/статистика .

Таким образом, мы можем разделить наше приложение на логические части. Например, вся логика, связанная с администратором, будет находиться за стеной /admin , в которую могут входить только пользователи-администраторы. Все пользователи, не являющиеся администраторами, будут перенаправлены на клиентскую часть приложения.

Несколько сопоставлений для каждого метода

При необходимости мы можем назначить несколько сопоставлений одному методу, например:

@RequestMapping({"/", "/index", "/home"})
public void helloWorld() {
    return "Hello World!";
}

Попадание в любую из этих конечных точек приведет к тому, что метод HelloWorld() обработает наш запрос.

Методы запроса

Наиболее распространенным используемым атрибутом является атрибут method , Который позволяет нам указывать и сужать метод запроса, который обрабатывает наш метод ( GET , POST , DELETE и т.д.):

@RequestMapping(value = "/addProduct", method = RequestMethod.POST)
public String addProductPost(@ModelAttribute("product") Product product) {
    // some code
}

Если мы не указываем метод запроса, по умолчанию используется метод запроса GET .

Заголовки запросов

Мы можем дополнительно указать сопоставление, определив один или несколько заголовков. В этом случае метод HelloWorld() обработает запрос, если его тип содержимого является текст/обычный или текст/html :

@RequestMapping(value = "/header", headers = {"content-type=text/plain", "content-type=text/html"})
String helloWorld() {
    return "Hello World!";
}

Переменные Пути

Многие веб-сайты полагаются на переменные пути для демонстрации определенного продукта, страницы, профиля и т. Д. конечному пользователю, например example.com/viewProduct/324 , где 324 является идентификатором продукта:

@RequestMapping("/viewProduct/{productId}")
public String viewProduct(@PathVariable int productId, Model model) {
    Product product = productService.getProductById(productId);
    model.addAttribute("product", product);

    return "viewProduct";
}

Здесь, после сопоставления, мы заключаем переменную path в фигурные скобки ( {} ) и присваиваем это значение нашему идентификатору продукта . Об этом заботится для нас аннотация @PathVariable . Затем мы можем найти продукт с помощью нашего Сервиса продуктов и показать его конечному пользователю.

Конечно, тот же подход может быть использован и для других переменных, таких как:

@RequestMapping("/users/{username}")
public String viewUser(@PathVariable("username") String username) {
    Profile profile = profileService.getProfileByUsername(username);
    // rest of the code
}

Параметры запроса

Очень похоже на переменные пути, многие приложения полагаются на параметры запроса для изменения состояния страницы. Мы можем использовать аннотацию @RequestParam для привязки параметра запроса к переменной:

@RequestMapping("/login")
public String login(@RequestParam(value = "error", required = false) String error, @RequestParam(value = "logout", required = false) String logout, Model model) {

    if (error != null) {
        model.addAttribute("error", "Wrong username or password!");
    }
    if (logout != null) {
        model.addAttribute("msg", "You have successfully logged out!");
    }
    return "login";
}

Производимые и расходуемые материалы

Используя аннотацию @RequestMapping , мы также можем создавать или использовать типы носителей. Для создания типа носителя, такого как “JSON”, вы можете использовать атрибут производит вместе с аннотацией @ResponseBody , в то время как для использования типа носителя вы можете использовать атрибут потребляет :

Git Essentials

Ознакомьтесь с этим практическим руководством по изучению Git, содержащим лучшие практики и принятые в отрасли стандарты. Прекратите гуглить команды Git и на самом деле изучите это!

@RequestMapping("/annotations")
public class SomeController {
    @RequestMapping(value = "/produce", produces = {"application/json"})
    @ResponseBody
    String produces() {
        return "Here's how you use the 'produces' attribute";
    }

    @RequestMapping(value = "/consume", consumes = {"application/JSON", "application/XML"})
    String consume() {
        return "Here's how you use a 'consume' attribute";
    }
}

Составленные варианты сопоставления @RequestMapping

Одно сопоставление может соответствовать различным методам, если мы гарантируем отсутствие двусмысленности в отношении того, какой метод должен обрабатывать ту или иную версию сопоставления.

У нас может быть несколько методов с одним и тем же отображением, если их метод запроса отличается:

@RequestMapping("/hello")
public String hello() {
    return "hello";
}

@RequestMapping(value = "/hello", method = RequestMethod.POST)
public String helloPost() {
    return "hello post";
}

@RequestMapping(value = "/hello", method = RequestMethod.PUT)
public String helloGet() {
    return "hello put";
}

@RequestMapping(value = "/hello", method = RequestMethod.DELETE)
public String helloDelete() {
    return "hello delete";
}

Этот же метод имеет 4 различных варианта:

  • По умолчанию (ПОЛУЧИТЬ)
  • ПОСТ
  • КЛАСТЬ
  • УДАЛИТЬ

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

Для этой цели мы познакомились с несколькими новыми аннотациями, вариантами @RequestMapping :

  • @GetMapping
  • @PostMapping
  • @Удаление сопоставления
  • @PutMapping
  • @@Сопоставление путей

Существуют буквально только версии ярлыков для приведенных выше сопоставлений, где @PostMapping("/привет") равно @RequestMapping(значение="/привет", метод запроса.СООБЩЕНИЕ) .

Более подробно рассмотрев, как определяются эти аннотации, мы можем получить четкое представление о том, что они делают:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@RequestMapping(method = RequestMethod.GET)
public @interface GetMapping {

    @AliasFor(annotation = RequestMapping.class)
    String name() default "";

    @AliasFor(annotation = RequestMapping.class)
    String[] value() default {};

    @AliasFor(annotation = RequestMapping.class)
    String[] path() default {};

    @AliasFor(annotation = RequestMapping.class)
    String[] params() default {};

    @AliasFor(annotation = RequestMapping.class)
    String[] headers() default {};

    @AliasFor(annotation = RequestMapping.class)
    String[] produces() default {};
}

Тем не менее, мы можем переписать приведенные выше примеры:

@GetMapping
public String hello() {
    return "hello";
}

@PostMapping
public String helloPost() {
    return "hello post";
}

@PutMapping
public String helloGet() {
    return "hello put";
}

@DeleteMapping
public String helloDelete() {
    return "hello delete";
}

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

Вывод

@RequestMapping – это квинтэссенция аннотации в Spring framework, которая позволяет нам сопоставлять HTTP-запросы с методами, которые мы хотели бы запустить.

Начиная с весны 4.3, предпочтительно и рекомендуется использовать ярлыки, созданные для этой аннотации, для более читаемой и менее подробной кодовой базы.