Java Web从如何启动到Servlet&Tomcat

平时我们在写一般的应用程序的时候,无论如何都会有一个main函数入口。而在进行web开发的时候,从头到尾我们都没有写过一个main函数。最后部署时,打了一个war包,传到web容器下面就可以了。到底这后面发生了什么,带着疑问让我开始吧。

基础知识

先了解一下java web应用目录组织结构:

  • WebRoot :Web应用所在目录,一般情况下虚拟目录要配置到此文件夹当中。
  • WEB-INF:此文件夹必须位WebRoot文件夹里面,而且必须以这样的形式去命名,字母都要大写。
  • Web.xml:配置文件,有格式要求,此文件必须以这样的形式去命名,并且必须放置到WEB-INF文件夹中。

在看看一个浏览器与服务器交互的流程:

Servlet

在java web项目中,我们无论是用什么框架,Spring MVC也好,Spring Boot也好,最后都是Servlet在起着决定性的作用。

Servlet是什么?

Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。

Servlet在Web应用程序的位置如下图所示:

image

Servlet程序是由web容器调用,也就解释了为什么我们所写的web应用程序不需要main函数的原因,它是由web容器根据请然后创建的。

Servlet主要作用有:

  • 读取客户端(浏览器)发送的数据 。
  • 处理数据并生成结果。这个过程可能需要访问数据库,调用 Web 服务,或者直接计算得出对应的响应。平时的业务逻辑就是在这个部分实现。
  • 发送处理过后的数据给客户端(浏览器)。

Servlet的运行过程

web容器收到客户端的访问请求后将进行如下处理:

  1. Web容器首先检查是否已经装载并创建了该Servlet的实例对象。如果是,则直接执行第4步,否则,执行第2步。
  2. 装载并创建该Servlet的一个实例对象。
  3. 调用Servlet实例对象的init()方法。
  4. 创建一个用于封装HTTP请求消息的HttpServletRequest对象和一个代表HTTP响应消息的HttpServletResponse对象,然后调用Servlet的service()方法并将请求和响应对象作为参数传递进去。
  5. WEB应用程序被停止或重新启动之前,Servlet引擎将卸载Servlet,并在卸载之前调用Servlet的destroy()方法。

具体来讲可以用下面的图说明:

其时序图可以用下图表示:

一个Servlet例子

有了上面的理论基础我们就可以写一个例子加深理解。最终实现一个现实header的效果。

源码如下:

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class DisplayHeaderServlet extends HttpServlet {
    // 处理 GET 方法请求的方法
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
        // 设置响应内容类型
        response.setContentType("text/html;charset=UTF-8");

        PrintWriter out = response.getWriter();
        String title = "HTTP Header 请求";
        String docType =
                "<!DOCTYPE html> \n";
        out.println(docType +
                "<html>\n" +
                "<head><meta charset=\"utf-8\"><title>" + title + "</title></head>\n"+
                "<body bgcolor=\"#f0f0f0\">\n" +
                "<h1 align=\"center\">" + title + "</h1>\n" +
                "<table width=\"100%\" border=\"1\" align=\"center\">\n" +
                "<tr bgcolor=\"#949494\">\n" +
                "<th>Header 名称</th><th>Header 值</th>\n"+
                "</tr>\n");

        Enumeration headerNames = request.getHeaderNames();

        while(headerNames.hasMoreElements()) {
            String paramName = (String)headerNames.nextElement();
            out.print("<tr><td>" + paramName + "</td>\n");
            String paramValue = request.getHeader(paramName);
            out.println("<td> " + paramValue + "</td></tr>\n");
        }
        out.println("</table>\n</body></html>");
    }
    // 处理 POST 方法请求的方法
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}

写完之后,还需要将文件便以为class文件,项目部署到tomcat目录下。启动tomcat Web容器访问对应路径即可。

在web.xml中配置一下加载的Servlet

    <servlet>
        <!-- servlet名,一般写成类名,并不一定严格是类名 -->
        <servlet-name>DisplayHeaderServlet</servlet-name>
        <!-- 所在的包 -->
        <servlet-class>com.xxx.xxx.DisplayHeaderServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <!-- 与上面的servlet-name相对应-->
        <servlet-name>DisplayHeaderServlet</servlet-name>
        <!-- 访问的网址 -->
        <url-pattern>/TomcatTest/DisplayHeaderServlet</url-pattern>
    </servlet-mapping>

