`

Web 的拦截器

    博客分类:
  • web
 
阅读更多
我们可能会定义一些拦截器,但是他在容器中是怎么工作的呢,什么时候初始化,什么时候执行,什么时候销毁.
比如做权限验证
    <filter>     
        <filter-name>Auth</filter-name>     
        <filter-class>UrlFilter</filter-class>     
        <init-param>     
            <param-name>fail</param-name>     
            <param-value>/index.jsp</param-value>     
        </init-param>     
    </filter>     
      
    <filter-mapping>     
        <filter-name>Auth</filter-name>
        <url-pattern>*.do</url-pattern>     
    </filter-mapping> 

比如做IP地址验证
<filter>
	<filter-name>AddressFilter</filter-name>
		<filter-class>AddressFilter</filter-class>
		<init-param> 
			<param-name>faill</param-name> 
			<param-value>/iperror.html</param-value> 
		</init-param>	
	</filter>
 
	<filter-mapping>
		<filter-name>AddressFilter</filter-name>
		<url-pattern>/*.do</url-pattern>
	</filter-mapping>


Filter 有三个方法:
public void init(FilterConfig filterConfig) throws ServletException
在Servlet容器加载filter的时候执行.
public void destroy().
在Servlet容器销毁filter的时候执行.
public void doFilter(ServletRequest servletRequest,
ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException
在每一个请求到达的时候执行。



	public void doFilter(ServletRequest servletRequest,
			ServletResponse servletResponse, FilterChain filterChain)
			throws IOException, ServletException {

		HttpServletRequest request = (HttpServletRequest) servletRequest;
		HttpServletResponse response = (HttpServletResponse) servletResponse;

		try {
			if (!checkIPAdress(request)) {
				log.error(new Exception("Invalid client IP - " +  getIpAddr(request)));
				response.sendRedirect(request.getContextPath() + redirectURL);
				return;
			}

			filterChain.doFilter(servletRequest, servletResponse);
		} catch (Exception e) {
			log.error("catch exception", e);
			response.sendRedirect(request.getContextPath() + unknownErrorURL);
		}
	}


这段代码就是验证了一下Address,如果不符合就Redirect到指定的URL,否则继续执行FilterChain的下一个filter.

接下来看tomcat怎么对filter的处理,

1. Filter init.

org.apache.catalina.core.StandardContext
 // Configure and call application filters
            if (ok) {
                if (!filterStart()) {
                    log.error("Error filterStart");
                    ok = false;
                }
            }

            // Load and initialize all "load on startup" servlets
            if (ok) {
                if (!loadOnStartup(findChildren())){
                    log.error("Error loadOnStartup");
                    ok = false;
                }
            }



咦!~~~, 好熟息, 下面是上一章介绍的Servlet初识化。
    /**
     * Configure and initialize the set of filters for this Context.
     * Return <code>true</code> if all filter initialization completed
     * successfully, or <code>false</code> otherwise.
     */
    public boolean filterStart() {

        if (getLogger().isDebugEnabled()) {
            getLogger().debug("Starting filters");
        }
        // Instantiate and record a FilterConfig for each defined filter
        boolean ok = true;
        synchronized (filterConfigs) {
            filterConfigs.clear();
            for (Entry<String,FilterDef> entry : filterDefs.entrySet()) {
                String name = entry.getKey();
                if (getLogger().isDebugEnabled()) {
                    getLogger().debug(" Starting filter '" + name + "'");
                }
                try {
                    ApplicationFilterConfig filterConfig =
                            new ApplicationFilterConfig(this, entry.getValue());
                    filterConfigs.put(name, filterConfig);
                } catch (Throwable t) {
                    t = ExceptionUtils.unwrapInvocationTargetException(t);
                    ExceptionUtils.handleThrowable(t);
                    getLogger().error(sm.getString(
                            "standardContext.filterStart", name), t);
                    ok = false;
                }
            }
        }

        return ok;
    }


    ApplicationFilterConfig(Context context, FilterDef filterDef)
        throws ClassCastException, ClassNotFoundException,
               IllegalAccessException, InstantiationException,
               ServletException, InvocationTargetException, NamingException {

        super();

        this.context = context;
        this.filterDef = filterDef;
        // Allocate a new filter instance if necessary
        if (filterDef.getFilter() == null) {
            getFilter();
        } else {
            this.filter = filterDef.getFilter();
            getInstanceManager().newInstance(filter);
            initFilter();
        }
    }

 private void initFilter() throws ServletException {
        if (context instanceof StandardContext &&
                context.getSwallowOutput()) {
            try {
                SystemLogHandler.startCapture();
                filter.init(this);
            } finally {
                String capturedlog = SystemLogHandler.stopCapture();
                if (capturedlog != null && capturedlog.length() > 0) {
                    getServletContext().log(capturedlog);
                }
            }
        } else {
            filter.init(this);
        }

        // Expose filter via JMX
        registerJMX();
    }


在容器启动的时候init Filter.

2. Filter doFilter.

代码太长了,截取一段吧, 这里初始化了FilterChain, 用脚趾头想想也知道是Filter链条。然后执行一个就能执行在链条上的所有filter.
  // Create the filter chain for this request
        ApplicationFilterFactory factory =
            ApplicationFilterFactory.getInstance();
        ApplicationFilterChain filterChain =
            factory.createFilterChain(request, wrapper, servlet);

        // Reset comet flag value after creating the filter chain
        request.setComet(false);

        // Call the filter chain for this request
        // NOTE: This also calls the servlet's service() method
        try {
            if ((servlet != null) && (filterChain != null)) {
                // Swallow output if needed
                if (context.getSwallowOutput()) {
                    try {
                        SystemLogHandler.startCapture();
                        if (request.isAsyncDispatching()) {
                            ((AsyncContextImpl)request.getAsyncContext()).doInternalDispatch();
                        } else if (comet) {
                            filterChain.doFilterEvent(request.getEvent());
                            request.setComet(true);
                        } else {
                            filterChain.doFilter(request.getRequest(),
                                    response.getResponse());
                        }


  @Override
    public void doFilter(ServletRequest request, ServletResponse response)
        throws IOException, ServletException {

        if( Globals.IS_SECURITY_ENABLED ) {
            final ServletRequest req = request;
            final ServletResponse res = response;
            try {
                java.security.AccessController.doPrivileged(
                    new java.security.PrivilegedExceptionAction<Void>() {
                        @Override
                        public Void run()
                            throws ServletException, IOException {
                            internalDoFilter(req,res);
                            return null;
                        }
                    }
                );
            } catch( PrivilegedActionException pe) {
                Exception e = pe.getException();
                if (e instanceof ServletException)
                    throw (ServletException) e;
                else if (e instanceof IOException)
                    throw (IOException) e;
                else if (e instanceof RuntimeException)
                    throw (RuntimeException) e;
                else
                    throw new ServletException(e.getMessage(), e);
            }
        } else {
            internalDoFilter(request,response);
        }
    }


 private void internalDoFilter(ServletRequest request,
                                  ServletResponse response)
        throws IOException, ServletException {

        // Call the next filter if there is one
        if (pos < n) {
            ApplicationFilterConfig filterConfig = filters[pos++];
            Filter filter = null;
            try {
                filter = filterConfig.getFilter();
                support.fireInstanceEvent(InstanceEvent.BEFORE_FILTER_EVENT,
                                          filter, request, response);

                if (request.isAsyncSupported() && "false".equalsIgnoreCase(
                        filterConfig.getFilterDef().getAsyncSupported())) {
                    request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR,
                            Boolean.FALSE);
                }
                if( Globals.IS_SECURITY_ENABLED ) {
                    final ServletRequest req = request;
                    final ServletResponse res = response;
                    Principal principal =
                        ((HttpServletRequest) req).getUserPrincipal();

                    Object[] args = new Object[]{req, res, this};
                    SecurityUtil.doAsPrivilege
                        ("doFilter", filter, classType, args, principal);

                } else {
                    filter.doFilter(request, response, this);
                }

                support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
                                          filter, request, response);
            } catch (IOException | ServletException | RuntimeException e) {
                if (filter != null)
                    support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
                                              filter, request, response, e);
                throw e;
            } catch (Throwable e) {
                e = ExceptionUtils.unwrapInvocationTargetException(e);
                ExceptionUtils.handleThrowable(e);
                if (filter != null)
                    support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
                                              filter, request, response, e);
                throw new ServletException
                  (sm.getString("filterChain.filter"), e);
            }
            return;
        }

        // We fell off the end of the chain -- call the servlet instance
        try {
            if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
                lastServicedRequest.set(request);
                lastServicedResponse.set(response);
            }

            support.fireInstanceEvent(InstanceEvent.BEFORE_SERVICE_EVENT,
                                      servlet, request, response);
            if (request.isAsyncSupported()
                    && !support.getWrapper().isAsyncSupported()) {
                request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR,
                        Boolean.FALSE);
            }
            // Use potentially wrapped request from this point
            if ((request instanceof HttpServletRequest) &&
                (response instanceof HttpServletResponse)) {

                if( Globals.IS_SECURITY_ENABLED ) {
                    final ServletRequest req = request;
                    final ServletResponse res = response;
                    Principal principal =
                        ((HttpServletRequest) req).getUserPrincipal();
                    Object[] args = new Object[]{req, res};
                    SecurityUtil.doAsPrivilege("service",
                                               servlet,
                                               classTypeUsedInService,
                                               args,
                                               principal);
                } else {
                    servlet.service(request, response);
                }
            } else {
                servlet.service(request, response);
            }
            support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
                                      servlet, request, response);
        } catch (IOException e) {
            support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
                                      servlet, request, response, e);
            throw e;
        } catch (ServletException e) {
            support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
                                      servlet, request, response, e);
            throw e;
        } catch (RuntimeException e) {
            support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
                                      servlet, request, response, e);
            throw e;
        } catch (Throwable e) {
            ExceptionUtils.handleThrowable(e);
            support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
                                      servlet, request, response, e);
            throw new ServletException
              (sm.getString("filterChain.servlet"), e);
        } finally {
            if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
                lastServicedRequest.set(null);
                lastServicedResponse.set(null);
            }
        }

    }


到这里就清楚了, Servlet容器是先执行filter.doFilter, 当所有的Filter都执行完了 ,再执行Servlet.service.
当然,要所有的Filter都执行完,如果在某一个Filter return, 那么Servlet是不会执行的,就像上面的例子,直接跳到错误页面,return 了.

3. Filter destroy.

当容器停止,或Servlet到期时,容器会调用stopInternal(). 这里就不上代码的,累.

分享到:
评论

相关推荐

    Spring Boot mvc web拦截器实现权限访问控制等功能(csdn)————程序.pdf

    在Spring Boot MVC应用中,权限访问控制是必不可少的一部分,它确保了...通过自定义拦截器并注册到Spring Boot的应用上下文中,我们可以轻松地在请求处理的各个阶段插入自己的逻辑,从而实现安全的、优雅的Web服务。

    grpc-web-devtools:Chrome和Firefox浏览器扩展程序可使用本机gRPC-Web拦截器帮助gRPC-Web开发

    gRPC-Web拦截器支持 这个分支增加了对本机gRPC-Web拦截器的支持。 与其他gRPC-Web拦截器不兼容并破坏了它们,这使得无法通过gRPC-Web调试JWT授权之类的东西。 此版本通过将扩展重新实现为一对本地gRPC-Web拦截器来...

    Java web拦截器inteceptor原理及应用详解

    Java Web拦截器Interceptor原理及应用详解 一、简介 Java Web拦截器Interceptor是一种基于Java反射机制实现的拦截技术,依赖于具体的接口,在运行期间动态生成字节码。它提供了一种机制可以使开发者在一个Action...

    WebService之自定义拦截器(server+client)

    在IT行业中,Web服务是应用程序之间进行通信的一种标准方法,而WebService之自定义拦截器的实现,无论是对于服务器端还是客户端,都是为了增强服务的功能性和安全性。本文将深入探讨自定义拦截器的概念、作用以及...

    spring-boot 自定义xml配置web请求拦截器

    标题中的"spring-boot 自定义xml配置web请求拦截器"指的是在Spring Boot项目中,通过XML配置方式实现对Web请求的拦截处理。这涉及到Spring Boot的Web层架构、AOP(面向切面编程)以及自定义拦截器的概念。Spring ...

    CXF3.0+Spring3.2 自定义拦截器

    在Java世界中,Apache CXF是一个非常流行的开源Web服务框架,它允许开发人员创建和消费各种Web服务。CXF3.0版本引入了许多改进和新特性...理解和熟练掌握自定义拦截器的使用,对于提升Web服务的质量和安全性至关重要。

    javaweb拦截器配置及原理.doc

    Java Web 拦截器配置及原理 Java Web 拦截器是一种强大且灵活的技术,允许开发者对 Web 服务器管理的所有 Web 资源进行拦截,以实现一些特殊的功能,例如实现 URL 级别的权限访问控制、过滤敏感词汇、压缩响应信息...

    SpringBoot拦截器原理解析及使用方法

    在SpringBoot框架中,拦截器是一个非常重要的...掌握拦截器的使用,对于开发安全、高效、易于维护的Web应用是非常有帮助的。在实际开发中,合理设计拦截器不仅可以简化业务逻辑,还可以提高系统的可扩展性和可维护性。

    自定义拦截器的实现以及拦截器的详细配置

    在Java Web开发中,拦截器(Interceptor)是一个重要的概念,特别是在使用MVC框架如Struts2时。拦截器可以理解为一种预处理和后处理机制,它在请求到达控制器之前和离开控制器之后进行操作,例如日志记录、权限检查...

    拦截器解决中文乱码问题

    2. **配置拦截器**:在Spring的配置文件(如`web.xml`或`spring-mvc.xml`)中,我们需要注册这个拦截器,将其添加到拦截器链中。 3. **设置请求编码**:在`preHandle`方法中,我们可以获取到HttpServletRequest对象...

    理解拦截器用于在某个方法或字段被访

    在Web开发框架如Struts 2中,拦截器扮演着关键的角色,它们可以实现日志记录、事务管理、权限检查等多种功能。 1. **拦截器的工作原理** 拦截器通常基于代理模式工作。当一个请求到达应用程序时,框架会根据配置...

    .Net WebApi消息拦截器之MessageHandler的示例.docx

    在.NET WebAPI中,消息拦截器(Message Handler)是一种强大的机制,允许开发者在HTTP请求到达控制器之前或响应离开控制器之后进行处理。Message Handler是通过继承`HttpMessageHandler`抽象类来实现的,它使得我们...

    springMVC拦截器项目

    SpringMVC 拦截器项目是一个典型的 Web 应用开发示例,它利用 SpringMVC 框架中的拦截器(Interceptor)机制来实现特定的功能,如权限控制、日志记录、性能统计等。SpringMVC 是 Spring 框架的一部分,专为构建基于 ...

    struts2 拦截器

    Struts2是一个非常著名的Java Web框架,它基于MVC(Model-View-Controller)设计模式,为开发人员提供了构建Web应用程序的强大工具。...在实际项目中,合理利用拦截器可以解决许多常见的问题,提高Web应用程序的质量。

    Struts2拦截器及其用法详细说明

    - XML配置:在`struts.xml`文件中,使用`&lt;interceptor&gt;`元素定义拦截器,`&lt;interceptor-stack&gt;`元素组合多个拦截器,`&lt;package&gt;`元素下的`interceptors`属性指定拦截器栈。 ```xml &lt;!-- 可以添加其他内置或...

    CXF WebService带有拦截器

    本篇文章将深入探讨如何使用CXF来开发具有权限控制功能的Web Service,并通过拦截器实现这一目标。 首先,我们需要理解Web Service拦截器的概念。在CXF中,拦截器是处理消息生命周期中的关键组件,它们可以在消息...

    webwork 权限拦截器

    在Web开发中,权限拦截器扮演着至关重要的角色,它可以在用户请求到达控制器之前进行预处理,判断用户是否有权访问特定的资源或执行特定的操作。这样可以有效地提高系统的安全性,避免非法用户对敏感数据或功能的不...

    struts拦截器的例子

    Struts拦截器是Java Web开发中的重要概念,尤其在基于Struts 2框架的应用中扮演着核心角色。这个"struts拦截器的例子"提供了一个学习和理解拦截器工作原理的起点,非常适合对这一主题感兴趣的初学者。 Struts 2框架...

Global site tag (gtag.js) - Google Analytics