Tomcat工作机制
Servlet(Server Applet)是Java Servlet的简称,称为小服务程序或服务连接器,用Java编写的服务器端程序,具有独立于平台和协议的特性,主要功能在于交互式地浏览和生成数据,生成动态Web内容。
狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类,一般情况下,人们将Servlet理解为后者。Servlet运行于支持Java的应用服务器中。从原理上讲,Servlet可以响应任何类型的请求,但绝大多数情况下Servlet只用来扩展基于HTTP协议的Web服务器。
Servlet采用Java语言编写,它可以调用Java API 中的对象及方法。此外,Servet 对象对Web应用进行了封装,提供了Servlet对Web应用的编程接口,还可以对HTTP请求进行相应的处理,如处理提交数据、会话跟踪、读取和设置HTTP头信息等。由于Servlet既拥有Java提供的API,而且还可以调用Servlet封装的Servlet API编程接口,因此,它在业务功能方面十分强大。
Java语言是跨越平台的,所谓跨越平台是指程字的运行不依赖于操作系统平台,它可以运行到多个系统平台中,如目前常用的操作系统Windows、Linux 和UNIX等,由于Servlet使用Java语言编写,所以,Servlet 继承了Java语言的优点,程序一次编码,多平台运行,拥有超强的可移植性。
Servlet对象在Servlet容器启动时被初始化,当第次被请求时,Servlet容器将其实例化,此时它驻存于内存中。如果存在多个请求,Servlet 不会再被实例化,仍然由此Servlet对其进行处理。每一个请求是一个线程,而不是一- 个进程,因此,Servlet 对请求处理的性能是十分高效的。
Servlet使用了Java 的安全框架,同时Servlet 容器还可以为Servlet提供额外的功能,它的安全性是非常高的。
Java语言是面向对象的编程语言,Servlet由Java语言编写,所以它继承了Java的面向对象的优点。在业务逻辑处理中,可以通过封装、继承。
JSP页面可以存在HTML代码与Java代码并存的情况,而Servlet需要承担客户请求与业务处理的中间角色,只有调用固定的方法才能将动态内容输出为静态的HTML,所以,JSP 更具有显示层的角色。
Servlet与JSP在编程方法,上存在很大的区别,使用Servlet 开发Web应用程序需要遵循Java的标准,而JSP需要遵循一定脚本语言规范。在Servlet代码中,需要调用Servlet 提供的相关API 接口方法,才可以对HTTP请求及业务进行处理,对于业务逻辑方面的处理功能更加强大。然而在JSP页面中,通过HTML代码与JSP内置对象实现对HTTP请求及页面的处理,其显示界面的功能更加强大。
Servlet需要在Java编译器编译后才可以运行,如果Servlet在编写完成或修改后没有被重新编译,则不能运行在Web容器中。而JSP则与之相反,JSP 由JSP Container对其进行管理,它的编辑过程也由JSP Container对JSP进行自动编辑,所以,无论JSP文件被创建还是修改,都不需要对其编译即可执行。
由于JSP页面由JSPContainer对其进行管理,在每次执行不同内容的动态JSP页面时,JSPContainer都要对其自动编译,所以,它的效率低于Servlet 的执行效率。而Servlet 在编译完成之后,则不需要再次编译,可以直接获取及输出动态内容。在JSP页面中的内容没有变化的情况下,JSP页面的编译完成之后,JSP Container不会再次对JSP进行编译。
Servlet 生命周期可被定义为从创建直到毁灭的整个过程。以下是 Servlet 遵循的过程:
现在让我们详细讨论生命周期的方法。
init 方法被设计成只调用一次。它在第一次创建 Servlet 时被调用,在后续每次用户请求时不再调用。因此,它是用于一次性初始化,就像 Applet 的 init 方法一样。
Servlet 创建于用户第一次调用对应于该 Servlet 的 URL 时,但是您也可以指定 Servlet 在服务器第一次启动时被加载。
当用户调用一个 Servlet 时,就会创建一个 Servlet 实例,每一个用户请求都会产生一个新的线程,适当的时候移交给 doGet 或 doPost 方法。init() 方法简单地创建或加载一些数据,这些数据将被用于 Servlet 的整个生命周期。
init 方法的定义如下:
public void init() throws ServletException {
// 初始化代码...
}
service() 方法是执行实际任务的主要方法。Servlet 容器(即 Web 服务器)调用 service() 方法来处理来自客户端(浏览器)的请求,并把格式化的响应写回给客户端。
每次服务器接收到一个 Servlet 请求时,服务器会产生一个新的线程并调用服务。service() 方法检查 HTTP 请求类型(GET、POST、PUT、DELETE 等),并在适当的时候调用 doGet、doPost、doPut,doDelete 等方法。
下面是该方法的特征:
public void service(ServletRequest request,
ServletResponse response)
throws ServletException, IOException{
}
service() 方法由容器调用,service 方法在适当的时候调用 doGet、doPost、doPut、doDelete 等方法。所以,您不用对 service() 方法做任何动作,您只需要根据来自客户端的请求类型来重写 doGet() 或 doPost() 即可。
doGet() 和 doPost() 方法是每次服务请求中最常用的方法。下面是这两种方法的特征。
GET 请求来自于一个 URL 的正常请求,或者来自于一个未指定 METHOD 的 HTML 表单,它由 doGet() 方法处理。
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
// Servlet 代码
}
POST 请求来自于一个特别指定了 METHOD 为 POST 的 HTML 表单,它由 doPost() 方法处理。
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
// Servlet 代码
}
destroy() 方法只会被调用一次,在 Servlet 生命周期结束时被调用。destroy() 方法可以让您的 Servlet 关闭数据库连接、停止后台线程、把 Cookie 列表或点击计数器写入到磁盘,并执行其他类似的清理活动。
在调用 destroy() 方法之后,servlet 对象被标记为垃圾回收。destroy 方法定义如下所示:
public void destroy() {
// 终止化代码...
}
下图显示了一个典型的 Servlet 生命周期方案。
第一步:创建一个JavaWeb项目,并创建一个servlet类-----HelloServlet,实现接口 Servlet
package com.ys.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 HelloServlet implements Servlet{
//只被调用一次,第一次请求Servlet时,创建Servlet的实例,调用构造器
public HelloServlet() {
System.out.println("构造器 HelloServelt()...");
}
//该方法用于初始化Servlet,就是把该Servlet装载入内存
//只被调用一次,在创建好实例后立即被调用
@Override
public void init(ServletConfig config) throws ServletException {
System.out.println("初始化方法 init()...");
}
//被多次调用,每次请求都会调用service方法。实际用于响应请求的
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
System.out.println("执行方法主体 service()...");
}
//只被调用一次,在当前Servlet所在的WEB应用被卸载前调用,用于释放当前Servlet所占用的资源
@Override
public void destroy() {
System.out.println("servlet 销毁时调用方法 destroy()...");
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public String getServletInfo() {
return null;
}
}
第二步:在 web.xml 文件中配置上面创建的 HelloServlet 映射关系
index.jsp
default.htm
default.jsp
helloServlet
com.ys.servlet.HelloServlet
helloServlet
/hello
第三步:将项目部署在 tomcat 服务器,然后启动服务器
这里我们项目的结构为:
①、我们直接通过项目名来访问,由于我们在 web.xml 文件中配置了
②、通过在 web.xml 文件中配置的
我们可以看控制台打印内容如下:
如果我们不断的刷新 http://localhost:8080/ServletImprove/hello 这个访问链接,那么控制台如下:
①、什么是 过滤器?
JavaWEB 的一个重要组件,可以对发送到 Servlet 的请求进行拦截,并对响应也进行拦截
②、如何实现一个过滤器?
第一步:创建一个过滤器类,实现 Filter 接口
package com.ys.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class HelloFilter implements Filter{
public HelloFilter() {
System.out.println("构造器 HelloFilter()...");
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("init()...");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("doFilter()...");
}
@Override
public void destroy() {
System.out.println("destroy()...");
}
}
第二步:在 web.xml 文件中配置过滤器
helloFilter
com.ys.filter.HelloFilter
helloFilter
/*
启动服务器:我们发现还没发送请求,过滤器的 构造方法和 init() 方法就已经开始运行了
服务器启动成功之后,我们输入任意连接,比如
每刷新一次,控制台都会打印 doFilter()...
总结:生命周期和 Servlet 的类似。只不过其构造方法和初始化方法是在容器启动时就调用了,而其 doFilter() 方法则是在每次请求的时候调用。故过滤器可以对请求进行拦截过滤。可以用来进行权限设置,对传输数据进行加密等等操作。
注意:在Servlet3.0中引入了若干个重要的新特性,例如新增的注释,有了注释就不用在web.xml中在配置,省了很多麻烦。