顺序如下
1 filter
2.1 interceptor-pre
3 valid参数校验
4.1 aop-pre
5 业务方法
4.2 aop-post(校验失败,异常时_不执行)
2.2 interceptor-post(校验失败,异常时_不执行)
6 全局异常捕获
2.3 interceptor-afterCompletion(校验失败,异常时_任然执行)
============================================
filter 过滤器 https://www.cnblogs.com/huanzi-qch/p/11239167.html
filter: post拿不到参数? POST的请求是在请求体body中,而POST请求中的body参数是以流形式存在的 https://blog.csdn.net/qq_40866897/article/details/111404480
Interceptor 拦截器 https://blog.csdn.net/worilb/article/details/114194446
https://www.cnblogs.com/eoooxy/p/6566347.html
①拦截器是基于Java的反射机制的,而过滤器是基于函数回调。
②拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
③拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
④拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。
⑤在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。
⑥拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。
===================
WebRequestInterceptor与HandlerInterceptor的异同?https://www.cnblogs.com/zhangww/p/13596039.html
WebRequestInterceptor的入参WebRequest是包装了HttpServletRequest 和HttpServletResponse的,通过WebRequest获取Request中的信息更简便。
2.WebRequestInterceptor的preHandle是没有返回值的,说明该方法中的逻辑并不影响后续的方法执行,所以这个接口实现就是为了获取Request中的信息,或者预设一些参数供后续流程使用。
3.HandlerInterceptor的功能更强大也更基础,可以在preHandle方法中就直接拒绝请求进入controller方法。
使用场景
Validator 参数校验 SpringBoot 参数校验的方法 - 木白的菜园 - 博客园
aop spring boot 通过 aop 实现全局打印请求参数和返回结果 - 链滴
===========================================
Filter
@WebFilter(filterName = "testFilter", urlPatterns = {"/test"})
@Component
public class TestFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
// 获取post时, 请求中的body参数是流的形式存在 request.getRequestParams()拿不到值
// 所以需要自行封装
RequestWrapper requestWrapper = new RequestWrapper(request);
System.out.println("TestFilter," + request.getRequestURI());
System.out.println(requestWrapper.getBodyString());
//执行
filterChain.doFilter(requestWrapper, servletResponse);
}
@Override
public void destroy() {
}
}
RequestWrapper 防止读取流后, controller获取不到值
import org.springframework.util.StreamUtils;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
public class RequestWrapper extends HttpServletRequestWrapper {
private final byte[] body;
public RequestWrapper(HttpServletRequest request) throws IOException {
super(request);
//保存一份InputStream,将其转换为字节数组
body = StreamUtils.copyToByteArray(request.getInputStream());
}
//转换成String
public String getBodyString(){
return new String(body, StandardCharsets.UTF_8);
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(getInputStream()));
}
//把保存好的InputStream,传下去
@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream bais = new ByteArrayInputStream(body);
return new ServletInputStream() {
@Override
public int read() throws IOException {
return bais.read();
}
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
}
};
}
}
Interceptor
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle...1");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle...3");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("postafterCompletionHandle...4");
}
}
注册拦截器
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Component
public class MyInterceptorConfig implements WebMvcConfigurer {
@Autowired
MyInterceptor myInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(myInterceptor).addPathPatterns("/test").excludePathPatterns("/admin");
}
}
aop
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class MyLogAspect {
@Pointcut("@annotation(com.xxx.annotation.MyLog)")
public void logCut() {
}
@Around("logCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
System.out.println("aop start");
Object result = point.proceed();
System.out.println("aop end");
return result;
}
}
controller
@RestController
@RequestMapping("")
public class TestController {
@RequestMapping("/test")
public String test() {
System.out.println("业务逻辑....2");
return "success";
}
}
==================
其他:
=================
如果 参数请求为json格式, 则可以通过调整日志级别 来实现快速打印请求参数
<logger name="org.springframework.web.servlet.DispatcherServlet" level="debug"/>
参考 DispatcherServlet 类的 logRequest()方法
org.springframework.web.servlet.DispatcherServlet [91]:POST "/test", parameters={}
org.springframework.web.servlet.DispatcherServlet [1131]:Completed 404 NOT_FOUND
org.springframework.web.servlet.DispatcherServlet [91]:"ERROR" dispatch for POST "/error", parameters={}
org.springframework.web.servlet.DispatcherServlet [1127]:Exiting from "ERROR" dispatch, status 404