在Spring Boot中,可以使用拦截器(Interceptor)来实现全局请求拦截。示例:
首先,创建一个拦截器类,实现HandlerInterceptor接口:
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
@Component
public class GlobalInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// 在请求处理之前进行调用(Controller方法调用之前)
// 返回true才会继续向下执行,返回false取消当前请求
System.out.println("GlobalInterceptor preHandle");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
// 请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)
System.out.println("GlobalInterceptor postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
// 整个请求结束之后被调用,也就是在DispatcherServlet渲染了对应的视图之后执行(主要是用于进行资源清理工作)
System.out.println("GlobalInterceptor afterCompletion");
}
}
然后,在配置类中注册拦截器:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private GlobalInterceptor globalInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 注册拦截器,并设置拦截路径
registry.addInterceptor(globalInterceptor).addPathPatterns("/**");
}
}
在上述示例中,GlobalInterceptor类实现了HandlerInterceptor接口,并重写了preHandle、postHandle和afterCompletion方法。在preHandle方法中,可以进行一些前置处理,如权限验证、日志记录等。在postHandle方法中,可以进行一些后置处理,如修改返回结果、添加额外的响应头等。在afterCompletion方法中,可以进行一些资源清理工作。
在WebConfig配置类中,通过addInterceptors方法将GlobalInterceptor注册为拦截器,并设置拦截路径为"/**"
,表示拦截所有请求。
这样,当有请求进入时,会先经过GlobalInterceptor的preHandle方法,然后进入Controller处理请求,最后再经过GlobalInterceptor的postHandle和afterCompletion方法。
RequestBodyAdvice
和ResponseBodyAdvice
是Spring框架提供的两个接口,用于在请求处理过程中对请求体和响应体进行处理。
RequestBodyAdvice
用于在请求到达Controller之前对请求体进行处理,可以对请求体进行修改、解析、验证等操作。
ResponseBodyAdvice
用于在Controller方法返回结果之后对响应体进行处理,可以对响应体进行修改、封装、加密等操作。
这两个接口可以同时使用,分别对请求体和响应体进行处理。可以通过实现RequestBodyAdvice
和ResponseBodyAdvice
接口,并注册为Spring的Bean来使用。
例如,可以创建一个实现RequestBodyAdvice
接口的类来处理请求体:
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice;
import java.io.IOException;
import java.lang.reflect.Type;
@ControllerAdvice
public class GlobalRequestBodyAdvice implements RequestBodyAdvice {
@Override
public boolean supports(MethodParameter methodParameter, Type targetType,
Class<? extends HttpMessageConverter<?>> converterType) {
// 判断是否支持对该请求进行处理
return true;
}
@Override
public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType,
Class<? extends HttpMessageConverter<?>> converterType) throws IOException {
// 对请求体进行处理,返回处理后的HttpInputMessage
return inputMessage;
}
@Override
public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType,
Class<? extends HttpMessageConverter<?>> converterType) {
// 请求体读取完成后的处理,可以对body进行进一步处理
return body;
}
@Override
public Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter,
Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
// 处理空请求体的情况
return body;
}
}
同时,可以创建一个实现ResponseBodyAdvice
接口的类来处理响应体:
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
@ControllerAdvice
public class GlobalResponseBodyAdvice implements ResponseBodyAdvice<Object> {
@Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
// 判断是否支持对该响应进行处理
return true;
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
Class<? extends HttpMessageConverter<?>> selectedConverterType,
ServerHttpRequest request, ServerHttpResponse response) {
// 对响应体进行处理,返回处理后的响应体
return body;
}
}
在上述示例中,GlobalRequestBodyAdvice
实现了RequestBodyAdvice
接口,用于对请求体进行处理。GlobalResponseBodyAdvice
实现了ResponseBodyAdvice
接口,用于对响应体进行处理。
通过@ControllerAdvice
注解,将这两个类注册为全局的控制器增强,使其生效。
这样,当有请求进入时,会先经过GlobalRequestBodyAdvice
对请求体进行处理,然后进入Controller
处理请求,最后再经过GlobalResponseBodyAdvice
对响应体进行处理。
注意:只有请求参数为@RequestBody,才会执行GlobalRequestBodyAdvice
拦截器(Interceptor)、RequestBodyAdvice和ResponseBodyAdvice可以同时使用。
它们之间的关系和区别如下:
拦截器(Interceptor):
RequestBodyAdvice:
ResponseBodyAdvice:
这三个功能可以同时使用,各自负责不同的处理逻辑:
通过同时使用拦截器、RequestBodyAdvice和ResponseBodyAdvice,可以实现更加灵活和全面的请求和响应处理。
拦截器和RequestBodyAdvice在功能和使用场景上有所不同,可以根据具体需求选择使用。
请求参数类型为@RequestBody,执行顺序如下:
GlobalInterceptor preHandle
GlobalRequestBody supports
GlobalRequestBody beforeBodyRead
GlobalRequestBody supports
GlobalRequestBody afterBodyRead
GlobalResponseBody supports
GlobalResponseBody beforeBodyWrite
GlobalInterceptor postHandle
GlobalInterceptor afterCompletion