zoukankan      html  css  js  c++  java
  • 深入刨析tomcat 之---第23篇 聊一下web容器的filter配置和defaultservet

    writedby 张艳涛,在一个webapp应用程序内如何配置filter?

    <?xml version="1.0" encoding="ISO-8859-1"?>
    
    <!DOCTYPE web-app
        PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
        "http://java.sun.com/dtd/web-app_2_3.dtd">
    
    <web-app>
      <filter>
        <filter-name>DispatcherFilter</filter-name>
        <filter-class>appdesign2.filter.DispatcherFilter</filter-class>
      </filter>
      <filter-mapping>
        <filter-name>DispatcherFilter</filter-name>
        <url-pattern>/appdesign2/*</url-pattern>
      </filter-mapping>
    </web-app>

    和<servlet>标签对比发现,二者是同一个层级上的,那么servlet被tomcat封装成一个standardWrapper,那么对Filter是如何处理的呢?

    先看下webruleset对标签的解析

    可见对web-app/filter的表情操作时生成了一个FilterDef 对象,并且加入的starndardcontex成员变量上去了

    成员变量

    对filter-mapping标签的解读

    新建了一个FilterMap类型的对象,复制对象,将 web-app/filter-mapping/url-pattern 设置为setURLPattern 

    web-app/filter-mapping/filter-name 设置为  setFilterName

    然后执行standardcontex的addFilterMap方法

    接着在standardcontextvalue中调用invoke方法

    进入到方法map内部,这个是一个standardcontextmapper

    看到有4个规则

    1. 第一个直接匹配 servletMappings.get(pattern));找到对应的wrapper
    2. 和 /A/B/C/D/E,将这个路径后面+/* 进行匹配找到wrapper如果找不到去掉/E,使用/A/B/C/D/* 来查找,知道遍历全部
    3.  /A/B/C/D/E .jpg先使用最后一个/E.jpg 如果有· 那么使用*.jpg进行匹配wrapper
    4. 以上都找不到,找default的servlet

    那么名字为default的servlet以前没配置过,其实这个是在/conf目录下的web.xml中配置的

        <servlet>
            <servlet-name>default</servlet-name>
            <servlet-class>
              org.apache.catalina.servlets.DefaultServlet
            </servlet-class>
            <init-param>
                <param-name>debug</param-name>
                <param-value>0</param-value>
            </init-param>
            <init-param>
                <param-name>listings</param-name>
                <param-value>false</param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
        </servlet>
    
    
    
        <!-- The mapping for the default servlet -->
        <servlet-mapping>
            <servlet-name>default</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>

    那么他是用来访问静态资源的比如你配置如下

    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>*.jpg</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>*.js</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>*.css</url-pattern>
    </servlet-mapping>

    那么一个,如果上述就会按照rule3 匹配到,那么当我们设置springmvc的时候

    给springmvc的匹配规则就是"/" 而不能是"/*,否则什么都给匹配了,

      <servlet>
           <servlet-name>springmvc</servlet-name>
           <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
           <!-- contextConfigLocation配置springmvc加载的配置文件(配置处理器映射器,适配器等等)
           如果不配置,默认加载的是/WEB-INF/[DispatcherServlet 的Servlet 名字]-servlet.xml(springmvc-servlet.xml) -->
           <init-param>
               <param-name>contextConfigLocation</param-name>
               <param-value>classpath:spring/springmvc.xml</param-value>
           </init-param>
           <load-on-startup>1</load-on-startup>
       </servlet>
       <servlet-mapping>
           <servlet-name>springmvc</servlet-name>
           <url-pattern>/</url-pattern>
       </servlet-mapping>

    那么就是就是将"/"的rule匹配上了,将原来的"/"对于为default,现在"/"对于为springmvc dispatcherservlet,可见对于源码的解读有助于学习sprngmvc

    接着聊


    现在什么也没匹配到,则,实际上是通过如果不使用springmvc,那么tomcat在default之中,实现了对静态资源的访问,

    那么接着看如何调用filter,

    在standardwrappervalue之中

    进入

    进入

    看到调用filter.doFilter(),方法,我们看自己定义的filter怎么写的

    package appdesign2.filter;
    import java.io.IOException;
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.RequestDispatcher;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    
    import javax.servlet.http.HttpServletRequest;
    
    import appdesign2.action.SaveProductAction;
    import appdesign2.form.ProductForm;
    import appdesign2.model.Product;
    import java.math.BigDecimal;
    
    
    public class DispatcherFilter implements Filter {
    
        @Override
        public void init(FilterConfig filterConfig)
                throws ServletException {
        }
    
        @Override
        public void destroy() {
        }
    
        @Override
        public void doFilter(ServletRequest request,
                ServletResponse response, FilterChain filterChain)
                throws IOException, ServletException {
            HttpServletRequest req = (HttpServletRequest) request;
            String uri = req.getRequestURI();
            /*
             * uri is in this form: /contextName/resourceName, for
             * example /appdesign2/input-product. However, in the
             * case of a default context, the context name is empty,
             * and uri has this form /resourceName, e.g.:
             * /input-product
             */
            // action processing
            int lastIndex = uri.lastIndexOf("/");
            String action = uri.substring(lastIndex + 1);
            String dispatchUrl = null;
            if ("input-product".equals(action)) {
                // do nothing
                dispatchUrl = "/jsp/ProductForm.jsp";
            } else if ("save-product".equals(action)) {
                // create form
                ProductForm productForm = new ProductForm();
                // populate action properties
                productForm.setName(request.getParameter("name"));
                productForm.setDescription(
                        request.getParameter("description"));
                productForm.setPrice(request.getParameter("price"));
                
                // create model
                Product product = new Product();
                product.setName(productForm.getName());
                product.setDescription(product.getDescription());
                try {
                    product.setPrice(new BigDecimal(productForm.getPrice()));
                } catch (NumberFormatException e) {
                }
                // execute action method
                SaveProductAction saveProductAction = 
                        new SaveProductAction();
                saveProductAction.save(product);
                
                // store model in a scope variable for the view
                request.setAttribute("product", product);
                dispatchUrl = "/jsp/ProductDetails.jsp";
            }
            // forward to a view
            if (dispatchUrl != null) {
                RequestDispatcher rd = request
                        .getRequestDispatcher(dispatchUrl);
                rd.forward(request, response);
            } else {
                // let static contents pass
                filterChain.doFilter(request, response);
            }
        }
    }

    看的,如果先接着访问下一个filter就执行 filterChain.doFilter(request, response); 返回到上级方法的执行链在doFilter,

    如果想打住就执行自己的操作,返回之后执行链会return

    从而执行完了调用,返回的connector中,执行response.finish()方法,

    这个filter的使用非常类似于自定义value

  • 相关阅读:
    20181123(编码问题)
    20181122笔记(列表、元组、字典和集合的数据类型及内置方法)
    20181121笔记(for,数字类型和字符串类型的内置方法)
    20181120笔记
    Python的第3堂课
    错误集合(想起来就更新)
    Python的第二堂课(2)
    Python的第二堂课(1)
    boost::bind实践2——来自《Beyond the C++ Standard Library ( An Introduction to Boost )》
    boost::bind实践
  • 原文地址:https://www.cnblogs.com/zytcomeon/p/15058175.html
Copyright © 2011-2022 走看看