• android开发 Tomcat服务器之Servlet生命周期


    Servlet是一种可以在Servlet容器中运行的组件,那么理所当然就应该有一个从创建到销毁的过程,这个过程我们可以称之为Servlet生命周 期。Servlet的生命周期可以分为加载、实例化、初始化、处理客户请求和卸载五个阶段,体现在方法上主要是init()、service()和 destroy()三个方法。生命周期的具体说明如下: 

    Servlet容器完成加载Servlet类和实例化一个Servlet对象 
    init()方法完成初始化工作,该方法由Servlet容器调用完成 
    service()方法处理客户端请求,并返回响应结果 
    destroy()方法在Servlet容器卸载Servlet之前被调用,释放一些资源 
    加载并初始化Servlet 
    在前面已经说过Servlet容器完成加载和实例化Servlet的工作,该工作既可以在容器启动时完成,也可以在容器收到请求时完成,或者是两 者之间的某个时间启动。之后需要初始化Servlet,即读取配置信息、读取初始化参数等,这些基本上在整个生命周期中只需要执行一次。关于init() 方法已经在积累GenericServlet中提供缺省实现,如果不需特殊处理则没有必要再进行定义,否则要重写。 
    处理客户端请求 
    当容器接收到客户端请求时,Servlet引擎将创建一个ServletRequest请求对象和一个ServletResponse响应对象,然后把这两个对象作为参数传递给对应Servlet对象的service方法。 
    该方法是一个重点实现的方法,ServletRequest对象可以获得客户端发出请求的相关信息,如请求参数等,ServletResponse对象可以使得Servlet建立响应头和状态代码,并可以写入响应内容返回给客户端。 
    在此说明一点,当Servlet中有doGet()或者doPost()方法时,那么service方法就可以省略,默认为调用这两个方法。 
    卸载Servlet 
    Servlet的卸载是由容器本身定义和实现,在卸载Servlet之前需要调用destroy()方法,以让Servlet自行释放占用的系统 资源。虽然Java虚拟机提供了垃圾自动回收处理机制,但是有一部分资源却是该机制不能处理或延迟很久才能处理的,如关闭文件,释放数据库连接等。 
    Servlet生命周期的五个阶段是相互关联的,后面几个阶段建立在前面阶段的基础之上,在使用Servlet的时候可以根据自己的需要灵活处理。

    一、Servlet简介 :
    Servlet:即为Servlet(服务器)+Let(小的)即为服务器端小程序。

    二、Servlet作用:
    开发网站 。它是一个Java程序,动态生成HTML网页。

    ***Request-Response模型 :
    1、客户端先发生请求,服务器端产生响应。
    2、请求和响应成对出现,一次请求对应一次响应。
    Servlet是基于请求-响应模型的。

    三、程序员开发Servlet做的事情 :

    必须实现SUN公司提供的Servlet接口(Servlet接口来自JavaEE API)编写class实现Servlet接口,在web工程中web.xml 配置文件中对Servlet进行注册。

    四、Servlet 快速入门 案例
    1、创建web project
    2、创建demo1.html默认 Visual HTML Designer 开发慢 ---- 将HTML 默认编辑器改为:MyEclipse HTML Editor
    window -- preferences -- general -- Editors -- File Associations --*.html--下边的HTML Editor设为default
    3、编写一个Servlet生成一个HTML页面 创建一个class 继承 HttpServlet。
    代码如下 :
    ------
    public class ServletDemo extends HttpServlet{
     @Override
     //处理GET请求
     protected void doGet(HttpServletRequest req, HttpServletResponse resp)
       throws ServletException, IOException {
      // TODO Auto-generated method stub
    //  super.doGet(req, resp);
      System.out.println("helloWorld!");
      // 通过Servlet动态生成HTML 通过响应对象 获得输出流

      // 获得输出流之前,设置响应输出编码集
      resp.setContentType("text/html;charset=utf-8");
      PrintWriter out=resp.getWriter();
      // 生成是HTML源代码
      out.println("<html>");
      out.println("<body>");
      for(int i=0;i<3;i++){
       out.println("<h1>这是一个用Servlet生成的网页!</h1>");
      }
      out.println("</body>");
      out.println("</html>");  
     }
     @Override
     //处理POST请求
     protected void doPost(HttpServletRequest req, HttpServletResponse resp)
       throws ServletException, IOException {
      // TODO Auto-generated method stub
     }
    }
    ------

    4、编写的Servlet程序 需要在web.xml 中进行注册 ---为Servlet 配置虚拟访问路径 ,客户端通过路径访问该Servlet /hello
    代码如下 :
    ------
    <servlet>
     <servlet-name>Hello</servlet-name>
     <servlet-class>cn.android.servlet.ServletDemo</servlet-class> 
    </servlet>

    <servlet-mapping>
     <servlet-name>Hello</servlet-name>
     <url-pattern>/hello</url-pattern>
    </servlet-mapping>

    (注:配置Servlet的最终目的是:用虚拟路径/hello访问类cn.android.servlet.ServletDemo。
    ------
    5、覆盖doGet 和 doPost 
    代码见以上第3点

    使用Servlet 动态Servlet 生成HTML

    总结 :编写Servlet的3个步骤是:
    1)继承javax.servlet.http.HttpServlet
    2)在web.xml中配置虚拟路径
    3)覆盖doGet doPost
    ---

    五、客户端访问服务器动态web 资源 ---- 通过虚拟路径 映射找到要执行Servlet 程序
    客户端请求方式 ---- 会决定去执行 doGet 或者 doPost

    Servlet没有main函数,不是独自运行,需要运行在tomcat服务器上,由tomcat程序调用Servlet执行

    开发JavaSE程序 导包 import ---- import java.io.Reader;  import java.util.ArrayList;  位于JRE/rt.jar中
    开发JavaEE程序 导包 import javax.servlet.http.HttpServlet;  MyEclipse提供javaee.jar  Tomcat提供 lib/servlet-api.jar

    六、实验:手动编译运行一个Servlet(练习 )

    1、在webapps 创建 mytest目录(网站根目录)
    2、在mytest下新建WEB-INF目录,在目录下新建 web.xml 
    3、Serlvet类编写在哪个目录(classes)
    * src中编写Servlet 运行到tomcat 时,类class文件 复制WEB-INF/classes目录  复制Demo1Servlet.java源码到classes
    4、对.java文件进行编译 需要tomcat提供 servlet-api.jar 
    javac -classpath E:\apache-tomcat-6.0.14\lib\servlet-api.jar -d . ServletDemo.java
    即:javac -classpath jar包的路径 -d . ServletDemo.java
    cn.itcast.servlet.Demo1Servlet 类编译class后  ---- classes/cn/itcast/servlet/Demo1Servlet.class

    sun 规定Servlet程序必须实现Servlet接口
    Servlet接口有实现类GenericServlet, GenericServlet子类 HttpServlet , 编写Servlet程序只需要继承HttpServlet 间接实现Servlet接口 (简化开发)

    Servlet接口和GenericServlet类中 并没有与协议相关API (只定义了通用API),HttpServlet 提供了很多与HTTP协议相关API

    Servlet接口中提供5个方法,其中init service destroy 这三个方法描述了Servlet 对象生命周期(Servlet对象从创建到销毁完整过程)

    第一次访问Servlet 时,Servlet构造方法执行、init 执行,执行service
    如果不是第一次访问Servlet ,直接执行service 
    正常关闭服务器 destroy 执行 --- 执行tomcat shutdown.bat

    结论:
    1、Servlet对象只会在服务器端创建一个,init 方法也只会执行一次 , 默认是在第一次访问Servlet时 创建对象 调用init
    2、每一次客户端HTTP请求,都将执行服务器Servlet对象 service方法 (以独立线程进行执行)
    * 不出现并发问题,Servlet对象只有一个实例,通常不编写Servlet对象成员变量
    * 栈空间是线程私有的 不会发生并发问题 ,只有堆空间是进程独享,进程由多个线程组成,堆空间上变量才能导致 多线程并发问题
    3、在服务器正常关闭时,执行一次 destroy

    之前快速入门案例 继承HttpServlet 覆盖doGet doPost 没有编写service ------ service 和 doGet/doPost 关系
    * 在HttpServlet中 service方法内 根据请求方式执行 doGet 或者 doPost  (查看Servlet源代码 )
    --- 导入源码

    默认Servlet程序是在第一次访问时,创建对象,执行init ----- 如果想在服务器启动时 创建Servlet对象 执行init 有无办法???
    * 在<Servlet> 元素中 添加<load-on-startup> 语法 <load-on-startup>数字(加载Servlet优先级 0-9 0优先级最高 )</load-on-startup>
    应用: Struts1 ActionServlet 核心控制器 在服务器启动时 加载配置文件

    编写Servlet注意事项
    1、Servlet初始化时覆盖init() ,无需覆盖init(config)
    * 覆盖无参数init 也会得到初始化执行,因为在GenericServlet中 init(config) 调用 init() 
    思考题
    class A extends HttpServlet {
       public void init(){
          sysout(1);
       }
       public void init(ServletConfig) { 
          sysout(2); 
       }
    }
    初始化时 执行哪个方法 ?答案:2 只会执行生命周期 init(config)

    2、继承HttpServlet 只需覆盖doGet 和 doPost 无需覆盖service

    3、当doGet 和 doPost 代码完全相同 互相调用 简化编程

     

    -------
    七、虚拟路径映射三种书写格式 :
    1、完全路径匹配:以/开始 ,不存在通配符*。例如:/demo1、/demo2、/aa/index.html 
    2、目录匹配:以/开始,使用通配符 *。   例如: /*   /aa/*   /bb/cc/*
    (注:*指某个目录下的所有资源)
    3、扩展名匹配:不能以/开始,使用通配符。*.do 、*.action ----- /*.do、/aa/*.action 错误的

    *** 假如有一天访问 html 都报404 时候,确认路径真的没写错 ----- 服务器启动时 没有正确加载工程
    优先顺序:完全路径> 目录 > 扩展名

    八、案例 乘法表 ---- 打印乘法表 
    需求:编写html页面在页面中提供form表单,要求用户输入一个数字
    服务器Demo4Servlet 根据用户输入数字打印 几乘几 乘法表

    路径写法:相对路径 、绝对路径
    相对路径 例如: hello ./hello ../hello
    * hello 当前目标hello资源 与 ./hello 意义相同
    * ../hello 代表上一级目录hello 

    九、例1 :http://localhost/day5/demo4/chengfabiao.html  ----- 目标:http://localhost/day5/demo4 答案 ../demo4
    http://localhost/day5/demo4/chengfabiao.html --- 链接 ./hello  结果 http://localhost/day5/demo4/hello
    http://localhost/day5/demo4/chengfabiao.html --- 链接 ../hello  结果http://localhost/day5/hello 
    * 如果使用相对路径,分析当前路径 与 目标路径  根据相对位置编写路径

    绝对路径 例如: /hello 、/day5/hello、http://localhost/day5/hello 
    分析/ 含义
    客户端访问服务器 http://localhost ---- 访问tomcat主页
    http://localhost/day5 ---- 访问day5工程主页
    http://localhost/day5/demo4 --- 访问乘法表Servlet
    * 绝对路径不用考虑当前文件url ,从服务器根目录 / 找到目标路径 就可以了

    目标:http://localhost/day5/demo4 ---- 绝对 /day5/demo4

    服务器端和客户端对于/ 的区别
    客户端访问 在tomcat服务器之外,找day5工程下 demo4 资源 ---- /day5/demo4
    服务器内部路径 在day5工程内 /demo4  ---- /当前工程

    结论:
    1、都用绝对路径
    2、客户端与服务器 / 写法不同
    客户端 /工程名/资源 ---- 在服务器外部
    服务器内部 /资源 --- 不需要写/工程名

     
    --------------------------------------下午---------------------------------------
    十、Servlet生命周期 
    Servlet 生命周期 init(ServletConfig) service(ServletRequest,ServletResponse) destroy()

    配置web.xml 通过<init-param> 为Servlet对象提供初始化参数,都可以通过init方法中ServletConfig对象获得
    * 在<Servlet> 标签中 
    * ServletConfig 只是接口,实现类由Tomcat服务器提供

    ServletConfig 通过下面方法获得初始化参数
    String getInitParameter(String name)  获得指定参数值,传入参数name
    Enumeration getInitParameterNames()  获得所有参数name的集合
    * Enumeration 接口 就是 Iterator前身 Enumeration 线程安全的  Iterator 线程不安全

    ArrayList 替代 Vector 、HashMap 替代 HashTable 、StringBuilder 替代 StringBuffer 
    * 线程不考虑安全问题的这些类 效率更高

    注意事项:ServletConfig 实例 针对每一个Servlet实例 提供初始化参数,一个Servlet对象应该有一个对应ServletConfig实例
    ServletConfig只能获得 当前Servlet实例初始化信息

    结论:在编写Servlet时,无需覆盖init(ServletConfig) 在Servlet类中只需通过getServletConfig() 方法 获得config对象
    * 覆盖有参数init 没有执行 this.config= config ---- 结果 getServletConfig 返回 null


    十一、ServletContext  每个工程对应一个独立ServletContext对象 ,全局Servlet控制对象
    1、获得ServletContext 需要通过ServletConfig接口 方法 
    2、因为ServletContext 是每个工程只有一个,实现数据共享
    ServletContext 应用
    1、获得整个web工程全局(该工程所有Servlet都可以访问)初始化参数 
    2、实现数据共享,ServletContext对象是全局唯一,保存到该对象数据,可以从当前应用任何程序获得
    3、利用ServletContext对象读取web应用中资源文件

    第一个应用:配置全局初始化参数
    ServletContext 与 ServletConfig 提供初始化参数不同 ??
    配置ServletContext全局参数 <context-param>

    getServletContext().getInitParameter(参数名称);

    第二个应用:使用ServletContext对象实现全局数据共享
    如果在ServletContext中保存一个数据,所有Servlet都可以访问该数据
    网站访问计数案例

    向ServletContext保存数据 setAttribute() ------- 相当于map.put
    取得ServletContext中数据 getAttribute ---- map.get 这里取出数据是 Object 需要强制类型转换

    第三个应用:通过ServletContext读取web 工程中资源文件
    回顾 java工程读取文件 通过main函数读取 ---- JVM中直接运行
    web 工程读文件 通过Servlet读取  ----- Tomcat中运行

    十二、创建四个文件 
    1.txt ---- 工程根目录
    2.txt ---- WebRoot目录
    3.txt ---- WEB-INF目录
    4.txt ---- src目录

    !!!!!!!!在web 工程读取文件必须使用绝对磁盘路径 D:\work\myclipse\work20120713\day5\1.txt
    1.txt在工程根目录,不在WebRoot 中 --- 只有WebRoot 会被发布 ---- 1.txt 不存在无法读取
    4.txt 在src目录 --- src中所有java文件编译.class 保存WEB-INF/classes  --- src中所有配置文件 
    会自动复制WEB-INF/classes --- 可以读取

    file = getServletContext().getRealPath("/2.txt"); ---- 将网站根目录下2.txt 文件路径 转换为绝对磁盘路径
    file = getServletContext().getRealPath("/WEB-INF/3.txt"); ---- 将网站根目录下WEB-INF目录下 3.txt 转换绝对磁盘路径
    file = getServletContext().getRealPath("/WEB-INF/classes/4.txt"); ---- 获得网站根目录下WEB-INF下classes 下4.txt 绝对磁盘路径

    如果读取文件 在WEB-INF/classes下 
    file = Demo9Servlet.class.getResource("/4.txt").getFile(); // 这里 / 代表classpath根目录


    十三、缺省Servlet:
    1、配置url-pattern 为 /
    2、所有静态WEB资源 html,都由缺省的Servlet返回给客户端。

    在tomcat中已经配置缺省Servlet : org.apache.catalina.servlets.DefaultServlet的Servlet
    conf/web.xml 
    * 位于tomcat/conf/web.xml 当前配置将对整个服务器内部所有网站 有效
    缺省Servlet
    1、获得客户端要访问哪个web资源
    2、判断服务器端该web资源是否存在
    3、如果资源存在,读取资源内容返回客户端
    4、如果资源不存在 ,返回404
    -------------------------------

    十四、文件复制掌握三个:
    1、一个字节一个字节读
    InputStream in ...
    OutputStream out ...
    int b;
    while((b=in.read)!=-1){
       out.write(b);
    }
    2、一行一行读
    BufferedReader reader ...
    PrintWriter out ...
    String line;
    while((line = reader.readLine())!=null){
       out.println(line);
    }

    3、使用数组缓冲读
    InputStream in ...
    OutputStream out ...
    byte[] buf = new byte[8192];
    int len;
    while((len = in.read(buf))!=-1){
       out.write(buf,0,len);
    }


    今日复习内容:
    1、Servlet的HelloWorld !  ---- 整理Servlet开发步骤
    1)继承javax.servlet.http.HttpServlet
    2)在web.xml中配置虚拟路径
    3)覆盖doGet doPost

    2、在MyEclipse链接Servlet源代码
    选中HttpServlet点Ctrl,然后将已存在的源码文件路径选中导入即可。

    3、修改Servlet模板

    4、Servlet生命周期 ? init方法 service方法 destroy方法何时执行?
    service 和 doGet doPost 关系
    init(ServletConfig) 和 init() 关系
    ---
    Servlet生命周期 :Servlet对象从创建到销毁完整过程。
    第一次访问Servlet 时,Servlet构造方法执行、init 执行,执行service
    如果不是第一次访问Servlet ,直接执行service 
    正常关闭服务器 destroy 执行 --- 执行tomcat shutdown.bat
    在HttpServlet中 service方法内 根据请求方式执行 doGet 或者 doPost
    Servlet初始化时覆盖init() ,无需覆盖init(config)
    * 覆盖无参数init 也会得到初始化执行,因为在GenericServlet中 init(config) 调用 init()
    5、url配置三种方式:完全匹配、目录匹配和扩展名 匹配
    1)、完全路径匹配 : 以/开始  例如:/demo1、/demo2、/aa/index.html  ----- 不存在通配符* 
    2)、目录匹配 : 以/开始 使用通配符* 例如:/*、/aa/*、/bb/cc/*  ---- /a*b* /a* 错误的
    * 某个目录下所有资源 
    3)、扩展名匹配:不能以/开始 使用通配符 例如:*.do 、*.action ----- /*.do、/aa/*.action 错误的

    6、乘法表案例

    7、ServletConfig 配置初始化参数
    ServletConfig 通过下面方法获得初始化参数
    String getInitParameter(String name)  获得指定参数值,传入参数name
    Enumeration getInitParameterNames()  获得所有参数name的集合

    8、ServletContext 全局参数、访问次数案例、读取web文件 (复习读取文件)

    9、缺省Servlet 案例 (复习文件复制三种写法)
    缺省Servlet
    1、配置url-pattern 为 /
    2、所有静态web资源 html、图片 都是由 缺省Servlet返回给客户端

    在tomcat中已经配置缺省Servlet : org.apache.catalina.servlets.DefaultServlet的Servlet
    conf/web.xml 
    * 位于tomcat/conf/web.xml 当前配置将对整个服务器内部所有网站 有效
    缺省Servlet
    1、获得客户端要访问哪个web资源
    2、判断服务器端该web资源是否存在
    3、如果资源存在,读取资源内容返回客户端
    4、如果资源不存在 ,返回404

  • 相关阅读:
    Part 17 Consuming ASP NET Web Service in AngularJS using $http
    Part 16 ng include directive in AngularJS
    Part 15 AngularJS ng init directive
    文本框
    mint上部署lamp环境
    18种有效有趣的读书方法(转载)
    可扩展的架构设计
    iisreset和w3wp的关系
    Ajax请求中带有IPv6地址后的百分号的问题
    IE中JavaScript 的异常处理
  • 原文地址:https://www.cnblogs.com/cuixiaodong427/p/3108270.html
Copyright © 2020-2023  润新知