过滤器和拦截器
目录
过滤器 filter
springboot使用filter
1、实现Filter接口
@WebFilter(urlPatterns = "/*")//匹配的url路径
public class AppFilter implements Filter {
<span class="hljs-comment">/**
* 通过WebFilter配置拦截器,可以注入成员
*/</span>
<span class="hljs-meta">@Autowired</span>
<span class="hljs-keyword">private</span> TestComponent testComponent;
<span class="hljs-meta">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">init</span><span class="hljs-params">(FilterConfig filterConfig)</span> <span class="hljs-keyword">throws</span> ServletException </span>{
System.out.println(<span class="hljs-string">"拦截器init"</span>);
}
<span class="hljs-comment">/**
* 拦截请求
*
* <span class="hljs-doctag">@param</span> servletRequest
* <span class="hljs-doctag">@param</span> servletResponse
* <span class="hljs-doctag">@param</span> filterChain
* <span class="hljs-doctag">@throws</span> IOException
* <span class="hljs-doctag">@throws</span> ServletException
*/</span>
<span class="hljs-meta">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">doFilter</span><span class="hljs-params">(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)</span> <span class="hljs-keyword">throws</span> IOException, ServletException </span>{
String method = testComponent.method();
System.out.println(<span class="hljs-string">"过滤器"</span>);
filterChain.doFilter(servletRequest, servletResponse);
}
<span class="hljs-comment">/**
* 程序终止的时候调用
*/</span>
<span class="hljs-meta">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">destroy</span><span class="hljs-params">()</span> </span>{
System.out.println(<span class="hljs-string">"拦截器destroy"</span>);
}
}
2、在主类上开启servlet组件的扫描(包括servlet,filter,listener)
@SpringBootApplication
@ServletComponentScan(basePackages = {"com.interceptortest.demo.filter"})//开启扫描filter
public class DemoApplication {
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
SpringApplication.run(DemoApplication.class, args);
}
}
拦截器 Intercepter
springboot中使用Intercepter
url路径的方式
1、继承HandlerInterceptorAdapter类,实现preHandle方法
@Component
public class AppIntercepter extends HandlerInterceptorAdapter {
<span class="hljs-meta">@Autowired</span>
<span class="hljs-keyword">private</span> TestComponent testComponent;
<span class="hljs-meta">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">preHandle</span><span class="hljs-params">(HttpServletRequest request, HttpServletResponse response, Object handler)</span> <span class="hljs-keyword">throws</span> Exception </span>{
System.out.println(<span class="hljs-string">"拦截器生效\t通过路径拦截"</span>);
<span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>;
}
}
2、实现WebMvcConfigurer接口,重写addInterceptors方法
@Configuration
public class IntercepterConfig implements WebMvcConfigurer {
<span class="hljs-meta">@Autowired</span>
<span class="hljs-keyword">private</span> AppIntercepter appIntercepter;
<span class="hljs-meta">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">addInterceptors</span><span class="hljs-params">(InterceptorRegistry registry)</span> </span>{
<span class="hljs-comment">//采用注入的方式配置,则Intercepter中可以自动注入成员变量</span>
registry.addInterceptor(appIntercepter).addPathPatterns(<span class="hljs-string">"/app/**"</span>);
<span class="hljs-comment">//如果是采用new的方式注入,则Intercepter中不能自动注入成员变量,需要手动获取</span>
registry.addInterceptor(<span class="hljs-keyword">new</span> TestIntercepter()).addPathPatterns(<span class="hljs-string">"/test/**"</span>);
}
}
使用注解方式
其实使用注解的方式,原理是将拦截器的作用的url设置为"/*",然后通过判断方法上是否有注解来进行处理
public class TestIntercepter extends HandlerInterceptorAdapter {
<span class="hljs-meta">@Autowired</span>
<span class="hljs-keyword">private</span> TestComponent testComponent;
<span class="hljs-meta">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">preHandle</span><span class="hljs-params">(HttpServletRequest request, HttpServletResponse response, Object handler)</span> <span class="hljs-keyword">throws</span> Exception </span>{
<span class="hljs-comment">//registry.addInterceptor(new TestIntercepter()).addPathPatterns("/test/**");</span>
<span class="hljs-comment">//如果是采用new的方式注入,则Autowired的字段不会生效,需要重新在上下文中获取</span>
<span class="hljs-keyword">if</span> (testComponent == <span class="hljs-keyword">null</span>) {
WebApplicationContext requiredWebApplicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext());
testComponent = (TestComponent) requiredWebApplicationContext.getBean(<span class="hljs-string">"testComponent"</span>);
}
HandlerMethod method = (HandlerMethod) handler;
Anno loginRequired = method.getMethodAnnotation(Anno.class);
<span class="hljs-keyword">if</span> (Objects.isNull(loginRequired)) {
System.out.println(<span class="hljs-string">"无需拦截"</span>);
<span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>;
} <span class="hljs-keyword">else</span> {
System.out.println(<span class="hljs-string">"通过注解拦截"</span>);
<span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>;
}
}
}
注意
registry.addInterceptor方法中,最好不要new一个拦截器,因为这样通过spring注入的成员会丢失。
解决方法
通过上下文重新获取
if (testComponent == null) {
WebApplicationContext requiredWebApplicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext());
testComponent = (TestComponent) requiredWebApplicationContext.getBean("testComponent");
}
拦截器Intercepter和过滤器filter区别
1、filter在intercepter之前执行
2、intercepter可以通过handler获取更多的信息,包括方法名等(但是获取不到方法参数),但filter只有http相关信息