Spring Boot RestController: перехватывает входящие запросы - PullRequest
0 голосов
/ 25 апреля 2019

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

В частности, я хочу и должен получить доступ к данным запросов (т.е. RequestEntity до того, как запрос будет обработанконтроллер остальных. В некотором смысле «перехватывает» запрос до того, как он будет обработан контроллером, и только затем позволяет контроллеру обрабатывать его.

Рассмотрим следующий код:

@RestController
@RequestMapping("/")
public class MyController {

    @GetMapping("/")
    @ResponseBody
    public ResponseEntity<String> getSomething(RequestEntity requestEntity) {

        MyClass.doStuffWithRequestEntity(requestEntity);
        // ...

Что теперьМне нужно, чтобы ExternalClass.doStuffWithRequestEntity(requestEntity); вызывался без необходимости явного вызова. Возможно ли иметь какой-либо метод в некотором вызываемом классе (с передачей ему RequestEntity!) Без необходимости явного вызова?

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

Я бы подумал что-то вроде

class RestController {
    @RestController
    @RequestMapping("/")
    public class MyController {

        @GetMapping("/")
        @ResponseBody
        public ResponseEntity<String> getSomething() {

            MyClass x = MyClass.getInstanceCreatedByInterceptor();
        }
    }
}

и

class Interceptor {
    public void doStuffWithRequestEntity(requestEntity) {

        MyClass x = new MyClass();
        x.fillObjectWithData();
    }
}

выполняется раньше.

Идея состоит в том, что КАЖДЫЙ (!) Входящий запрос анализируется и его содержимое декодируется сПрограммисту контроллера отдыха приходится вообще об этом заботиться.Они должны просто получить доступ к данным через / из экземпляра MyClass.

Есть ли способ сделать это?

Ответы [ 3 ]

2 голосов
/ 25 апреля 2019

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

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

@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {

  @Autowired 
  HandlerInterceptor customInjectedInterceptor;

  @Override
  public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(...)
    ... 
    registry.addInterceptor(customInjectedInterceptor).addPathPatterns("/**");
  }
}

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

Начиная с пружины 5.xx или загрузочной пружины 2 и далее , WebMvcConfigurerAdapter помечен как устаревший. Интерфейс WebMvcConfigurer (реализованный абстрактным классом WebMvcConfigurerAdapter), начиная с Spring 5, содержит реализации по умолчанию для всех своих методов. В результате абстрактный класс адаптера был помечен как устаревший. Вы можете принять его, если хотите, следующим образом:

@Configuration
public WebConfig implements WebMvcConfigurer {
    // ...
}
1 голос
/ 29 апреля 2019

Для всех тех, кто сталкивается с таким же или похожим вопросом, вот рабочий минимальный пример для приложения SpringBoot (2.1.4) с перехватчиком:

Minimal.java:

@SpringBootApplication
public class Minimal
{
    public static void main(String[] args)
    {
        SpringApplication.run(Minimal.class, args);
    }
}

MinimalController.java:

@RestController
@RequestMapping("/")
public class Controller
{
    @GetMapping("/")
    @ResponseBody
    public ResponseEntity<String> getMinimal()
    {
        System.out.println("MINIMAL: GETMINIMAL()");

        return new ResponseEntity<String>("returnstring", HttpStatus.OK);
    }
}

Config.java:

@Configuration
public class Config implements WebMvcConfigurer
{
    //@Autowired
    //MinimalInterceptor minimalInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry)
    {
        registry.addInterceptor(new MinimalInterceptor());
    }
}

MinimalInterceptor.java:

public class MinimalInterceptor extends HandlerInterceptorAdapter
{
    @Override
    public boolean preHandle(HttpServletRequest requestServlet, HttpServletResponse responseServlet, Object handler) throws Exception
    {
        System.out.println("MINIMAL: INTERCEPTOR PREHANDLE CALLED");

        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception
    {
        System.out.println("MINIMAL: INTERCEPTOR POSTHANDLE CALLED");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception exception) throws Exception
    {
        System.out.println("MINIMAL: INTERCEPTOR AFTERCOMPLETION CALLED");
    }
}

работает как рекламируется

Вывод даст вам что-то вроде:

> Task :Minimal.main()

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.1.4.RELEASE)

2019-04-29 11:53:47.560  INFO 4593 --- [           main] io.minimal.Minimal                       : Starting Minimal on y with PID 4593 (/x/y/z/spring-minimal/build/classes/java/main started by x in /x/y/z/spring-minimal)
2019-04-29 11:53:47.563  INFO 4593 --- [           main] io.minimal.Minimal                       : No active profile set, falling back to default profiles: default
2019-04-29 11:53:48.745  INFO 4593 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2019-04-29 11:53:48.780  INFO 4593 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2019-04-29 11:53:48.781  INFO 4593 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.17]
2019-04-29 11:53:48.892  INFO 4593 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2019-04-29 11:53:48.893  INFO 4593 --- [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1269 ms
2019-04-29 11:53:49.130  INFO 4593 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2019-04-29 11:53:49.375  INFO 4593 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2019-04-29 11:53:49.380  INFO 4593 --- [           main] io.minimal.Minimal                       : Started Minimal in 2.525 seconds (JVM running for 2.9)
2019-04-29 11:54:01.267  INFO 4593 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2019-04-29 11:54:01.267  INFO 4593 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2019-04-29 11:54:01.286  INFO 4593 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 19 ms
MINIMAL: INTERCEPTOR PREHANDLE CALLED
MINIMAL: GETMINIMAL()
MINIMAL: INTERCEPTOR POSTHANDLE CALLED
MINIMAL: INTERCEPTOR AFTERCOMPLETION CALLED
1 голос
/ 29 апреля 2019
import javax.servlet.http.HttpServletRequest ;
import javax.servlet.http.HttpServletResponse;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

@Configuration
public class AuthenticationHandlerInterceptor implements HandlerInterceptor {

    @Override
    public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
            throws Exception {
    }

    @Override
    public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
            throws Exception {
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception {

        if (validrequest) {
         //fill data here add pass to next level
            return true;
        } else {
      // if you opt to not to proceed the request further you can simply return false here
            return false;
        }
    }

}

prehandle () - вызывается перед выполнением фактического обработчика, но представление еще не сгенерировано postHandle () - вызывается после выполнения обработчика

afterCompletion () - вызывается после завершения полного запроса и создания представления

...