servlet 技术
张彦星
1.Servlet 介绍
1.1什么是Servlet
Servlet(java服务器小程序) 是用java编写的服务器端程序,是由服务器调用和执行的、按照Servlet自身规范编写的java类。Servlet可以看成是用Java编写的CGI,但是他的功能和性能比CGI更加强大。
1.2 Servlet 的生命周期
Servlet 部署在容器里,它的生命周期由容器管理。
Servlet 的生命周期概括为以下几个阶段:
- 装载Servlet:这项操作一般是动态执行的。
- 创建Servlet实例
- 调用Servlet的init()方法
- 服务
- 销毁:实例被销毁。通过调用destory()来销毁Servlet。
1.3 开发、部署一个简单的Servlet
HelloWorldServlet
package com.starxing.ch7;import java.io.IOException;import java.io.PrintWriter;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class HelloWorldServlet extends HttpServlet { /** * Constructor of the object. */ /** * The doGet method of the servlet.
* * This method is called when a form has its tag value method equals to get. * * @param request the request send by the client to the server * @param response the response send by the server to the client * @throws ServletException if an error occurred * @throws IOException if an error occurred */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html:charset=gb2312"); PrintWriter out = response.getWriter(); out.println(""); out.println(" HelloWord"); out.println(" "); out.println(" Hello World! "); out.println("你好!世界。"); out.println(this.getClass()); out.println("
"); out.println(""); out.flush(); out.close(); } /** * The doPost method of the servlet.
* * This method is called when a form has its tag value method equals to post. * * @param request the request send by the client to the server * @param response the response send by the server to the client * @throws ServletException if an error occurred * @throws IOException if an error occurred */ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println(""); out.println(""); out.println(" A Servlet"); out.println(" "); out.print(" This is "); out.print(this.getClass()); out.println(", using the POST method"); out.println(" "); out.println(""); out.flush(); out.close(); } /** * Initialization of the servlet.
* * @throws ServletException if an error occure */}web.xml
xmlns=""
xmlns:xsi=""
xsi:schemaLocation="
/web-app_2_4.xsd">
JSP应用开发详解
This is the display name of my J2EE component
HelloWorldServlet
com.starxing.ch7.HelloWorldServlet
HelloWorldServlet
/hello
2 Servlet常用接口的使用
Servlet 的类接口可以从以下几个方面进行分类。
- Servlet 实现相关:定义了用于实现Servlet相关的类和方法
- Servlet 配置相关:主要包括ServletConfig接口
- Servlet 异常相关:Servlet API定义了两个异常,它们是:ServletException、UnavailableException。
- 请求和响应相关:用于接收客户端的请求,并且做出对应的响应。
- 会话跟踪:用于跟踪和客户端的会话
- Servlet 上下文:通过这个接口,可以在多个Web应用程序中共享数据。
- Servlet 协议:主要是RequestDispatcher接口,用于进行视图派发。
- 过滤:定义了请求响应过滤的相关API和接口
- 其他类:Cookie和HttpUtils类
2.1 Servlet 实现相关
1、Servlet
声明:public interface Servlet
这个接口是所有Servlet必须直接或者间接实现的接口。他定义了以下的方法:
- init(ServletConfig config):用于初始化Servlet。
- destory():销毁Servlet。
- getServletInfo():获得Servlet的信息。
- getServletConfig():获得Servlet配置相关信息。
- service(ServletRequest req,ServletRespones res):运行应用程序逻辑的入口点,他接收两个参数,ServletRequest表示客户端请求的信息,ServletResponse表示对客户端的响应。
2、GenericServlet
声明:public abstract class GenericServlet implements Servlet,ServletConfig,java.io.Serializable
GenerServlet 提供了对Servlet接口的基本实现。它是一个抽象类,它的service()方法是一个抽象方法,GenericServlet的派生类必须直接或者间接实现这个方法。
3、HttpServlet
声明:public abstract class HttpServlet extends GenericServlet implements java.io.Serializable
HttpServlet 类是针对使用Http协议的Web服务器的Servlet类。HttpServlet类通过执行Servlet接口,能够提供Http协议的功能。
HttpServlet的子类必须实现以下方法中的一个。
- doGet:支持Http Get 请求
- doPost:支持Http Post 请求
- doPut: 支持Http Put 请求
- doDelete:支持Http Delete 请求
- init和destroy:管理Servlet占用的资源。
- getServletInfo: 获得Servlet 自身的信息。
2.2 Servlet 配置相关
javax.servlet.ServletConfig 接口代表了Servlet的配置,Servlet配置包括Servlet的名字、Servlet的初始化参数和Servlet上下文。
例程:
testServlet testExample encoding gb2312 ServletConfig
声明:public interface ServletConfig
这个接口的主要方法有以下几个。
- getInitParameter(String name):返回特定名字的初始化参数。
- getInitParameterNames():返回所有的初始化参数的名字。
- getServletContext():返回Servlet的上下文对象的引用。
2.3 Servlet异常相关
1、ServletException
声明: public class ServletException extends Exception
它包含几个构造方法和一个获得一样原因的方法,这个方法如下:
getRootCause():返回造成这个ServletException的原因。
2、UnavailableException
声明 public class UnavailableException extends ServletException
当Servlet 或者 Filter 暂时或者永久不能使用时,就会抛出责这个异常。
2.4 请求和相应相关
和请求响应相关的类和接口非常多,主要以下几种。
- ServletRequest:代表Servlet的请求,它是以个高层接口,HttpServletRequest是他的子接口
- ServletResponse:代表了Servlet的响应,它是一个高层接口,HttpServletResponse是他的子接口。
- ServletInputStream:Servlet的输入流
- ServletOutputStream:servlet的输出流
- ServletRequestWarpper:它是ServletRequest 的实现
- ServletResponseWarpper:它是ServletResponse的实现
- HttpServletRequst:代表了Http的请求,继承了ServletRequest接口
- HttpServletResponse:代表了Http的响应,继承了ServletResponse接口
- HttpServletRequestWrapper:HttpServletRequest的实现
- HttpServletResponseWrapper:HttpServletResponse的实现
下面着重介绍HttpServletRequest和HttpServletResponse两个接口
1、HttpServletRequest
声明:public interface HttpServeltRequest extends ServletRequest
这个接口中最常用的方法就是获得请求中的参数,这个请求中的参数是客户端表单中的数据。HttpServletRequest接口可以获取有客户端传送的阐述名称,也可以获取客户端正在使用的通信协议,可以获取产生请求并且接收请求的服务器远端主机名和其他IP地址等一些这样的信息。
HttpServletRequest接口提供获取数据流的Servlet、ServletInputStream方法,这些数据是客户端引用中使用Http Post和Put方法递交的。一个ServletRequest的子类可以让Servlet获取更多的协议特性数据。例如:httpServletRequest 包含获取头部信息的方法有request.getMethod(),request.getProtocol(),request.getPathInfo()等。
JSP中的内建对象request是一个HttpServletRequest实例,我们来看一下他的一些重要方法。
- getCookies():获得客户端发送的Cookies。
- getSession():返回和客户端关联的Session,如果没有给客户端分配Session,返回null。
- getSession(boolean create):和上一个方法类似,不同的是,如果没有给客户端分配Session,则创建一个新的Session并返回。
- getParameter(String name):获取请求中名字为name的参数的值,如果没有这个参数则返回null。
- getParameterValues(String name):返回请求中名为name的参数值,这个值往往是checkbox或者select控件提交的,获取的值是一个String数组。
2、HttpServletResponse
声明public interface HttpServletResponse extends ServletResponse
他代表了对客户端的Http响应。HttpServletResponse 接口给出响应客户端的Servlet方法,他允许Servlet设置内容长度和回应的MIME类型,并且提供输出留ServletOutputStream。
- addCookies(Cookies cookies):在响应中增加一个Cookies。
- encodeURL(String url):使用URL和一个SessionId重写这个URL。
- sendRedirect(String location):把响应发送到另外一个页面或者Servlet进行处理。
- SetContentType(String type):设置响应的MIME类型。
- setCharacterEncoding(String charset):设置响应的字符编码类型。
2.5 会话跟踪
和会话跟踪相关的类和接口有:HttpSession。
HttpSession
声明 public interface HttpSession
这个接口被Servlet引擎用来实现Http客户端和Http会话两者之间的关联。这种关联可能在多处连接和请求中持续一段给定时间。Session用来在无状态的Http协议下越过多个请求页面来维持状态和识别用户。
一个Session可以通过Cookies或重写URL来维持。
它的常用方法有以下几种。
- getCreationTime():返回创建Session的时间。
- getId():返回分配给这个Session的标识符。一个Http Session 的标识坏是一个由服务器来建立和维持的唯一的字符串。
- getLastAccessedTime():返回客户端最后一次发出与这个Session有关的请求的时间,如果这个Session是新建立的,返回-1。
- getMaxInactiveInterval():返回一个秒数,制革秒数表示客户端在不发出请求是Session被Servlet引擎维持的最长时间。在这个时间之后,Session可能被Servlet引擎终止。如果这个Session不会被终止,这个方法返回-1。
- getValues(String name):返回一个以给定的名字绑定到Session上的对象,如果不存在这样的绑定,返回为空值。
- getValueNames():以一个数组返回绑定到Session上的所有数据的名称。
- invalidate();public void invalidate():这个方法终止这个Session。所有绑定在这个Session上的数据都会被清除。
- isNews():返回一个布尔值以判断这个Session 是不是新的。如果一个Session已经被服务器建立但是还没有收到响应的客户端请求,这个Session将被认为是一个新的,这就意味着,责合格客户端还没有进入会话或者没有被会话公认。在他发出下一个请求时还不能返回适当的Session认证信息。当Session无效后,再调用这个方法会抛出一个IllegalStateException。
- putValue(String name,Object value):以给定的名字绑定给定的对象到Session中。已经存在的同名的绑定会被重置,这时会调用 HttpSessionBindingListener接口的valueBound方法。
- removeValue(Sting name):取消给定名字的对象在Session上的绑定。如果未找到,这个方法什么也不做。这时则会调用HttpSessionBindingListener接口的valueUnbound方法。
- setMaxInactiveInterval(Int interval):设置一个秒数,这个秒数表示客户端在不发出请求时,Session被Servlet引擎保持的最长时间。
2.6 Servlet 上下文
和Servlet上下文相关的接口有ServletContext。
ServletContext
声明:public interface ServletContext
在服务器上使用Session对象来维持同单个客户相关的状态,而当为多个用户的Web应用维持一个状态时,则应使用Servlet环境(context)。
ServletContext对象表示一组Servlet共享的资源,在Servlet API的1.0和2.0的版本中,ServletContext对象仅仅提供访问有关Servlet环境信息的方法。例如:提供了访问服务器名称、MIME类型映射等方法和可以将信息写入服务器日志文件中的log()方法。大部分实现程序会为一台主机中的所有Servlet或每个虚拟机主机提供一个Servlet环境。
常用的方法有以下几种。
- getAttribute(String name):获得ServletContext中的名字为name的属性
- getContext(String uripath):返回给定的uripath的应用的Servlet上下文,如ServetContext test = getContext("/test")。
- removeAttribute(String name):删除名字为name的属性
- setAttribute(String name,Object object):在ServletContext中设置一个属性。
2.7 Servlet协作
Servlet协作主要是RequestDispatcher接口,他可以把一个请求转发到另外一个Servlet。
RequestDispatcher
声明:pubilc interface RequestDispatcher
它包含两个方法如下所示:
- forward(ServletRequest,ServletResponse):把请求转发到服务器的另外一个资源(Servlet、JSP、HTML)
- include(ServletRequest request,ServletResponse response):把服务器上的另一个资源(Servlet、JSP、HTML)包含到响应中。
2.8 过滤
在Web应用中实施过滤是我们常使用的技术,通过过滤,可以对请求进行统一编码,对请求进行认证等。每个Filter可能只担任很少的工作,多个Filter可以互助协作,通过这些协作可以完成一个复杂的功能。
1、Filter
声明 public interface Filter
它是Filter必须实现的接口,它包含以下方法:
- init(FilterConfig filterconfig):初始化Filter
- doFilter(ServletRequest request,ServletResponse response):Filter的业务方法就在这里实现。
- destroy():释放Filter占用资源。
2、FilterChain
声明 public interface FilterChain
它是代码的过滤链,通过这个接口把过滤的任务在不同的Filter之间转移。
doFilter(ServletRequest request,ServletResponse response):通过这个方法来调用下一个Filter,如果没有下一个Filter,那么将调用目标的资源。
3、FilterConfig
声明:public interface FilterConfig
代表了Filter的配置,和Servlet一样,Filter也有一些配置信息,它包含的方法:
- getFilterName():返回Filter名字。
- getInitParamter(String name):获得名字为name的初始化参数。
- getServletContext():返回这个Filter所在的Servlet上下文对象。
- getInitParamterNames():获得Filter配置中的所有初始化参数的名字。
3 使用HttpServlet 处理客户端请求
Servlet 被设计成请求的驱动。Servlet的请求可能包含多个数据项每当Web容器接收到某个Servlet的请求时,它把它封装成一个HttpServletRequest对象,然后把此对象传给Servlet的对应服务方法,服务方法通常是doGet和doPost方法。另外,HttpServlet也提供了一些高级的处理方法,他们有doPut、doTrace、doDeldte。
1.doGet()
2.doPost()
3.doPut():Put的调用和Post类似,他允许客户端把真正的文件存放在服务器上,而不仅仅是传送数据。
4.doDelete()
它与Put调用相似,他允许客户端删除服务器端的文件和Web页面。他的使用非常少。
5.doTrace():由容器调用以使次Servlet能够处理Trace请求。这个方法主要用于调试,它是不可以覆盖的方法。
6.doHead():它用于处理客户端的Head调用,并且返回一个response。当客户端只需要知道响应的Header时,它就发出一个Header请求。这种情况下客户端往往关心响应的长度和响应的MIME类型。
7.doOptions():他用于处理客户端的Options调用,通过这个调用,客户端可以获得次Servlet支持的方法。如某个Servlet覆盖了doPost方法,那么将返回: Allow:POST,TRACE,OPTIONS,HEAD一般情况下不需要覆盖这个方法。
4 获得Servlet初始化参数
Servlet可以配置一些初始化参数,我们可以在Servlet中获得这些初始的参数。在前面我们曾经介绍过和Servlet配置相关的一个接口,他就是ServletConfig接口,通过这个接口我们获得Servlet的初始化参数。
假如我们要编写一个使用JDBC连接数据库的URL、用户名和密码配置到Web.xml文件中,当Servlet执行操作时,通过ServletConfig来获得初始的参数以连接数据库。
JDBCServlet.java
package com.starxing.ch7;import java.io.IOException;import java.io.PrintWriter;import java.sql.Connection;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class JSBCServlet extends HttpServlet { private String driver; private String url; private String user; private String password; /** * Constructor of the object. */ public JSBCServlet() { super(); } /** * Destruction of the servlet.
*/ public void destroy() { super.destroy(); // Just puts "destroy" string in log // Put your code here } /** * The doGet method of the servlet.
* * This method is called when a form has its tag value method equals to get. * * @param request the request send by the client to the server * @param response the response send by the server to the client * @throws ServletException if an error occurred * @throws IOException if an error occurred */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=gb2312"); PrintWriter out = response.getWriter(); out.println("
"); try {// Class.forName() Connection con = getConnection(); Statement stmt = con.createStatement(); ResultSet rst = stmt.executeQuery("select * from user_info"); while(rst.next()) { out.println(rst.getString("userId")); out.println("
"); } rst.close(); stmt.close(); con.close(); }catch(Exception e) { e.printStackTrace(); } } public Connection getConnection() { Connection con=null; try { Class.forName(driver); con = DriverManager.getConnection(url,user,password); }catch(Exception e) { e.printStackTrace(); } return con; } /** * The doPost method of the servlet.
* * This method is called when a form has its tag value method equals to post. * * @param request the request send by the client to the server * @param response the response send by the server to the client * @throws ServletException if an error occurred * @throws IOException if an error occurred */ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request,response); } /** * Initialization of the servlet.
* * @throws ServletException if an error occure */ public void init() throws ServletException { // Put your code here driver = getInitParameter("DRIVER"); url = getInitParameter("URL"); password = getInitParameter("PASSWORD"); user = getInitParameter("USER"); }}web.xml
This is the description of my J2EE component This is the display name of my J2EE component JSBCServlet com.starxing.ch7.JSBCServlet URL jdbc:microsoft:sqlserver://127.0.0.1:1433;DatabaseName=jspdev DRIVER com.microsoft.jdbc.sqlserver.SQLServerDriver USER sa PASSWORD starxing JSBCServlet /servlet/JSBCServlet 5 Servlet 的配置
前面已经陆续介绍过Servlet的配置,本节将总结前面介绍的配置,在新介绍一些配置方法。
总的来说,Servlet配置包含Servlet的名字,Servlet的类(如果是JSP,那么就指定JSP文件)、初始化参数、启动装入的优先级、Servlet的映射、运行的安全设置。Servlet配置和的DTD描述如下:
init-param*,load-on-startup?,run-as?,sencurity-role-ref*)>
下面我们结合一个实际的例子介绍这些配置。
CounterServlet.java
package com.starxing.ch7;import java.io.IOException;import java.io.PrintWriter;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class CounterServlet extends HttpServlet { /** * Constructor of the object. */ int counter = 0; int org = 0; public CounterServlet() { super(); } /** * Destruction of the servlet.
*/ public void destroy() { super.destroy(); // Just puts "destroy" string in log // Put your code here } /** * The doGet method of the servlet.
* * This method is called when a form has its tag value method equals to get. * * @param request the request send by the client to the server * @param response the response send by the server to the client * @throws ServletException if an error occurred * @throws IOException if an error occurred */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=GB2312"); PrintWriter out = response.getWriter(); counter++; out.println(""); out.println(""); out.println(" A Servlet"); out.println(" "); out.print("自从Servlet载入,他已经被访问了"+counter+"次,加上初始的配置共访问"+(org+counter)+"次"); out.println(" "); out.println(""); out.flush(); out.close(); } /** * The doPost method of the servlet.
* * This method is called when a form has its tag value method equals to post. * * @param request the request send by the client to the server * @param response the response send by the server to the client * @throws ServletException if an error occurred * @throws IOException if an error occurred */ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request,response); } /** * Initialization of the servlet.
* * @throws ServletException if an error occure */ public void init() throws ServletException { // Put your code here String c = getInitParameter("counter"); try { org = Integer.parseInt(c); }catch(Exception e) { e.printStackTrace(); } }}
Web.xml
This is the description of my J2EE component This is the display name of my J2EE component CounterServlet com.starxing.ch7.CounterServlet counter 3 CounterServlet /servlet/CounterServlet 5.1 Servlet的名字、类和其他杂项
在配置Servlet时,必须指定Servlet的名字、Servlet的类(如果是JSP,鄙视指定JSP文件的位置)。另外,可以选择性地给出Servlet增加的一定的描述,并且指定它在部署时显示的名字,部署时显示的Icon。
counterServlet的部分配置
学习Servlet配置
This is the display name of my J2EE component
CounterServlet
com.starxing.ch7.CounterServlet
…………………………
如果配置的Servlet是一个JSP文件,那么可以这样
NewUserServlet
newUser.jsp
5.2 初始化参数
描述如下:
........
counter
3
5.3 启动装入优先级
启动装入优先级通过来配置的,如:
---------------------------------------
NewUserServlet
newUser.jsp
10
HelloWorldServlet
com.starxing.ch7.HelloWordServlet
30
PrintServlet
com.starxing.ch7.HellWordServlet2
AnyTime
---------------------------------------
那么可以保证NewUserServlet在HelloWordServlet之前被载入,PrintServlet可以在服务器启动后的任何时候载入。
5.4 Servlet的映射
可以给一个Servlet作多个映射,这样,我们可以根据不同的方式来访问这个Servlet。
---------------------------------------
HelloWorldServlet
/hello
DoGetTestServlet
/doget_servlet
JSBCServlet
/servlet/JSBCServlet/jdbc.html
CounterServlet
/servlet/CounterServlet
counterServlet
/count/*
---------------------------------------
最后一个方式,他只要以/count开头,都能访问到这个Servlet。
5.5 运行安全配置
关于Web应用的安全设置,我们将在后面介绍。
6 用Servlet生成动态图像
Servlet比JSP强大之处在于后台处理,他不仅可以生成动态的HTML内容,也可以动态生成图像。
JPEGServlet.java
package com.starxing.ch7;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
public class JPEGServlet extends HttpServlet {
/**
* Constructor of the object.
*/
public JPEGServlet() {
super();
}
/**
* Destruction of the servlet.
*/
public void destroy() {
super.destroy(); // Just puts "destroy" string in log
// Put your code here
}
/**
* The doGet method of the servlet.
*
* This method is called when a form has its tag value method equals to get.
*
* @param request the request send by the client to the server
* @param response the response send by the server to the client
* @throws ServletException if an error occurred
* @throws IOException if an error occurred
*/
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("image/jpeg");
ServletOutputStream out = response.getOutputStream();
BufferedImage image = new BufferedImage(750,30,BufferedImage.TYPE_INT_RGB);
int per = 0;
try
{
per = Integer.parseInt((String)request.getParameter("size"));
}catch(Exception e)
{
e.printStackTrace();
}
Graphics graphics = image.getGraphics();
graphics.setColor(Color.green);
graphics.fillRect(0,0,750,30);
graphics.setColor(Color.yellow);
graphics.fillRect(0,0,750*per/100,30);
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
encoder.encode(image);
out.close();
}
/**
* The doPost method of the servlet.
*
* This method is called when a form has its tag value method equals to post.
*
* @param request the request send by the client to the server
* @param response the response send by the server to the client
* @throws ServletException if an error occurred
* @throws IOException if an error occurred
*/
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request,response);
}
/**
* Initialization of the servlet.
*
* @throws ServletException if an error occure
*/
public void init() throws ServletException {
// Put your code here
}
}