Servlet
什么是Servlet?
- Servlet是一个符合特定规范的 JAVA 程序 , 是一个基于JAVA技术的Web组件。
- Servlet运行在服务器端,由Servlet容器所管理,用于处理客户端请求并作出相应。
- Servlet 没有 main 方法,不能够独立的运行,它的运行需要容器的支持,Tomcat 是最常用的 JSP/Servlet 容器。Servlet 运行在 Servlet 容器中,并由容器管理从创建到销毁的整个过程。
说明
-
Servlet容器:Servlet容器也称为 Servlet引擎,是 WEB 服务器或应用程序服务器的一部分,用于在发送的请求和响应之上提供网络服务。
-
管理和运行 Servlet/JSP的容器也称Web容器;
-
Servlet容器、JSP 容器和 Web容器是同义的;
-
Servlet主要用于生成动态的内容,他可以接受和处理请,求并动态生成 HTML 内容对客户端进行响应;
Servlet 有以下几点优势
- 性能明显更好。
- Servlet 在 Web 服务器的地址空间内执行。这样它就没有必要再创建一个单独的进程来处理每个客户端请求。
- Servlet 是独立于平台的,因为它们是用 Java 编写的。
- 服务器上的 Java 安全管理器执行了一系列限制,以保护服务器计算机上的资源。因此,Servlet 是可信的。
- Java 类库的全部功能对 Servlet 来说都是可用的。它可以通过 sockets 和 RMI 机制与 applets、数据库或其他软件进行交互。
Servlet与JSP的区别和关系
在使用JSP技术开发 WEB 程序时,我们所要做的是在 JSP 中写入 JAVA 代码,当服务器运行JSP时,将JSP转换成JAVA类并编译执行,动态获取数据生成 HTML 代码 , 最终显示在客户浏览器上。
- jsp经编译后就变成了Servlet(JSP的本质就是Servlet,JVM只能识别java的类,不能识别JSP的代码,Web容器将JSP的代码编译成JVM能够识别的java类)
- jsp更擅长表现于页面显示,servlet更擅长于逻辑控制。
- Servlet中没有内置对象,Jsp中的内置对象都是必须通过HttpServletRequest对象,HttpServletResponse对象以及HttpServlet对象得到。
- Jsp是Servlet的一种简化,使用Jsp只需要完成程序员需要输出到客户端的内容,Jsp中的Java脚本如何镶嵌到一个类中,由Jsp容器完成。
- 而Servlet则是个完整的Java类,这个类的Service方法用于生成对客户端的响应。
JSP和Servlet的联系
-
JSP 实际上是为了简化Servlet的开发而产生的,避免了编写繁杂的输出方法,更加适用于开发带有页面内容的表示层组件。
-
JSP是Servlet技术的扩展,本质上就是Servlet的简易方式。JSP编译后是“类servlet”。
Servlet API
API:API(Application Programming Interface,应用程序编程接口)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,或理解内部工作机制细节。
- Servlet API包含在两个包内,
javax. Servlet
包中的类和接口是通用的不依赖协议的 Servlet API,包括Servlet
、ServletRequest
、ServletResponse
、ServletConfig
、ServletContext
接口及抽象类GenericServlet
,javax.servlet.http
包中的类和接口是用于支持 HTTP协议的Servlet API;
Servlet接口
- 定义了所有Servlet需要实现的方法;
GenericServlet抽象类
- 提供了Servlet接口和ServletConfig接口,给出了方法的默认实现(service( )方法除外);定义了通用的、不依赖于协议的Servlet。
HttpServlet抽象类
- 大多数的网络应用是通过 HTTP协议访问服务器资源的,因此我们编写的 Servlet大多也是应用于处理 HTTP协议的请求和响应。
- 抽象类
HttpServlet
继承自GenericServlet
类,具有与GenericServlet
类似的方法,并提供了与 HTTP相关的实现,支持对HTTP的POST、GET 等请求方式进行差异化处理;开发中,如果需要编写Servlet
,主要就是继承HttpServlet
抽象 - HttpServlet的service (HttpServletRequest req, HttpServletResponse res )方法相当于一个分发器,可以根据请求方法的类型,调用相应的doXxx()方法。所以在编写Servlet时只需要根据应用的需要,重写doGet()或者doPost()方法即可;
ServletConfig接口
- Servlet容器使用ServletConfig在Servlet初始化过程中获取配置信息,一个Servlet只有一个ServletConfig对象;
ServletContext接口
ServletReques和HttpServletRequest接口
ServletReques接口
- ServletRequest 接口:当客户请求时,由 Servlet 容器创建 ServletRequest 对象用于封装客户的请求信息,这个对象将容器作为 service ( ) 方法的参数之一传递给 Servlet , Servlet 能够利用 ServletRequest 对象获取客户端请求数据。
HttpServletRequest接口
- HttpServletRequest接口:HttpServletReqiest 位于 javax.servlet.http包中,继承自ServletRequest 接口,通过该接口同样可以获取请求中的参数。HttpServletRequest 接口除了继承了ServletRequest 接口中的方法,还增加了一些用于读取请求信息的方法;
ServletResponse和HttpServletResponse 接口
ServletResponse接口
- ServletResponse接口:Servlet 容器在接收客户请求时,除了创建 ServletRequest 对象用于封装客户的请求信息外,还建了一个 ServletResponse 对象,用于封裝响应数据,并且同时将这两个对象一并作为参数传递给Servlet。Servlet利用ServletRequest 对象获取客户端的请求数据,经过处理后由 ServletResponse 对象发送响应数据;
HttpServletResponse接口
- HttpServletResponse:与 HttpServletRequest 接口类似,HttpServletResponse 接口也继承自 ServletResponse 接口,用于客户端的请求执行响应。它除了具有ServletResponse接口的常用方法外、还增加了新的方法;
Servlet 的应用
1. 手动创建
-
创建Servlet,导入对应的包
-
继承HttpServlet
-
重写doPost()或doGet()方法
部署Servlet
-
编译Servlet到/WEB-INF/classes目录
-
编辑部署描述文件web.xml
<web - app>
<servlet>
<servlet-name> Servlet的名字</servlet-name>
<servlet-class> Servlet 类的完全限定名</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>给出 Servlet 的名字,必须与在< servlet >元素中声明的Servlet 名字相同</servlet-name>
<url-pattern>指定 Servlet 的 URL</url-pattern>
</servlet-mapping>
</web - app>
- 启动Tomcat,访问Servlet
2. 直接在IDE中生成Servlet
分析:在示例中,web.xml 文件中使用了< servlet >和
<servlet-mapping>
两个 XML 元素把用户访问的URL 映射到 Servlet,
-
在 web.xml文件中,
< servlet >
元素可包含多个子元素,其中<servlet-name>
指定 Servlet的名字 , 这个名字在同一个 Web 应用中必须唯一,<servlet-class>
指定 Servlet 类的完全限定名; -
<servlet-mapping>
元素在 Servlet 和 URL 之间定义映射,它包含两个子元素<servlet-name>
和<url-pattern>:
(1)<servlet-name>
给出 Servlet 的名字,必须与在< servlet >元素中声明的Servlet 名字相同,
(2)<url-pattern>
元素指定 Servlet 的 URL , 需要特别注意的是,该路径是相对于 Web 应用程序的路径,在配置Servlet 与 URL的映射后,当 Servlet 容器接收到一个请求时,对请求的路径和Servlet映射的路径进行匹配,进而调用具体Servlet类的相关方法。
下面介绍在web.xml 中常用设置方法:
-
<url-pattern>
/xxx</url-pattern>
精确匹配 , 如<url-pattern>
/ helloServlet</url-pattern>
; -
<url-pattern>
/xxx/</url-pattern>
,路径匹配,如果没有精确匹配,对/xxx/路径的所有请求将由该 Servlet 进行处理,如<url-pattern>
/ helloServlet/</url-pattern>
; -
<url-pattern>
*.xxx</url-pattern>
如果没有精确匹配和路径匹配,则所有针对. xxx扩展名的请求将由该 Servlet 处理;
扩展:有时需指定在容器启动时 Servlet 的加载次序,可以在元素中增加元素。该元素的值必须是整数,如果为负数或没有指定这个元素,容器将在客户端首次访问 Servlct 时进行加载;如果为正数或0;客器将在启动时根据值的顺序加载 Servlet,且值越小加载优先级越高;
访问 Servlet
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>ServletTest</title>
</head>
<body>
<form action="HttpServletTest" method="post">
姓名:<input type="text" name="username" />
<input type="submit" value="提交"/>
</form>
</body>
</html>
-
为了方便管理,通常将创建的 Servlet 单独放在一个包中,如 com.bdqn.servlet。
-
通过 IDE工具可以快速创建和部署 Servlet: 右击专门存放 Servlet 的包—>New—>Servlet—>Name: XxxServletName (为创建的 Servlet 命名)—>Next ( 此步骤的窗口信息用于部署 web.xml , 配置 Servlet 可以选择各项的默认值,也可以根据需要修改Servlet名称和 Servlet的映射路径,即修改’Servlet/JSP Name:’ 和’ Servlet/JSP Mapping URL:’,对于 “Display Natne:”和 “Description “后面的解释内容, 可以删除)—>Finish;
-
用工具创建的Servlet只是一个Servlet模扳,可以根据业务需求编写;
使用Servlet实现控制台
Servlet与 JSP 的区别
-
JSP文件在用户第一次请求时会被编译成Servlet, 然后由这个Servlet处理用户的请求,所以 JSP 也可以看成是运行时的Servlet;
-
JSP页面在 HTML 元素中嵌入Java脚本代码和 JSP 标记,比使用传统Servlet技术开发表示层更加容易。JSP的部署也更加简单,JSP容器 (Servlet容器)会对扩展名是.jsp的URL统一配置,将其转换为 Servlelt为客户端服务,无需为每一个 JSP 文件配置 URL 映射;
-
JSP 页面 HTM元素与 java脚本混合的语法 , 对于请求处理过程中编写流程控制代码,数据访问代码等却是不利的,难以模块化开发及重用,此时更适合采用传统 Java 类的形式进行开发。因此使用 Servlet 在服务器上解释和执行浏览器的请求,充当客户端和其他层之间的中间层角色更加合适;
-
通过上面的分祈,Servlet 和 JSP 各有所长,JSP 可以方便地开发表示层组件. 而Servlet适合编写流程控制代码. 在开发 Wab 应用时,可以针对两者的特点结合使用,合理分工;
实现控制器
- Servlet充当控制器的角色,它接受请求、负责实例化 JavaBean 对象对业务逻辑进行处理,并为JSP页面准备封装的JavaBean对象,接着将请求分发给适当的JSP页面来产生响应;
Servlet的生命周期
- Servlet的生命周期是通过 Servlet接口中的 init()、servicef() 和 destroy() 方法来表示的;
生命周期的过程
- 加载
- 实例化
- 初始化
- 销毁
-
加载和实例化: Servlet不能独立运行,它必须被部署至Servlet 容器中,由容器实例化和调用 Servlet 的方法,Servlet容器在 Servlet的生命周期内管理 Servlet,当Servlet容器启动或者当客户端发送一个请求时, Servlet容器会查找内存中是否存在Servlet的实例, 如果不存在,就创建一个 Servlet实例,如果存在该Servlet的实例,就直接从内存中取出该实例响应请求;
-
初始化: 在Servlet容器完成 Servlet 实例化后,Servlet容器将调用 Servlet的 init()方法进行初始化,初始化的目的是让Servlet对象在处理客户端请求前完成一些准备或资源预加载工作,如设置数据库连接参数,建立 JDBC 连接,或者是建立对其他资源的引用。
注:对于每一个Servlet实例 init()方法只能被调用一次;
-
服务: Servlet被初始化后 , 就处于能响应请求的就绪状态,当Servlet容器接收客户端请求时,调用Servlet的 service()方法处理客户端请求,HttpServlet 的service()方法会根据 GET 或 POST 请求转调doGet()或 doPost()方法,Servlet实例通过 ServletRequest 对象获得客户端的请求,通过调用ServletResponse 对象的方法设置响应信息;
-
销毁: Servlet 的实例是由 Servlet 容器创建的,所以实例的销毁也是由容器来完成的,Servlet容器判断一个 Servlet容器是否应当被释放时(容器关闭或需要回收资源),容器就会调用 Servlet 的 destroy()方法,该方法指明哪些资源可以被系统回收,而不是由 destroy()方法直接回收 Servlet 实例;
当再一次提交请求时, Servlet 的init()方法没有被执行,这说明 init ()方法只有在加载当前的Servlet时候被执行,并且只被执行一次。
当停止Tomcat服务,destroy()方法被执行,显示信息:释放系统资源时,destroy()方法被调用!
初识化参数及访问应用上下文
获得 Servlet 初始化参数
- 设置 初始化参数 需要修改 web .xml文件,在元素中增加元素
<servlet>
<servlet-name>HelloServlet</servlet-name
<servlet-class>demo.servlet.HelloServlet</servlet-class>
<init-param>
<param-name>initParam</param-name>
<param-value>Hello Servlet</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/HelloServlet</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>HelloServlet</welcome-file>
</welcome-file-list>