Spring Boot RestController:拦截传入请求

Xen*_*ite 3 spring request interceptor

我目前正在编写某种框架,允许其他人为它编写 REST 控制器。自然地,我希望那些“其他人”与我的代码中发生的事情有尽可能少的互动。

具体来说,我想要并且需要访问请求数据(即 RequestEntity在其余控制器处理请求之前。在控制器处理请求之前“拦截”请求,然后才让控制器处理它。

考虑以下代码:

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

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

        MyClass.doStuffWithRequestEntity(requestEntity);
        // ...
Run Code Online (Sandbox Code Playgroud)

现在我需要的是ExternalClass.doStuffWithRequestEntity(requestEntity);在不需要明确调用它的情况下调用它。是否可以调用某个类中的某些方法(将 RequestEntity 传递给它!)而不必显式调用它?

此外,所述拦截器类应该创建和配置一个对象,然后该对象再次可供其余控制器使用。

我会想像

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

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

            MyClass x = MyClass.getInstanceCreatedByInterceptor();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

class Interceptor {
    public void doStuffWithRequestEntity(requestEntity) {

        MyClass x = new MyClass();
        x.fillObjectWithData();
    }
}
Run Code Online (Sandbox Code Playgroud)

之前被执行。

这个想法是解析每个(!)传入的请求并对其内容进行解码,而其余控制器的程序员根本不必关心这一点。他们应该只通过/从 MyClass 实例访问数据。

有没有办法做到这一点?

Ana*_*han 8

Spring-boot 允许我们配置自定义拦截器。通常在 Spring Boot 应用程序中,所有内容都是自动配置的,在这种情况下,我们可以使用.Just 扩展并提供此类中所需的配置来自定义它。WebMvcConfigurerAdapterWebMvcConfigurerAdapter

请记住添加@Configuration注释,以便 spring 在组件扫描期间拾取该类。

@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {

  @Autowired 
  HandlerInterceptor customInjectedInterceptor;

  @Override
  public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(...)
    ... 
    registry.addInterceptor(customInjectedInterceptor).addPathPatterns("/**");
  }
}
Run Code Online (Sandbox Code Playgroud)

这就是您通常向 Spring Boot 应用程序添加拦截器的方式。希望这可以帮助回答您的问题。

从 spring 5.xx 或 spring-boot 2 开始WebMvcConfigurerAdapter被标记为已弃用。WebMvcConfigurer该接口(由抽象类实现WebMvcConfigurerAdapter)从 Spring 5 开始,包含其所有方法的默认实现。因此,抽象适配器类被标记为已弃用。如果您愿意,可以采用它,如下所示:

@Configuration
public WebConfig implements WebMvcConfigurer {
    // ...
}
Run Code Online (Sandbox Code Playgroud)


Xen*_*ite 5

对于所有最终遇到相同或类似问题的人,这里是一个带有拦截器的 SpringBoot (2.1.4) 应用程序的最小工作示例:

最小的.java:

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

最小控制器.java:

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

        return new ResponseEntity<String>("returnstring", HttpStatus.OK);
    }
}
Run Code Online (Sandbox Code Playgroud)

配置文件:

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

    @Override
    public void addInterceptors(InterceptorRegistry registry)
    {
        registry.addInterceptor(new MinimalInterceptor());
    }
}
Run Code Online (Sandbox Code Playgroud)

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");
    }
}
Run Code Online (Sandbox Code Playgroud)

像宣传的那样工作

输出会给你类似的东西:

> 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
Run Code Online (Sandbox Code Playgroud)