美文网首页javaweb+servlet+jsp
Servlet的原理、周期、创建方法、Servlet的线程安全、

Servlet的原理、周期、创建方法、Servlet的线程安全、

作者: 莫失丿莫忘 | 来源:发表于2017-09-27 11:01 被阅读70次

    1.什么是servlet

    servlet是一个Java类,是用来专门处理请求和响应的,是部署在服务器上工作的小程序,之所以叫小程序,是因为它只要部署上去就自动运行工作了可以处理事情了。servlet 通常通过 HTTP(超文本传输协议)接收和响应来自 Web 客户端的请求。
    HTTP:
    ★ HTTP是HyperText Transfer Protocol(超文本传输协议)的简写,传输HTML文件。
    ★ 用于定义WEB浏览器与WEB服务器之间交换数据的过程及数据本身的格式。

    2.操作步骤:

    a.创建一个实现servlet接口的Java类(ServletDemo1)。
    ServletDemo1爆红是因为实现了Servlet接口就需要重写里面的方法。实现接口所定义的方法。
    在service方法里添加输出语句

    @Override
      public void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException {
          // TODO Auto-generated method stub
          System.out.println("执行Servlet里的方法");
          
      }
    

    b.在web.xml中配置servlet的信息。
    我们的目的就是让用户通过url来访问我们的刚刚实现了servlet接口的类,然后在这个类里面做一些处理。但是我们的类是写在src中,然后编译成字节码.class文件是存放在WEB-INF中的,我们部署应用的时候就把WEB-INF的东西部署到服务器上,而WEB-INF文件中的东西是不允许外部访问的,所以如果想要访问的这个类(严格意义上说是这个类生成的字节码文件),我们就需要通过一些配置来告诉服务器某个URL地址是用来访问某个类的。这就是我们为什么要配置web.xml的原因。(服务器Tomcat启动后加载项目最先扫描执行web.xml文件)

    image.png

    web.xml主要代码:

    <servlet>
      <!-- 一般把类名首字母变小写作为servlet-name-->
        <servlet-name>ServelDemo1</servlet-name>
        <servlet-class>com.szy.web.servlet.ServelDemo1</servlet-class>
      </servlet>
    
    这里的访问逻辑是,我们在浏览器输入localhost:8080/应用名/demo1后,它就会找到中相应的url(在中),然后根据这个url找到对应的叫servletDemo1,然后就在这个节点里再找到该对应的。至此,就自动找到这个类,去执行相应的任务了。
      <servlet>
        <servlet-name>servelDemo1</servlet-name>
        <servlet-class>com.cms.Demo1.Service.ServelDemo1</servlet-class>
      <!-- 2,填数字越小优先级越高,越先执行,让该servlet在服务器启动时就创建,不建议写零 -->
        <load-on-startup>2</load-on-startup>
      </servlet>
     <!-- 给Servlet映射一个可访问的URI :http://localhost:8080/项目名/demo1即可通过servelDemo1映射到ServelDemo1访问该类-->
      <servlet-mapping>
        <servlet-name>servelDemo1</servlet-name>
        <url-pattern>/demo1</url-pattern>
      </servlet-mapping>
    

    com.szy.web.servlet.ServelDemo1路径的获得操作如下图:


    image.png

    执行结果:

    浏览器显示空白页面但是控制台输出了ServletDemo1类里的执行结果。

    image.png

    3.Servlet的生命周期

    此接口定义了初始化 servlet 的方法 init()、为请求提供服务的方法 service()和从服务器移除 servlet 的方法 destroy()。这些方法称为生命周期方法,它们是按以下顺序调用的:

    a .初始化阶段 :
    构造 servlet,然后使用 init 方法将其初始化。
    b.响应客户请求阶段:
    处理来自客户端的对 service 方法的所有调用。
    c.终止阶段:
    从服务中取出 servlet,然后调用 destroy 方法销毁它,最后进行垃圾回收并终止它。

    除了生命周期方法之外,此接口还提供了 getServletConfig 方法和 getServletInfo 方法,servlet 可使用前一种方法获得任何启动信息,而后一种方法允许 servlet 返回有关其自身的基本信息,比如作者、版本和版权。

    package com.szy.web.servlet;
    import java.io.IOException;
    import javax.servlet.Servlet;
    import javax.servlet.ServletConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    public class ServelDemo1  implements Servlet {  
        public  ServelDemo1() {
            // 实例化方法
        }
        @Override
        public void init(ServletConfig arg0) throws ServletException {
            // 初始化      
        }
        @Override
        public void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException {
            // 服务
            System.out.println("执行Servlet里的方法");        
        }
        @Override
        public void destroy() {
            //销毁        
        }
        @Override
        public ServletConfig getServletConfig() {
            // TODO Auto-generated method stub
            return null;
        }
        @Override
        public String getServletInfo() {
            // TODO Auto-generated method stub
            return null;
        }
    }
    

    注意:
    Servlet何时被创建:
      ★ 默认情况下,当WEB客户第一次请求访问某个Servlet的时候,WEB容器将创建这个Servlet的实例。
      ★ 当web.xml文件中如果<servlet>元素中指定了<load-on-startup>子元素时,Servlet容器在启动web服务器时,将按照顺序创建并初始化Servlet对象。
      ★ 在web.xml文件中,某些Servlet只有<serlvet>元素,没有<servlet-mapping>元素,这样我们无法通过url的方式访问这些Servlet,这种Servlet通常会在<servlet>元素中配置一个<load-on-startup>子元素,让容器在启动的时候自动加载这些Servlet并调用init()方法,完成一些全局性的初始化工作。

    4.servlet的三种创建方式

    Servlet --> GenericServlet --> HttpServlet -->我们定义的继承HttpServlet的类
    曾祖父 爷爷 爸爸 孙子

    方法如下:
    a. 实现javax.servlet.Servlet接口(参见:编写一个servlet程序)
    要实现此接口,还可以编写一个扩展 javax.servlet.GenericServlet 的一般 servlet,或者编写一个扩展 javax.servlet.http.HttpServlet 的 HTTP servlet。

    image.png

    b. 继承javax.servet.GenericServlet类(适配器模式)

    image.png

    只需重写抽象 service 方法,因为它里面只有一个抽象方法。

    image.png image.png

    c. 继承javax.servlet.http.HttpServlet类(模板方法设计模式)
    我们自己写Servlet的时候,处理请求的时候实现Service()就好。不重写Service()方法,而是重写doGet和doPost2个方法,在HttpServlet抽象类中,已经实现了Service方法了,在有请求进来Servlet的时候首先从请求中获取到请求提交的方式,所以我们直接重写doGet和doPost方法就好。通常来说不确定是什么请求的情况下,默认是Get请求,在doGet和doPost中实现一个就够了,如果方法的实现写在
    HTTP的请求方式包括DELETE,GET,OPTIONS,POST,PUT和TRACE,在HttpServlet类中分别提供了相应的服务方法,它们是,doDelete(),doGet(),doOptions(),doPost(), doPut()和doTrace().
    项目开发一般都用这种方式创建Servlet;
    第一步:创建Servlet类文件
    Ctrl+N;输入Servlet:

    image.png

    第二步:输入类名

    image.png

    第三步:映射路径的名字,默认为类名,可点击Edit编辑


    image.png

    第三步:勾选需要重写的方法:都默认勾选Doget和Dopost方法,点击Finish:
    继承HttpServlet后不要重写service的方法,因为service方法里包含调用doget跟dopost的方法,重写了那两方法不执行就作废了


    image.png

    第五步:检查生成的类和Web.xml的Servlet配置信息

    package com.cms.Demo1.Service;
    
    import java.io.IOException;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    /**
     * Servlet implementation class ServletDemo4
     */
    public class ServletDemo4 extends HttpServlet {
        private static final long serialVersionUID = 1L;
           
        /**
         * @see HttpServlet#HttpServlet()
         */
        public ServletDemo4() {
            super();
            // TODO Auto-generated constructor stub
        }
    
        /**
         * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
         */
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // TODO Auto-generated method stub
            response.getWriter().append("Served at: ").append(request.getContextPath());
        }
    
        /**
         * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
         */
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // TODO Auto-generated method stub
            doGet(request, response);
        }
    
    }
    
    
        <servlet>
            <display-name>ServletDemo4</display-name>
            <servlet-name>ServletDemo4</servlet-name>
            <servlet-class>com.cms.Demo1.Service.ServletDemo4</servlet-class>
        </servlet>
     
      <servlet-mapping>
        <servlet-name>ServletDemo4</servlet-name>
        <url-pattern>/ServletDemo4</url-pattern>
      </servlet-mapping>
    

    注意:查看GenericServlet 的源码包导Tomcat的源码包,apache-tomcat-7.0.81-src.zip。Outline的窗口带三角的说明是继承过来重写的方法,没有的才是自己本身的。

    image.png

    servet映射细节

    通配符* 代表任意字符串
    url-pattern: *.do 以.字符串的请求都可以访问 注:不要加/
    url-pattern: /* 任意字符串都可以访问
    url-pattern: /action/
    以/action开头的请求都可以访问
    匹配规则:
    优先级:从高到低
    绝对匹配--> /开头匹配 --> 扩展名方式匹配

    如果url-pattern的值是/,表示执行默认映射。所有资源都是servlet

    5. Servlet的线程安全

    ★ 单实例:每次访问多线程
    ★ 解决线程安全问题的最佳办法,不要写全局变量,而写局部变量。
    ★ Servlet的线程安全问题只有在大量的并发访问时才会显现出来,并且很难发现,因此在编写Servlet程序时要特别注意。
    ★ servlet处于服务器进程中,它通过多线程方式运行其service方法,一个实例可以服务于多个请求,并且其实例一般不会销毁,所以你的项目中如果只有一个servlet,那么web容器就只会创建一个实例。所以其默认非线程安全,如果需要线程安全需要指明。

    6.ServletConfig

    作用:
    ★ 可以获取servlet配置信息
    ★ 可以获得ServletContext对象

    6.1Servlet配置信息的获取:

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

    <servlet>
            <display-name>servletDemo4</display-name>
            <servlet-name>ServletDemo4</servlet-name>
            <servlet-class>com.cms.Demo1.Service.ServletDemo4</servlet-class>
            <!-- 初始化参数 -->
            <init-param>
            <param-name>encoding</param-name>
            <param-value>GBK</param-value>
            </init-param>
        </servlet>
    

    获取配置信息:GBK

    package com.cms.Demo1.Service;
    
    import java.io.IOException;
    
    import javax.servlet.ServletConfig;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    /**
    * Servlet implementation class ServletDemo4
    */
    public class ServletDemo4 extends HttpServlet {
      private ServletConfig config;//config对象专门操作配置文件信息
    
      @Override
      public void init(ServletConfig config) throws ServletException {
          // TODO Auto-generated method stub
          this.config = config;
      }
    
      protected void doGet(HttpServletRequest request, HttpServletResponse response)
              throws ServletException, IOException {
          String encoding = config.getInitParameter("encoding");//获得配置文件中的信息
          System.out.println(encoding);
      }
    
      protected void doPost(HttpServletRequest request, HttpServletResponse response)
              throws ServletException, IOException {
          doGet(request, response);
      }
    
    }
    
    

    总结:
    这样做的好处是:如果将数据库信息、编码方式等配置信息放在web.xml中,如果以后数据库的用户名、密码改变了,则直接很方便地修改web.xml就行了,避免了直接修改源代码的麻烦。
    获取Servlet配置信息的方式(关键得到ServletConfig对象):

    方式一:


    image.png

    方式二:

    image.png

    方式三:

    image.png

    7. ServletContext

    ServletContext: 代表的是整个应用。一个应用只有一个ServletContext对象。单实例。

    ServletContext与ServletConfig的区别:

    image.png

    作用:

    a. 作为 域对象:在一定范围内(当前应用),使多个Servlet共享数据。

    ★ 域对象:在一个可以被看见的范围内共享数据用到对象
    ★ 作用范围:整个web应用范围内共享数据
    ★ 生命周期:当服务器启动web应用加载后创建出ServletContext对象后,域产生。当web应用被移除出容器或服务器关闭,随着web应用的销毁域销毁。
    常用方法:
    void setAttribute(String name,object value);//向ServletContext对象的map中添加数据
    Object getAttribute(String name);//从ServletContext对象的map中取数据
    void rmoveAttribute(String name);//根据name去移除数据
    把数据添加到ServletContext的map里:

    package com.cms.Demo1.Service;
    
    import java.io.IOException;
    
    import javax.servlet.ServletContext;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    /**
     * Servlet implementation class ServletDemo5
     */
    public class ServletDemo5 extends HttpServlet {
    
        /**
         * @see HttpServoGet(HttpServletRequest request, HttpServletResponse response)
         */
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //通过GenericServlet类 继承的的getServletContext()方法得到ServletContext对象
        ServletContext application = this.getServletContext();//输完this.getServletContext() 后Ctrl+回车,对象ServletContext通常用application(应用)表示。
    //向ServletContext添加一个键值对
        application.setAttribute("name", "value");
        
        }
    
        /**
         * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
         */
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doGet(request, response);
        }
    
    }
    
    

    取出:

    package com.cms.Demo1.Service;
    
    import java.io.IOException;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    /**
     * Servlet implementation class ServletDemo6
     */
    public class ServletDemo6 extends HttpServlet {
    
    
        /**
         * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
         */
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            String name = (String) this.getServletContext().getAttribute("name");
            System.out.println(name);
            if(name==null){
                System.out.println("你无权访问");
            }
            System.out.println();
        
        }
    
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doGet(request, response);
        }
    
    }
    
    
    b. 获取全局配置信息:

    web.xml文件:
    String类型--getInitParameter(String name) //根据配置文件中的key得到value

    image.png

    Java文件:

    image.png
    c.获取资源路径:

    String getRealPath(String path);//根据资源名称得到资源的绝对路径.
    可以得到当前应用任何位置的任何资源。

    image.png

    注意:
    getRealPath的路径是参考部署后(publish)的文件路径
    '/'代表当前项目部署后的根目录:D:\apache-tomcat-7.0.52\webapps\webService

    实现Servlet的转发:
    image.png

    注意:
    RequestDispatcher getRequestDispatcher(String path) ;//参数表示要跳转到哪去

    相关文章

      网友评论

        本文标题:Servlet的原理、周期、创建方法、Servlet的线程安全、

        本文链接:https://www.haomeiwen.com/subject/yyoyextx.html