Java Servlet技术的核心就是在服务端创建能响应用户请求的对象,被创建的对象习惯上称为一个Servlet对象。
编写一个创建servlet对象的类就是编写一个特殊类的子类,这个特殊的类就是javax.servlet.http包中HttpServlet类。HttpServlet类实现了Servlet接口,实现了响应用户的方法。HttpSerlet类的子类被习惯地称为一个Servlet类,这样的类创建的对象习惯地被称为一个servlet对象。
1部署servlet
使用Tomcat 5.x后的Tomcat服务器,要求Servlet类必须有包名。然和Bean一样,需要将编译好的字节码复制到与包相应的目录下(\WEB-INF\classes目录下)。
*************************
为了编译Servlet源文件、需要HttpServlet、HttpServletRequest等类。JDK内置中并不包含这些类文件,需要将Tomcat服务器中common/lib目录下的servlet-api.jar文件复制到JDK安装目录的\jre\lib\ext子目录中。
一个Servlet实例:
package star.moon;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class HelloBeijing extends HttpServlet{
public void init(ServletConfig config)throws ServletException{
super.init(config);
}
public void service(HttpServletRequest request,HttpServletResponse response)throws IOException{
response.setContentType("text/html;Charset=GB2312");
PrintWriter out=response.getWriter();
out.println("<html><body>");
out.println("<h2>北京奥运圆满成功!</h2>");
out.println("</body></html>");
}
}
为了能让Tomcat服务器用Servlet字节码文件创建对象,必须为Tomcat服务器编写一个部署文件,该部署文件是一个XML文件,名字是web.xml(WEB-INF目录下),该文件由Tomcat服务器负责管理。使用该xml文件的应用程序(Tomcat服务器)配有内置的解析器,可以解析xml标记中的数据,可以在Tomcat服务器的webapps目录的root目录找到一个web.xml文件,参照它编写自己的web.xml文件。
例web.xml:
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app>
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>star.moon.HelloBeijing</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/lookhello</url-pattern>
</servlet-mapping>
</web-app>
一个XML文件应当以XML声明作为文件的第一行,在前面不能有空白、其他的处理指令或注释。XML声明以"<?xml"标识开始,以"?>"标识结束。注意<?与xml之间以及?与>之间不要有空格。如果在XML声明中没有显式地指定encoding属性的值,那么该属性的默认值为UTF-8编码。如果编写XML文件时只准备使用ASCII字符,也可以将encoding属性的值设置为ISO-8859-1。这时XML文件必须使用ANSI编码保存,Tomcat服务器中XML解析器根据encoding属性的值识别XML文件中的标记并正确解析标记中的内容。如果encoding属性的值为UTF-8,XML文件必须按照UTF-8编码来保存。
web.xml文件中标记的具体内容及其作用:
根标记:xml文件必须有一个根标记,web.xml文件的根标记是<web-app>。
<servlet>标记及子标记。<servlet>需要有两个子标记<servlet-name>和<servlet-class>。其中<servlet-name>标记的内容是Tomcat服务器创建的servlet对象的名字。<servlet-class>标记的内容指定Tomcat服务器用哪个类创建servlet对象。
<servlet-mapping>标记及子标记。该标记和<servlet>标记都是根标记的直接子标记。<servlet-mapping>标记需要有两个子标记:<servlet-name>和<url-pattern>,其中<servlet-name>标记的内容是Tomcat服务器创建的servlet对象的名字。<url-pattern>标记用来指定用户用怎样的模式请求servlet对象。如<url-pattern>/lookhello</url-pattern>,那么用户必须通过当前Web服务目录来请求servlet。用户要请求服务器运行servlet对象hello为其服务,那么在浏览器的地址栏应该输入:http://127.0.0.1:8000/ch7/lookhello
一个web服务目录的web.xml文件负责管理该目录下的servlet对象,当该Web服务目录需要提供更多的servlet对象时,只要在web.xml文件中增加<servlet>和<servlet-mapping>子标记即可。
Servlet类可以使用getServletName()方法返回配置文件中<servlet-name>标记给出的servlet的名字。
2servlet的工作原理
Servlet的生命周期
一个servlet对象是javax.servlet包中HttpServlet类的子类的一个实例,又服务器创建并完成其初始化工作。当多个客户请求一个servlet时,服务器为每个客户请求一个servlet时,服务器为每个客户启动一个线程而不是一个进程。
一个servlet对象的生命周期主要由下列三个过程组成:
初始化servlet对象。servlet对象第一次被请求加载时,服务器初始化这个servlet对象,即创建一个servlet对象,这对象调用init方法完成必要的初始化工作。
诞生的servlet对象在调用service方法响应客户的请求。
当服务器关闭时,调用destroy方法,消灭servlet对象。
init方法只被调用一次,即在servlet第一次被请求加载时调用该方法,当后续的客户请求servlet服务时,web服务将为每个客户启用一个新线程,在该线程中,servlet对象调用service方法响应客户的请求。
init方法
方法是HttpServlet类中的方法,可以在Servlet类中重写这个方法。init方法的声明格式:
public void init(ServletConfig config) throws ServletException
该方法在执行时,服务器会把一个ServletConfig类型的对象传递给init()方法,这个对象被保存在servlet对象中, 直到servlet被消灭。ServletConfig对象负责向servlet传递服务设置信息,如果传递失败就会发生ServletException。
service方法
该方法是HttpServlet类中的方法,可以在Servlet类中直接继承该方法或重写这个方法。service方法的声明格式:
public void service(HttpServletRequest request,HttpServletResponse response)throw ServletException,IOException
当servlet对象成功创建和初始化之后,该对象就调用service方法来处理用户的请求并返回响应。服务器将两个参数传递给该方法,一个是HttpServletRequest类型的对象,该对象封装了用户的请求信息;另一个参数对象是HttpServletResponse类型的对象,用来响应用户的请求。每个客户的每次请求都导致service方法被调用执行,调用过程运行在不同的线程中,不同线程的service方法中的局部变量互不干扰。
destroy方法
该方法是HttpServlet类中的一个方法。一个Servlet类可直接继承这个方法,一般不需要重写。destroy方法的声明格式:public destroy()
当服务器终止服务时,destroy()方法会被执行。
3通过JSP页面调用servlet
Web服务目录下的JSP页面都可以通过表单或超链接请求该Web服务目录下的某个servlet。
***通过表单向servlet提交数据***
注意如果servlet的请求格式是/name,那么JSP页面请求servlet时,必须要写成name,不可以写成/name,否则将变成请求root服务目录下的某个servlet。
****该servlet文件就是<url-pattern>/name</url-pattern>处的名字***
例:<FORM action="servlet文件" method=post>....</FORM>
***通过超链接访问servlet***
可以在JSP页面中,单击一个超链接,访问servlet对象。例:<A href="Servlet文件">...</A>
Servlet类是HttpServlet的一个子类,在编写子类时可以声明某些成员变量。那么Servlet类的成员变量被所有请求该servlet的用户共享。
***通过forward动作表来来访问servlert***
<jsp:forward page="要转向的页面或者是servlet"/>
例如
<jsp:forward page="/DBServlet" />
4doGet和doPost方法
HttpServlet类除了init、service、destroy方法外,该类还有两个很重要的方法doGet和doPost,用来处理客户的清求并做出响应。
每当服务器在接收到一个servlet请求时,就会产生一个新线程,在这个线程中servlet对象调用service方法检查HTTP请求类型(get、post等),并在service方法中根据用户的请求方式,对应地调用doGet和doPost方法。
5sendRedirect方法
void sendRedirect(java.lang.String location)方法是HttpServletResponse类中的方法。当用户请求一个servlet时,该servlet在处理数据后,可以使用该方法将用户重定向到一个JSP页面或另一个 servlet。重定向方法仅仅将用户从当前页面或servlet定向到另一个JSP页面或servlet,但不能将用户对当前页面或另一个servlet的请求转发给所定向的JSP页面或servlet。即:重定向的目标页面或servlet对象无法使用request获取用户提交的数据。
6RequestDispatcher对象
RequestDispatcher对象可以把用户对当前JSP页面或servlet的请求转发给另一个JSP页面或servlet。而且将用户对当前JSP页面或servlet的请求和响应传递给所转发的JSP页面或servlet。当前所要转发的目标页面或servlet对象可以使用request获取用户提交的数据。
实现转发有两个步骤:
得到RequestDispatcher对象
用户所请求的当前JSP或servlet可以让HttpServletRequest对象request调用
public RequestDispatcher getRequestDispatcher(java.lang.String path)
返回一个RequestDispatcher对象,其中参数path是要转发的JSP也页面或servlet的地址。
转发
在步骤1中获取RequestDispatcher对象调用下面的方法可以将用户对当前JSP页面或servlet的请求转发给RequestDispatcher对象所指定的JSP页面或servlet。
void forward(ServletRequest request,ServletResponse response)throws ServletExcpetion,java.io.IOException
使用forward的方法必须抛出ServletException。(throws ServletException)
7获取用户的会话
HttpServletRequest对象request调用getSession方法获取用户的会话对象:
HttpSession session=request.getSession(true);
一个用户在不同的servlet对象中获取的session对象是完全相同的。但是不同的用户的session对象互不相同。
例:
package shili;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class ShowLetter extends HttpServlet {
@Override public void init(ServletConfig config) throws ServletException{
super.init(config);
}
@Override public void service(HttpServletRequest request,HttpServletResponse response)throws IOException{
response.setContentType("text/html;charset=GB2312");
PrintWriter out=response.getWriter();
out.println("<html><body>");
out.print("<br>小写希腊字母:");
for(char c=‘a‘;c<=‘w‘;c++){
out.print(" "+c);
}
out.print("<br>大写希腊字母:");
for(char c=‘A‘;c<=‘W‘;c++){
out.print(" "+c);
}
out.println("</body></html>");
}
}
**************************************
如何指定应用事件监听程序
应用事件监听器程序是建立或修改servlet环境或会话对象时通知的类。它们是servlet规范的版本2.3中的新内容。这里只简单地说明用来向Web应用注册一个监听程序的web.xml的用法。
注册一个监听程序涉及在web.xml的web-app元素内放置一个listener元素。在listener元素内,listener-class元素列出监听程序的完整的限定类名,如下所示:
<listener>
<listener-class>package.ListenerClass</listener-class>
</listener>
虽然listener元素的结构很简单,但请不要忘记,必须正确地给出web-app元素内的子元素的次序。
*******************
listener元素位于所有的servlet 元素之前以及所有filter-mapping元素之后。此外,因为应用生存期监听程序是serlvet规范的2.3版本中的新内容,所以必须使用 web.xml DTD的2.3版本,而不是2.2版本。
servlet版本和jsp版本查看:
找到jsp-api.jar servlet-api.jar解压这两个文件,用记事本分别打开META-INF下的MAINMEFT.MF文件。该文件记录了它们的版本号。
*******************
例如,程序清单5-20给出一个名为ContextReporter的简单的监听程序,只要Web应用的Servlet-Context建立(如装载Web应用)或消除(如服务器关闭)时,它就在标准输出上显示一条消息。程序清单5-21给出此监听程序注册所需要的web.xml文件的一部分。
程序清单5-20 ContextReporterjava
package moreservlets;
import javax.servlet.*;
import java.util.*;
public class ContextReporter implements ServletContextListener {
public void contextInitialized(ServletContextEvent event) {
//ServletContextEvent的实例的getServletContext()方法返回SevletContext对象
ServletContext servletContext = event.getServletContext();
System.out.println("Context created on " +
new Date() + ".");
}
public void contextDestroyed(ServletContextEvent event) {
System.out.println("Context destroyed on " +
new Date() + ".");
}
}
程序清单5-21 web.xml(声明一个监听程序的摘录)
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<!-- ... -->
<filter-mapping> … </filter-mapping>
<listener>
<listener-class>package.ListenerClass</listener-class>
</listener>
<servlet> ... </servlet>
<!-- ... -->
</web-app>
ServletContextListener监听ServletContext。当创建ServletContext时,激发contextInitialized(ServletContextEvent sce)方法;当销毁ServletContext时,激发contextDestroyed(ServletContextEvent sce)方法。