Spring Boot RestController:拦截传入请求
Spring Boot RestController: Intercept incoming requests
我目前正在编写某种允许其他人为其编写 REST 控制器的框架。当然,我希望那些 "others" 尽可能少地与我的代码中发生的事情交互。
具体来说,我想要并且需要访问请求数据(即
RequestEntity
在 rest 控制器处理请求之前。 "intercepting" 请求在控制器处理之前排序,然后才让控制器处理它。
考虑以下代码:
@RestController
@RequestMapping("/")
public class MyController {
@GetMapping("/")
@ResponseBody
public ResponseEntity<String> getSomething(RequestEntity requestEntity) {
MyClass.doStuffWithRequestEntity(requestEntity);
// ...
现在我需要的是调用 ExternalClass.doStuffWithRequestEntity(requestEntity);
而无需显式调用它。是否可以调用某些 class 中的某些方法(将 RequestEntity 传递给它!)而不必显式调用它?
此外,拦截器 class 应该创建和配置一个对象,然后再次提供给其余控制器。
我会这么想
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();
}
}
之前正在执行。
这个想法是解析每个(!)传入的请求并解码其内容,而其余控制器的程序员根本不必关心这个。他们应该只访问数据 via/from MyClass 实例。
有办法吗?
Spring-boot 允许我们在 spring 引导应用程序中配置自定义 interceptors.Usually 一切都是自动配置的,在这种情况下我们可以 customize 它通过使用 WebMvcConfigurerAdapter
。只需扩展 WebMvcConfigurerAdapter
并提供您在此 class.
中需要的配置
记得添加 @Configuration
注释,这样 class 将在组件扫描期间被 spring 拾取。
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
@Autowired
HandlerInterceptor customInjectedInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(...)
...
registry.addInterceptor(customInjectedInterceptor).addPathPatterns("/**");
}
}
这就是您通常将拦截器添加到 spring 引导的方式 applications.Hope 这可能有助于回答您的问题。
从spring5.x.x或spring-boot 2开始,WebMvcConfigurerAdapter
标记为deprecated.The WebMvcConfigurer
接口(由抽象 class WebMvcConfigurerAdapter
实现),从 Spring 5 开始,包含其所有方法的默认实现。因此,抽象适配器 class 被标记为 deprecated.You 如果您愿意,可以采用它,如下所示:
@Configuration
public WebConfig implements WebMvcConfigurer {
// ...
}
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()
– 在完成请求并生成视图后调用
对于所有在这里遇到相同或类似问题的人,这里有一个带有拦截器的 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
我目前正在编写某种允许其他人为其编写 REST 控制器的框架。当然,我希望那些 "others" 尽可能少地与我的代码中发生的事情交互。
具体来说,我想要并且需要访问请求数据(即
RequestEntity
在 rest 控制器处理请求之前。 "intercepting" 请求在控制器处理之前排序,然后才让控制器处理它。
考虑以下代码:
@RestController
@RequestMapping("/")
public class MyController {
@GetMapping("/")
@ResponseBody
public ResponseEntity<String> getSomething(RequestEntity requestEntity) {
MyClass.doStuffWithRequestEntity(requestEntity);
// ...
现在我需要的是调用 ExternalClass.doStuffWithRequestEntity(requestEntity);
而无需显式调用它。是否可以调用某些 class 中的某些方法(将 RequestEntity 传递给它!)而不必显式调用它?
此外,拦截器 class 应该创建和配置一个对象,然后再次提供给其余控制器。
我会这么想
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();
}
}
之前正在执行。
这个想法是解析每个(!)传入的请求并解码其内容,而其余控制器的程序员根本不必关心这个。他们应该只访问数据 via/from MyClass 实例。
有办法吗?
Spring-boot 允许我们在 spring 引导应用程序中配置自定义 interceptors.Usually 一切都是自动配置的,在这种情况下我们可以 customize 它通过使用 WebMvcConfigurerAdapter
。只需扩展 WebMvcConfigurerAdapter
并提供您在此 class.
记得添加 @Configuration
注释,这样 class 将在组件扫描期间被 spring 拾取。
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
@Autowired
HandlerInterceptor customInjectedInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(...)
...
registry.addInterceptor(customInjectedInterceptor).addPathPatterns("/**");
}
}
这就是您通常将拦截器添加到 spring 引导的方式 applications.Hope 这可能有助于回答您的问题。
从spring5.x.x或spring-boot 2开始,WebMvcConfigurerAdapter
标记为deprecated.The WebMvcConfigurer
接口(由抽象 class WebMvcConfigurerAdapter
实现),从 Spring 5 开始,包含其所有方法的默认实现。因此,抽象适配器 class 被标记为 deprecated.You 如果您愿意,可以采用它,如下所示:
@Configuration
public WebConfig implements WebMvcConfigurer {
// ...
}
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()
– 在完成请求并生成视图后调用
对于所有在这里遇到相同或类似问题的人,这里有一个带有拦截器的 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