Servlet需要注意

Servlet访问URL映射配置

由于客户端是通过URL地址访问web服务器中的资源,所以Servlet程序若想被外界访问,必须把servlet程序映射到一个URL地址上。

这个工作在web.xml文件中使用<servlet>元素和<servlet-mapping>元素完成。<servlet>元素用于注册Servlet,它包含有两个主要的子元素:<servlet-name><servlet-class>,分别用于设置Servlet的注册名称和Servlet的完整类名。

一个<servlet-mapping>元素用于映射一个已注册的Servlet的一个对外访问路径,它包含有两个子元素:<servlet-name><url-pattern>,分别用于指定Servlet的注册名称和Servlet的对外访问路径。

  • 同一个Servlet可以被映射到多个URL上,即多个<servlet-mapping>元素的<servlet-name>子元素的设置值可以是同一个Servlet的注册名。
  • 同一个Url不能对应多个Servlet。否则会报错Caused by: java.lang.IllegalArgumentException: The servlets named [xxx] and [xxx] are both mapped to the url-pattern xxx

Servlet访问URL使用*通配符映射

在Servlet映射到的URL中也可以使用*通配符,但是只能有两种固定的格式:一种格式是"*.扩展名",另一种格式是以正斜杠(/)开头并以"/*"结尾

但是如果存在了冲突,比如都有*。规则又是怎样的呢?

