1、Servlet的生命周期

简单的解析就是:

创建servlet实例(调用构造器)---->调用init()方法---->调用service()方法----->调用destroy()方法

构造方法:创建servlet时被调用,默认情况下,第一次访问servlet的时,创建servlet对象值只调用一次,证明servlet对象在tomcat是单实例.
init方法:创建玩servlet对象是调用。只调用一次
service方法:每次发送请求时被调用。调用n次(有多少次请求,就调用多少次)
destroy方法:销毁servlet对象时调用,只调用一次。(停止服务器或者重启服务器【重新部署web应用】的时候销毁servlet对象)

1.1、实例

 package com.shore.myservlet;

 import java.io.IOException;

 import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; /**
* @author DSHORE / 2018-9-14
*
*/
public class MyServletOne extends HttpServlet {
//构造方法
public MyServletOne() {
System.out.println("构造器被调用");
} //调用init()方法,servlet被初始化
public void init() throws ServletException {
System.out.println("调用init方法");
} //servlet服务
@Override
protected void service(HttpServletRequest arg0, HttpServletResponse arg1)
throws ServletException, IOException {
System.out.println("调用service方法");
}
//调用destroy()方法,servlet被销毁!
public void destroy() {
System.out.println("调用destroy方法");
//super.destroy();
}
}

配置文件:web.xml

 <?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name></display-name> <!-- servlet的配置文件 -->
<servlet>
<!--servlet内部名称(类名),可以自定义 -->
<servlet-name>MyServletOne</servlet-name>
<!-- servlet类名:包名+简单类名 -->
<servlet-class>com.shore.myservlet.MyServletOne</servlet-class>
</servlet> <!-- servlet的映射配置 -->
<servlet-mapping>
<!-- servlet内部名称(类名),可以自定义,和上面保持一致 -->
<servlet-name>MyServletOne</servlet-name>
<!-- servlet访问名称:/名称 -->
<url-pattern>/MyServletOne</url-pattern>
</servlet-mapping> <welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>

结果图

1.2、Servlet生命周期的业务逻辑过程解析(以上面的实例作为解析案例)

浏览器                                                       Tomcat服务器                                               MyServletOne对象

 (1) 向服务器发送请求 http://localhost:8080/MyServlet/MyServletOne(可以看浏览器端的请求头信息)
 (2) 截取/MyServlet,进入webapps目录下的MyServlet目录。
 (3) 截取/MyServletOne,去MyServlet下的web.xml文件中查找是否有匹配的<url-patten>/MyServletOne</url-patten>
 (4) 如果匹配,则在web.xml文件中查找是否有名称相同的servlet配置。
 (5) 如果找到,则去寻找servlet配置中的servlet-class的内容:com.shore.myservlet.MyServletOne
 (6) 创建MyServletOne对象。
 (7) 调用构造方法:public MyServletOne(){.....}
 (8) 构造方法被调用,创建ServletConfig对象,调用init方法
 (9) init方法被调用,创建request、response对象
(10) service被调用(service根据页面传过来的的请求方式,决定调用doGet方法/doPost方法)
(11) 返回被修改的response对象,并且把response对象解析成相应的格式的数据(浏览器端的响应头信息可以体现)
(12) 如果服务器停止,则调用destroy方法,销毁本次servlet请求。

附录

1、servlet的自动加载

默认情况下,第一次访问servlet的时候创建servlet对象。如果servlet的构造方法或者init方法中执行比较多的逻辑代码,那么会导致第一次访问的时候比较慢。
    解决方法:改变servlet创建对象的时机

 <!-- servlet的配置文件 -->
<servlet>
<!--servlet内部名称(类名),可以自定义 -->
<servlet-name>MyServletOne</servlet-name>
<!-- servlet类名:包名+简单类名 -->
<servlet-class>com.shore.myservlet.MyServletOne</servlet-class>
<!-- 作用:服务器一启动,构造器和init方法就被提前加载 。 注意:整数值越大,创建优先级越低 -->
<load-on-startup>1</load-on-startup>
</servlet> <!-- servlet的映射配置 -->
<servlet-mapping>
<!-- servlet内部名称(类名),可以自定义,和上面保持一致 -->
<servlet-name>MyServletOne</servlet-name>
<!-- servlet访问名称:/名称 -->
<url-pattern>/MyServletOne</url-pattern>
</servlet-mapping>

2、Servlet的多线程并发问题

注意:servlet对象在tomcat服务器是单实例多线程
    因为servlet是多线程的,所以,当有多个servlet线程访问servlet的共享数据时,如果成员变量(即:全局变量),可能会引发线程安全问题。
