过滤器(Filter):当你有一堆东西的时候,你只盼望选择符合你要求的某一些东西。界说这些要求的工具,就是过滤器。 拦截器(Interceptor):在一个流程正在举行的时候,你盼望干预它的盼望,乃至停止它举行,这是拦截器做的事变。 监听器(Listener):当一个变乱发生的时候,你盼望得到这个变乱发生的具体信息,而并不想干预这个变乱本身的进程,这就要用到监听器。
过滤器
过滤器Filter基于Servlet实现,过滤器的重要应用场景是对字符编码、跨域等标题举行过滤。Servlet的工作原理是拦截设置好的客户端哀求,然后对Request和Response举行处置惩罚。Filter过滤器随着web应用的启动而启动,只初始化一次。
- init() :web 应用步伐启动时,web 服务器将创建Filter 的实例对象,并调用其init方法,读取web.xml设置,完成对象的初始化功能,从而为后续的用户哀求作好拦截的准备工作(filter对象只会创建一次,init方法也只会实行一次)。开辟职员通过init方法的参数,可得到代表当前filter设置信息的FilterConfig对象。
- doFilter() :该方法完成实际的过滤操纵,当客户端哀求方法与过滤器设置匹配的URL时,Servlet容器将先调用过滤器的doFilter方法。FilterChain用户访问后续过滤器。
- destroy(): 当容器烧毁 过滤器实例时调用该方法,一般在方法中烧毁或关闭资源,在过滤器 Filter 的整个生命周期也只会被调用一次
Springboot使用过滤器
public class MyFilter implements Filter { private String url; /** * 可以初始化Filter在web.xml内里设置的初始化参数 * filter对象只会创建一次,init方法也只会实行一次。 * @param filterConfig * @throws ServletException */ @Override public void init(FilterConfig filterConfig) throws ServletException { this.url = filterConfig.getInitParameter("URL"); System.out.println("我是过滤器的初始化方法!URL=" + this.url + ",生存开始........."); } /** * 重要的业务代码编写方法 * @param servletRequest * @param servletResponse * @param filterChain * @throws IOException * @throws ServletException */ @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("我是过滤器的实行方法,客户端向Servlet发送的哀求被我拦截到了"); filterChain.doFilter(servletRequest, servletResponse); System.out.println("我是过滤器的实行方法,Servlet向客户端发送的相应被我拦截到了"); } /** * 在烧毁Filter时主动调用。 */ @Override public void destroy() { System.out.println("我是过滤器的被烧毁时调用的方法!,活不下去了................" ); }}@Configurationpublic class FilterConfig1 { @Bean public FilterRegistrationBean registFilter() { FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setFilter(new MyFilter()); registration.addUrlPatterns("/*"); registration.setName("iceaFilter"); registration.addInitParameter("URL","http://localhost:8080"); registration.setOrder(1); return registration; } }代码块拦截器
拦截器(Interceptor)同 Filter 过滤器一样,它俩都是面向切面编程——AOP 的具体实现(AOP切面编程只是一种编程头脑而已)。你可以使用 Interceptor 来实行某些任务,比方在 Controller 处置惩罚哀求之前编写日志,添加或更新设置……,在 Spring中,当哀求发送到 Controller 时,在被Controller处置惩罚之前,它必须颠末 Interceptors(0或多个)。
- preHandler(HttpServletRequest request, HttpServletResponse response, Object handler) 方法在哀求处置惩罚之前被调用。该方法在 Interceptor 类中开始实行,用来举行一些前置初始化操纵或是对当前哀求做预处置惩罚,也可以举行一些判断来决定哀求是否要继承举行下去。该方法的返回至是 Boolean 范例,当它返回 false 时,表现哀求竣事,后续的 Interceptor 和 Controller 都不会再实行;当它返回为 true 时会继承调用下一个 Interceptor 的 preHandle 方法,假如已经是末了一个 Interceptor 的时候就会调用当前哀求的 Controller 方法。
- postHandler(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) 方法在当前哀求处置惩罚完成之后,也就是 Controller 方法调用之后实行,但是它会在 DispatcherServlet 举行视图返回渲染之前被调用,以是我们可以在这个方法中对 Controller 处置惩罚之后的 ModelAndView 对象举行操纵。
- afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex) 方法必要在当前对应的 Interceptor 类的 preHandle 方法返回值为 true 时才会实行。顾名思义,该方法将在整个哀求竣事之后,也就是在 DispatcherServlet 渲染了对应的视图之后实行。此方法重要用来举行资源整理。
Springboot使用拦截器
public class LoginFilter implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("拦截器Interceptor 前置"); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("拦截器Interceptor 处置惩罚中"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception { System.out.println("拦截器Interceptor 后置"); }}@Configurationpublic class FilterConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { InterceptorRegistration interceptor = registry.addInterceptor(new LoginFilter()); interceptor.addPathPatterns("/**").excludePathPatterns("/login","/toLogin","/css/**","/js/**","/kaptcha"); }}原理
当用户在客户端发送哀求,会调用dispatchServlet中的 doDispatch()方法(下面是这个方法的一部分)
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { HttpServletRequest processedRequest = request; HandlerExecutionChain mappedHandler = null; boolean multipartRequestParsed = false; WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); try { ModelAndView mv = null; Exception dispatchException = null; try { processedRequest = checkMultipart(request);//是否上传文件 multipartRequestParsed = (processedRequest != request); //根据request信息Uri找到对应HandlerExecutionChain实行链 mappedHandler = getHandler(processedRequest); if (mappedHandler == null) { //没有找到HandlerExecutionChain 的通过response反馈 noHandlerFound(processedRequest, response); return; } //通过已找到的Handler取得HandlerAdapter HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); //缓存 String method = request.getMethod(); boolean isGet = "GET".equals(method); if (isGet || "HEAD".equals(method)) { long lastModified = ha.getLastModified(request, mappedHandler.getHandler()); if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) { return; } } // 留意: 实行Interceptor中PreHandle()方法 if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; } //实行handle,Controller方法 mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); if (asyncManager.isConcurrentHandlingStarted()) { return; } applyDefaultViewName(processedRequest, mv); //post拦截器实行(倒序)留意:实行Interceptor中PostHandle 方法【抛出非常时无法实行】 mappedHandler.applyPostHandle(processedRequest, response, mv); } catch (Exception ex) { dispatchException = ex; } catch (Throwable err) { // As of 4.3, we're processing Errors thrown from handler methods as well, // making them available for @ExceptionHandler methods and other scenarios. dispatchException = new NestedServletException("Handler dispatch failed", err); } //页面跳转,相应信息 processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); } catch (Exception ex) { triggerAfterCompletion(processedRequest, response, mappedHandler, ex); } catch (Throwable err) { triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", err)); } finally { if (asyncManager.isConcurrentHandlingStarted()) { // Instead of postHandle and afterCompletion if (mappedHandler != null) { mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); } } else { // Clean up any resources used by a multipart request. if (multipartRequestParsed) { cleanupMultipart(processedRequest); } } } }监听器
web监听器是Servlet中-种的特别的类,能资助开辟者监听web中的特定变乱,比如ServletContext,HttpSession, ServletRequest 的创建和烧毁;变量的创建、烧毁和修改等。可以在某些动作前后增优点置惩罚, 实现监控。比方可以用来统计在线人数等。
监听器有三类8种:
(1)监听生命周期:
ServletRequestListener
HttpSessionListener
ServletContextListener
(2)监听值的变革:
ServletRequestAttributeListener
HttpSessionAttributeListener
ServletContextAttributeListener
(3)针对session中的对象:
(3)针对session中的对象:
监听session中的java对象(javaBean),是javaBean直接实现监听器的接口。
过滤器和拦截器的区别
过滤器 和 拦截器 均表现了AOP的编程头脑,都可以实现诸如日志纪录、登录鉴权等功能,但二者的差别点也是比力多的。
1.实现原理差别
过滤器和拦截器 底层实现方式大不雷同,过滤器 是基于函数回调的,拦截器 则是基于Java的反射机制(动态代理)实现的。
2.使用范围差别
我们看到过滤器 实现的是 javax.servlet.Filter 接口,而这个接口是在Servlet规范中界说的,也就是说过滤器Filter 的使用要依赖于Tomcat等容器,导致它只能在web步伐中使用。
而拦截器(Interceptor) 它是一个Spring组件,并由Spring容器管理,并不依赖Tomcat等容器,是可以单独使用的。不光能应用在web步伐中,也可以用于Application、Swing等步伐中。
3.触发机会差别
过滤器Filter是在哀求进入容器后,但在进入servlet之进步行预处置惩罚,哀求竣事是在servlet处置惩罚完以后。
拦截器 Interceptor 是在哀求进入servlet后,在进入Controller之进步行预处置惩罚的,Controller 中渲染了对应的视图之后哀求竣事。
4.拦截的哀求范围差别
过滤器几乎可以对全部进入容器的哀求起作用,而拦截器只会对Controller中哀求或访问static目次下的资源哀求起作用。
5.访问范围
filter在servlet前后起作用,拦截器可以或许深入方法的前后,非常抛出前后。
过滤器和拦截器的使用场景
实用场景:
拦截器的应用场景:权限控制,日志打印,参数校验
过滤器的应用场景:跨域标题办理,编码转换,shiro权限过滤 |