请求Url Url1 Url2 规则
/abc/a.html /abc/* /* Servlet引擎将调用/abc/*
/abc /abc/* /abc Servlet引擎将调用/abc
/abc/a.do /abc/* *.do Servlet引擎将调用/abc/*
/a.do /* *.do Servlet引擎将调用/*
/xxx/yyy/a.do /* *.do Servlet引擎将调用/*

匹配的原则就是"谁长得更像就找谁" 。但是当请求url完全匹配的时候就走完全匹配的rul。如上面的第二条。

Servlet与普通Java类的区别

Servlet是一个供其他Java程序(Servlet引擎,比如tomcat web容器)调用的Java类,它不能独立运行,它的运行完全由Servlet引擎来控制和调度。这也是开发Web项目没有些main方法的原因。

针对客户端的多次Servlet请求,通常情况下,服务器只会创建一个Servlet实例对象,也就是说Servlet实例对象一旦创建,它就会驻留在内存中,为后续的其它请求服务,直至web容器退出,servlet实例对象才会销毁

在Servlet的整个生命周期内,Servlet的init方法只被调用一次。而对一个Servlet的每次访问请求都导致Servlet引擎调用一次servlet的service方法。

对于每次访问请求,Servlet引擎都会创建一个新的HttpServletRequest请求对象和一个新的HttpServletResponse响应对象,然后将这两个对象作为参数传递给它调用的Servlet的service()方法,service方法再根据请求方式分别调用doXXX方法。

如果在<servlet>元素中配置了一个<load-on-startup>元素,那么WEB应用程序在启动时,就会装载并创建Servlet的实例对象、以及调用Servlet实例对象的init()方法。

    <servlet>
        <servlet-name>invoker</servlet-name>
        <servlet-class>
            org.apache.catalina.servlets.InvokerServlet
        </servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

可以用于为web应用写一个InitServlet,这个servlet配置为启动时装载,为整个web应用创建必要的数据库表和数据。很多第三方框架也需要在应用一加载就实例化Serlvet,比如SpringMVC中的org.springframework.web.servlet.DispatcherServlet

<!-- springMVC的核心控制器 -->
<servlet>
    <servlet-name>springMVC</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath*:springMVC-servlet.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
    <async-supported>true</async-supported>
</servlet>
<servlet-mapping>
    <servlet-name>springMVC</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

缺省Servlet

如果某个Servlet的映射路径仅仅为一个正斜杠(/),那么这个Servlet就成为当前Web应用程序的缺省Servlet。

凡是在web.xml文件中找不到匹配的<servlet-mapping>元素的URL,它们的访问请求都将交给缺省Servlet处理,也就是说,缺省Servlet用于处理所有其他Servlet都不处理的访问请求。

比如在tomcat中\conf\web.xml文件中,注册了一个名称为org.apache.catalina.servlets.DefaultServlet的Servlet,并将这个Servlet设置为了缺省Servlet。

    <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>

当访问Tomcat服务器中的某个静态HTML文件和图片时,实际上是在访问这个缺省Servlet。

Servlet的线程安全问题

当多个客户端并发访问同一个Servlet时,web服务器会为每一个客户端的访问请求创建一个线程,并在这个线程上调用Servlet的service方法,因此service方法内如果访问了同一个资源的话,就有可能引发线程安全问题

所有在Servlet中尽量避免使用实例变量 ,最好使用局部变量。

Servlet如何处理多个请求访问

Servlet容器默认是采用单实例多线程的方式处理多个请求的:

  • 当web服务器启动的时候(或客户端发送请求到服务器时),Servlet就被加载并实例化(只存在一个Servlet实例)
  • 容器初始化化Servlet主要就是读取配置文件(例如tomcat,可以通过servlet.xml的<Connector>设置线程池中线程数目,初始化线程池通过web.xml,初始化每个参数值等等。
  • 当请求到达时,Servlet容器通过调度线程(Dispatchaer Thread) 调度它管理下线程池中等待执行的线程(Worker Thread)给请求者。
  • 线程执行Servlet的service方法。
  • 请求结束,放回线程池,等待被调用;

从上面可以看出(好处):

  1. Servlet单实例,减少了产生servlet的开销;
  2. 通过线程池来响应多个请求,提高了请求的响应时间;
  3. Servlet容器并不关心到达的Servlet请求访问的是否是同一个Servlet还是另一个Servlet,直接分配给它一个新的线程。
  4. 如果是同一个Servlet的多个请求,那么Servlet的service方法将在多线程中并发的执行;
  5. 每一个请求由ServletRequest对象来接受请求,由ServletResponse对象来响应该请求;

Servlet相关对象

ServletConfig

上面讲了可以设置Servlet对应的url,那么如何需要配置Serlvet初始化参数怎么办,这就需要用到ServletConfig。在Servlet的配置文件web.xml中,可以使用一个或多个<init-param>标签为servlet配置一些初始化参数。

<servlet>
    <servlet-name>ServletConfigDemo1</servlet-name>
    <servlet-class>com.xxx.xxx.xxx</servlet-class>
    <!--配置ServletConfig的初始化参数 -->
    <init-param>
        <param-name>name</param-name>
        <param-value>xxx</param-value>
    </init-param>
     <init-param>
        <param-name>password</param-name>
        <param-value>123</param-value>
    </init-param>
    <init-param>
        <param-name>charset</param-name>
        <param-value>UTF-8</param-value>
    </init-param>
</servlet>

当servlet配置了初始化参数后,web容器在创建servlet实例对象时,会自动将这些初始化参数封装到ServletConfig对象中,并在调用servlet的init方法时,将ServletConfig对象传递给servlet。进而,我们通过ServletConfig对象就可以得到当前servlet的初始化参数信息。

获取方式如下:

    /**
     * 定义ServletConfig对象来接收配置的初始化参数
     */
    private ServletConfig config;
    
    /**
     * 当servlet配置了初始化参数后,web容器在创建servlet实例对象时,
     * 会自动将这些初始化参数封装到ServletConfig对象中,并在调用servlet的init方法时,
     * 将ServletConfig对象传递给servlet。进而,程序员通过ServletConfig对象就可以
     * 得到当前servlet的初始化参数信息。
     */
    @Override
    public void init(ServletConfig config) throws ServletException {
        this.config = config;
    }

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //获取在web.xml中配置的初始化参数
        //获取指定的初始化参数
        String paramVal = this.config.getInitParameter("name");
        response.getWriter().print(paramVal);
        
        response.getWriter().print("<hr/>");
        //获取所有的初始化参数
        Enumeration<String> e = config.getInitParameterNames();
        while(e.hasMoreElements()){
            String name = e.nextElement();
            String value = config.getInitParameter(name);
            response.getWriter().print(name + "=" + value + "<br/>");
        }
    }

