1.什么是servlet?
Servlet(Server Applet),全称Java Servlet,未有中文译文。是用Java编写的服务器端程序。其主要功能在于交互式地浏览和修改数据,生成动态Web内容。狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类,一般情况下,人们将Servlet理解为后者。
Servlet运行于支持Java的应用服务器中。从实现上讲,Servlet可以响应任何类型的请求,但绝大多数情况下Servlet只用来扩展基于HTTP协议的Web服务器。
最早支持Servlet标准的是JavaSoft的Java Web Server。此后,一些其它的基于Java的Web服务器开始支持标准的Servlet。
我们可以把Servlet看成可以看成是用java编写的CGI.
CGI(Common GatewayInterface)是HTTP服务器与你的或其它机器 上的程序进行“交谈”的一种工具,其程序须运行在网络服务器上。
2.Servlet 特点
1.可移植性
Servlet用Java编写,ServletAPI具有完善的标准。
2.功能比较强大
可以使用Java API的所有功能
3.高效耐久
一旦载入,它就驻留在内存中,加快响应速度
4.方便
Servlet提供了大量的实用工具例程,例如自动地解析和解码HTML表单数据、读取和设置HTTP头、处理Cookie、跟踪会话状态等。
3.工作模式
客户端发送请求至服务器
服务器启动并调用Servlet,Servlet根据客户端请求生成响应内容并将其传给服务器
服务器将响应返回客户端
4.Servlet继承关系
Servlet接口中定义了五个方法:
Methods | |
---|---|
public void | destroy() 由 servlet 容器调用,指示将从服务中取出该 servlet。此方法仅在 servlet 的 service 方法已退出或者在过了超时期之后调用一次。在调用此方法之后,servlet 容器不会再对此 servlet 调用service 方法。 此方法为 servlet 提供了一个清除持有的所有资源(比如内存、文件句柄和线程)的机会,并确保任何持久状态都与内存中该 servlet 的当前状态保持同步。 |
public void | init(ServletConfig config) throwsServletException servlet 容器仅在实例化 servlet 之后调用 |
public void | service(ServletRequest req, ServletResponse res) throws ServletException, java.io.IOException 由 servlet 容器调用,以允许 servlet 响应某个请求。 此方法仅在 servlet 的 应该为抛出或发送错误的 servlet 设置响应的状态代码。 servlet 通常运行在可同时处理多个请求的多线程 servlet 容器中。开发人员必须知道要同步对所有共享资源(比如文件、网络连接以及 servlet 的类和实例变量)的访问。有关 Java 中多线程编程的更多信息,可从the Java tutorial on multi-threaded programming 中获得。 |
Properties | |
---|---|
public ServletConfig | getServletConfig() 返回 ServletConfig 对象,该对象包含此 servlet 的初始化和启动参数。返回的 ServletConfig 对象是传递给 init 方法的对象。 此接口的实现负责存储 |
public String | getServletInfo() 返回有关 servlet 的信息,比如作者、版本和版权。 此方法返回的字符串应该是纯文本,不应该是任何种类的标记(比如 HTML、XML,等等)。 |
在web容器启动后,会读取标注(Annotation)或者web.xml的配置,根据当中的每个Servlet配置,将servlet类载入,并实例化,并为每个servlet的配置产生一个ServletConfig对象,然后调用Servlet里面的init()方法,并将产生的ServletConfig对象当作参数输入进去。
ServletConfig对象:
ServletConfig是针对特定的Servlet的参数或属性。ServletConfig是表示单独的Servlet的配置和参数,只是适用于特定的Servlet。从一个servlet被实例化后,对任何客户端在任何时候访问有效,但仅对本servlet有效,一个servlet的ServletConfig对象不能被另一个servlet访问。
1.首先要设置初始化参数,如果只有一个特定的servlet要设定的参数(Servlet名字以及其它参数等),其它servlet不能共享,应该配置为ServletConfig参数,如一个读取附件的servlet要用到绝对目录,而别的servlet不会用到:
<web-app>
<servlet>
<servlet-name>GetAtt</servlet-name>
<servlet-class>mail.GetAttServlet</servlet-class>
<init-param>
<param-name>absPath</param-name>
<param-value>/usr/mail/ax/axman/Maildir/</param-value>
</init-param>
</servlet>
</web-app>
2.其次要取得ServletConfig对象:
1).从init()方法中得到.
public class Test extends HttpServlet {
ServletConfig config;
public void init(ServletConfig config) throws ServletException {
super.init(config);
this.config = config;
}
2).从getServletConfig()方法中得到.
ServletConfig config=this.getServletConfig();
if(config.getInitParameter("absPath").eaquals("adsd"){
.......
}
GenericServlet类
GenericServlet 类可以说时JDK中最重要的类,也是最基本的类。程序员要编写Servlet 应用程序,一般要继承JSDK 提供的GenericServlet 类或它的子类HttpServlet类。service() 方法是类GenericServlet中最重要的方法。每次客户向服务器发出请求时,服务器就会调用这个方法。编程人员若想对客户的请求进行响应的话,就必须覆盖这个方法,并在这个方法中加入自己的代码来具体实现对客户的响应。Service有两个参数,ServletRequest 和ServletResponse。其中ServletRequest 保存了客户向服务器发请求的各种属性。
对象ServletResponse用来设置如何对客户进行响应,它有以下三个方法:
*setContentType(String) 用来设置对客户响应的类型。
*setContentlength(int) 用来设置对客户响应的长度。
*getOutputStream() 它返回一个写响应数据的输出流。
例如:
public class HelloWorldServlet extends GenericServlet { @Override public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { // TODO Auto-generated method stub Date today = new Date(); ServletOutputStream out = res.getOutputStream(); out.println("HELLO WORLD"); out.println(today.toString()); } }
GenericServlet用于定义一般的且与协议无关的servlet 如果是继承GenericServlet的话,必须要重写service方法service方法是一个抽象方法,并且在每次访问servlet都会访问
在访问继承了HttpServlet的servlet的时候,首先访问的还是service方法 获取请求的类型,根据类型判断调用具体的doXXX()方法,所以通常继承HttpServlet抽象类的servlet只需要重写doXXX()方法
继承genericServlet和继承HttpServlet的差别:
1、继承genericServlet必须要重写service方法,而HttpServlet不需要
2、genericServlet通常用于处理与请求协议无关的servlet,httpServlet处理与HTTP协议相关的请求
3、继承httpServlet的话,最少必须要重写doXXX()方法之一
HttpServlet中Service方法源代码如下:
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String method = req.getMethod(); if (method.equals(METHOD_GET)) { long lastModified = getLastModified(req); if (lastModified == -1) { // servlet doesn't support if-modified-since, no reason // to go through further expensive logic doGet(req, resp); } else { long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE); if (ifModifiedSince < (lastModified / 1000 * 1000)) { // If the servlet mod time is later, call doGet() // Round down to the nearest second for a proper compare // A ifModifiedSince of -1 will always be less maybeSetLastModified(resp, lastModified); doGet(req, resp); } else { resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED); } } } else if (method.equals(METHOD_HEAD)) { long lastModified = getLastModified(req); maybeSetLastModified(resp, lastModified); doHead(req, resp); } else if (method.equals(METHOD_POST)) { doPost(req, resp); } else if (method.equals(METHOD_PUT)) { doPut(req, resp); } else if (method.equals(METHOD_DELETE)) { doDelete(req, resp); } else if (method.equals(METHOD_OPTIONS)) { doOptions(req,resp); } else if (method.equals(METHOD_TRACE)) { doTrace(req,resp); } else { // // Note that this means NO servlet supports whatever // method was requested, anywhere on this server. // String errMsg = lStrings.getString("http.method_not_implemented"); Object[] errArgs = new Object[1]; errArgs[0] = method; errMsg = MessageFormat.format(errMsg, errArgs); resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg); } }通过源码我们可以看出,在Service方法中,系统已经帮我们处理好了get和post方式请求,所以我们在使用Servlet的时候,直接继承于HttpServlet,不需要重写Service方法,只需要重写dopost或者doget方法。