Что такое неоднозначное отображение в Spring?

создать личный бренд в качестве инженера-программиста Изучение

Spring — это слабосвязанная среда Java, означающая, что все объекты не зависят друг от друга и могут легко управляться и модифицироваться. Базовая архитектура в каждом весеннем проекте включает использование контроллеров или REST-контроллеров, любого инструмента сборки, такого как maven, gradle или Groove, СУБД, сервисные уровни и т. д. Кто-то, кто только начинает работать с Spring Framework, скорее всего, столкнется с неоднозначным сопоставлением. При сопоставлении запроса с конкретным контроллером есть вероятность возникновения двусмысленности, если не позаботиться о некоторых вещах.

1. Использование «имя =» вместо «значение =»

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

Java

@RequestMapping(name = "/getName", method = GET)

Свойство name аннотации @RequestMapping только предоставляет имя для вашего сопоставления, но фактически не определяет сопоставление, что приводит к неоднозначному сопоставлению. Решением этой проблемы было бы просто заменить атрибут «имя» атрибутом «значение» следующим образом:

Java

// Changed 'name' to 'value'  
@RequestMapping(value = "/getName", method = GET)

Давайте рассмотрим другой распространенный вариант использования, когда возникает эта двусмысленность:

2. Нет родительского сопоставления в Rest Controller

Допустим, в вашем проекте есть 2 контроллера, а именно: HomeController и TaskController. А как мы знаем, под каждый контроллер мы определили различные маппинги для каждого запроса, полученного от клиента. Теперь, возможно, вы забыли добавить сопоставление поверх вашего контроллера или в сопоставлении поверх вашего контроллера есть опечатка.

Потому что, когда у нас есть более 1 контроллера, лучше добавить родительское сопоставление к контроллеру, и причина этого может заключаться в том, что вы определили так много @RequestMappings внутри контроллера, и некоторые или один из них одинаковы в оба контроллера, тогда это создаст двусмысленность в структуре Spring, потому что он не сможет решить, какому контроллеру следует делегировать вызов! Отсюда снова возникает двусмысленность.

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

HomeController.java:

Java

package com.geeksforgeeks.ambiguousmapping.controller;
 
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
@RestController
public class HomeController {
   
    @RequestMapping(value = "/writeArticles")
    public String writeArticles() {
        return "5 Articles written on GeeksForGeeks !";
    }
     
    @RequestMapping(value = "/doLaundry")
    public String doLaundry() {
        return "Laundry done at 5 PM !";
    }

TaskController.java:

Java

package com.geeksforgeeks.ambiguousmapping.controller;
 
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
@RestController
public class TaskController {
   
    @RequestMapping(value = "/writeArticles")
    public String writetwoMoreArticles() {
        return "2 More Articles written !";
    }
     
    @RequestMapping(value = "/doLaundry")
    public String checkLaundry() {
        return "Laundry already done @5 PM !";
    }
}

Объяснение кода:

Мы создали 2 класса и пометили их аннотацией @Controller, поэтому Spring будет рассматривать их как контроллеры, а @Controller наследуется от @Component, поэтому этот класс будет сканироваться во время сканирования компонентов. И внутри обоих контроллеров мы определили разные методы, имеющие одно и то же сопоставление запросов, что может вызвать двусмысленность. (Имена методов не имеют значения, здесь вызов решается с помощью @RequestMappings). Теперь, когда мы запускаем наше приложение Spring Boot, оно будет вызывать следующие исключения:

1. BeanCreationException

2. Вызвано: IllegalStateException

См. выделенный текст на следующем изображении: «Неоднозначное сопоставление. Не удается сопоставить метод «taskController»

выделенный текст на следующем изображ

Решение неоднозначного сопоставления

Давайте сделаем это шаг за шагом:

Шаг 1. Перейдите в Spring Initilizr и создайте проект, используя зависимость — Spring WEB.

Шаг 2. Создайте новый пакет. Убедитесь, что имя пакета такое же, как у предыдущего пакета, и добавьте в конце.controller. Потому что Spring рекурсивно сканирует все пакеты.

Шаг 3. Затем создайте 2 новых класса внутри этого пакета, а именно: HomeController и TaskController, и соответственно вставьте приведенный ниже код.

В приведенном ниже коде мы преодолели проблему неоднозначного сопоставления, просто предоставив еще один RequestMapping поверх нашего класса контроллера, который помог бы провести различие между двумя контроллерами и сопоставить запрос с соответствующим контроллером REST. Вам просто нужно добавить еще один @RequestMapping поверх вашего RestController. Давайте посмотрим на код:

HomeController.java:

Java

package com.geeksforgeeks.ambiguousmapping.controller;
 
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
@RestController
@RequestMapping(value = "/home")
public class HomeController {
   
    @RequestMapping(value = "/writeArticles")
    public String writeArticles() {
        return "5 Articles written on GeeksForGeeks !";
    }
     
    @RequestMapping(value = "/doLaundry")
    public String doLaundry() {
        return "Laundry done at 5 PM !";
    }
}

TaskController.java:

Java

package com.geeksforgeeks.ambiguousmapping.controller;
 
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
@RestController
@RequestMapping(value = "/task")
public class TaskController {
   
    @RequestMapping(value = "/writeArticles")
    public String writetwoMoreArticles() {
        return "2 More Articles written !";
    }
     
    @RequestMapping(value = "/doLaundry")
    public String checkLaundry() {
        return "Laundry already done @5 PM !";
    }
}

Как видите, мы добавили еще один @RequestMapping поверх обоих наших остальных контроллеров, которые теперь будут вызываться соответствующим образом, и не будет никакой двусмысленности. Итак, теперь давайте перейдем к браузеру и проверим это. Перейдите по адресу: localhost:8080/home/writeArticles и localhost:8080/task/writeArticles (или на настроенный вами порт вместо 8080)

Вы получите следующий вывод:

localhost 8090 home writeArticles (я настроил свой порт

URL: localhost:8090/home/writeArticles (я настроил свой порт на 8090, поэтому я использую 8090)

 настроил свой порт на 8090, поэтому я 

URL: localhost:8090/task/writeArticles (я настроил свой порт на 8090, поэтому я использую 8090)

Читайте также:  Объясните Explain Type в TypeScript
Оцените статью
bestprogrammer.ru
Добавить комментарий