比如在使用SpringMVC的时候,在web.xml就使用到了ServletConfig

    <servlet>
        <servlet-name>SpringMVC</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--配置ServletConfig的初始化参数 -->
        <init-param>
            <description>SpringMVC</description>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring/spring-mvc.xml</param-value>
        </init-param>
        <!--web容器一旦加载就会创建这个servlet,并且会调用init方法-->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>SpringMVC</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

ServletContext

对于ServletContext需要我们注意一下几点:

  • WEB容器在启动时,它会为每个WEB应用程序都创建一个对应的ServletContext对象,它代表当前web应用。
  • ServletConfig对象中维护了ServletContext对象的引用,开发人员在编写servlet时,可以通过ServletConfig.getServletContext方法获得ServletContext对象。
  • 由于一个WEB应用中的所有Servlet共享同一个ServletContext对象,因此Servlet对象之间可以通过ServletContext对象来实现通讯。ServletContext对象通常也被称之为context域对象。

类似于ServletContext(应用上下文)这种设计思想,很多地方都有类似的应用。比如iOS中的画图CGContext 。

来一个数据共享的例子:

存储数据:

public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String data = "data";
        /**
         * ServletConfig对象中维护了ServletContext对象的引用,开发人员在编写servlet时,
         * 可以通过ServletConfig.getServletContext方法获得ServletContext对象。
         */
         //获得ServletContext对象
        ServletContext context = this.getServletConfig().getServletContext();
         //将data存储到ServletContext对象中
         //将data存储到ServletContext对象中
        context.setAttribute("data", data);  
    }

读取数据:

 public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        ServletContext context = this.getServletContext();\
        //从ServletContext对象中取出数据
        String data = (String) context.getAttribute("data");
        response.getWriter().print("data="+data);
    }

更多的情况下是通过web.xml中读取初始化参数。如下:

    <!-- 配置WEB应用的初始化参数 -->
    <context-param>
        <param-name>url</param-name>
        <param-value>xxx.xxx.xxxx</param-value>
    </context-param>

读取web.xml中的初始化参数

public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        ServletContext context = this.getServletContext();
        //获取整个web站点的初始化参数
        String contextInitParam = context.getInitParameter("url");
        response.getWriter().print(contextInitParam);
    }

除了读取web.xml中的初始化参数,还可以通过ServletContext读取对象文件。比如常见在项目中使用的xxx.properties文件。很多第三方也是用的这种方式来读取对应的配置文件

 /**
     * 读取src目录下的com.xxx.xxx包中的xxx.properties配置文件
     * @param response
     * @throws IOException
     */
    private void readPropCfgFile2(HttpServletResponse response)
            throws IOException {
        InputStream in = this.getServletContext().getResourceAsStream("/WEB-INF/classes/com/xxx/xxx/xxx.properties");
        Properties prop = new Properties();
        prop.load(in);
        String driver = prop.getProperty("driver");
        String url = prop.getProperty("url");
        String username = prop.getProperty("username");
        String password = prop.getProperty("password");
        response.getWriter().println("读取src目录下的com.xxx.xxx包中的xxx.properties配置文件:");
        response.getWriter().println(
                MessageFormat.format(
                        "driver={0},url={1},username={2},password={3}", 
                        driver,url, username, password));
    }

除了通过ServletContext读取资源文件,还可以通过类装载器读取资源文件。也有很多第三方是通过这样的方式读取资源文件

   /**
     * 读取类路径下的资源文件
     * @param response
     * @throws IOException
     */
    private void test1(HttpServletResponse response) throws IOException {
        //获取到装载当前类的类装载器
        ClassLoader loader = ServletContextDemo7.class.getClassLoader();
        //用类装载器读取src目录下的db1.properties配置文件
        InputStream in = loader.getResourceAsStream("db1.properties");
        Properties prop = new Properties();
        prop.load(in);
        String driver = prop.getProperty("driver");
        String url = prop.getProperty("url");
        String username = prop.getProperty("username");
        String password = prop.getProperty("password");
        response.getWriter().println("用类装载器读取src目录下的db1.properties配置文件:");
        response.getWriter().println(
                MessageFormat.format(
                        "driver={0},url={1},username={2},password={3}", 
                        driver,url, username, password));
    }

