第一个Servlet程序
在Servlet前置知识 中有对Servlet的基本介绍。
Sun公司定义了一套专门用于Servlet程序的Java类和接口,这些类和接口提供了Servlet程序开发中所涉及的各种功能,他们统称为Servlet API
(Servlet Application Programming Interface)。
Servlet的开发工具包的目录为<Tomcat安装目录>/lib/servlet-api.jar
,此处Tomcat版本为8.0。Servlet API帮助文档在线地址:http://tomcat.apache.org/tomcat-8.5-doc/servletapi/index.html。
Servlet程序的编写
一个Servlet程序就是运行在Web服务器端的特殊Java类,这个特俗的Java类必须实现javax.servlet.Servlet
接口,Servlet接口定义了Servlet引擎与Servlet程序之间通信的协议约定。Servlet API本身提供了一个实现了Servlet接口的Servlet类。即javax.servlet.GenericServlet
,这个类实现了Servlet程序的基本特征和功能。
Servlet API还提供了一个继承自javax.servlet.GenericServlet
的专用于HTTP协议的HttpServlet类,为了更方便的使用HTTP协议,我们自己的Servlet直接继承HttpServlet类即可,然后根据我们的请求类型覆写doGet或doPost方法即可(没有必要覆写service方法,它本身就根据请求类型将请求分发给对应的doMethod方法)。
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class HelloServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head>");
out.println("<title>Hello World!</title>");
out.println("</head>");
out.println("<body>");
out.println("<h1>Hello World!</h1>");
out.println("</body>");
out.println("</html>");
}
}
因为是覆写,记得删掉继承的代码:
super.doGet(req, resp);
HttpServletRequest
封装了Http的请求消息,HttpServletResponse
的getWriter方法可以获得一个文本输出流对象,通过这个流对象写入的数据将会作为Http响应消息的实体内容部分发送给客户端。
编译Servlet程序
我们在命令行下编译上面的Servlet程序:
javac HelloServlet.java
一般情况下会编译错误,提示找不到类,那是因为我们没有在环境变量中配置相关jar包。
vim ~/.bash_profile
# set classpath
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_161.jdk/Contents/Home
export CATALINA_HOME=/Users/oyty/Documents/tomcat
export SERVLET_JAR=$CATALINA_HOME/lib/servlet-api.jar
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$SERVLET_JAR
source ~/.bash_profile
重新编译后得到HttpServlet.class文件。
Servlet的注册和运行
Servlet程序必须通过Web服务器和Servlet引擎来启动运行,对此,Servlet的存储有一定的规范。编译后的class文件需要存储在<Web应用程序目录>/Web-INF/classes/目录中,另外,Servlet程序也必须在和Web-INF的同级目录下的web.xml文件中注册,才可以被Servlet引擎加载和被外界访问。
注册和映射Servlet
web.xml文件的模板可以在tomcat例子程序中找到。
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1"
metadata-complete="true">
<display-name>Welcome to Tomcat</display-name>
<description>
Welcome to Tomcat
</description>
<servlet>
<servlet-name>Hello</servlet-name>
<servlet-class>HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Hello</servlet-name>
<url-pattern>/hello/helloservlet</url-pattern>
</servlet-mapping>
</web-app>
一个<servlet>用于注册一个Servlet,<servlet-name>为Servlet的注册名,<servlet-class>为Servlet的完整类名。完整类名是什么意思呢?当前的例子中,HttpServlet类不在任何包下,所以这里配置直接是类名,如果HttpServlet的包名为com.hello
,那么此处注册名为com.hello.HelloServlet
,编译后的HttpServlet.class文件也存储在classes目录下的根据包名生成的目录下:.../Web_INF/classed/com/hello/HelloServlet.class
。
一个<servlet-mapping>用于映射一个Servlet,<servlet-name>需要与前面注册名相同,<url-pattern>需要以/
开头,表示Web程序的根目录,后面可随意指定,地址映射可以使用*
通配符,须记住*.扩展名
的优先级最低。
运行第一个Servlet程序
一切配置好后,重启Tomcat,在浏览器中输入http://localhost:8080/hello/helloservlet
,会得到doGet方法中的返回信息
。
Servlet生命周期
当servlet被部署在应用服务器中(应用服务器中用于管理Java组件的部分被抽象成为容器)以后,由容器控制servlet的生命周期。除非特殊指定,否则在容器启动的时候,servlet是不会被加载的,servlet只会在第一次请求的时候被加载和实例化。servlet一旦被加载,一般不会从容器中删除,直至应用服务器关闭或重新启动。但当容器做内存回收动作时,servlet有可能被删除。也正是因为这个原因,第一次访问servlet所用的时间要大大多于以后访问所用的时间。
servlet在服务器的运行生命周期为,在第一次请求(或其实体被内存垃圾回收后再被访问)时被加载并执行一次初始化方法,跟着执行正式运行方法,之后会被常驻并每次被请求时直接执行正式运行方法,直到服务器关闭或被清理时执行一次销毁方法后实体销毁。
参考:
张孝祥《深入体验Java Web开发内幕-核心基础》