Servlet入门1
1.1 关于Servlets
Servlets是JAVA 2.0中新增的一个全新功能。JAVA Servlets 是运行在请求/面向请求服务器上的模块,好比一个Java-enabled web 服务器, 和相似这样的延伸场合. 例如, 一个servlet能够从一个HTML订单表中获取数据而后用一些商业上的算法来更新公司相应的订单数据库。
也就是说:servlet可以象CGI脚本同样扩展WEB服务器功能,可是servlet占用不多密集资源,有不少用CGI脚本编制的一些站点由 于访问量剧增,性能迅速降低,这是CGI脚本一个缺点。同时因为servlet 是用java编写的,所以是跨平台的。实际servlet是电子商务真正的开始。
Servlet API, 是用来写servlet的, 编写servlet是已没有CGI脚本那样诸如关心一个servlet是这样被装载, servlet运行的服务器环境是什么, 或者用来传输数据的协议是什么等等,这样servlets就能够融合在不一样的web服务器中.
Servlet能够至关有效地替代CGI脚本: 它能够方便地产生容易编写并且运行快的动态文本. 能够很方便的调试寻找出程序问题. Servlet程序是用Java Servlet API开发的, a standard Java extension. 但不是Java 核心框架的一部分,能够做为通用的附加产品包被商家购买使用.
1.2 举例
下面是一些servlet应用范围:
用于处理HTML表单经过HTTPS产生POSTed数据, 包括买卖订单或信用卡数据. 所以servlet能够成为订单处理系统的一部分, 和产品存货数据库一道工做,也许能够用在在线支付系统上.
容许人们之间的合做. 一个servlet能并发处理多个请求; 他们可使用在诸如在线会议这样的同步请求支持系统.
转送请求. Servlet能够转送请求给其余的服务器和servlets. 这就容许在镜象一样内容的几个服务器之间平衡负载. 按照任务类型或组织范围,能够容许被用来在几个服务器中划分逻辑上的服务器.
servlet 编写者们能够定义彼此之间共同工做的激活代理,每一个代理者是一个servlet, 并且代理者可以在他们之间传送数据.
1.3 Servlet 结构总视
在具体掌握servlet以前,须对java语言有所了解。下面是基于您了解java基础上的,在Servlet API中最重要的是Servlet interface. 全部的servlets implement(执行)这个interface, 方式多种:或者是直接的,或者经过extending 这个class执行它,如 HttpServlet. 这个Servlet interface 提供安排servlet与客户端联系的方法. Servlet 编写者能够在他们开发 servlet程序时提供更多一些或全部的这样方法.
当一个servlet接收来自客户端的调用请求, 它接收两个对象: 一个是ServletRequest,另一个是ServletResponse. 这个ServletRequest class 归纳从客户端到服务器之间的联系, 而 ServletResponse class 归纳从servlet 返回客户端的联系.
ServletRequest interface 能够获取到这样一些信息如由客户端传送的阐述名称,客户端正在使用的协议, 产生请求而且接收请求的服务器远端主机名. 它也提供获取数据流的servlet, ServletInputStream, 这些数据是客户端引用中使用HTTP POST 和 PUT 方法递交的. 一个ServletRequest的子类可让 servlet获取更多的协议特性数据. 例如: HttpServletRequest 包含获取 HTTP-specific头部信息的方法.
ServletResponse interface 给出相应客户端的servlet方法. 它容许servlet 设置内容长度和回应的mime类型, 而且提供输出流, ServletOutputStream, 经过编写者能够发回相应数据. ServletResponse子类能够给出更多 protocol-specific容量的信息。 例如: HttpServletResponse 包含容许servlet 操做HTTP-specific头部信息的方法.
上面有关classes 和 interfaces描述构成了一个基本的Servlet框架. HTTP servlets有一些附加的能够提供session-tracking capabilities的方法. servlet编写者能够用这些API在有他人操做时维护servlet与客户端之间的状态.
1.4 Servlet Lifecycle
服务器装载运行servlets:接收来自客户端的多个请求而且返回数据给客户端. 而后在删除移开servlets. 这就是servlets lifecycle过程. 下面详细描述:
当一个服务器装载servlet时, 它运行servlet的 init 方法. 这个方法不能反复调用,一旦调用就是再装载servlet. 直到服务器调用 destroy 方法卸载 servlet后才能再调用.
在服务器装载初始化后servlet, servlet就可以处理客户端的请求. 用 service 方法作到这一点. 每一个客户端请求有它本身service方法: 这些方法接收客户端请求, 而且发回相应的响应.
Servlets能同时运行多个service. 这是很重要的, 这样, service方法能够按一个thread-safe 样式编写. 如:service方法更新servlet对象中的一个字段field, 这个字段能够同时存取的. 假如某个服务器不能同时并发运行 service方法,也能够用SingleThreadModel interface. 这个 interface 保证不会有两个以上的线程threads并发运行.
Servlets一直运行到他们被服务器卸载。
在servlet的lifecycle中, 编写一个thread-safe编码以卸载servlet是很重要的。html
Servlet入门外2
Servlets 执行 javax.servlet.Servlet interface. 当servlet编写者能够经过直接implement interface开发servlet, 但这样一般没有必要. 由于大多数servlet是针对用HTTP协议的web服务器, 这样最通用开发servlet办法是用 javax.servlet.http.HttpServlet 内.
HttpServlet 类经过extend GenericServlet基类执行 Servlet interface, 提供了处理HTTP协议的功能. 他的service方法支持标准HTTP/1.1请求.
通常地, 用HttpServlet指定的类编写的servlets能够多线程地并发运行 service方法.
2.1 与客户端的交互性
Servlet编写者注意HttpServlet类有几个欠缺的方法,你能够本身定义方法中内容,可是必须使用这些方法名称以使servlet知道你想作什么,
doGet, 用于处理 GET、有条件的GET 和头部 HEAD请求
doPost, 用户处理 POST 请求
doPut, 用于处理 PUT 请求
doDelete, 用于处理 DELETE请求
HttpServlet的service方法, 通常地, 当它接收到一个OPTIONS请求时,会调用doOptions 方法, 当接收一个TRACE请求是调用doTrace . doOptions缺省执行方式是自动决定什么样的HTTP被选择而且返回哪一个信息.
在你使用这些方法时,必须带两个阐述. 第一个包含来自客户端的数据 HttpServletRequest. 第二个参数包含客户端的响应HttpServletResponse. 在下例中是这样的状况.
一个HttpServletRequest对象提供到达HTTP 头部数据, 也容许你获取客户端的数据. 怎样获取这些数据取决于HTTP端请求方法.
无论任何HTTP方式, 你能够用 getParameterValues 方法, 这个用来返回特定名称的参数值. 对于用 HTTP GET 请求的方式, 这个 getQueryString 方法将会返回一个能够用来解剖分析的.
对于用HTTP POST, PUT, 和 DELETE请求的方式, 你有两种方法能够选择. 若是是文本数据,你能经过getReader方法用BufferedReader获取 ; 若是是二进制数据, 能经过getReader 方法用 ServletInputStream获取.
为了响应客户端, 一个HttpServletResponse对象提供返回数据给用户的两个方法. 你能够用getWriter 方法返回,或者 getOutputStream 方法以输出流返回. 你应该用getWriter返回文本数据,而用getOutputStream返回二进制数据.
在使用Writer 或 OutputStream以前, HTTP 头部应该先被设置. HttpServletResponse内提供这样一个方法,以后能够用writer 或 outputstream 将响应主体部分发回用户. 完成后要关闭 writer 或 output stream以便让服务器知道响应已经完毕.
2.2 一个HTTP Servlet处理GET和HEAD方法的例子
public class SimpleServlet extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException
{
// 首先设置头部
res.setContentType("text/html");
// 用 writer方法返回响应数据
PrintWriter out = res.getWriter();
out.println("<HEAD><TITLE> SimpleServlet Output</TITLE></HEAD><BODY>");
out.println("<h1> SimpleServlet Output </h1>");
out.println("<P>This is output is from SimpleServlet.");
out.println("</BODY>");
out.close();
}
public String getServletInfo() {
return "A simple servlet";
}
}
这个例子完整地现实了一个servlet.
2.3 一个HTTP Servlet处理POST方式的例子
这里是个用HTML带POST表单的例子:
<html>
<head><title>JdcSurvey</title></head>
<body>
<form action=http://demo:8080/servlet/survey method=POST>
<input type=hidden name=survey value=Survey01Results>
<BR><BR>How Many Employees in your Company?<BR>
<BR>1-100<input type=radio name=employee value=1-100>
<BR>100-200<input type=radio name=employee value=100-200>
<BR>200-300<input type=radio name=employee value=200-300>
<BR>300-400<input type=radio name=employee value=300-400>
<BR>500-more<input type=radio name=employee value=500-more>
<BR><BR>General Comments?<BR>
<BR><input type=text name=comment>
<BR><BR>What IDEs do you use?<BR>
<BR>JavaWorkShop<input type=checkbox name=ide value=JavaWorkShop>
<BR>J++<input type=checkbox name=ide value=J++>
<BR>Cafe'<input type=checkbox name=ide value=Cafe'>
<BR><BR><input type=submit><input type=reset>
</form>
</body>
</html>
这里的servlet将表单数据写入一个文件,而且用一个thank you信息响应用户. 这里servlet的方法,以下例:
public void doPost(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException
{
// 首先设置响应的 "content type" 头部
res.setContentType("text/html");
//获得响应的 PrintWriter以返回文本给客户端.
PrintWriter toClient = res.getWriter();
try {
//打开一个文件写入Survey的结果.
String surveyName = req.getParameterValues("survey")[0];
FileWriter resultsFile = new FileWriter(resultsDir
+ System.getProperty("file.separator")
+ surveyName + ".txt", true);
PrintWriter toFile = new PrintWriter(resultsFile);
// 从客户端获得表单数据 & 存贮在这个文件中
toFile.println("");
Enumeration values = req.getParameterNames();
while(values.hasMoreElements()) {
String name = (String)values.nextElement();
String value = req.getParameterValues(name)[0];
if(name.compareTo("submit") != 0) {
toFile.println(name + ": " + value);
}
}
toFile.println("");
//关闭文件.
resultsFile.close();
// 用一个thank you返回客户端
toClient.println("");
toClient.println("");
toClient.println("Thank you for participating");
toClient.println("");
} catch(IOException e) {
e.printStackTrace();
toClient.println(
"A problem occured while recording your answers. "
+ "Please try again.");
}
// 关闭writer; 响应完成.
toClient.close();
}
这个doPost方法是用getParameterNames和getParameterValues方法来从表单中获取数据的. 由于它返回文本给客户端, doPost 将调用 getWriter 方法. 在写入响应主体部分以前,它设置了响应头部字段的设置, 但响应完成后,关闭.java
Servlet入门3
Lifecycle 方法
3.1 重编Init 初始化方法
在初始化过程当中, servlet应当准备好它要安排的一些资源, 以便这个servlet 可以接收请求,作到这些能够不用考虑多线程, 由于在servlet初始化是只能是单进程的。 一旦初始化方法完成, servlet就能接收客户端的请求。 固然若是初始化不能成功,这个方法会扔出throw UnavailableException解释的.
初始化方法使用ServletConfig 对象做为参数. 这个方法应该保存这个对象, 以便它能有方法getServletConfig返回. 最简单的办法是,搞出一个新类,他的初始化方法数调用super.init. 若是确实这样作, 你就应当本身保存ServletConfig 对象, 而且本身重编getServletConfig 方法以便它能重新的位置获得对象.
下面是个初始化方法的例子. 它是来自Survey Servlet的初始化方法, 从一个表单接收输入而后存储到文件中,为了存储survey信息, 它须要一个目录. 它以初始化参数接收这个目录.
public void init(ServletConfig config)
throws ServletException
{
super.init(config);
//获取目录
resultsDir = getInitParameter("resultsDir");
//若是没有目录, 不处理客户端
if (resultsDir == null) {
throw new UnavailableException (this,
"Not given a directory to write survey results!");
}
}
这里的初始化方法调用super.init 方法来管理安排ServletConfig对象. 这个初始化方法也设置了一个字段: resultsDir, 做为初始化参数提供的目录名. 若是没有目录名被提供, 这个 servlet扔出一个不适用的解释. 若是初始化 方法成功完成,servlet将能处理客户端请求
初始化参数
初始化参数的规定是一个服务器方面的规定。若是初始化参数被规定, 均可以用一样的方法获得: 用 getInitParameter方法. 这个方法将参数名做为本身的参数项.
3.2 重编Destroy 方法
当服务器卸载一个servlet, 它将调用servlet的destroy方法. 这个 destroy方法是与初始化方法相反,同时从内存中释放servlet.
并非全部的调用了初始化init方法是也必须调用destroy方法.
对于大多数的servlets, 一些初始化的工做必须反作的. 如, 假设有一个servlet,它在初始化时打开一个数据库链接,他的destroy 方法以下显示:须要关闭这个链接的
/**
* 关闭数据库链接
*/
public void destroy() {
try {
con.close();
} catch (SQLException e) {
while(e != null) {
log("SQLException: " + e.getSQLState() + '\t' +
e.getMessage() + '\t' +
e.getErrorCode() + '\t');
e = e.getNextException();
}
} catch (Exception e) {
e.printStackTrace();
}
}
关于一个Servlet中断涉及的多线程
但一个服务器卸载一个servlet, 它会在全部的service已经完成后调用 destroy. 若是你的操做运行须要很长时间, 但destroy 被调用时还有线程在运行. 这个servlet编写者有责任确保全部的线程都已经完成;
长时间运行响应客户端请求的那些servlet应当保留当前有多少方法在运行的记录. 他的 long-running 方法应当周期性地轮询以确保他们可以继续运行下去. 若是servlet被destroy方法调用, 那么这个long-running 方法若是必要必须中止工做或清除.
举例, 变量serviceCounter用来统计有多少service方法在运行, 变量 shuttingDown显示这个servlet是否被destory. 每一个变量有它本身的获取方法:
public ShutdownExample extends HttpServlet {
private int serviceCounter = 0;
private Boolean shuttingDown;
...
// serviceCounter
protected synchronized void enteringServiceMethod() {
serviceCounter++;
}
protected synchronized void leavingServiceMethod() {
serviceCounter--;
}
protected synchronized int numServices() {
return serviceCounter;
}
//shuttingDown
protected setShuttingDown(Boolean flag) {
shuttingDown = flag;
}
protected Boolean isShuttingDown() {
return shuttingDown;
}
}
这个service方法每次在它进入时要增长,而在它返回退出时要减小:
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
enteringServiceMethod();
try {
super.service(req, resp);
} finally {
leavingServiceMethod();
}
}
destroy方法应当检查serviceCounter, 若是存在长时间方式运行的话, 设置变量shuttingDown . 这个变量将会让那个正在处理请求的线程知道:该结束了,关闭吧! destroy 方法应当等待这几个service 方法完成, 这样就是一个清楚的关闭过程了.
public void destroy() {
/* 检查是否有线程在运行,若是存在,告诉他们stop. */
if (numServices() > 0) {
setShuttingDown(true);
}
/* 等待他们stop. */
while(numService() > 0) {
try {
thisThread.sleep(interval);
} catch (InterruptedException e) {
}
}
}
long-running 方法如必要应当检查这个变量,而且解释他们的工做:
public void doPost(...) {
...
for(i = 0; ((i < lotsOfStuffToDo) && !isShuttingDown()); i++) {
try {
partOfLongRunningOperation(i);
} catch (InterruptedException e) {
}
}
}
3.3 提供关于Servlet的信息
/**
* This is a simple example of an HTTP Servlet. It responds to the GET
* and HEAD methods of the HTTP protocol.
*/
public class SimpleServlet extends HttpServlet {
...
public String getServletInfo() {
return "A simple servlet";
}
}web
注明:本文转载自http://www.cnblogs.com/goody9807/archive/2007/06/13/782519.html#undefined。算法