JSP 与 SERVLET 的关系
综述:Java Servlet 是 JSP 技术的基础,而且大型的 Web 应用程序的开发需要 Java Servlet 和 JSP 配合才能完成。现在许多 Web 服务器都支持 Servlet,即使不直接支持 Servlet 的 Web 服务器,也可以通过附件的应用服务器和模块来支持 Servlet,这得益于 Java 的跨平台特性。另外,由于 Servlet 内部以线程方式提供提供服务,不必对于每个请求都启动一个进程,并且利用多线程机制可以同时为多个请求服务,因此 Servlet 的效率非常高。
但它并不是没有缺点,和传统的 CGI、ISAPI、NSAPI 方式相同,Java Servlet 也是利用输出 HTML 语句来实现动态网页的,如果用它来开发整个网站,动态部分和静态页面的整合过程将变得无法想象。这就是 SUN 还要推出 JSP 的原因。
如何正确理解 servlet?
servlet 的基本概念
一、Servlet 的结构
在具体掌握 servlet 之前,须对 Java 语言有所了解。我们假设读者已经具备一定的 Java 基础。在 Servlet API 中最重要的是 Servlet 接口(interface),所有的 servlets 都必须实现该接口,途径有很多:一是直接实现该接口,二是通过扩展类(class)来实现,如 HttpServlet。 这个 Servlet 接口提供了 servlet 与客户端联系的方法。Servlet 编写者可以在他们开发 servlet 程序时提供更多一些或所有的这样方法。
当一个 servlet 接收来自客户端的调用请求, 它接收两个对象:一个是 ServletRequest,另外一个是 ServletResponse。这个 ServletRequest 类概括从客户端到服务器之间的联系,而 ServletResponse 类概括从 servlet 返回客户端的联系。
ServletRequest 接口可以获取到这样一些信息,如由客户端传送的阐述名称,客户端正在使用的协议,产生请求并且接收请求的服务器远端主机名。它也提供获取数据流的 ServletInputStream, 这些数据是客户端引用中使用 HTTP POST 和 PUT 方法递交的。一个 ServletRequest 的子类可以让 servlet 获取更多的协议特性数据。例如: HttpServletRequest 包含获取 HTTP-specific 头部信息的方法。
ServletResponse 接口给出相应客户端的 servlet 方法。它允许 servlet 设置内容长度和回应的 mime 类型,并且提供输出流 ServletOutputStream,通过编写者可以发回相应的数据。 ServletResponse 子类可以给出更多 protocol- specific 内容的信息。 例如:HttpServletResponse 包含允许 servlet 操作 HTTP-specific 头部信息的方法。
上面有关类和接口的描述,构成了一个基本的 Servlet 框架。HTTP servlets 有一些附加的可以提供 session-tracking capabilities 的方法。servlet 编写者可以利用这些 API,在有他人操作时维护 servlet 与客户端之间的状态。
二、Servlet 的接口
我们编写的 Servlet ,一般从 Javax 包的 HttpServlet 类扩展而来,在 HttpServlet 中加入了一些附加的方法,这些方法可以被协助处理 HTTP 基本请求的 HttpServlet 类中的方法 service 自动地调用。这些方法有:
· doGet 用来处理 HTTP 的 GET 请求。
这个 GET 操作仅仅允许客户从 HTTP server 上取得(GET)资源。重载此方法的用户自动允许支持方法 HEAD。这个 GET 操作被认为是安全的,没有任何的负面影响,对用户来说是很可靠的。比如,大多数的正规查询都没有副作用。打算改变存储数据的请求必须用其他的 HTTP 方法。这些方法也必须是个安全的操作。方法 doGet 的缺省实现将返回一个 HTTP 的 BAD_REQUEST 错误。
方法 doGet 的格式:
protected void doGet(HttpServletResquest request, HttpServletResponse response)
throws ServletException,IOException;
· doPost 用来处理 HTTP 的 POST 请求。
这个 POST 操作包含了在必须通过此 servlet 执行的请求中的数据。由于它不能立即取得资源,故对于那些涉及到安全性的用户来说,通过 POST 请求操作会有一些副作用。
方法 doPost 的缺省实现将返回一个 HTTP 的 BAD_REQUEST 错误。当编写 servlet 时,为了支持 POST 操作必须在子类 HttpServlet 中实现(implement)此方法。
此方法的格式:
protected void doPost(HttpServletResquest request, HttpServletResponse response)
throws ServletException,IOException;
· doPut 用来处理 HTTP 的 PUT 请求。
此 PUT 操作模拟通过 FTP 发送一个文件。对于那些涉及到安全性的用户来说,通过 PUT 请求操作也会有一些副作用。
此方法的格式:
protected void doPut(HttpServletResquest request,HttpServletResponse response)
throws ServletException,IOException;
· doDelete 用来处理 HTTP 的 DELETE 请求。
此操作允许客户端请求一个从 server 移出的 URL。对于那些涉及到安全性的用户来说,通过 DELETE 请求操作会有一些副作用。
方法 doDelete 的缺省实现将返回一个 HTTP 的 BAD_REQUEST 错误。当编写 servlet 时,为了支持 DELETE 操作,必须在子类 HttpServlet 中实现(implement)此方法。
此方法的格式:
protected void doDelete (HttpServletResquest request, HttpServletResponse response)
throws ServletException,IOException;
· doHead 用来处理 HTTP 的 HEAD 请求。
缺省地,它会在无条件的 GET 方法执行时运行,但是不返回任何数据到客户端。只返回包含内容信息的长度的 header。由于用到 GET 操作,此方法应该是很安全的(没有副作用)也是可重复使用的。此方法的缺省实现(implement)自动地处理了 HTTPDE 的 HEAD 操作并且不需要通过一个子类实现(implement)。
此方法的格式:
protected void doHead (HttpServletResquest request,HttpServletResponse response)
throws ServletException,IOException;
· doOptions 用来处理 HTTP 的 OPTIONS 请求。
此操作自动地决定支持什么 HTTP 方法。比如说,如果读者创建 HttpServlet 的子类并重载方法 doGet,然后方法 doOptions 会返回下面的 header:
Allow:GET,HEAD,TRACE,OPTIONS
一般不需要重载方法 doOptions。
此方法的格式:
protected void doOptions (HttpServletResquest request, HttpServletResponse response)
throws ServletException,IOException;
· doTrace 用来处理 HTTP 的 TRACE 请求。
此方法的缺省实现产生一个包含所有在 trace 请求中的 header 的信息的应答(response)。在开发 servlet 时,多数情况下需要重载此方法。
此方法的格式:
protected void doTrace (HttpServletResquest request, HttpServletResponse response)
throws ServletException,IOException;
在开发以 HTTP 为基础的 servlet 中,Servlet 开发者关心方法 doGet 和方法 doPost 即可。
三、Servlet 的生命周期
如果读者写过 Java 的小应用程序(Applet),那 Servlet 对你来说就不会太难,也许更为简单。因为 Servlet 不用考虑图形界面的应用。与小应用程序一样,Servlet 也有一个生命周期。Servlet 的生命周期是当服务器装载运行 servlets:接收来自客户端的多个请求并且返回数据给客户端,然后再删除移开 servlets。下面详细描述如下:
1.初始化时期 当一个服务器装载 servlet 时,它运行 servlet 的 init() 方法。
public void init(ServletConfig config) throws ServletException
{
super.init(); //一些初始化的操作,如数据库的连接
}
需要记住的是一定要在 init()结束时调用 super.init()。init()方法不能反复调用,一旦调用就是重装载 servlet。直到服务器调用 destroy 方法卸载 servlet 后才能再调用。
2.Servlet 的执行时期 在服务器装载初始化 servlet 后,servlet 就能够处理客户端的请求,我们可以用 service 方法来实现。每个客户端请求有它自己 service 方法:这些方法接收客户端请求,并且发回相应的响应。Servlets 能同时运行多个 service。这是很重要的,这样,service 方法可以按一个thread-safe 样式编写。如:service 方法更新 servlet 对象中的一个字段 field,这个字段是可以同时存取的。假如某个服务器不能同时并发运行 service 方法,也可以用SingleThreadModel 接口。这个接口保证不会有两个以上的线程(threads)并发运行。在 Servlet 执行期间其最多的应用是处理客户端的请求并产生一个网页。其代码如下:
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head><title>"# Servlet </title></head>");
out.println("<body>");
out.println("Hello World");
out.println("</body></html>");
out.close();
3.Servlet 结束时期 Servlets 一直运行到他们被服务器卸载。在结束的时候需要收回在 init()方法中使用的资源,在 Servlet 中是通过 destory()方法来实现的。
public void destroy()
{
//回收在init()中启用的资源,如关闭数据库的连接等。
}
JSP 与 servlet 之间是怎样的关系?
JSP 主要关注于 HTML(或者 XML)与 Java 代码的结合,以及加入其中的 JSP 标记。如果一个支持 JSP 的服务器遇到一个 JSP 页面,它首先查看该页面是否被编译成为一个 servlet。由此可见,JSP 被编译成 servlet,即被转变为纯 Java,然后被装载入服务器执行。当然,这一过程,根据不同的 JSP 引擎而略有不同。
JSP 和 servlet 在应用上有什么区别
简单的说,SUN 首先发展出 SERVLET,其功能比较强劲,体系设计也很先进,只是,它输出 HTML 语句还是采用了老的 CGI 方式,是一句一句输出,所以,编写和修改 HTML 非常不方便。
后来 SUN 推出了类似于 ASP 的嵌套型的 JSP,把 JSP TAG 嵌套到 HTML 语句中,这样,就大大简化和方便了网页的设计和修改。新型的网络语言如 ASP,PHP 都是嵌套型的。
从网络三层结构的角度看,一个网络项目最少分三层:data layer,business layer,,presentation layer。当然也可以更复杂。
SERVLET 用来写 business layer 是很强大的,但是对于写 presentation layer 就很不方便。JSP 则主要是为了方便写 presentation layer 而设计的。当然也可以写 business layer。写惯了 ASP,PHP,CGI 的朋友,经常会不自觉的把 presentation layer 和 business layer 混在一起。比如把数据库处理信息放到 JSP 中,其实,它应该放在 business layer 中。
根据 SUN 自己的推荐,JSP 中应该仅仅存放与 presentation layer 有关的部分,也就是说,只放输出 HTML 网页的部份。而所有的数据计算、数据分析、数据库联结处理,统统是属于 business layer,应该放在 JAVA BEANS 中。通过 JSP 调用 JAVA BEANS,实现两层的整合。
实际上,微软前不久推出的 DNA 技术,简单说,就是 ASP+COM/DCOM 技术。与 JSP+BEANS 完全类似,所有的 presentation layer 由 ASP 完成,所有的 business layer 由 COM/DCOM 完成。通过调用,实现整合。
为什么要采用这些组件技术呢?因为单纯的 ASP/JSP 语言是非常低效率执行的,如果出现大量用户点击,纯 SCRIPT 语言很快就到达了他的功能上限,而组件技术就能大幅度提高功能上限,加快执行速度。
另外一方面,纯 SCRIPT 语言将 presentation layer 和 business layer 混在一起,造成修改不方便,并且代码不能重复利用。如果想修改一个地方,经常会牵涉到十几页 CODE,采用组件技术就只改组件就可以了。
综上所述,SERVLET 是一个不完善的产品,写 business layer 很好,写 presentation layer 就很逊色许多了,并且两层混杂。所以,推出 JSP+BAEN,用 JSP 写 presentation layer,用 BAEN 写 business layer。SUN 自己的意思也是将来用 JSP 替代 SERVLET。
所以,学了 JSP,不会用 JAVA BEAN 并进行整合,等于没学。
如何调用 servlet?
要调用 Servlet 或 Web 应用程序,请使用下列任一种方法:由 URL 调用、在