第四章
Servlet技术:
Servlet接口:
Servlet就是一种实现了Servlet接口的类。它是由Web容器负责创建并调用,用于接收和响应用户的请求
Servlet接口定义了5个抽象方法:
方法声明 | 功能描述 |
void init(ServletConfig config) | 负责Servlet初始化工作 |
ServletConfig getServletConfig() | 返回容器调用init(ServletCOnfig config)方法时传递给Servlet的ServletConfig对象 |
String getServletInfo() | 返回一个字符串,其中包含关于Servlet的信息;例如,作者、版本和版权等信息 |
void service(ServletRequest request,ServletResponse response) | 负责响应用户的请求,当容器收到客户端访问Servlet对象的请求时调用 |
void destroy() | 负责释放Servlet对象占用的资源 |
init()、service()、destroy()这三个方法都是Servlet生命周期方法,会在特定时刻调用
Servlet程序:(基于Tomcat和cmd命令行的操作,可以了解的更深刻一点,不需要的可以跳过去,但本人觉得需要)
D:\cn\itcast\firstapp\servlet此目录下编写一个Servlet,
如果实现接口需要实现很多方法,烦,直接继承他的实现类javax.servlet.GenericServlet,此类除了service方法,其余的都实现了
HelloWorldServlet.java
package cn.itcast.firstapp.servlet;
import java.io.*;
import javax.servlet.*;
public class HelloWorldServlet extends GenericServlet{
public void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//得到输出流PrintWriter对象,Servlet使用输出流来产生响应
PrintWriter out=response.getWriter();
//使用输出流对象向客户端发送字符数据
out.write("Hello World");
}
}
cmd中进入到D:\cn\itcast\firstapp\servlet目录
执行:javac HelloWorldServlet.java
嗯,很好,失败了!!!程序中引入了Servlet包,导包吧。找到Tomcat的lib目录:servlet-api.jar
去classpath中配置:
在cmd的D:\cn\itcast\firstapp\servlet当前目录下执行:
set classpath=”%classpath%”; H: \apachetomcat7.0.27\apache-tomcat-7.0.27\lib\servlet-api.jar;(我的Tomcat在H盘)
再执行:javac HelloWorldServlet.java
OK,D:\cn\itcast\firstapp\servlet目录下生成了一个classs文件
再来:在Tomcat的webapps目录下新建文件chapter04,chapter04目录下创建\WEB-INF\classes目录,将之前的那个class文件复制到当前文件下(也就是直接把cn文件复制到classes文件下,delete到java文件),在WEB-INF目录下编写web.xml,这个就不好说了,自己去eclipse去新建一个web项目,参考一下那个项目下的web.xml
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<servlet>
<servlet-name>TestServlet01</servlet-name>
<servlet-class>cn.itcast.chapter04.servlet.TestServlet01</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>TestServlet01</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
启动Tomcat服务器,主要在于
<servlet>和
<servlet-mapping>;元素<servlet>用于注册Servlet,它的两个子元素<servlet-name>和<servlet-class>分别用来指定Servlet名称及其完整类名。元素<servlet-mapping>用于映射Servlet对外访问的虚拟路径,它的子元素<setvlet-name>和上同,<url-pattern>用于指定访问该Servlet的虚拟路径,该路径以“/”开头,代表当前web应用程序的根目录
在Tomcat的bin目录下点击startup.bat或者Tomcat7.exe
或者在cmd命令行下切换到Tomcat的bin目录下,启动这其中的一个
在浏览器中输入http://localhost:8080/chapter04/HelloWorldServlet
http://127.0.0.1:8080/chapter04/HelloWorldServlet
Servlet的生命周期
当客户端向Servlet容器发出HTTP请求要求访问Servlet时,Servlet容器首先会解析请求,检查内存中是否已经有了该Servlet对象,有直接用,没有就创建,然后init()方法初始化
整个生命周期中init()方法只执行一次,you know
在Servlet的生命周期内,对于Servlet的每一次访问请求,Servlet容器都会调用一次service()方法,并创建新的ServletRequest和ServletResponse对象,也就是说service()方法在Servlet生命周期中会被调用多次
destroy()也只调用一次,you know
修改HelloWroldServlet.java代码:
package cn.itcast.firstapp.servlet;
import java.io.*;
import javax.servlet.*;
public class HelloWorldServlet extends GenericServlet{
public void init(ServletConfig config) throws ServletException{
System.out.println("init method is called");
}
public void service(ServletRequest request,ServletResponse response) throws ServletException,IOException{
System.out.println("Hello World");
}
public void destroy(){
System.out.println("destroy method is called");
}
}
将生成的class文件复制到那个classes文件中,启动Tomcat服务器,在浏览器中访问编译运行(方法上面找,应该脑海有影响)
cmd中会打印消息,依次调用init、service,移除的时候会调用destroy()方法
自动加载Servlet程序
<servlet>
<servlet-name>TestServlet01</servlet-name>
<servlet-class>cn.itcast.chapter04.servlet.TestServlet01</servlet-class>
<!—设置Servlet在Web应用启动时初始化-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>TestServlet01</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
Servlet高级应用:在<load-on-startup>元素中的值必须是整数,如果是负数或者没有设定这个元素则在客户端首次请求这个Servlet的时候加载,如果是正整数或0,则在Tomcat启动时加载,值越小越被先加载
HttpServlet:
抽象类,继承自GenericServlet,专门用于创建应用于HTTP的Servlet
里面有一个doGet()和doPost()方法
还是这个目录:D:\cn\itcast\firstapp\servlet
RequestMethodServlet.java
package cn.itcast.firstapp.servlet;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class RequestMethodServlet extends HttpServlet{
public void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{
PrintWriter out=response.getWriter();
out.write("this is doGet method");
}
public void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{
PrintWriter out=response.getWriter();
out.write("this is doGet method");
}
}
同时配置chapter04的web.xml中的映射路径编译运行:产生的class文件copy过来,老规矩
<servlet>
<servlet-name> RequestMethodServlet </servlet-name>
<servlet-class>cn.itcast.chapter04.servlet. RequestMethodServlet </servlet-class>
</servlet>
<servlet-mapping>
<servlet-name> RequestMethodServlet </servlet-name>
<url-pattern>/ RequestMethodServlet </url-pattern>
</servlet-mapping>
实现的是doGet重启Tomcat服务器,浏览器中访问
webapps\chapter04下编写一个form.html
<form action=”/chapter04/RequestMethodServlet” method=”post”>
姓名:<input type=”text” name=”name”/><br />
密码:<input type=”text” name=”pwd”/><br />
<input type=”submit” name=”提交”/>
</form>
点提交,实现的是doPost启动Tomcat服务器,浏览器中访问:
http://localhost:8080/chapter04/form.html
使用Eclipse工具开发Servlet
至于安装和创建部署项目的步骤就不说了,没必要,需要的网上有
Servlet虚拟路径的映射:
多重映射:
<?xml version="1.0" encoding="UTF-8"?>
<servlet>
<servlet-name>TestServlet01</servlet-name>
<servlet-class>cn.itcast.chapter04.servlet.TestServlet01</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>TestServlet01</servlet-name>
<url-pattern>/ TestServlet01</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name> TestServlet01</servlet-name>
<url-pattern>/Test1</url-pattern>
</servlet-mapping>
第二种方式可以映射两个或多个虚拟路径
<servlet>
<servlet-name>TestServlet01</servlet-name>
<servlet-class>cn.itcast.chapter04.servlet.TestServlet01</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>TestServlet01</servlet-name>
<url-pattern>/ TestServlet01</url-pattern>
<url-pattern>/Test1</url-pattern>
</servlet-mapping>
Servlet映射路径中使用通配符:合在一个里面写,作用一样
格式两种:
“*.扩展名”:匹配以扩展名结尾的所有URL地址
“/*”:例,“/abc/*”,匹配以“/abc”开始的所有URL地址
这两种不能混用,是不合法的。
当客户端访问一个Servlet时,如果请求的URL地址能够匹配多个虚拟路径,那么Tomcat将采用最具体匹配原则查找与请求URL最接近的虚拟映射路径
例:
/abc/*映射到Servlet1
/*映射到Servlet2
/abc映射到Servlet3
*.do映射到Servlet4
当请求URL为”/abc/a.html”,”/abc/*”和”/*”都可以匹配这个URL,则Tomcat调用Servlet1
当请求URL为”/abc”,”/abc/*”和”/abc”都可以匹配这个URL,则Tomcat调用Servlet1
当请求URL为”/a.do”,”/*”和”/*.do”都可以匹配这个URL,则Tomcat调用Servlet1
当请求URL为”/xxx/yyy/a.do”,”/*.do”和”/*”都可以匹配这个URL,则Tomcat调用Servlet1
默认Servlet:
<servlet>
<servlet-name>TestServlet01</servlet-name>
<servlet-class>cn.itcast.chapter04.servlet.TestServlet01</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>TestServlet01</servlet-name>
<url-pattern>/ </url-pattern>
</servlet-mapping>
<url-pattern>/ </url-pattern>为默认,当找不到匹配的<servlet-mapping>元素的URL,则交给默认的Servlet处理
如:http://localhost:8080/chapter04/abcde
ServletConfig和ServletContext:
在Servlet运行期间,经常需要一些辅助信息,如文件的编码等,可以在web.xml文件中使用一个或多个<init-param>元素进行配置。
当Tomcat初始化一个Servlet时,会将该Servlet的配置信息封装到一个ServletConfig对象中,通过调用init(ServletConfigconfig)方法将ServletConfig对象传递给Servlet。ServletConfig定义了一系列获取配置信息的方法
ServletConfig接口的常用方法:
方法说明 | 功能描述 |
String getInitParameter(String name) | 根据初始化参数名返回对应的初始化参数值 |
Enumeration getInitParameterNames() | 返回一个Enumeration对象,其中包含所有的初始化参数名 |
ServletContext getServletContext() | 返回一个代表当前Web应用的ServletContext对象 |
String getServletName() | 返回Servlet的名字,即web.xml中<servlet-name>元素的值 |
getInitParameter()方法
<servlet>
<servlet-name>TestServlet02</servlet-name>
<servlet-class>cn.itcast.chapter04.servlet.TestServlet02</servlet-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>TestServlet02</servlet-name>
<url-pattern>/TestServlet02</url-pattern>
</servlet-mapping>
TestServlet02.java
package cn.itcast.chapter04.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class TestServlet02 extends HttpServlet {
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
PrintWriter out = response.getWriter();
ServletConfig config = this.getServletConfig();
String param = config.getInitParameter("encoding");
out.print("encoding=" + param);
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
运行测试
ServletContext接口:
获取Web应用程序的初始化参数:
在<web-app>元素下
<servlet>
<servlet-name>TestServlet03</servlet-name>
<servlet-class>cn.itcast.chapter04.servlet.TestServlet03</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>TestServlet03</servlet-name>
<url-pattern>/TestServlet03</url-pattern>
</servlet-mapping>
<context-param>
<param-name>companyName</param-name>
<param-value>itcast</param-value>
</context-param>
<context-param>
<param-name>address</param-name>
<param-value>beijing</param-value>
</context-param>
TestServlet03.java
package cn.itcast.chapter04.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class TestServlet03 extends HttpServlet {
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
PrintWriter out = response.getWriter();
ServletContext context = this.getServletContext();
Enumeration<String> paramNames = context.getInitParameterNames();
out.print("all this paramName and paramValue are following:");
out.print("<br>");
while (paramNames.hasMoreElements()) {
String name = paramNames.nextElement();
String value = context.getInitParameter(name);
out.println(name + ":" + value);
out.println("<br>");
}
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
运行测试
实现多个Servlet对象共享数据:
由于一个Web应用中的所有Servlet共享一个ServletCOntext对象,因此ServletContext对象的域属性可以被该Web应用中的所有Servlet访问。
在ServletContext接口中定义了分别用于增加、删除、设置ServletContext域属性的4个方法:
方法说明 | 功能描述 |
Enumeration getAttributeNames() | 返回一个Enumeration对象,该对象包含所有存放在ServletContext中的所有域属性名 |
Object getAttribute(String name) | 根据参数指定的属性名返回一个与之匹配的域属性名 |
void removeAttribute(String name) | 根据参数指定的域属性名,从ServletContext中删除匹配的域属性 |
void setAttribute(String name,Object obj) | 设置ServletContext的域属性,其中name是域属性名,obj是域属性 |
TestServlet04.java
package cn.itcast.chapter04.servlet;
import java.io.IOException;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class TestServlet04 extends HttpServlet {
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
ServletContext context = this.getServletContext();
context.setAttribute("data", "this servlet save data");
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
TestServlet05.java
package cn.itcast.chapter04.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class TestServlet05 extends HttpServlet {
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
PrintWriter out = response.getWriter();
ServletContext context = this.getServletContext();
String data = (String) context.getAttribute("data");
out.print(data);
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
web.xml
<servlet>
<servlet-name>TestServlet04</servlet-name>
<servlet-class>cn.itcast.chapter04.servlet.TestServlet04</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>TestServlet04</servlet-name>
<url-pattern>/TestServlet04</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>TestServlet05</servlet-name>
<servlet-class>cn.itcast.chapter04.servlet.TestServlet05</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>TestServlet05</servlet-name>
<url-pattern>/TestServlet05</url-pattern>
</servlet-mapping>
运行测试
读取Web应用下的资源文件:
ServletContext接口的常用方法:
方法说明 | 功能描述 |
Set getResourcePath(String path) | 返回一个Set集合,集合中包含资源目录中子目录和文件的路径名称。参数path必须以(/)开始,指定匹配资源的部分路径 |
String getRealPath(String path) | 返回资源文件在服务器文件系统上的真实路径(文件的绝对路径)。参数path代表资源文件的虚拟路径,它应该以(/)开始,“/”表示当前Web应用的根目录,如果Servlet容器不能将虚拟路径转换为文件系统的真实路径,则返回null |
URL getResource(String path) | 返回映射到某个资源文件的URL对象。参数path必须以(/)开始,“/”表示当前Web应用的根目录 |
InputStream getResourceAsStream(String path) | 返回映射到某个资源文件的InputStream输入流对象。参数path传递规则和getResource()方法完全一致 |
Src下创建文件itcast.properties
Company=itcast
Address=Beijing
读取资源文件
TestServlet06.java
package cn.itcast.chapter04.servlet;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Properties;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class TestServlet06 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
PrintWriter out = response.getWriter();
ServletContext context = this.getServletContext();
InputStream in=context.getResourceAsStream("/WEB-INF/classes/itcast.properties");
Properties pros=new Properties();
pros.load(in);
out.println("Company="+pros.getProperty("Company")+"<br>");
out.println("Address="+pros.getProperty("Address")+"<br>");
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
web.xml
<servlet>
<servlet-name>TestServlet06</servlet-name>
<servlet-class>cn.itcast.chapter04.servlet.TestServlet06</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>TestServlet06</servlet-name>
<url-pattern>/TestServlet06</url-pattern>
</servlet-mapping>
运行测试
获取资源的绝对路径getRealPath(String path)
修改TestServlet06.java
package cn.itcast.chapter04.servlet;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Properties;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class TestServlet06 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
PrintWriter out = response.getWriter();
ServletContext context = this.getServletContext();
String path=context.getRealPath("/WEB-INF/classes/itcast.properties");
FileInputStream in=new FileInputStream(path);
Properties pros=new Properties();
pros.load(in);
out.println("Company="+pros.getProperty("Company")+"<br>");
out.println("Address="+pros.getProperty("Address")+"<br>");
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}