Web容器

上一篇讲了Servlet,提到Servlet由容器调用。拿么Web容器是干嘛的呢。

比较权威的解释:

web容器是一种服务程序,在服务器一个端口就有一个提供相应服务的程序,而这个程序就是处理从客户端发出的请求,如JAVA中的Tomcat容器,ASP的IIS或PWS都是这样的容器。比如tomcat容器,它提供的接口严格遵守 J2EE 规范中的 WEB APPLICATION 标准。我们把遵守该标准的 WEB 服务器就叫做 J2EE 中的 WEB 容器。 这套标准就是当有客户端请求,自动调用对应的Servlet的标准

为了加强理解这里再次说明一下:

servlet没有main方法,那我们如何启动一个servlet,如何结束一个servlet,如何寻找一个servlet等等,都受控于另一个java应用,这个应用我们就称之为web容器。

比如tomcat就是这样一个容器。如果web服务器应用得到一个指向某个servlet的请求,此时服务器不是把servlet交给servlet本身,而是交给部署该servlet的容器。要有容器向servlet提供http请求和响应,而且要由容器调用servlet的方法,如doPost或者doGet。

接下来就以Tomcat为例子

Tomcat

Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache、Sun 和其他一些公司及个人共同开发而成。由于有了Sun 的参与和支持,最新的Servlet 和JSP 规范总是能在Tomcat 中得到体现,Tomcat 5支持最新的Servlet 2.4 和JSP 2.0 规范。因为Tomcat 技术先进、性能稳定,而且免费,因而深受Java 爱好者的喜爱并得到了部分软件开发商的认可,成为目前比较流行的Web 应用服务器。

体系结构

  • Tomcat服务器的启动是基于一个server.xml文件的,Tomcat启动的时候首先会启动一个Server,Server里面就会启动Service,Service里面就会启动多个Connector(连接器)。
  • 每一个Connector(连接器)都在等待客户机的连接,当有用户使用浏览器去访问服务器上面的web资源时,首先是连接到Connector(连接器),Connector(连接器)是不处理用户的请求的,而是将用户的请求交给一个Engine(引擎)去处理。
  • Engine(引擎)接收到请求后就会解析用户想要访问的Host,然后将请求交给相应的Host。
  • Host收到请求后就会解析出用户想要访问这个Host下面的哪一个Web应用,一个web应用对应一个Context。

一个简单的配置例子,对照着上面的体系结构来看

<?xml version='1.0' encoding='utf-8'?>
<Server port="8005" shutdown="SHUTDOWN">
  <Service name="Catalina">
    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
    <Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol"
               maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
               clientAuth="false" sslProtocol="TLS" 
               keystoreFile="conf/.keystore" keystorePass="123456"/>
    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
    <Engine name="Catalina" defaultHost="localhost">

      <Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="localhost_access_log." suffix=".txt"
               pattern="%h %l %u %t &quot;%r&quot; %s %b" />
      </Host>
      <!-- host对应的根目录 --> 
      <Host name="www.xxx.xxx" appBase="F:\JavaWebApps">
        <!-- 具体context对应的目录 --> 
        <Context path="" docBase="F:\JavaWebApps\xxxx"/>
      </Host>

    </Engine>
  </Service>
</Server>

Tomcat web.xml

应用服务器启动时web.xml加载过程,至于这些节点在xml文件中的前后顺序没有关系,不过有些应用服务器,比如websphere就严格要求web.xml的节点顺序,否则部署不成功,所以还是最好按照web.xml标准格式写 :

具体的配置和加载顺序:content-param --> listener --> filter --> servlet

