Перейти к основному содержимому

Добавить префикс ко всем контроллерам загрузки Spring

· 5 мин. чтения

1. Введение

В приложениях Spring Boot каждый контроллер может иметь собственное сопоставление URL-адресов. Это позволяет одному приложению легко предоставлять конечные веб-точки в нескольких местах. Например, мы можем сгруппировать наши конечные точки API в логические группы, такие как внутренние и внешние.

Однако могут быть случаи, когда мы хотим, чтобы все наши конечные точки имели общий префикс. В этом руководстве мы рассмотрим различные способы использования общего префикса для всех контроллеров Spring Boot.

2. Контекст сервлета

Основным компонентом, отвечающим за обработку веб-запросов в приложениях Spring, является DispatcherServlet . Настраивая этот компонент, мы получаем достаточный контроль над маршрутизацией запросов.

Давайте рассмотрим два разных способа настройки DispatcherServlet , которые сделают все конечные точки нашего приложения доступными по общему префиксу URL.

2.1. Весенняя фасоль

Первый способ — ввести новый bean-компонент Spring:

@Configuration
public class DispatcherServletCustomConfiguration {

@Bean
public DispatcherServlet dispatcherServlet() {
return new DispatcherServlet();
}

@Bean
public ServletRegistrationBean dispatcherServletRegistration() {
ServletRegistrationBean registration = new ServletRegistrationBean(dispatcherServlet(), "/api/");
registration.setName(DispatcherServletAutoConfiguration.DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME);
return registration;
}
}

Здесь мы создаем компонент ServletRegistrationBean , который обертывает компонент DispatcherServlet . Обратите внимание, что мы предоставляем явный базовый URL-адрес /api/ . Это означает, что все наши конечные точки должны быть доступны по этому базовому префиксу URL .

2.2. Свойства приложения

Мы также можем добиться того же результата, просто используя свойства приложения. В версиях Spring Boot после 2.0.0 мы бы добавили в наш файл application.properties следующее:

server.servlet.contextPath=/api

До этой версии имя свойства немного отличалось:

server.contextPath=/api

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

2.3. Плюсы и минусы

Основное преимущество этих двух подходов является также и основным недостатком: они влияют на каждую конечную точку в приложении.

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

3. Аннотации

Еще один способ добавить префикс ко всем контроллерам в приложении Spring — использовать аннотации. Ниже мы рассмотрим два разных подхода.

3.1. SpEL

Первый способ предполагает использование Spring Expression Language (SpEL) со стандартной аннотацией @RequestMapping . При таком подходе мы просто добавляем свойство к каждому контроллеру, которому хотим добавить префикс:

@Controller
@RequestMapping(path = "${apiPrefix}/users")
public class UserController {

}

Затем мы просто указываем значение свойства в нашем application.properties :

apiPrefix=/api

3.2. Пользовательская аннотация

Другой способ добиться этого — создать собственную аннотацию:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
@RequestMapping("/api/")
public @interface ApiPrefixController {
@AliasFor(annotation = Component.class)
String value() default "";
}

Затем нам нужно только применить аннотацию к каждому контроллеру, к которому мы хотим добавить префикс:

@Controller
@ApiPrefixController
public class SomeController {
@RequestMapping("/users")
@ReponseBody
public String getAll(){
// ...
}
}

3.3. Плюсы и минусы

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

4. Переадресация на стороне сервера

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

Для начала напишем простой контроллер с двумя конечными точками:

@Controller
class EndpointController {
@GetMapping("/endpoint1")
@ResponseBody
public String endpoint1() {
return "Hello from endpoint 1";
}

@GetMapping("/endpoint2")
@ResponseBody
public String endpoint2() {
return "Hello from endpoint 2";
}
}

Затем мы создаем новый контроллер на основе нужного нам префикса:

@Controller
@RequestMapping("/api/endpoint")
public class ApiPrefixController {

@GetMapping
public ModelAndView route(ModelMap model) {
if(new Random().nextBoolean()) {
return new ModelAndView("forward:/endpoint1", model);
}
else {
return new ModelAndView("forward:/endpoint2", model);
}
}
}

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

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

> curl http://localhost:8080/api/endpoint
Hello from endpoint 2
> curl http://localhost:8080/api/endpoint
Hello from endpoint 1
> curl http://localhost:8080/api/endpoint
Hello from endpoint 1
> curl http://localhost:8080/api/endpoint
Hello from endpoint 2
> curl http://localhost:8080/api/endpoint
Hello from endpoint 2

Главное преимущество этого подхода в том, что он очень мощный. Мы можем применить любую логику, которую хотим определить, как пересылать запрос: URL-адрес, метод HTTP, заголовки HTTP и т. д.

5. Вывод

В этой статье мы узнали о нескольких способах применения общего префикса к каждому контроллеру в приложении Spring. Как и в большинстве решений, у каждого подхода есть свои плюсы и минусы, которые следует тщательно взвесить перед внедрением.

Как всегда, примеры кода в этом руководстве можно найти на GitHub .