Servlet开发
servlet接口
针对Servlet技术的开发,Sun公司提供了一系列接口和类,其中最重要的是javax.servlet.Servlet接口,Servlet就是一种实现了Servlet接口的类,它是由Web容器负责创建并调用,用于接收和响应应用的请求。
在Servlet接口中定义了5个抽象方法,具体
方法声明 | 功能描述 |
---|---|
void init(ServletConfig config) | 负责Servlet初始化工作。容器在创建好Servlet对象后,就会调用此方法。该方法接收一个ServletConfig类型的参数,Servlet容器通过这个参数向Servlet传递初始化配置信息 |
ServletConfig getServletConfig() | 返回容器调用init(ServletConfig config)方法时传递给Servlet的ServletConfig对象 |
String getServletInfo() | 返回一个字符串,其中包含关于Servlet的信息,例如,作者,版本和版权等信息 |
void service(ServletRequest request,ServletResponse response) | 负责响应用户请求,当容器接收到客户端访问Servlet对象的请求时,就会调用此方法。容器会构造一个表示客户端请求信息的ServletRequest对象和一个用于响应客户端的ServletResponse对象作为参数传递给service()方法。在service()方法中,可以通过ServletRequest对象得到客户端的相关信息和请求信息,在对请求进行处理后,调用ServletResponse对象的方法设置响应信息 |
void destroy() | 负责释放Servlet对象占用的资源。当Servlet对象被销毁时,容器会调用此方法 |
手动编译一个Servlet程序
1、编写一个Servlet程序
在目录D:cn/itcast/firstapp/servlet下编写HelloWorldServlet.java,由于直接继承Servlet接口来编写servlet非常不方便。因此可以通过继承Servlet接口的实现类javax.servlet.GenericServlet来实现
package cn.itcast.firstapp.servlet;
import java.io.*;
import javax.servlet.*;
public class HelloWorldServlet extends GenericServlet{
public void service(ServletRequest request,ServletResponse response) throws ServletException,IOException{
PrintWriter out = response.getWriter();
out.println("Hello World");
}
}
HelloWorldServlet类只实现了service方法,这是因为除了service之外的方法GenericServlet都实现了。
2、打开命令窗口,进入HelloWorldServlet所在目录,编译
错误提示没有找到javax.servlet包
3、找到javax.servlet包路径
进入Tomcat安装目录下的lib目录,里面包含许多与Tomcat服务器有关的jar包,其中servlet-api.jar文件就是与Servlet相关的jar文件
4、通过set classpath命令添加jar路径
5、重新编译
成功得到class文件
6、将servlet应用放置在tomcat下
在Tomcat安装目录的webapps下创建目录chapter04,chapter04为Web应用的名称,然后在chapter04目录下创建\WEB-INF\class目录,将整个包目录复制到其下(\cn…)
7、配置web.xml
进入目录WEB-INF新建一个web.xml文件
<?xml version="1.0" encoding="ISO-8859-1"?>
<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>HelloWorldServlet</servlet-name>
<servlet-class>cn.itcast.firstapp.servlet.HelloWorldServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloWorldServlet</servlet-name>
<url-pattern>/HelloWorldServlet</url-pattern>
</servlet-mapping>
</web-app>
上面配置文件信息中,元素<servlet>用于注册Servlet,他的两个子元素<servlet-name>和<servlet-class>分别用来指定Servlet名称以及其完整类名。元素<servlet-mapping>用于映射Servlet对外访问的虚拟路径,他的子元素<servlet-name>与servlet元素中的相同,<url-pattern>则是用来指定访问该Servlet的虚拟路径,该路径以(/)开头,代表当前Web应用的根目录。
8、启动Tomcat服务器,使用浏览器访问
使用浏览器访问localhost:8080/chapter04/HelloWorldServlet
至此第一个Servlet程序实现了。
Servlet生命周期
图中描述了Servlet的生命周期。按照功能不同,大致可以分为三个阶段。
1、初始化阶段
当客户端向Servlet容器发出http请求要求访问Servlet时,Servlet容器首先会解析请求,检查内存中是否已经有了该Servlet容器,如果有直接使用该Servlet对象,如果没有就创建Servlet实例对象,然后通过调用init()方法实现Servlet的初始化工作。需要注意的是,在Servlet整个生命周期中,他的init()方法只被调用一次。
2、运行阶段
这是Servlet生命周期中最重要的阶段,在这个阶段,Servlet容器会为这个请求创建代表Http请求的ServletRequest对象和代表Http响应的ServletResponce对象,然后将他们作为参数传递给service()方法。在service()方法中,可以通过ServletRequest对象得到客户端的相关信息和请求信息,在对请求进行处理后,调用ServletResponse对象的方法设置响应信息。在Servlet整个生命周期中,对于Servlet的每次访问请求,Servlet容器都会调用一次Servlet的service()方法,并且创建新的ServletRequest和ServletResponce对象,也就是说,service()方法在整个生命周期中被多次调用。
3、销毁阶段
当服务器关闭或web应用被移出容器时,Serlet随着Web应用的销毁而销毁。在销毁Servlet之前,Servlet容器会调用Servlet的destroy()方法,以便让Servlet对象释放占用的资源。在整个生命周期中destroy()方法也仅会调用一次。,Servlet对象一旦创建就会驻留在内存中等待客户端的访问,直到服务器关闭,或Web应用被移出容器。
代码演示
package cn.itcast.firstapp.servlet;
import javax.servlet.*;
public class TestServlet01 extends GenericServlet {
private static final long serialVersionUID = 1L;
public void init(ServletConfig config)throws ServletException{
System.out.println("init methed is called");
}
public void service(ServletRequest request,ServletResponse response)throws ServletException{
System.out.println("Hello World");
}
public void destroy(){
System.out.println("destroy methed is called");
}
}
该Servlet在init被调用时向命令行输出一句init methed is called,在service被调用时向命令行输出一句Hello World,在destroy()被调用时输出destroy methed is called
首次访问Servlet
表明第一次访问Servlet,Servlet容器调用了init()和service()
之后多次访问Servlet
之后再次访问,只会调用service()。
在管理平台将servlet移出
自动加载Servlet程序
有时候我们需要有些Servlet程序随Tomcat启动时启动。例如在启动服务器时,对数据库初始化。这时需要配置web.xml中的<load-on-startup>元素。
<load-on-startup>元素是<servlet>元素的子元素,用于指定Servlet被加载的时机和顺序。在<load-on-startup>元素中,其值必须是一个整数。如果这个值是一个负数或没有设置,那么Servlet会在用户首次请求的时候加载;如果这个值是正整数或0,Servlet容器将在web应用启动时加载并初始化该Servlet并且<load-on-startup>元素的值越小优先级越高。
Servlet高级应用
由于大多数Web应用都是通过HTTP和客户端进行交互的,因此,在Servlet接口中,提供了一个抽象类javax.servlet.http.HttpServlet的子类,专门用于创建应用于HTTP的Servlet应用。
HttpServlet主要有两大功能,
1、根据用户请求方式的不同,定义相应的doXXX()方法处理用户请求。例如与GET请求方式对应的doGet()方法,与POST请求方式对应的doPost()方法。
2、通过service()方法将HTTP请求和响应分别转为HttpServletRequest和HttpServletResponce类型的对象。
在定义的类继承HttpServlet后,只需要根据请求方式修改对应的doXxx方法即可,而不需要重写service()方法。
使用Eclipse工具开发Servlet
之前为了理解Servlet开发过程,我们没有借助开发工具实现了Servlet,其过程相当繁琐。但是实际开发中,通常会使用Eclipse工具完成Servlet的开发,Eclipse不仅会自动编译Servlet还会自动创建web.xml文件,完成Servlet虚拟机路径的映射。
1、新建Web工程
选择工具栏File->New->Other选项
选择Dynamic Web Project,单击Next
填写项目名,选择运行环境,单击next
ecplise会自动将src目录下的文件编译成class文件存放到class目录中,需要注意的是,src目录和class目录都是可以更改的。这里直接使用默认配置
2、创建Servlet程序
右击src文件,选择New->Other选项,进入创建Servlet的界面。
Servlet代码
web.xml
可以看到这里没有进行虚拟机映射的配置,只是因为,ecplise在servlet代码中进行了配置,不在需要更改web.xml
部署和访问Servlet
打开servers选项卡,选中应用的Tomcat服务器,右击并选择Add and Remove选项
选中想部署的Web工程添加到服务器
启动Esplice中的Tomcat服务器
使用浏览器访问servlet
Servlet的多重映射
Servlet的多重映射是指同一个Servlet可以被映射成多个虚拟路径
web.xml
通过修改web.xml映射,只需要额外添加<servlet-mapping>子元素即可
<servlet-name>Ex01</servlet-name>
<servlet-class>cn.itcast.ex1.servlet.Ex01</servlet-class>
</servlet>
<!-- 映射成/Ex01 -->
<servlet-mapping>
<servlet-name>Ex01</servlet-name>
<url-pattern>/Ex01</url-pattern>
</servlet-mapping>
<!-- 映射成/myapp -->
<servlet-mapping>
<servlet-name>Ex01</servlet-name>
<url-pattern>/myapp</url-pattern>
</servlet-mapping>
或者在servlet-name元素下新增一个url-pattern元素。
<servlet>
<servlet-name>Ex01</servlet-name>
<servlet-class>cn.itcast.ex1.servlet.Ex01</servlet-class>
</servlet>
<!-- 映射成/Ex01 -->
<servlet-mapping>
<servlet-name>Ex01</servlet-name>
<url-pattern>/Ex01</url-pattern>
<url-pattern>/eex01</url-pattern>
</servlet-mapping>
@WebServlet
要想启用注解需要检查在web.xml最外层的<web-app>中有没有metadata-complete属性,该属性若为true表示完全依赖描述文件,不再使用注解,该属性的默认值是flase,若有且值为true需要修改掉。
多重映射只需要将输入参数变为{}中间用‘,’隔开。
@WebServlet({"/Ex01","/ex01"})
Servlet映射路径中使用通配符
有时候我们希望某个目录下的所有路径都可以访问同一个Servlet,这样我们可以使用统配符,具体有两种格式:
1、格式*.拓展名
,例如*.do
匹配以.do结尾的所有url地址。
2、格式/*
,例如/abc/*
匹配以/abc/开始的所有url地址
需要注意的是,这两种通配符格式不能混合使用,例如,/abc*.do
就是不合法的映射路径,另外,如果请求的url地址能够匹配多个虚拟路径,那么Tomcat将采取最具体匹配原则查找与请求url最接近的虚拟映射路径。
默认Servlet
如果某个Servlet的映射路径仅仅是一个正斜线,那么这个Servlet就是当前Web应用的默认Servlet。Servlet服务器在接收到访问请求时,如果在web.xml文件中找不到匹配的<servlet-mapping>元素的url,就会将访问请求交给默认Servlet处理,也就是说,默认Servlet用于处理其他Servlet不处理的访问请求。
也可以在conf/web.xml中配置全局默认Servlet
ServletConfig接口
在运行Servlet运行期间,经常需要一些辅助信息,例如,文件使用的编码,这些信息可以在web.xml文件中使用一个或多个<init-pararm>进行配置。当Tomcat初始化一个Servlet时,会将该Servlet的配置信息封装到一个ServletConfig对象中,通过调用init方法将ServletConfig对象传递给Servlet。ServletConfig定义了一系列获取配置信息的方法,
String getInitParameter(String name) | 初始化参数名返回对应的初始化参数值 |
---|---|
Enumeration getInitParameterNames() | 返回一个Enumeration对象,其中包括所有的初始化参数名 |
ServletContext getServletContext() | 返回一个代表当前Web应用的ServletContext对象 |
String getServletName() | 返回Servlet的名字,即web.xml中<servlet-name>元素的值 |
1、在web.xml文件中为Servlet配置一些参数信息
<servlet>
<servlet-name>Ex01</servlet-name>
<servlet-class>cn.itcast.ex1.servlet.Ex01</servlet-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</servlet>
<!-- 映射成/Ex01 -->
<servlet-mapping>
<servlet-name>Ex01</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
2、编写Ex01
package cn.itcast.ex1.servlet;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class Ex01 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter out=response.getWriter();
ServletConfig config=this.getServletConfig();
String param=config.getInitParameter("encoding");
out.println("encoding="+param);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
ServletContext接口
1、获取Web应用程序的初始化参数
在web.xml文件中,不仅可以配置Servlet的初始化信息,还可以配置整个web应用的初始化信息。Web应用初始化参数的配置方法
<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>
<context-param>元素位于根元素<web-app>中,它的子元素<param-name>和<param-value>分别用来指定参数的名字和参数值。
2、编写Ex01
package cn.itcast.ex1.servlet;
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class Ex01 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
PrintWriter out=response.getWriter();
ServletContext context=this.getServletContext();
Enumeration<String>paramNames=context.getInitParameterNames();
//out.print("all the paramName and paramValue are following:");
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 {
doGet(request, response);
}
}
实现多个Servlet对象共享数据
由于一个web应用下的所有Servlet共享一个ServletContext对象,因此Servlet-Context对象的域属性可以被该Web应用中的所有Servlet访问。再ServletContext接口中定义了分别用于增加、删除、设置ServletContext域属性的4个方法
Enumeration getAttributeName() | 返回一个Enumeration对象,该对象包含存放再ServletContext的所有属性域 |
---|---|
Object getAttibute(String name) | 根据参数指定的属性名返回一个与之匹配的属性域 |
void removeAttibute(String name) | 根据参数指定的域属性名,从ServletContext中删除匹配的域属性 |
void setAttibute(String name.Object obj) | 设置ServletContext的域属性,其中name是域属性名,obj是域属性值 |
save.java
package cn.itcast.ex1.servlet;
import java.io.*;
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
@WebServlet("/save")
public class save extends HttpServlet {
private static final long serialVersionUID = 1L;
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 {
// TODO Auto-generated method stub
doGet(request, response);
}
}
getdata.class获得了sava.class存储的字符串。
读取Web应用下的资源文件
Set getResourcePaths(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()方法完全一致 |
1、新建一个资源文件
右击src目录,选择New->Other选项,进入创建页面
2、编写读取itcast.properties资源文件的Ex02
package cn.itcast.ex1.servlet;
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
@WebServlet("/Ex02")
public class Ex02 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
ServletContext context=this.getServletContext();
PrintWriter out=response.getWriter();
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("Company="+pros.getProperty("Address")+"<br>");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
3、有时候我们需要调用资源绝对路径
我们可以通过getRealPath(String path)方法
编写Ex03
package cn.itcast.ex1.servlet;
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
@WebServlet("/Ex03")
public class Ex03 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
ServletContext context=this.getServletContext();
PrintWriter out=response.getWriter();
String path=context.getRealPath("/WEB-INF/classes/itcast.properties");
InputStream in=new FileInputStream(path);
Properties pros=new Properties();
pros.load(in);
out.println("Company="+pros.getProperty("Company")+"<br>");
out.println("Company="+pros.getProperty("Address")+"<br>");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}