SpringBoot过滤器和Servlet3.0配置过滤器
filter简单理解:人--->检票员(filter)---> 景点
1、SpringBoot启动默认加载的Filter
characterEncodingFilter
hiddenHttpMethodFilter
httpPutFormContentFilter
requestContextFilter
2、Filter优先级
Ordered.HIGHEST_PRECEDENCE
Ordered.LOWEST_PRECEDENCE
低位值意味着更高的优先级 Higher values are interpreted as lower priority
自定义Filter,避免和默认的Filter优先级一样,不然会冲突
注册Filter的bean FilterRegistrationBean
同模块里面有相关默认Filter
web->servlet->filter
3、自定义Filter
1)使用Servlet3.0的注解进行配置
2)启动类里面增加 @ServletComponentScan,进行扫描
3)新建一个Filter类,implements Filter,并实现对应的接口
4) @WebFilter 标记一个类为filter,被spring进行扫描urlPatterns:拦截规则,支持正则
5)控制chain.doFilter的方法的调用,来实现是否通过放行不放行,web应用resp.sendRedirect("/index.html");
场景:权限控制、用户登录(非前端后端分离场景)等
init 启动的时候加载
doFilter 请求到达过滤器的时候
destory 销毁时触发
Servlet3.0 自定义Servlet
启动类加@ServletComponentScan注解
@WebServlet(name = "userServlet",urlPatterns = "/v1/api/test/customs")
public class UserServlet extends HttpServlet{
@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().print("custom sevlet");
resp.getWriter().flush();
resp.getWriter().close();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
}
自定义监听器:主要做资源的加载(缓存)
(常用的监听器 ServletContextListener、HttpSessionListener、ServletRequestListener)
加@WebListener注解
1)实现ServletRequeststListener
2)重写requestDestoryed(ServletRequestEvent sqe)方法
3)重写requestInitialized方法
@WebListener
public class RequestListener implements ServletRequestListener {
@Override
public void requestDestroyed(ServletRequestEvent sre) {
// TODO Auto-generated method stub
System.out.println("======requestDestroyed========");
}
@Override
public void requestInitialized(ServletRequestEvent sre) {
System.out.println("======requestInitialized========");
}
自定义拦截器:
1、@Configuration
继承WebMvcConfigurationAdapter(SpringBoot2.X之前旧版本)
SpringBoot2.X 新版本配置拦截器 implements WebMvcConfigurer
2、自定义拦截器 HandlerInterceptor
preHandle:调用Controller某个方法之前
postHandle:Controller之后调用,视图渲染之前,如果控制器Controller出现了异常,则不会执行此方法
afterCompletion:不管有没有异常,这个afterCompletion都会被调用,用于资源清理
3、按照注册顺序进行拦截,先注册,先被拦截
拦截器不生效常见问题:
1)是否有加@Configuration
2)拦截路径是否有问题 ** 和 *
3)拦截器最后路径一定要 “/**”, 如果是目录的话则是 /*/
Filter
是基于函数回调 doFilter(),而Interceptor则是基于AOP思想
Filter在只在Servlet前后起作用,而Interceptor够深入到方法前后、异常抛出前后等
依赖于Servlet容器即web应用中,而Interceptor不依赖于Servlet容器所以可以运行在多种环境。
在接口调用的生命周期里,Interceptor可以被多次调用,而Filter只能在容器初始化时调用一次。
Filter和Interceptor的执行顺序
过滤前->拦截前->action执行->拦截后->过滤后
重写addInterceptors方法()
addInterceptor()要一个Interceptor对象
LoginInterceptor要impl HandlerInterceptor
//api2下的自路径的所有方法进行拦截
@Configuration
public class CustomWebMvcConfigure implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginIntercepter()).addPathPatterns("/api2/*/**");
WebMvcConfigurer.super.addInterceptors(registry);
}
}
//具体拦截器的业务类
public class LoginIntercepter implements HandlerInterceptor {
//进入controller方法之前 做数据库查询和校验工作
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 查看token是否存在于缓存或者redis当中
// 符合放行 否则跳转等
String access_token = request.getParameter("access_token");
// response.getWriter().println("faile");
System.out.println("preHandle");
return false;
}
// 调用完controller之后,试图渲染之前
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("PostHandler");
}
//整个完成之后,通常用于资源清理
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("After");
}
}
开始没有用父类的方法,所以跳转失败
默认return false;
registry.addInterceptor(new LoginIntercepter()).addPathPatterns("/api2/*/**").excludePathPatterns("不进行拦截的/api2/xx/**");
//具体拦截器的业务类
public class LoginIntercepter implements HandlerInterceptor {
//进入controller方法之前 做数据库查询和校验工作
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 查看token是否存在于缓存或者redis当中
// 符合放行 否则跳转等
String access_token = request.getParameter("access_token");
// response.getWriter().println("faile");
System.out.println("preHandle");
System.out.println("access_token"+access_token);
return HandlerInterceptor.super.preHandle(request,response,handler);
}
// 调用完controller之后,试图渲染之前
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("PostHandler");
HandlerInterceptor.super.postHandle(request,response,handler,modelAndView);
}
//整个完成之后,通常用于资源清理
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("After");
HandlerInterceptor.super.afterCompletion(request,response,handler,ex);
}
}
多个拦截:
registry.addInterceptor(new LoginIntercepter()).addPathPatterns("/api2/*/**").excludePathPatterns(); registry.addInterceptor(new TwoIntercepter()).addPathPatterns("/api2/*/**").excludePathPatterns(); 先到显得 队列