解决办法:
  1)把使用共享的数据代码进行同步(synchronized(锁)关键字进行同步)
  2)建议在servlet类中尽量不要使用成员变量。如果确实要使用成员变量,必须同步,而且尽量缩小同步代码块的范围。(哪里使用到了成员变量就同步哪里!),以避免因为同步而导致效率降低

2.1、出现多个线程并发的例子

web.xml文件

 <?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<display-name></display-name>
<servlet>
<servlet-name>MyServlet</servlet-name>
<servlet-class>com.shore.mservlet.MyServlet</servlet-class>
</servlet> <servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>/MyServlet</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>

MyServlet类 文件

 package com.shore.mservlet;

 import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; /**
* @author DSHORE / 2018-9-18
*
*/
public class MyServlet extends HttpServlet {
int counnt = 1;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setCharacterEncoding("GBK");
response.getWriter().write("第"+counnt+"次");
//睡眠5秒钟 19到25行代码的作用:测试时 更容易看出是否是线程并发问题
Thread thread = new Thread();
try {
thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
counnt++;
} public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}

结果图

由上图,可以看出:同时出现了一个“4”,说明出现了线程问题;解决方法看下面的例子

2.2、解决多线程并发的例子

在MyServlet类中,需要共享的数据,用同步代码块 同步掉,即可。

 package com.shore.mservlet;

 import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; /**
* @author DSHORE / 2018-9-18
*
*/
public class MyServlet extends HttpServlet {
int counnt = 1;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setCharacterEncoding("GBK");
synchronized (MyServlet.class) {//MyServlet.class是惟一的
response.getWriter().write("第"+counnt+"次");
counnt++;
}
} public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}

结果图

就算有很多个人,同时访问 也不会出现重复的数字(即:不会出现线程安全问题)

3、Servlet编程知识点

1) servlet生命周期

构造方法:创建servlet对象,默认情况下,第一次访问servlet对象时,值调用一次。
init方法(有参):创建servlet对象后调用,只调用一次。 注意:会调用无参的init方法
service方法:service提供服务的方法,每次方式请求调用。注意:request对象,response对象
destroy方法:tomcat停止或者web应用重新部署,servlet对象销毁,destroy方法被调用。

2)servletConfig对象

获取servlet的初始化参数:
        getInitParameter(“name”);
        getInitParameterNames();

3)servletContext对象

得到web应用路径:
          Context.getContextPath();
          Request.getContextPath();
    得到web应用的参数:
          context.getInitParameter(“name”);
          context.getInitParameterNames();
    域对象:
          Context.setAttribute(“name”,objext); //保存数据
          Context.getAttribute(“name”); //得到数据
          Context.removeAttribute(“name”); //清除数据
    转发:
          Context.getRequestDispatcher(“路径”).forward(request,response);
          Request. getRequestDispatcher(“路径”).forward(request,response);
    得到web应用的资源:
          Context.getRealPath(“路径”);
          Context.getResourceAsStream(“路径”);

原创作者:DSHORE

作者主页:http://www.cnblogs.com/dshore123/

原文出自:https://www.cnblogs.com/dshore123/p/9605400.html

欢迎转载,转载务必说明出处。(如果本文对您有帮助,可以点击一下右下角的 推荐,或评论,谢谢!

最新文章

  1. 简易线程池Thread Pool
  2. 原生js添加和删除类
  3. iOS开发多线程篇—线程的状态
  4. partial(C# 参考)
  5. 2014 Multi-University Training Contest 7
  6. 使用wget和ftp共享文件
  7. vsftpd限制用户不能更改根目录
  8. KoaHub平台基于Node.js开发的Koa的rewrite and index support插件代码详情
  9. 201521123044 《Java程序设计》第14周学习总结
  10. Zabbix (五)
  11. Scratch不仅适合小朋友,程序员和大学老师都应该广泛使用!!!
  12. 设计模式のDecoratorPattern(装饰器模式)----结构模式
  13. docker的使用 -- windows
  14. P1993 小K的农场
  15. pytorch 中的重要模块化接口nn.Module
  16. eclipse web module版本问题:Cannot change version of project facet Dynamic Web Module to 2.5.
  17. python中的jion
  18. C#用log4net记录日志
  19. java 标准异常
  20. shell学习(四)

热门文章

  1. Linux命令之ipcalc
  2. 实现运行在独立线程池的调度功能,基于Spring和Annotation
  3. 【DSU on tree】【CF741D】Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths
  4. 【枚举&amp;数据结构】【P2484】 [SDOI2011]打地鼠
  5. 图像处理之CSC性能优化(源码)
  6. servlet与tomcat的关系
  7. python的匿名函数 lambda的使用方法详解以及使用案例
  8. 「Vue」自定义按键修饰符
  9. U33405 纽约
  10. Java基础-IO流对象之数据流(DataOutputStream与DataInputStream)