结合上面所讲的ServletConfig及ServletContext。

  1. 启动WEB项目的时候,应用服务器会去读它的配置文件web.xml.读两个节点:<context-param></context-param><listener></listener>
  2. 紧接着,容器创建一个ServletContext(上下文),这个WEB项目所有部分都将共享这个上下文。
  3. 容器将<context-param></context-param>转化为键值对,并交给ServletContext。
  4. 容器创建<listener></listener>中的类实例,即创建监听。
  5. 在监听中会有contextInitialized(ServletContextEvent args)初始化方法,在这个方法中获得:ServletContext = ServletContextEvent.getServletContext(); context-param的值 = ServletContext.getInitParameter("context-param的键");
  6. 得到这个context-param的值之后,你就可以做一些操作了.注意,这个时候你的WEB项目还没有完全启动完成,这个动作会比所有的Servlet都要早。换句话说,这个时候,你对<context-param>中的键值做的操作,将在你的WEB项目完全启动之前被执行.如果想在项目启动之前就打开数据库,那么这里就可以在<context-param>中设置数据库的连接方式,在监听类中初始化数据库的连接,这个监听是自己写的一个类,除了初始化方法,它还有销毁方法.用于关闭应用前释放资源.比如说数据库连接的关闭。

顺序

以 filter 为例,web.xml 中当然可以定义多个 filter,与 filter 相关的一个配置节是 filter-mapping,这里一定要注意,对于拥有相同 filter-name 的 filter 和 filter-mapping 配置节而言,filter-mapping 必须出现在 filter 之后,否则当解析到 filter-mapping 时,它所对应的 filter-name 还未定义

web 容器启动时初始化每个 filter 时,是按照 filter 配置节出现的顺序来初始化的,当请求资源匹配多个 filter-mapping 时,filter 拦截资源是按照 filter-mapping 配置节出现的顺序来依次调用 doFilter() 方法的。 servlet 同 filter 类似!

比如filter 需要用到 bean ,但加载顺序是: 先加载filter 后加载spring,则filter中初始化操作中的bean为null;所以,如果过滤器中要使用到 bean,可以将spring 的加载 改成 Listener的方式

<listener>

    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

</listener>

节点详解

web-app

根节点

<web-app></web-app>

context-param

用来设定web站台的环境参数。

它包含两个子元素:

  • <param-name></param-name> 用来指定参数的名称
  • <param-value></param-value> 用来设定参数值

在此设定的参数,可以在servlet中用 getServletContext().getInitParameter("my_param")来取得。

例子:

 <context-param>

  <param-name>log4jConfigLocation</param-name>

  <param-value>classpath*:/log4j.properties</param-value>

 </context-param>

listener

用来设定Listener接口,它的主要子元素为:

  • <listener-class></listener-class> 定义Listener的类名称

例子:

<listener>

     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

 </listener>

filter

是用来声明filter的相关设定

  • <filter-name></filter-name> 这当然就是指定filter的名字
  • <filter-class></filter-class> 这是用来定义filter的类的名称
  • <init-param></init-param> 用来定义参数,它有两个子元素:
  • <param-name></param-name> 用来指定参数的名称
  • <param-value></param-value> 用来设定参数值

例子:

<filter>

  <filter-name>encodingFilter</filter-name>

  <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>

  <init-param>

   <param-name>encoding</param-name>

   <param-value>GBK</param-value>

  </init-param>

  <init-param>

   <param-name>forceEncoding</param-name>

   <param-value>true</param-value>

  </init-param>

 </filter>

servlet

来声明一个servlet的数据,主要有以下子元素:

  • <servlet-name></servlet-name> 指定servlet的名称
  • <servlet-class></servlet-class> 指定servlet的类名称
  • <jsp-file></jsp-file> 指定web站台中的某个JSP网页的完整路径
  • <init-param></init-param> 用来定义参数,和前面的<init-param>差不多

同样,与<servlet></servlet>一起使用的是<servlet-mapping></servlet-mapping> 用来定义servlet所对应的URL,包含两个子元素:<servlet-name></servlet-name> 指定servlet的名称<url-pattern></url-pattern> 指定servlet所对应的URL

 <servlet>

  <servlet-name>DemoServlet</servlet-name>

  <servlet-class>com.test.DemoServlet</servlet-class>

 </servlet>

 <servlet-mapping>

  <servlet-name>DemoServlet</servlet-name>

  <url-pattern>/demoServlet</url-pattern>

 </servlet-mapping>

