`
Tyrion
  • 浏览: 260866 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

Tomcat7中web应用加载原理(二)web.xml解析

阅读更多

前一篇文章讲了org.apache.catalina.startup.HostConfig的lifecycleEvent方法中所做的事情。最后看到在Tomcat启动时或启动后(后台线程定时扫描)会调用HostConfig类的deployApps方法:

    /**
     * Deploy applications for any directories or WAR files that are found
     * in our "application root" directory.
     */
    protected void deployApps() {

        File appBase = appBase();
        File configBase = configBase();
        String[] filteredAppPaths = filterAppPaths(appBase.list());
        // Deploy XML descriptors from configBase
        deployDescriptors(configBase, configBase.list());
        // Deploy WARs
        deployWARs(appBase, filteredAppPaths);
        // Deploy expanded folders
        deployDirectories(appBase, filteredAppPaths);

    }

可以看到这里部署应用有三种方式:XML文件描述符、WAR包、文件目录。三种方式部署的总体流程很相似,都是一个web应用分配一个线程来处理,这里统一放到与Host内部的线程池对象中(startStopExecutor),所以有时会看到在默认配置下Tomcat启动后可能有一个叫“-startStop-”的线程还会运行一段时间才结束。但浏览这三种部署方式的实现代码,里面都是构建一个Context对象,并将构建好的Context对象与Host组件关联起来(即调用host.addChild(context)这句,具体代码在HostConfig类的deployDescriptor(ContextName cn, File contextXml)、deployDirectory(ContextName cn, File dir)、deployWAR(ContextName cn, File war)三个方法中,这里不再贴出代码来详细分析)。

前一篇文章只分析到这步,可以看出与一个web应用相对应的一个Context对象已经构建出来了,但如果容器只执行到这里根本无法响应一个浏览器的一次请求。就web服务器的实现来看一次请求过来除了需要根据内部Context构建找到这次请求访问的web应用具体所对应的Context对象,还需要包含web应用中具体的哪个Servlet来处理这次请求,中间是否还需要执行相应的过滤器(filter)、监听器(listener)等,做过java的web开发的都知道,这些信息是配置在一个web应用的WEB-INF\web.xml文件的(servlet3中已经支持将这些配置信息放到Java文件的注解中,但万变不离其宗,总归要在web应用的某个地方说明,并在容器启动时加载,这样才能真正提供web服务,响应请求)。

 

看到这里可以猜到Tomcat容器加载web应用时必定会有对于每个应用的web.xml文件的解析过程,本文就来看看这个解析过程。

 

在本文开头提到的三种部署应用的实现代码中有一些共通的代码,这里摘出来说明一下:

            Class<?> clazz = Class.forName(host.getConfigClass());
            LifecycleListener listener =
                (LifecycleListener) clazz.newInstance();
            context.addLifecycleListener(listener);
            host.addChild(context);

第一段是在所有Context对象构建时会添加一个监听器,这里监听器的类名是StandardHost类的实例变量configClass,其默认值就是org.apache.catalina.startup.ContextConfig。第二段是将当前构建的Context对象添加到父容器Host对象中。

先看下StandardHost的addChild方法的实现:

    public void addChild(Container child) {

        child.addLifecycleListener(new MemoryLeakTrackingListener());

        if (!(child instanceof Context))
            throw new IllegalArgumentException
                (sm.getString("standardHost.notContext"));
        super.addChild(child);

    }

可以看到这段代码最后调用了父类的addChild方法:

    public void addChild(Container child) {
        if (Globals.IS_SECURITY_ENABLED) {
            PrivilegedAction<Void> dp =
                new PrivilegedAddChild(child);
            AccessController.doPrivileged(dp);
        } else {
            addChildInternal(child);
        }
    }

这里看下addChildInternal方法的实现:

    private void addChildInternal(Container child) {

        if( log.isDebugEnabled() )
            log.debug("Add child " + child + " " + this);
        synchronized(children) {
            if (children.get(child.getName()) != null)
                throw new IllegalArgumentException("addChild:  Child name '" +
                                                   child.getName() +
                                                   "' is not unique");
            child.setParent(this);  // May throw IAE
            children.put(child.getName(), child);
        }

        // Start child
        // Don't do this inside sync block - start can be a slow process and
        // locking the children object can cause problems elsewhere
        if ((getState().isAvailable() ||
                LifecycleState.STARTING_PREP.equals(getState())) &&
                startChildren) {
            try {
                child.start();
            } catch (LifecycleException e) {
                log.error("ContainerBase.addChild: start: ", e);
                throw new IllegalStateException
                    ("ContainerBase.addChild: start: " + e);
            }
        }

        fireContainerEvent(ADD_CHILD_EVENT, child);
    }

可以看到会调用子容器的start方法,就是指调用StandardContext的start方法。

即给host对象添加子容器时将会调用子容器的start方法,按照前面文章的分析,调用StandardContext的start方法最终会调用org.apache.catalina.core.StandardContext类的startInternal方法(该方法代码较长,建议自己阅读,不再贴出),这里将会发布一系列事件,按调用前后顺序这些事件包括:BEFORE_INIT_EVENT、AFTER_INIT_EVENT、BEFORE_START_EVENT、CONFIGURE_START_EVENT、START_EVENT、AFTER_START_EVENT。

 

前面提到在构建Context对象时都会注册一个监听器org.apache.catalina.startup.ContextConfig,看下这个类的lifecycleEvent方法中(为什么会执行这个方法可以看本博文章的分析)监听了哪些事件:

    /**
     * Process events for an associated Context.
     *
     * @param event The lifecycle event that has occurred
     */
    @Override
    public void lifecycleEvent(LifecycleEvent event) {

        // Identify the context we are associated with
        try {
            context = (Context) event.getLifecycle();
        } catch (ClassCastException e) {
            log.error(sm.getString("contextConfig.cce", event.getLifecycle()), e);
            return;
        }

        // Process the event that has occurred
        if (event.getType().equals(Lifecycle.CONFIGURE_START_EVENT)) {
            configureStart();
        } else if (event.getType().equals(Lifecycle.BEFORE_START_EVENT)) {
            beforeStart();
        } else if (event.getType().equals(Lifecycle.AFTER_START_EVENT)) {
            // Restore docBase for management tools
            if (originalDocBase != null) {
                context.setDocBase(originalDocBase);
            }
        } else if (event.getType().equals(Lifecycle.CONFIGURE_STOP_EVENT)) {
            configureStop();
        } else if (event.getType().equals(Lifecycle.AFTER_INIT_EVENT)) {
            init();
        } else if (event.getType().equals(Lifecycle.AFTER_DESTROY_EVENT)) {
            destroy();
        }

    }

与Context的start方法调用相关的事件监听前后顺序为:AFTER_INIT_EVENT(执行init方法)、BEFORE_START_EVENT(执行beforeStart方法)、CONFIGURE_START_EVENT(执行configureStart方法)。

在configureStart方法将直接调用webConfig方法,正是在这个方法中将会解析web.xml文件:

    /**
     * Scan the web.xml files that apply to the web application and merge them
     * using the rules defined in the spec. For the global web.xml files,
     * where there is duplicate configuration, the most specific level wins. ie
     * an application's web.xml takes precedence over the host level or global
     * web.xml file.
     */
    protected void webConfig() {
        /*
         * Anything and everything can override the global and host defaults.
         * This is implemented in two parts
         * - Handle as a web fragment that gets added after everything else so
         *   everything else takes priority
         * - Mark Servlets as overridable so SCI configuration can replace
         *   configuration from the defaults
         */

        /*
         * The rules for annotation scanning are not as clear-cut as one might
         * think. Tomcat implements the following process:
         * - As per SRV.1.6.2, Tomcat will scan for annotations regardless of
         *   which Servlet spec version is declared in web.xml. The EG has
         *   confirmed this is the expected behaviour.
         * - As per http://java.net/jira/browse/SERVLET_SPEC-36, if the main
         *   web.xml is marked as metadata-complete, JARs are still processed
         *   for SCIs.
         * - If metadata-complete=true and an absolute ordering is specified,
         *   JARs excluded from the ordering are also excluded from the SCI
         *   processing.
         * - If an SCI has a @HandlesType annotation then all classes (except
         *   those in JARs excluded from an absolute ordering) need to be
         *   scanned to check if they match.
         */
        Set<WebXml> defaults = new HashSet<WebXml>();
        defaults.add(getDefaultWebXmlFragment());

        WebXml webXml = createWebXml();

        // Parse context level web.xml
        InputSource contextWebXml = getContextWebXmlSource();
        parseWebXml(contextWebXml, webXml, false);

        ServletContext sContext = context.getServletContext();

        // Ordering is important here

        // Step 1. Identify all the JARs packaged with the application
        // If the JARs have a web-fragment.xml it will be parsed at this
        // point.
        Map<String,WebXml> fragments = processJarsForWebFragments();

        // Step 2. Order the fragments.
        Set<WebXml> orderedFragments = null;
        orderedFragments =
                WebXml.orderWebFragments(webXml, fragments, sContext);

        // Step 3. Look for ServletContainerInitializer implementations
        if (ok) {
            processServletContainerInitializers(orderedFragments);
        }

        if  (!webXml.isMetadataComplete() || typeInitializerMap.size() > 0) {
            // Step 4. Process /WEB-INF/classes for annotations
            if (ok) {
                // Hack required by Eclipse's "serve modules without
                // publishing" feature since this backs WEB-INF/classes by
                // multiple locations rather than one.
                NamingEnumeration<Binding> listBindings = null;
                try {
                    try {
                        listBindings = context.getResources().listBindings(
                                "/WEB-INF/classes");
                    } catch (NameNotFoundException ignore) {
                        // Safe to ignore
                    }
                    while (listBindings != null &&
                            listBindings.hasMoreElements()) {
                        Binding binding = listBindings.nextElement();
                        if (binding.getObject() instanceof FileDirContext) {
                            File webInfClassDir = new File(
                                    ((FileDirContext) binding.getObject()).getDocBase());
                            processAnnotationsFile(webInfClassDir, webXml,
                                    webXml.isMetadataComplete());
                        } else {
                            String resource =
                                    "/WEB-INF/classes/" + binding.getName();
                            try {
                                URL url = sContext.getResource(resource);
                                processAnnotationsUrl(url, webXml,
                                        webXml.isMetadataComplete());
                            } catch (MalformedURLException e) {
                                log.error(sm.getString(
                                        "contextConfig.webinfClassesUrl",
                                        resource), e);
                            }
                        }
                    }
                } catch (NamingException e) {
                    log.error(sm.getString(
                            "contextConfig.webinfClassesUrl",
                            "/WEB-INF/classes"), e);
                }
            }

            // Step 5. Process JARs for annotations - only need to process
            // those fragments we are going to use
            if (ok) {
                processAnnotations(
                        orderedFragments, webXml.isMetadataComplete());
            }

            // Cache, if used, is no longer required so clear it
            javaClassCache.clear();
        }

        if (!webXml.isMetadataComplete()) {
            // Step 6. Merge web-fragment.xml files into the main web.xml
            // file.
            if (ok) {
                ok = webXml.merge(orderedFragments);
            }

            // Step 7. Apply global defaults
            // Have to merge defaults before JSP conversion since defaults
            // provide JSP servlet definition.
            webXml.merge(defaults);

            // Step 8. Convert explicitly mentioned jsps to servlets
            if (ok) {
                convertJsps(webXml);
            }

            // Step 9. Apply merged web.xml to Context
            if (ok) {
                webXml.configureContext(context);
            }
        } else {
            webXml.merge(defaults);
            convertJsps(webXml);
            webXml.configureContext(context);
        }

        // Step 9a. Make the merged web.xml available to other
        // components, specifically Jasper, to save those components
        // from having to re-generate it.
        // TODO Use a ServletContainerInitializer for Jasper
        String mergedWebXml = webXml.toXml();
        sContext.setAttribute(
               org.apache.tomcat.util.scan.Constants.MERGED_WEB_XML,
               mergedWebXml);
        if (context.getLogEffectiveWebXml()) {
            log.info("web.xml:\n" + mergedWebXml);
        }

        // Always need to look for static resources
        // Step 10. Look for static resources packaged in JARs
        if (ok) {
            // Spec does not define an order.
            // Use ordered JARs followed by remaining JARs
            Set<WebXml> resourceJars = new LinkedHashSet<WebXml>();
            if (orderedFragments != null) {
                for (WebXml fragment : orderedFragments) {
                    resourceJars.add(fragment);
                }
            }
            for (WebXml fragment : fragments.values()) {
                if (!resourceJars.contains(fragment)) {
                    resourceJars.add(fragment);
                }
            }
            processResourceJARs(resourceJars);
            // See also StandardContext.resourcesStart() for
            // WEB-INF/classes/META-INF/resources configuration
        }

        // Step 11. Apply the ServletContainerInitializer config to the
        // context
        if (ok) {
            for (Map.Entry<ServletContainerInitializer,
                    Set<Class<?>>> entry :
                        initializerClassMap.entrySet()) {
                if (entry.getValue().isEmpty()) {
                    context.addServletContainerInitializer(
                            entry.getKey(), null);
                } else {
                    context.addServletContainerInitializer(
                            entry.getKey(), entry.getValue());
                }
            }
        }
    }

这个方法里面做的事情,在英文注释中说的很清楚了,概括起来包括合并Tomcat全局web.xml、当前应用中的web.xml、web-fragment.xml和web应用的注解中的配置信息,并将解析出的各种配置信息(如servlet配置、filter配置等)关联到Context对象中(在上面的代码第140行:webXml.configureContext(context))。

看下configureContext方法:

    /**
     * Configure a {@link Context} using the stored web.xml representation.
     *
     * @param context   The context to be configured
     */
    public void configureContext(Context context) {
        // As far as possible, process in alphabetical order so it is easy to
        // check everything is present
        // Some validation depends on correct public ID
        context.setPublicId(publicId);

        // Everything else in order
        context.setEffectiveMajorVersion(getMajorVersion());
        context.setEffectiveMinorVersion(getMinorVersion());

        for (Entry<String, String> entry : contextParams.entrySet()) {
            context.addParameter(entry.getKey(), entry.getValue());
        }
        context.setDisplayName(displayName);
        context.setDistributable(distributable);
        for (ContextLocalEjb ejbLocalRef : ejbLocalRefs.values()) {
            context.getNamingResources().addLocalEjb(ejbLocalRef);
        }
        for (ContextEjb ejbRef : ejbRefs.values()) {
            context.getNamingResources().addEjb(ejbRef);
        }
        for (ContextEnvironment environment : envEntries.values()) {
            context.getNamingResources().addEnvironment(environment);
        }
        for (ErrorPage errorPage : errorPages.values()) {
            context.addErrorPage(errorPage);
        }
        for (FilterDef filter : filters.values()) {
            if (filter.getAsyncSupported() == null) {
                filter.setAsyncSupported("false");
            }
            context.addFilterDef(filter);
        }
        for (FilterMap filterMap : filterMaps) {
            context.addFilterMap(filterMap);
        }
        for (JspPropertyGroup jspPropertyGroup : jspPropertyGroups) {
            JspPropertyGroupDescriptor descriptor =
                new ApplicationJspPropertyGroupDescriptor(jspPropertyGroup);
            context.getJspConfigDescriptor().getJspPropertyGroups().add(
                    descriptor);
        }
        for (String listener : listeners) {
            context.addApplicationListener(
                    new ApplicationListener(listener, false));
        }
        for (Entry<String, String> entry : localeEncodingMappings.entrySet()) {
            context.addLocaleEncodingMappingParameter(entry.getKey(),
                    entry.getValue());
        }
        // Prevents IAE
        if (loginConfig != null) {
            context.setLoginConfig(loginConfig);
        }
        for (MessageDestinationRef mdr : messageDestinationRefs.values()) {
            context.getNamingResources().addMessageDestinationRef(mdr);
        }

        // messageDestinations were ignored in Tomcat 6, so ignore here

        context.setIgnoreAnnotations(metadataComplete);
        for (Entry<String, String> entry : mimeMappings.entrySet()) {
            context.addMimeMapping(entry.getKey(), entry.getValue());
        }
        // Name is just used for ordering
        for (ContextResourceEnvRef resource : resourceEnvRefs.values()) {
            context.getNamingResources().addResourceEnvRef(resource);
        }
        for (ContextResource resource : resourceRefs.values()) {
            context.getNamingResources().addResource(resource);
        }
        for (SecurityConstraint constraint : securityConstraints) {
            context.addConstraint(constraint);
        }
        for (String role : securityRoles) {
            context.addSecurityRole(role);
        }
        for (ContextService service : serviceRefs.values()) {
            context.getNamingResources().addService(service);
        }
        for (ServletDef servlet : servlets.values()) {
            Wrapper wrapper = context.createWrapper();
            // Description is ignored
            // Display name is ignored
            // Icons are ignored

            // jsp-file gets passed to the JSP Servlet as an init-param

            if (servlet.getLoadOnStartup() != null) {
                wrapper.setLoadOnStartup(servlet.getLoadOnStartup().intValue());
            }
            if (servlet.getEnabled() != null) {
                wrapper.setEnabled(servlet.getEnabled().booleanValue());
            }
            wrapper.setName(servlet.getServletName());
            Map<String,String> params = servlet.getParameterMap();
            for (Entry<String, String> entry : params.entrySet()) {
                wrapper.addInitParameter(entry.getKey(), entry.getValue());
            }
            wrapper.setRunAs(servlet.getRunAs());
            Set<SecurityRoleRef> roleRefs = servlet.getSecurityRoleRefs();
            for (SecurityRoleRef roleRef : roleRefs) {
                wrapper.addSecurityReference(
                        roleRef.getName(), roleRef.getLink());
            }
            wrapper.setServletClass(servlet.getServletClass());
            MultipartDef multipartdef = servlet.getMultipartDef();
            if (multipartdef != null) {
                if (multipartdef.getMaxFileSize() != null &&
                        multipartdef.getMaxRequestSize()!= null &&
                        multipartdef.getFileSizeThreshold() != null) {
                    wrapper.setMultipartConfigElement(new MultipartConfigElement(
                            multipartdef.getLocation(),
                            Long.parseLong(multipartdef.getMaxFileSize()),
                            Long.parseLong(multipartdef.getMaxRequestSize()),
                            Integer.parseInt(
                                    multipartdef.getFileSizeThreshold())));
                } else {
                    wrapper.setMultipartConfigElement(new MultipartConfigElement(
                            multipartdef.getLocation()));
                }
            }
            if (servlet.getAsyncSupported() != null) {
                wrapper.setAsyncSupported(
                        servlet.getAsyncSupported().booleanValue());
            }
            wrapper.setOverridable(servlet.isOverridable());
            context.addChild(wrapper);
        }
        for (Entry<String, String> entry : servletMappings.entrySet()) {
            context.addServletMapping(entry.getKey(), entry.getValue());
        }
        if (sessionConfig != null) {
            if (sessionConfig.getSessionTimeout() != null) {
                context.setSessionTimeout(
                        sessionConfig.getSessionTimeout().intValue());
            }
            SessionCookieConfig scc =
                context.getServletContext().getSessionCookieConfig();
            scc.setName(sessionConfig.getCookieName());
            scc.setDomain(sessionConfig.getCookieDomain());
            scc.setPath(sessionConfig.getCookiePath());
            scc.setComment(sessionConfig.getCookieComment());
            if (sessionConfig.getCookieHttpOnly() != null) {
                scc.setHttpOnly(sessionConfig.getCookieHttpOnly().booleanValue());
            }
            if (sessionConfig.getCookieSecure() != null) {
                scc.setSecure(sessionConfig.getCookieSecure().booleanValue());
            }
            if (sessionConfig.getCookieMaxAge() != null) {
                scc.setMaxAge(sessionConfig.getCookieMaxAge().intValue());
            }
            if (sessionConfig.getSessionTrackingModes().size() > 0) {
                context.getServletContext().setSessionTrackingModes(
                        sessionConfig.getSessionTrackingModes());
            }
        }
        for (Entry<String, String> entry : taglibs.entrySet()) {
            TaglibDescriptor descriptor = new ApplicationTaglibDescriptor(
                    entry.getValue(), entry.getKey());
            context.getJspConfigDescriptor().getTaglibs().add(descriptor);
        }

        // Context doesn't use version directly

        for (String welcomeFile : welcomeFiles) {
            /*
             * The following will result in a welcome file of "" so don't add
             * that to the context
             * <welcome-file-list>
             *   <welcome-file/>
             * </welcome-file-list>
             */
            if (welcomeFile != null && welcomeFile.length() > 0) {
                context.addWelcomeFile(welcomeFile);
            }
        }

        // Do this last as it depends on servlets
        for (JspPropertyGroup jspPropertyGroup : jspPropertyGroups) {
            String jspServletName = context.findServletMapping("*.jsp");
            if (jspServletName == null) {
                jspServletName = "jsp";
            }
            if (context.findChild(jspServletName) != null) {
                for (String urlPattern : jspPropertyGroup.getUrlPatterns()) {
                    context.addServletMapping(urlPattern, jspServletName, true);
                }
            } else {
                if(log.isDebugEnabled()) {
                    for (String urlPattern : jspPropertyGroup.getUrlPatterns()) {
                        log.debug("Skiping " + urlPattern + " , no servlet " +
                                jspServletName);
                    }
                }
            }
        }

        for (Entry<String, String> entry : postConstructMethods.entrySet()) {
            context.addPostConstructMethod(entry.getKey(), entry.getValue());
        }

        for (Entry<String, String> entry : preDestroyMethods.entrySet()) {
            context.addPreDestroyMethod(entry.getKey(), entry.getValue());
        }
    }

可以看到里面对context调用了各种set、add方法,从而将web.xml中的各种配置信息与表示一个web应用的context对象关联起来。

3
2
分享到:
评论
5 楼 Tyrion 2017-03-24  
PS:这里的博客已经不更新了,新博客在简书:http://www.jianshu.com/u/6c5d73c5b4cb
Tomcat的源码分析是几年前搞的了,现在精力主要focus在微服务的相关技术实践上。
4 楼 Tyrion 2017-03-24  
小帅1127 写道
确实难得得好文 就是不知道作者现在还从不从事软件开发了

啊好久不登javaeye了,刚看到,我从毕业到现在一直在coding。。。
3 楼 小帅1127 2017-03-02  
确实难得得好文 就是不知道作者现在还从不从事软件开发了
2 楼 akka_li 2016-04-03  
非常感谢楼主!终于对容器解析web.xml的过程有了一点点了解了!!
1 楼 steafler 2013-09-19  
wonderful, come on baby.

相关推荐

    在web.xml中引入其他xml配置文件的步骤

    2. **启用实体解析**:如果是在Tomcat服务器上运行的应用程序,则需要在`context.xml`文件中启用实体解析。在`&lt;Context&gt;`元素中加入`xmlBlockExternal="false"`属性。 ```xml ``` 3. **调整安全设置**:某些...

    无法在web.xml或使用此应用程序部署的jar文件中解析绝对uri:[http://java.sun.com/jsp/jstl

    在web.xml配置文件中,我们需要正确引用这些TLD文件,以便Web容器(如Tomcat)能识别并加载JSTL库。 描述中提到的解决方案是提供了一个压缩包,包含`lib`和`tld`两个文件夹。`lib`文件夹通常用于存放应用所需的JAR...

    Tomcat(二) Tomcat实现:Servlet与web.xml介绍 以及 源码分析Tomcat实现细节1

    - **启动/初始化**:Tomcat启动时会解析web.xml,创建并初始化应用的组件。 - **并发线程模式**:Tomcat使用线程池来处理并发请求,提高性能。 - **接收请求与处理**:Tomcat通过Coyote Connector接收HTTP请求,...

    tomcat6 server.xml 详解

    在Java Web开发中,Tomcat作为一款广泛应用的开源Servlet容器,其配置文件server.xml的重要性不言而喻。本文将深入探讨Tomcat6版本中的server.xml,揭示其中的核心配置元素,帮助开发者更好地理解和定制服务器环境。...

    Tomcat Web.xml 详解

    ### Tomcat Web.xml 详解 #### 一、概述 ...通过以上解析可以看出,`web.xml` 文件在Java Web应用中扮演着非常重要的角色。合理地利用这些元素可以帮助我们更好地组织和管理Web应用,提高开发效率和应用性能。

    tomcatserver.xml配置详解.pdf

    - reloadable="true":设置是否监视在WEB-INF/classes和WEB-INF/lib目录下的class文件的改动,如果检测到变动,将自动重新加载Web应用。 7. 连接器相关配置:如HTTP连接器可能配置的redirectPort,用于指定包含...

    Tomcat web.xml 文件详解

    `web.xml` 是部署在Tomcat服务器上的Web应用程序的核心配置文件之一。对于初次接触Tomcat部署的开发者而言,理解和掌握`web.xml`的配置至关重要。本文旨在深入解析`web.xml`的各项配置细节,并通过示例代码来帮助...

    Tomcat中web.xml文件的详细说明

    在Java的Web应用中,Tomcat作为常用的Servlet容器,其配置文件`web.xml`起着至关重要的作用。它是Web应用程序的部署描述符,定义了应用的行为、组件、安全性和资源引用等信息。以下是对`web.xml`文件中各主要元素的...

    java/jsp web.xml详解

    在Java和JSP开发中,`web.xml`文件是一个至关重要的组成部分,它是Servlet容器(如Tomcat)的部署描述符。这个文件包含了关于Web应用程序的配置信息,包括Servlet的定义、过滤器、监听器、会话配置、MIME类型映射、...

    Web.xml配置文件.pdf

    `Web.xml`文件是Servlet容器(如Tomcat、Jetty)解析的配置文件,它为Web应用程序提供了元数据,包括Servlet、过滤器、监听器、会话配置、错误页面等。该文件位于`WEB-INF`目录下,是Java Web应用的标准配置部分。 ...

    用web.xml控制Web应用的行为

    虽然XML文件的解析通常不依赖于元素顺序,但`web.xml`中某些元素的位置是有意义的。例如,servlet和filter的声明应在它们被引用之前定义。 3. **分配名称和定制的URL** - **分配名称**:通过`&lt;servlet-name&gt;`元素...

    Tomcat的server.xml文件

    《深入解析Tomcat的server.xml文件》 在Java Web开发中,Tomcat作为一个广泛应用的开源Servlet容器,扮演着至关重要的角色。它的配置核心在于`server.xml`文件,这是Tomcat服务器的主要配置文件,包含了服务器的...

    web.xml中ContextLoaderListener的运行过程解析

    1. **初始化阶段**:当Servlet容器启动并加载Web应用时,会扫描`web.xml`文件,找到所有`&lt;listener&gt;`标签,为每个监听器创建实例。 2. **注册监听器**:Servlet容器将`ContextLoaderListener`实例注册为`...

    tomcat7.0下载

    在Tomcat7.0中,管理工具也得到了改善,例如,通过web管理界面可以更加便捷地管理应用程序、查看服务器状态以及进行安全配置。此外,7.0版本对内存管理和线程池进行了优化,提升了整体性能。 【标签】:“tomcat” ...

    web.xml配置详细介绍(CHM)

    `web.xml`是Servlet容器(如Tomcat、Jetty等)启动时读取的配置文件,用于指导服务器如何处理Web应用中的请求和资源。通过这个文件,你可以设置初始化参数、映射Servlet、配置过滤器、声明安全约束等。 2. **基本...

    web.xml sample

    `web.xml`是Java Web应用程序的核心配置文件,用于定义应用的结构、行为和组件。它遵循Servlet和JavaServer Pages(JSP)规范,是Servlet容器(如Tomcat)解析和执行的重要部分。在这个例子中,我们将详细分析给出的...

    tomcat_server.xml_配置详解

    本文将详细解析`server.xml`中的关键元素、属性及其含义,帮助读者深入理解Tomcat的工作机制。 1. `&lt;Server&gt;`元素 `&lt;Server&gt;`元素是整个Tomcat实例的顶级容器,它由`org.apache.catalina.Server`接口定义。此元素...

    Tomcat连接池配置方法详解 源代码 JSP context.xml

    本篇文章将深入解析如何在Tomcat 6.0中配置数据库连接池,包括在JSP应用中使用和调用的方法。 首先,我们要创建`context.xml`文件。这个文件位于项目的`META-INF`目录下,而不是`WEB-INF`。`context.xml`是Tomcat...

    web.xml文件加载顺序[归纳].pdf

    首先,当Web应用程序启动时,Web容器(如Tomcat、Jetty等)会读取web.xml文件。在这个过程中,它会首先处理`&lt;listener&gt;`和`&lt;context-param&gt;`这两个元素。`&lt;listener&gt;`定义了监听器,这些监听器在Servlet上下文...

Global site tag (gtag.js) - Google Analytics