拦截器,过滤器,监听器

计算机软件开发 2024-10-7 09:36:41 96 0 来自 中国
过滤器(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等步伐中。

4.png 3.触发机会差别
过滤器Filter是在哀求进入容器后,但在进入servlet之进步行预处置惩罚,哀求竣事是在servlet处置惩罚完以后。
拦截器 Interceptor 是在哀求进入servlet后,在进入Controller之进步行预处置惩罚的,Controller 中渲染了对应的视图之后哀求竣事。

4.拦截的哀求范围差别
过滤器几乎可以对全部进入容器的哀求起作用,而拦截器只会对Controller中哀求或访问static目次下的资源哀求起作用。
5.访问范围
filter在servlet前后起作用,拦截器可以或许深入方法的前后,非常抛出前后。
过滤器和拦截器的使用场景

实用场景:
拦截器的应用场景:权限控制,日志打印,参数校验
过滤器的应用场景:跨域标题办理,编码转换,shiro权限过滤
您需要登录后才可以回帖 登录 | 立即注册

Powered by CangBaoKu v1.0 小黑屋藏宝库It社区( 冀ICP备14008649号 )

GMT+8, 2024-10-18 16:51, Processed in 0.141357 second(s), 35 queries.© 2003-2025 cbk Team.

快速回复 返回顶部 返回列表