zoukankan      html  css  js  c++  java
  • 这些Servlet知识你一定要知道,金九银十大厂面试官都爱问

    前言

    Servlet是服务器端的Java应用程序,可以生产动态Web页面。透过JSP执行过程可以知道JSP最终被编译成一个.class文件,查看该文件对应的Java类,发现该Java类继承自org.apache.jasper.runtime.HttpJspBase类,而HttpJspBase继承自HttpServlet类,由此可知JSP第一次运行时实质上是被JSP引擎翻译成了一个Servlet,然后再编译,最后再执行。

    自定义Servlet类继 承HttpServlet抽象类,HttpServlet抽象类继承自GenericServlet抽象类,GenericServlet抽象类实现了Servlet、ServletConfig和Serializable接口

    Servlet声明周期:

    1、加载及实例化

    Servlet容器负责加载和实例化Servlet。当客户端第一次(在web.xml文件中,通过load-on-startup标签可以配置Servlet,当web项目发布后立即创建Servlet实例) 给服务器发送该Servlet请求时,Servlet容器会加载并创建Servlet实例,(注意:默认情况下不是Tomcat服务器或服务器上的Web应用启动的时候加载并实例化Servlet)。当客户端(可以是非第一次请求的客户端)再次向服务器发送该Servlet请求时,服务器会从内存中查找该Servlet实例,并用找到的Servlet实例处理用户请求。

    在该过程中,Servlet容器会创建一个ServletConfig对象,该对象包含了Servlet的初始化配置信息。根据用户请求的URL地址,Servlet容器会根据配置信息查找该请求对应的Servlet类,由容器创建并管理该Servlet。

    2、初始化

    在Servlet容器完成Servlet类的实例化操作后,Servlet容器会调用Servlet的init()方法(在javax.servelt.Servlet接口中定义)对该Servlet进行初始化。对于每一个Servlet实例来说,init()方法只会被调用一次。初始化的目的是让Servlet在处理用户请求之前,做一些必要的准备工作,例如建立数据库连接,引用其他资源等。

    3、处理请求

    Servlet初始化之后,就处于就绪状态等待接收用户请求。当Servlet容器接收到客户端针对该Servlet的请求后,首先会针对这个请求创建ServletRequest和ServletResponse对象,之后调用Servlet的service()方法并把这两个参数传递给service()方法处理客户端请求。Servlet实例通过ServletRequest对象获得客户端的请求,通过调用ServletResponse对象的方法进行响应。请求处理完毕,ServletRequest和ServletResponse对象被销毁。

    不管客户端发送请求的方式是Get还是POST,这个请求都由service方法来处理。在service方法的处理过程中,会根据客户端发送请求的方式不同,调用doGet和doPost方法分别进行处理,通过HttpServlet类中的service方法可以了解这一调用过程,如下代码:

    protected void service(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {
            String method = req.getMethod();
            if (method.equals(METHOD_GET)) {
                long lastModified = getLastModified(req);
                if (lastModified == -1) {
                    doGet(req, resp);
                } else {
                    long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
                    if (ifModifiedSince < lastModified) {
                        maybeSetLastModified(resp, lastModified);
                        doGet(req, resp);
                    } else {
                        resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
                    }
                }
            } else if (method.equals(METHOD_HEAD)) {
                long lastModified = getLastModified(req);
                maybeSetLastModified(resp, lastModified);
                doHead(req, resp);
            } else if (method.equals(METHOD_POST)) {
                doPost(req, resp);
            } else if (method.equals(METHOD_PUT)) {
                doPut(req, resp);
            } else if (method.equals(METHOD_DELETE)) {
                doDelete(req, resp);
            } else if (method.equals(METHOD_OPTIONS)) {
                doOptions(req,resp);
            } else if (method.equals(METHOD_TRACE)) {
                doTrace(req,resp);
            } else {
                String errMsg = lStrings.getString("http.method_not_implemented");
                Object[] errArgs = new Object[1];
                errArgs[0] = method;
                errMsg = MessageFormat.format(errMsg, errArgs);
                
                resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
            }
        }
    

      

    4、销毁

    销毁Servlet 由Servlet容器完成。默认情况下,用户第一次发送Servlet请求,该Servlet加载、实例化、初始化、处理用户请求,当请求处理完毕后,该Servlet通常情况下驻留在内存中,等待处理下一个针对该Servlet的请求。当下一个针对该Servlet的请求到达时,直接从内存中获取该Servlet实例并对该请求进行处理。如果Tomcat这个Web应用服务器关闭(服务器上所有的Web应用都关闭),或者该Servlet所在的Web应用关闭,该Servlet实例会被销毁。

    Web应用被关闭时,Servlet容器会先调用Servlet实例的destroy方法,然后再销毁Servlet实例,同时也会销毁与Servlet相关联的ServletConfig对象。程序员通常在destroy()方法的实现中释放该Servlet所占用的资源,如关闭数据库连接,关闭文件输入/输出流等。

    通过Servlet声明周期可以知道所创建的Servlet对象属于单例。

    Servlet2.X配置

    在web.xml文件中,通过在<web-app>节点下配置servlet元素和servlet-mapping元素,把用户访问的URL映射到指定的Servlet类,如下代码:

    <web-app>
      <!-- 省略其他配置 -->
      <servlet>
        <!-- servlet-name指定Servlet名,要与下面servlet-mapping元素中的servlet-name保持一致 -->
        <servlet-name>doLogin</servlet-name>
        <!-- servlet-class对应着Servlet类完全限定名 -->
        <servlet-class>com.jd.serlvet.LoginServlet</servlet-class>
      </servlet>
      
      <servlet-mapping>
        <!-- servlet-name要与上面servlet元素中的servlet-name保持一致 -->
        <servlet-name>doLogin</servlet-name>
        <!-- url-pattern设定当前Servlet在浏览器中运行时的url -->
        <url-pattern>/doLogin</url-pattern>
      </servlet-mapping>
    </web-app>
    

      

    上面采用了精确匹配的形式配置了URL到Servlet之间的映射关系,接下来介绍两种非精确匹配的Servlet配置方式:

    <!-- 对doLogin路径下的所有请求都由doLogin对应的Servlet类进行处理 -->
      <servlet-mapping>
        <servlet-name>doLogin</servlet-name>
        <url-pattern>/doLogin/*</url-pattern>
      </servlet-mapping>
      
      <!-- 对所有以.do为后缀的请求都由doLogin对应的Servlet类进行处理 -->
        <servlet-mapping>
        <servlet-name>doLogin</servlet-name>
        <!-- 不能为/*.do -->
        <url-pattern>*.do</url-pattern>
      </servlet-mapping>
    

      

    在配置了URL与Servlet的映射后,当Servlet容器收到一个请求时,首先确定是由哪个Web应用响应这个请求,然后从该Web应用的web.xml文件中查找URL对应的Servlet类进行处理。

    Servlet初始化参数设置

    在web.xml文件中配置Servlet时,还可以在servlet元素中添加init-param元素预先对Servlet进行初始化设置,当Servlet加载时即可从该Servlet配置文件中获取初始化参数。

      <!-- 省略其他配置 -->
      <servlet>
        <servlet-name>doLogin</servlet-name>
        <servlet-class>com.jd.serlvet.LoginServlet</servlet-class>
        <!-- 配置多个初始化参数,则需要写多个init-param元素 -->
        <init-param>
                <param-name>name</param-name>
                <param-value>Tom</param-value>
        </init-param>
      </servlet>
      
      <servlet-mapping>
        <servlet-name>doLogin</servlet-name>
        <url-pattern>/doLogin</url-pattern>
      </servlet-mapping>
    

      

    如何获取:

    a、在无参init方法中直接调用getInitParameter(String name)方法即可,如下代码:

    @Override
    public void init() throws ServletException {
        String name = getInitParameter("name");
        System.out.println(name);
    }
    

      

    b、在参数为ServletConfig的方法中调用ServletConfig内getInitParameter(String name)方法即可,如下代码:

    @Override
    public void init(ServletConfig config) throws ServletException {
        String name = config.getInitParameter("name");
        System.out.println(name);
    }
    

      

    Servlet上下文(环境对象)初始化参数设置

    有时候不仅需要针对单个Servlet进行初始化参数设置,还需要对包含该Web引用中所有Servlet的环境对象进行初始化参数设置,使该参数能被所有的Servlet共享,如下代码:

      <!-- 省略其他配置 -->
      <!-- 配置多个初始化参数,则需要写多个context-param元素 -->
       <context-param>
        <param-name>name</param-name>
        <param-value>Tom</param-value>
       </context-param>
     
      <servlet>
        <servlet-name>doLogin</servlet-name>
        <servlet-class>com.jd.serlvet.LoginServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
      </servlet>
      
      <servlet-mapping>
        <servlet-name>doLogin</servlet-name>
        <url-pattern>/doLogin</url-pattern>
      </servlet-mapping>
    </web-app>
    

      

    如何获取:

    a、在无参init方法中直接调用getServletContext ()方法获取Servlet上下文对象,然后使用该对象调用getInitParameter方法即可,如下代码:

    @Override
    public void init() throws ServletException {
        String name = getServletContext ().getInitParameter("name");
        System.out.println(name);
    }
    

      

    b、在参数为ServletConfig的方法中调用ServletConfig内getServletContext ()方法获取Servlet上下文对象,然后使用该对象调用getInitParameter方法即可,如下代码:

    @Override
    public void init(ServletConfig config) throws ServletException {
        ServletContext servletContext = config.getServletContext();
        String name = servletContext.getInitParameter("name");
        System.out.println(name);
    }
    

      

    Servlet 3.0

    Servlet API包含javax.servlet和javax.servlet.http两个包,从Servlet 3.0开始,为了实现Servlet3.0的一些新特性,又增加了javax.sevlet.annotation和javax.sevlet.descriptor两个包,Tomcat服务器必须是7.0及其以上版本

    Servlet3.0的重大革新之一是支持注解,通过使用注解定义并部署Servlet,程序员无须在web.xml文件中配置Servlet,如下代码:

    @WebServlet(name="doLogin",urlPatterns="/doLogin",initParams={@WebInitParam(name="name",value="Tom")})
    public class LoginServlet extends HttpServlet {
        private static final long serialVersionUID = 1L;
        
        protected void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            response.sendRedirect("success.jsp");
        }
    }
    

      

    说明:

    name属性:指定Servlet名,类似于web.xml中servlet-name元素;

    urlPatterns属性:指定访问URL,类似于web.xml中的url-pattern元素;可以是数组,URL之间使用逗号间隔。

    initParams属性:设置初始化参数,该属性中使用@WebInitParam注解设置单个初始化参数;在@WebInitParam注解中,name属性指定参数名,类似于web.xml中的param-name元素;value属性指定参数值,类似于web.xml中的param-value元素。可以在initParams属性中配置多个@WebInitParam注解,用于初始化多个参数。

    wb.xml:

    <!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>
      <display-name>Archetype Created Web Application</display-name>
      <context-param>
            <param-name>name</param-name>
            <param-value>lucy</param-value>
      </context-param>
      <servlet>
        <servlet-name>TestServlet</servlet-name>
        <display-name>TestServlet</display-name>
        <description></description>
        <servlet-class>com.jd.servlet.TestServlet</servlet-class>
        <init-param>
            <param-name>mobile</param-name>
            <param-value>120</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
      </servlet>
      <servlet-mapping>
        <servlet-name>TestServlet</servlet-name>
        <url-pattern>/TestServlet</url-pattern>
      </servlet-mapping>
    </web-app>
    

      

    TestServlet.java:

    package com.jd.servlet;
     
    import java.io.IOException;
     
    import javax.servlet.ServletConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
     
    /**
     * Servlet implementation class TestServlet
     */
    public class TestServlet extends HttpServlet {
        private static final long serialVersionUID = 1L;
           //Servlet对象属于单实例(程序运行结束之前,缓存中只有一个对象存在)
        public TestServlet() {
            //用于为成员变量赋值,会触发对象创建:默认情况下第一次使用该Servlet时创建对象执行;
            //web.xml中加入<load-on-startup>1</load-on-startup>,在tomcat启动时对象创建,TestServlet执行,随之init()方法也立即执行
            
            super();
            System.out.println("TestServlet"+this);
           
        }
     
        //
        @Override
        public void destroy() {
            super.destroy();
             System.out.println("destroy"+this);
        }
     
     
        @Override
        public void init() throws ServletException {//初始化;对于每一个Servlet实例来说,创建对象执行init()方法,并且只会被调用一次
            super.init();
            String name=getServletContext().getInitParameter("name");//调用公共参数
            System.out.println("1111111"+name);
            System.out.println("init())"+this);
        }
        
     
        @Override
        public void init(ServletConfig config) throws ServletException {
            super.init(config);
            String name=config.getServletContext().getInitParameter("name");//调用公共参数
            System.out.println("你好"+name);
            String mobile=config.getInitParameter("mobile");//调用私人参数
            System.out.println("快打"+mobile);
            System.out.println("init(config))"+this);
        }
     
        
        
        //请求最先到达service判断执行哪个方法,doGet还是doPost
        @Override
        protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            super.service(req, resp);
            System.out.println("service"+this);
        }
     
        //a标签,form表单method是 get方法   异步默认type是get方法
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
             System.out.println("doGet"+this);
        }
        //form表单method是 post方法  异步指定type是post方法
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
             System.out.println("doPost"+this);
        }
     
    }
    

      

    最后

    感谢你看到这里,看完有什么的不懂的可以在评论区问我,觉得文章对你有帮助的话记得给我点个赞,每天都会分享java相关技术文章或行业资讯,欢迎大家关注和转发文章!

  • 相关阅读:
    net core 使用 rabbitmq
    asp.net core WebApi 返回 HttpResponseMessage
    asp.net core 2.1 WebApi 快速入门
    JQuery EasyUI combobox动态添加option
    php截取字符去掉最后一个字符
    JQuery EasyUI Combobox的onChange事件
    对于不返回任何键列信息的 selectcommand 不支持 updatecommand 的动态 sql 生成
    Access2007 操作或事件已被禁用模式阻止解决办法
    Easyui 中 Tabsr的常用方法
    Win 7 IE11不能下载文件,右键另存为也不行
  • 原文地址:https://www.cnblogs.com/lwh1019/p/13393846.html
Copyright © 2011-2022 走看看