description

是对站台的描述

例子:

<description>传道、授业、解惑</description> 

display-name

定义站台的名称
例子:

<display-name>我的站点</display-name>

icon

icon元素包含small-icon和large-icon两个子元素.用来指定web站台中小图标和大图标的路径.
<small-icon>/路径/smallicon.gif</small-icon>

small-icon元素应指向web站台中某个小图标的路径,大小为16 X 16 pixel,但是图象文件必须为GIF或JPEG格式,扩展名必须为:.gif或.jpg.

<large-icon>/路径/largeicon-jpg</large-icon>
large-icon元素应指向web站台中某个大图表路径,大小为32 X 32 pixel,但是图象文件必须为GIF或JPEG的格式,扩展名必须为; gif或jpg.
例子:

<icon> 

 <small-icon>/images/small.gif</small-icon> 

 <large-icon>/images/large.gir</large-icon> 

</icon>

distributable

是指定该站台是否可分布式处理

session-config

用来定义web站台中的session参数

包含一个子元素:
<session-timeout></session-timeout> 用来定义这个web站台所有session的有效期限,单位为 分钟

mime-mapping

定义某一个扩展名和某一个MIME Type做对应该
包含两个子元素:

  • <extension></extension> 扩展名的名称
  • <mime-type></mime-type> MIME格式

例子:

 <mime-mapping>

  <extension>doc</extension>  

  <mime-type>application/vnd.ms-word</mime-type>

 </mime-mapping>    

 <mime-mapping>

  <extension>xls</extension>

  <mime-type>application/vnd.ms-excel</mime-type>

 </mime-mapping>

error-page

例子

<error-page> <error-page>

     <error-code>500</error-code>

     <location>/message.jsp</location>

 </error-page>

 <error-page>

     <error-code>400</error-code>

     <location>/message.jsp</location>

 </error-page>

 <error-page>

     <error-code>403</error-code>

     <location>/message.jsp</location>

 </error-page>

 <error-page>

     <error-code>404</error-code>

     <location>/message.jsp</location>

 </error-page>

 <error-page>

     <error-code>502</error-code>

     <location>/index.jsp</location>

 </error-page>

jsp-config

例子

<jsp-config> 

 <taglib>

 <taglib-uri>/struts-tags</taglib-uri>

 <taglib-location>/WEB-INF/struts-tags.tld</taglib-location>

 </taglib>

 <taglib>

 <taglib-uri>/struts-dojo-tags</taglib-uri>

 <taglib-location>/WEB-INF/struts-dojo-tags.tld</taglib-location>

 </taglib>

 <taglib>

 <taglib-uri>/s</taglib-uri>

 <taglib-location>/WEB-INF/struts-tags.tld</taglib-location>

 </taglib>

 </jsp-config>

welcome-file-list

 <welcome-file-list>

 <welcome-file>index.html</welcome-file>

 <welcome-file>index.htm</welcome-file>

 <welcome-file>index.jsp</welcome-file>

 </welcome-file-list>

resource-ref

定义利用JNDI取得站台可利用的资源
有五个子元素:

  • <description></description> 资源说明
  • <rec-ref-name></rec-ref-name> 资源名称
  • <res-type></res-type> 资源种类
  • <res-auth></res-auth> 资源经由Application或Container来许可
  • <res-sharing-scope></res-sharing-scope> 资源是否可以共享,有Shareable和Unshareable两个值,默认为Shareable

比如,配置数据库连接池就可在此配置

 <resource-ref>

 <description>JNDI JDBC DataSource of shop</description>

 <res-ref-name>jdbc/sample_db</res-ref-name>

 <res-type>javax.sql.DataSource</res-type>

 <res-auth>Container</res-auth>

 </resource-ref>

扩展阅读

Tomcat服务器学习和使用(一)

JavaWeb学习总结

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,233评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,013评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,030评论 0 241
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,827评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,221评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,542评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,814评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,513评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,225评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,497评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,998评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,342评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,986评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,812评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,560评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,461评论 2 266

推荐阅读更多精彩内容