什么是Servlet?
狭义上 :
Servlet就是一个接口,全名Servlet.class,位于Servlet-api.jar包里的javax.servlet包内,
我们看一下Servlet.class的源码 :
广义上:
任何实现了这个Servlet接口的类,都可以叫做是Servlet.一般我们说Servlet是指广义上的Servlet.
Servlet是干嘛的?
接口的作用是规范!
servlet接口定义的是一套处理网络请求的规范,所有实现servlet的类,都需要实现它那五个方法.
其中最主要的是两个生命周期方法 init()和destroy(),还有一个处理请求的service()
所有实现servlet接口的类,或者说,所有想要处理网络请求的类,都需要回答这三个问题:
*你初始化时要做什么
*你销毁时要做什么
*你接到请求时要做什么
servlet可以直接处理请求吗?
答案是,不能! 相信我,你从来不会在servlet中写什么监听8080端口的代码,servlet不会直接和客户端打交道!
那请求怎么来到servlet呢?答案是servlet容器,比如我们最常用的tomcat.
Servlet框架构成
HttpServlet
HttpServlet是一个抽象类,继承自GenericServlet(抽象类),而GenericServlet实现了Servlet接口
在使用servlet编写web应用时,控制层的servlet类都要继承HttpServlet类,重写doGet(),doPost,或者doService()以完成客户端的请求
为什么要专门做一个HttpServlet类?它和Servlet类有什么区别?
HttpServlet是专门处理http请求的Servlet !
因为我们现在处理的请求,都是基于http协议的,所以就有了专门为处理HTTP请求的Servlet,即HttpServlet.
HttpServlet中的doGet(), doPost(), doService()等方法,参数都是HttpServletRequest和HttpServletResponse,
而Servlet中的参数则是ServletRequest和ServletResponse.
Servlet的生命周期
- 调用
init()
方法初始化 - 调用
service()
方法来处理客户端的请求 - 调用
destroy()
方法释放资源,标记自身为可回收 - 被垃圾回收器回收
Servlet在服务器运行过程中,
***只会初始化(init)一次***
***只会消亡(destroy)一次***
***一个Servlet只会产生一个实例***
当多个请求同时访问Servlet时,容器会起多个线程同时访问Servlet的service()方法
Servlet的线程安全问题
由上面内容我们可以得知,当同时有多个请求访问service()方法时,就会涉及线程安全问题.
我们排列情况如下:
service()方法访问的内容 | 是否有读写操作 | 是否线程安全 |
Servlet的成员变量 | 只有只读操作 | 线程安全 |
Servlet的成员变量 | 有读写操作 | 不安全,需要加上同步控制语句 |
全局的静态变量 | 有读写操作 | 不安全,需要加上同步控制语句 |
全局资源(文件,数据库连接等) | 有读写操作 | 不安全,需要加上同步控制语句 |
Servlet是单实例多线程
Servlet容器处理请求的流程:
- 当web服务器启动的时候(或客户端发送请求到服务器时),Servlet就被加载并实例化(只存在一个Servlet实例)
- 容器初始化化Servlet主要就是读取配置文件
- 当请求到达时,Servlet容器通过调度线程(Dispatchaer Thread),调度它管理下线程池中等待执行的线程(Worker Thread)给请求者
- 线程执行对应Servlet的service方法;
- 请求结束,线程被放回线程池,等待被调用;
Servlet单实例多线程的特点
- Servlet单实例,减少了产生servlet的开销
- 通过线程池来响应多个请求,减少了请求的响应时间
- Servlet容器并不关心到达的Servlet请求访问的是否是同一个Servlet还是另一个Servlet,直接分配给它一个新的线程;如果是同一个Servlet的多个请求,那么Servlet的service方法将在多线程中并发的执行
Servlet的实际应用
1.编写Servlet类(省略)
2.在web.xml配置Servlet映射
servletDemo
com.test.servletDemo
servletDemo
/test/servletDemo
未完待续......