java基础78 Servlet的生命周期
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 欢迎转载,转载务必说明出处。(如果本文对您有帮助,可以点击一下右下角的 推荐,或评论,谢谢!) |
java基础78 Servlet的生命周期的更多相关文章
- IT兄弟连 Java Web教程 Servlet的生命周期
JavaWeb应用的生命周期由Servlet容器来控制,而Servlet作为JavaWeb应用的最核心的组件,其生命周期也由Servlet容器来控制.Servlet的生命周期可以分为3个阶段:初始化阶 ...
- Servlet基础(二) Servlet的生命周期
Servlet基础(二) Servlet的生命周期 Servlet的生命周期可以分为三个阶段: 1.初始化阶段 2.响应客户请求阶段 3.终止阶段 Servlet的初始化阶段 在下列时刻Servlet ...
- j2ee基础(1)servlet的生命周期
Servlet的生命周期 Servlet 生命周期规定了 Servlet 如何被加载.实例化.初始化. 处理客户端请求,以及何时结束服务. 该生命周期可以通过 javax.servlet.Servle ...
- servlet基础(组成与生命周期)
servlet基础作用:servlet是运行在Web服务器或应用服务器上的程序:担当web浏览器或其他HTTP客户程序发出的请求与HTTP服务器上的数据库或应用程序之间的中间层.1.读取客户程序发送的 ...
- Java Web -- Servlet(5) 开发Servlet的三种方法、配置Servlet具体解释、Servlet的生命周期(2)
三.Servlet的生命周期 一个Java servlet具有一个生命周期,这个生命周期定义了一个Servlet怎样被加载并被初始化,怎样接收请求并作出对请求的响应,怎样被从服务中清除.Servlet ...
- WEB基础(二)--servlet的生命周期
Servlet的生命周期一般可以用三个方法来表示: init():仅执行一次,负责在装载Servlet时初始化Servlet对象 service() :核心方法,一般HttpServlet中会有get ...
- JavaWeb学习之Servlet(二)----Servlet的生命周期、继承结构、修改Servlet模板
[声明] 欢迎转载,但请保留文章原始出处→_→ 文章来源:http://www.cnblogs.com/smyhvae/p/4140466.html 一.http协议回顾: 在上一篇文章中:JavaW ...
- (转)JavaWeb学习之Servlet(二)----Servlet的生命周期、继承结构、修改Servlet模板
[声明] 欢迎转载,但请保留文章原始出处→_→ 文章来源:http://www.cnblogs.com/smyhvae/p/4140466.html 一.http协议回顾: 在上一篇文章中:JavaW ...
- (转)Servlet的生命周期——初始化、运行、销毁全部过程
背景:面试中很基础的一个问题,所以有必要好好整理一番. Servlet体系结构是建立在 Java 多线程机制上的,它的生命周期由 Web 容器负责. 当客户端第一次请求某个 Servlet 时,Ser ...
随机推荐
- UOJ #126 【NOI2013】 快餐店
题目链接:快餐店 震惊!某ZZ选手此题调了一天竟是因为……>>点击查看 一般碰到这种基环树的题都要先想想树上怎么做.这道题如果是在树上的话……好像求一遍直径就做完了?答案就是直径长度的一半 ...
- Reactor模式,或者叫反应器模式 - 为什么用多路io复用提供吞吐量
Reactor这个词译成汉语还真没有什么合适的,很多地方叫反应器模式,但更多好像就直接叫reactor模式了,其实我觉着叫应答者模式更好理解一些.通过了解,这个模式更像一个侍卫,一直在等待你的召唤,或 ...
- 单点登录(十六)-----遇到问题-----cas4.2.x登录成功后报错No principal was found---cas中文乱码问题完美解决
情况 我们之前已经完成了cas4.2.x登录使用mongodb验证方式并且自定义了加密. 单点登录(十五)-----实战-----cas4.2.x登录mongodb验证方式实现自定义加密 但是悲剧的是 ...
- std::async
https://www.cnblogs.com/qicosmos/p/3534211.html https://bobjin.com/blog/c_cpp_docs/reference/en/cpp/ ...
- 图像处理之CSC性能优化(源码)
1 CSC基本实现 根据前一篇CSC转换的文档了解到,RGB与YUV的变换公式如下: YCbCr(256 级别) 可以从8位 RGB 直接计算,计算公式如下: Y = 0.299 R + 0.587 ...
- body内常用标签
一.标签内使用的符号 # 特殊字符 空格 > 大于 < 小于 更多特殊字符:Here 二.P标签 作用:p标签表示段落 <body> <p> 吃葡萄不吐葡萄皮 ...
- P2831 愤怒的小鸟
P2831 愤怒的小鸟 从 \((0, 0)\) 发射一只鸟, 轨迹满足抛物线, 问最少几只鸟可以打完 \(n <= 18\) 只猪 错误日志: 处理抛物线数组没有初始化 Solution 数据 ...
- ios中iframe的scroll滚动事件替代方法
在公众号的开发中,遇到ios中iframe的scroll滚动事件失效,在此做下记录. 因为接口获取的数据必须放在iframe中展示,滚动到底部按钮变亮,如图: 代码如下: <!DOCTYPE h ...
- 3.Filter和interceptor的区别
https://blog.csdn.net/qq_36411874/article/details/53996873
- java抽象类和普通类的区别
1.抽象类不能被实例化. 2.抽象类可以有构造函数,被继承时子类必须继承父类一个构造方法,抽象方法不能被声明为静态. 3.抽象方法只需申明,而无需实现,抽象类中可以允许普通方法有主体 4.含有抽象方法 ...