tomcat源码学习--轰炸机core(一)

前言:
    catalina下面的core包,包含了很多我们平时一直使用到的东西,以前一直用不知道原理,也只知道j2EE api里面的东西,在tomcat下写了这么久得程序,一直疑惑它到底是怎么做到的,下面就可以好好看看了。


    首先application,实现javax.servlet Interface ServletContext
引用

Defines a set of methods that a servlet uses to communicate with its servlet container, for example, to get the MIME type of a file, dispatch requests, or write to a log file.

There is one context per "web application" per Java Virtual Machine. (A "web application" is a collection of servlets and content installed under a specific subset of the server's URL namespace such as /catalog and possibly installed via a .war file.)

In the case of a web application marked "distributed" in its deployment descriptor, there will be one context instance for each virtual machine. In this situation, the context cannot be used as a location to share global information (because the information won't be truly global). Use an external resource like a database instead.

The ServletContext object is contained within the ServletConfig object, which the Web server provides the servlet when the servlet is initialized.

    这家伙很重要,那么每个容器必须自己实现他的规则,tomcat如何实现呢?
eclipse果断查找


    ApplicationContextFacade是为ApplicationContext服务的一个类,ApplicationContext才是标准实现了这个借口的类,至于JspCServletContext是Simple ServletContext
  那么就重点看ApplicationContext,有的属性如下

构造方法如下:
引用

  /**
     * Construct a new instance of this class, associated with the specified
     * Context instance.
     *
     * @param context The associated Context instance
     */
    public ApplicationContext(String basePath, StandardContext context) {
        super();
        this.context = context;
        this.basePath = basePath;
    }

    里面的StandardContext是实现标准Context借口的类,这个上下文借口是tomcat自己定义的,里面涉及到tomcat容器的众多处理,并且他还是个集成Container借口的接口,这么看来这个StandardContext是相当强大,当然没有这么一个强大的处理类注入,并且这个注入的类也需要从从操作里面反馈给自己很多东西
   具体看里面的方法,经常用到的属性值set/getAttribute(String) ,重点看set,能解决很多以前的疑惑,里面的层层判断说明不是自己想得那样就是map里面put,它有自己的策略,没次还要去看readOnlyAttributes里面是否有这个key,有就不能移除。

public void setAttribute(String name, Object value) {

        // Name cannot be null
        if (name == null)
            throw new IllegalArgumentException
                (sm.getString("applicationContext.setAttribute.namenull"));

        // Null value is the same as removeAttribute()
        if (value == null) {
            removeAttribute(name);
            return;
        }

        Object oldValue = null;
        boolean replaced = false;

        // Add or replace the specified attribute
        // Check for read only attribute
        if (readOnlyAttributes.containsKey(name))
            return;
        oldValue = attributes.get(name);
        if (oldValue != null)
            replaced = true;
        attributes.put(name, value);

        // Notify interested application event listeners
        Object listeners[] = context.getApplicationEventListeners();
        if ((listeners == null) || (listeners.length == 0))
            return;
        ServletContextAttributeEvent event = null;
        if (replaced)
            event =
                new ServletContextAttributeEvent(context.getServletContext(),
                                                 name, oldValue);
        else
            event =
                new ServletContextAttributeEvent(context.getServletContext(),
                                                 name, value);

        for (int i = 0; i < listeners.length; i++) {
            if (!(listeners[i] instanceof ServletContextAttributeListener))
                continue;
            ServletContextAttributeListener listener =
                (ServletContextAttributeListener) listeners[i];
            try {
                if (replaced) {
                    context.fireContainerEvent
                        ("beforeContextAttributeReplaced", listener);
                    listener.attributeReplaced(event);
                    context.fireContainerEvent("afterContextAttributeReplaced",
                                               listener);
                } else {
                    context.fireContainerEvent("beforeContextAttributeAdded",
                                               listener);
                    listener.attributeAdded(event);
                    context.fireContainerEvent("afterContextAttributeAdded",
                                               listener);
                }
            } catch (Throwable t) {
                if (replaced)
                    context.fireContainerEvent("afterContextAttributeReplaced",
                                               listener);
                else
                    context.fireContainerEvent("afterContextAttributeAdded",
                                               listener);
                // FIXME - should we do anything besides log these?
                log(sm.getString("applicationContext.attributeEvent"), t);
            }
        }

    }


   容器里面使用的是哪一个呢?我们并不知道,我们完全是面对借口来编程,遵循j2ee api规范,然后具体的方法具体的容器有自己的实现。

    同样下面还有req reps,分别有两个实现,比如继承自HttpServletRequestWrapper或者ServletRequestWrapper的两个类,还来了句这个,顶层都是ServletRequest
引用

WARNING</strong>:  Due to Java's lack of support for multiple
* inheritance, all of the logic in <code>ApplicationRequest</code> is
* duplicated in <code>ApplicationHttpRequest</code>.  Make sure that you
* keep these two classes in synchronization when making changes!

   我比较关注session,里面还是一些session的策略,如果怎样变怎样,session为了安全只有一份,原来这两个getSession(),getSession(boolean create)是这么个关系,以前都挺纠结的
    /**
     * Return the session associated with this Request, creating one
     * if necessary.
     */
    public HttpSession getSession() {
        return (getSession(true));
    }

 /**
     * Return the session associated with this Request, creating one
     * if necessary and requested.
     *
     * @param create Create a new session if one does not exist
     */
    public HttpSession getSession(boolean create) {

        if (crossContext) {
            
            // There cannot be a session if no context has been assigned yet
            if (context == null)
                return (null);

            // Return the current session if it exists and is valid
            if (session != null && session.isValid()) {
                return (session.getSession());
            }

            HttpSession other = super.getSession(false);
            if (create && (other == null)) {
                // First create a session in the first context: the problem is
                // that the top level request is the only one which can 
                // create the cookie safely
                other = super.getSession(true);
            }
            if (other != null) {
                Session localSession = null;
                try {
                    localSession =
                        context.getManager().findSession(other.getId());
                    if (localSession != null && !localSession.isValid()) {
                        localSession = null;
                    }
                } catch (IOException e) {
                    // Ignore
                }
                if (localSession == null && create) {
                    localSession = 
                        context.getManager().createSession(other.getId());
                }
                if (localSession != null) {
                    localSession.access();
                    session = localSession;
                    return session.getSession();
                }
            }
            return null;

        } else {
            return super.getSession(create);
        }

    }


    ps:好累啊,看不动了,下次重点看下面的几个复杂的容器类ContainerBase Lifecycle







猜你喜欢

转载自blognojava.iteye.com/blog/1144388