1.1 简介
典型的桌面应用程序的示例有记事本,媒体播放器等等。是本地.exe程序。用户和桌面程序的交互如图1.1。
图1.1 用户和桌面程序的交互
随着Internet的兴起,现在大多数电脑用户更加习惯Internet的Web应用。用户和Web应用程序的交互如图1.2所示。
图1.2 用户访问网站
Web应用程序和桌面程序相比,优点如下。
首先,Web应用程序的访问更加容易,用于访问Web应用的标准协议为HTTP协议,为绝大多数操作系统所支持。此外,所要求的客户端仅仅是浏览器。
其次,维护和部署成本低,Web应用程序在浏览器中请求运行,不需要在每个客户端系统上安装客户端软件。Web应用程序代码可以再服务器端进行修改和维护,这将节省更新和部署应用程序所需要的时间和成本。
Web应用运行在服务器上,服务器是一台设备,它为网络上的不同设备,即客户端的请求提供信息。最初,通过编写CGI(Common Gateway Interface,通用网关接口)程序来实现数据在Web上的传输,但是,对于客户端作出的每个请求,必须创建CGI程序的一个新实例,这将占用大量内存。因此,为了解决这个问题,引入了Servlet技术。
Servlet是一个用Java编写的应用程序,在服务器上运行,处理请求的信息并将其发送到客户端。Servlet的客户端可以提出请求并获得该请求的响应,它可以使任何Java应用程序、浏览器或任何设备。对于所有的客户端请求,只需要创建Servlet的实例一次,因此节省了大量的内存。Servlet在初始化后即驻留内存中,因此每次作出请求时无需加载。
1.2 HTTP基础知识
用户的请求和Web应用程序的相应需要通过Internet从一台计算机发送到另一台计算机或服务器,使用超文本传输协议HTTP。HTTP是互联网上应用最为广泛的一种网络协议,是一个客户端和服务器端请求和应答的标准。客户端是终端用户,服务器端是网站。通过使用Web浏览器等工具,客户端发起一个到服务器上指定端口的HTTP请求。应答的服务器上存储着一些资源,比如HTML文件和图像。HTTP协议并没有规定必须使用它和基于它支持的层。事实上,HTTP可以在任何其他互联网协议上,或者在其他网络上实现。HTTP只假定其下层协议提供可靠的传输,任何能够提供这种保证的协议都可以被其使用。
1.2.1 GET和POST方法区别
HTTP请求消息使用GET或POST方法以便在Web上传输请求。
检索信息时一般用GET方法,如检索文档、图表、或数据库查询结果。要检索的信息作为字符序列传递,称为查询字符串。因此,传递的数据对客户端是可见的,即将查询字符串附加到URL中,但是,查询字符串的长度有限制,最多124字节。GET方法是表单默认的方法。
我们用google检索“java”,可以知道google使用了GET方法对用户输入的搜索字符串检索搜索结果。如图1.1所示。
图1.1
HTTP定义的另一种请求方法是POST方法。使用POST发送的数据对客户端是不可见的,且对发送的数据的量没有限制。
下面我们来对比一下GET和POST方法。
GET是从服务器上获取数据;POST是向服务器传送数据。
在客户端,GET通过URL提交数据,数据在URL中可见;POST把数据放在form 的数据体内提交。
GET提交的数据最多只有1024字节;POST提交的数据量无限制。
由于使用GET时,参数会显示在地址栏上,而POST不会,所以,如果这些数据是非敏感数据,那么使用GET;如果包含敏感数据,为了安全,用POST。
1.3 Servlet简介和优点
自427年1月Sun Microsystems公司所组成的JavaSoft部门将Servlet API定案以来,推出了Servlet API1.0,就当时功能来说,Servlet所提供的功能包含了当时的CGI与Netscape Server API(NSAPI)之类产品的功能。发展至今,它依旧是一个具有跨平台特性、10% Pure Java的Server-Side程序,Servlet不只限定于HTTP协议,开发人员可以利用Servlet自定义或延伸任何支持Java的Server,包括Web Server、Mail Server、Ftp Server、Application Server或任何自定义的Server。
Server有以下优点:
可移植性,Servlet皆是利用Java语言来开发的,因此,延续Java在跨平台上的表现,不论Server的操作系统是什么,Windows、Linux、Solaris、HP-UX等,都能够将我们写好的Servlet程序放在这些操作系统上执行,借助Servlet的优势,就可以真正达到Write Once,Serve Anywhere的境界。Servlet是在Server端执行的,所以,程序员只要专心开发能在实际应用的平台环境下测试无误即可。除非从事做Servlet Container的公司,否则不须担心写出来的Servlet是否能在所有的Java Server平台上执行。
强大的功能,Servlet能够完全发挥Java API的威力,包括网络和URL存取、多线程、影像处理、RMI(Remote Method Invocation)、分布式服务器组件、对象序列化等。若想写个网络目录查询程序,则可以利用JNDI API,相连接数据库可以用JDBC,偶这些强大功能的API做后盾,相信Servlet更能发挥其优势。
性能,Servlet在加载执行后,其对象实体通常会一直停留在Server的内存中,若有请求发生时,服务器再调用Servlet来服务,假若收到相同服务的请求时,Servlet会利用不同的线程来处理,不像CGI程序必须产生许多进程来处理数据。在性能表现上,大大超过CGI程序。Servlet在执行时,不是一直停留在内存中,服务器会自动将停留时间过长一直没有执行的Servlet从内存中移除,不过有时候也可以自行写程序来控制,至于停留时间长短通常和选用的服务器有关。
安全性,Servlet也有类型检查的特性,并且利用Java的垃圾回收与没有指针的设计,使得Servlet避免内存管理的问题。由于在Java的异常处理机制下,Servlet能够安全地处理各种错误,不会因为发生程序上逻辑错误而导致整体服务器系统的崩溃。例如,某个Servlet发生除以零或其他不合法的运算时,会抛出一个异常让服务器处理,如记录在Log日志中。
1.4 第一个Servlet例程
我们现在来创建一个简单的Servlet:FirstServlet类,功能只是输出“Hello!大家好!”。代码如例1.1。
/*
* FirstServlet.java
* 2002-06-16
* 功能:通过Servlet输出页面
*/
package com.jy.sample.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
*HelloWorld Servlet.
*@author JY
*/
public class FirstServlet extends HttpServlet {
/**serialVersionUID.*/
private static final long serialVersionUID = 217251451801586160L;
@Override
protected void doGet(HttpServletRequest req,
HttpServletResponse resp)
throws ServletException, IOException {
// 设定内容类型为HTML网页UTF-8编码
resp.setContentType("text/html;charset=UTF-8");
// 输出页面
PrintWriter out = resp.getWriter();
out.println("
");out.println("
out.println("
");out.println("Hello!大家好!");
out.println("");
out.close();
}
}
例1.1
下面我们来看看这段代码,一开始我们必须导入javax.servlet.*和javax.servlet.http.*。其中,javax.servlet.* 存放与HTTP协议无关的一般性Servlet类;javax.servlet.http.* 增加了与HTTP协议有关的功能。
所有Servlet都必须实现javax.servlet.Servlet接口,但是通常我们都会从javax.servlet.GenericServlet或javax.servlet.http.HttpServlet择一来实现。如果写的Servlet代码和HTTP协议无关,那么必须继承GenericServlet类;若有关,就必须继承HttpServlet类。我们的例子中继承的是HttpServlet类。
javax.servlet.* 里面的ServletRequest和ServletResponse接口提供存取一般的请求
和响应;而javax.servlet.http.* 里面的HttpServletRequest和HttpServletResponse接口,则提供HTTP请求及响应的存取服务。通过代码了解到,我们代码中用到的是HttpServletRequest和HttpServletResponse。
我们的代码中,利用HttpServletResponse接口的setContentType()方法来设定内容类型,我们要显示为HTML网页类型,因此,内容类型设为“text/html”,这是HTML 网页的标准MIME类型值。之后,用getWriter()方法返回PrintWriter类型的out对象,它与PrintStream类似,但是它能够对Java的Unicode字符进行编码转换。最后,利用out对象把“Hello!大家好!”的字符串显示在网页上。
代码写好后,我们来设定web.xml文件,web.xml文件在我们Web项目的WEB-INF 文件夹内。如图1.4。
图1.4
我们来详细看一看web.xml中这段关于Servlet的配置。配置一个Servlet需要配置两个标签,第一个
对于
对于
当我们的页面中设定的连接和
最后,我们看看FirstServlet的执行结果,如图1.5所示。
图1.5
1.4.1 Servlet应用程序体系结构
Servlet容器将Servlet动态地加载到服务器上。HTTP Servlet使用HTTP请求和HTTP响应标题与客户端进行交互。因此Servlet容器支持请求和相应所用的HTTP协议。Servlet应用程序体系结构如图1.6所示。
图1.6 Servlet应用程序体系结构
图1.6说明客户端对Servlet的请求首先会被HTTP服务器接收,HTTP服务器将客户的HTTP请求提交Servlet容器,Servlet容器调用相应的Servlet,Servlet作出的响应传递到Servlet容器,并进而由HTTP服务器将响应传输给客户端。Web服务器提供静态内容并将所有客户端对Servlet作出的请求传递到Servlet容器。
我们已经学习过T omcat,它是一个小型的轻量级应用服务器,在中小型系统和并发用户不是很多的情况下被广泛应用,和IIS、Apache一样,具有处理HTML的功能(但处理静态HTML的能力不如Apache强),同时,它还是一个Servlet和JSP容器,开发和调试JSP、Servlet的首选。对于图1.6,T omcat就是HTTP服务器和Servlet容器两个部分。
1.4.2 Servlet层次结构
Servlet是实现javax.servlet.Servlet接口的对象。大多数Servlet通过从
GenericServlet或HttpServlet类进行扩展来实现。Servlet API包含于两个包中,即javax.servlet和javax.servlet.http。下边我们分别来介绍。
javax.servlet
接口
ServletConfig 定义了在Servlet初始化的过程中由Servlet容器传递给Servlet
的配置信息对象
ServletContext 定义Servlet使用的方法以获取其容器的信息ServletRequest 定义一个对象封装客户向Servlet的请求信息ServletResponse 定义一个对象辅助Servlet将请求的响应信息发送给客户端Servlet 定义所有Servlet必须实现的方法
类
ServletInputStream 定义名为readLine()的方法,从客户端读取二进制数据ServletOutputStream 向客户端发送二进制数据
GenericServlet 抽象类,定义一个通用的、独立于底层协议的Servlet javax.servlet.http
接口
HttpSession 用于标识客户端并存储有关客户端的信息HttpSessionAttributeListener 这个侦听接口用于获取会话的属性列表的改变的通知HttpServletRequest 扩展ServletRequest接口,为HTTP Servlet提供
HTTP请求信息
HttpServletResponse 扩展ServletResponse接口,提供HTTP特定的发送
响应的功能
类
HttpServlet 扩展了GenericServlet的抽象类,用于扩展创建Http
Servlet
Cookie 创建一个Cookie,用于存储Servlet发送给客户端的
信息
在这里,我们需要详细了解下HttpServletRequest获得参数名和参数值的方法。getParameter(String key) 返回一个字符串,获得name和key一样的表单控件
的数据,如果有重复的name,则返回第一个的值。getParameterValues(String key) 返回一个字符串数组,获得name和key一样的表单
控件的数据,但相同name的控件会有多个,如同名
的多个checkbox等。
getParameterMap() 返回一个包含所有参数的Map,为key-String[]模
式,即,key是表单控件的name,同时,为了防止有
重复name的控件存在,每个name对应的值是一个
字符串数组。
getParameterNames() 返回一个枚举类型值,返回所有表单中所有表看控件
的name。
图1.2
1.5 Servlet的生命周期
这一节我们来讲讲Servlet的生命周期,Servlet的生命周期如图1.1所示。
图1.1 Servlet的生命周期
Servlet运行在Servlet容器中,其生命周期由容器来管理。Servlet的生命周期通过javax.servlet.Servlet接口中的init()、service()和destroy()方法来表示。
Servlet的生命周期包含了下面4个阶段:
加载和实例化
Servlet容器负责加载和实例化Servlet。当Servlet容器启动时,或者在容器检测到需要这个Servlet来响应第一个请求时,创建Servlet实例。当Servlet容器启动后,它必须要知道所需的Servlet类在什么位置,Servlet容器可以从本地文件系统、远程文件系统或者其他的网络服务中通过类加载器加载Servlet类,成功加载后,容器创建Servlet的实例。因为容器是通过Java的反射API来创建Servlet实例,调用的是Servlet的默认构造方法(即不带参数的构造方法),所以我们在编写Servlet类的时候,不应该提供带参数的构造方法。
初始化
在Servlet实例化之后,容器将调用Servlet的init()方法初始化这个对象。初始化的目的是为了让Servlet对象在处理客户端请求前完成一些初始化的工作,如建立数据库的连接,获取配置信息等。对于每一个Servlet实例,init()方法只被调用一次。在初始化期间,Servlet实例可以使用容器为它准备的ServletConfig对象从Web应用程序的配置信
息(在web.xml中配置)中获取初始化的参数信息。这样servlet的实例就可以把与容器相关的配置数据保存起来供以后使用,在初始化期间,如果发生错误,Servlet实例可以抛出ServletException异常,一旦抛出该异常,servlet就不再执行,而随后对它的调用会导致容器对它重新载入并再次运行此方法。
请求处理
Servlet容器调用Servlet的service()方法对请求进行处理。要注意的是,在service()方法调用之前,init()方法必须成功执行。在service()方法中,通过ServletRequest对象得到客户端的相关信息和请求信息,在对请求进行处理后,调用ServletResponse对象的方法设置响应信息。对于HttpServlet类,该方法作为HTTP请求的分发器,这个方法在任何时候都不能被重载。当请求到来时,service()方法决定请求的类型(GET、POST、HEAD、OPTIONS、DELETE、PUT、TRACE),并把请求分发给相应的处理方法(doGet()、doPost()、doHead()、doOptions()、doDelete()、doPut()、doTrace())每个do方法具有和第一个service()相同的形式。我们常用的就是doGet()和doPost()方法,为了响应特定类型的HTTP请求,我们必须重载相应的do方法。如果Servlet收到一个HTTP请求而你没有重载相应的do方法,它就返回一个说明此方法对本资源不可用的标准HTTP错误。
服务终止
当容器检测到一个Servlet实例应该从服务中被移除的时候,容器就会调用实例的destroy()方法,以便让该实例可以释放它所使用的资源,保存数据到持久存储设备中。当需要释放内存或者容器关闭时,容器就会调用Servlet实例的destroy()方法。在destroy()方法调用之后,容器会释放这个Servlet实例,该实例随后会被Java的垃圾收集器所回收。如果再次需要这个Servlet处理请求,Servlet容器会创建一个新的Servlet实例。在整个Servlet的生命周期过程中,创建Servlet实例、调用实例的init()和destroy()方法都只进行一次,当初始化完成后,Servlet容器会将该实例保存在内存中,通过调用它的service()方法,为接收到的请求服务。
1.6 总结
HTTP协议定义了GET和POST两种请求方法,POST方法对请求发送的数据量没有限制。
Servlet允许用户在服务器上运行Java代码和生成动态内容。
Servlet运行于Servlet容器中。
扩展HttpServlet类的Servlet必须覆盖如下至少一个方法:doGet、soPost、doPut、doDelete、init、destroy和getServletInfo。
Servlet声明周期包含三种方法:init()、service()和destroy()。
Servlet API包含在两个包中,javax.servlet和javax.servlet.http。
通过从GenericServlet类或HttpServlet类扩展,可以编写Servlet。
第一章 Tomcat概述 一、Tomcat简介 TOMCAT是APACHE JAKARTA软件组织的一个子项目,TOMCAT是一个JSP/SERVLET容器,它是在SUN公司的JSWDK(JAVA SERVER WEB DEVELOPMENT KIT)基础上发展起来的一个JSP和SERVLET规范的标准实现,使用TOMCAT可以体验JSP和SERVLET的最新规范。经过多年的发展,TOMCAT不仅是JSP和SERVLET规范的标准实现,而且具备了很多商业JAVA SERVLET容器的特性,并被一些企业用于商业用途。 1、Tomcat Tomcat在严格意义上并不是一个真正的应用服务器,它只是一个可以支持运行Serlvet/JSP 的Web容器,不过Tomcat也扩展了一些应用服务器的功能,如JNDI,数据库连接池,用户事务处理等等。Tomcat 是一种具有JSP环境的Servlet容器。Servlet容器是代替用户管理和调用Servlet的运行时外壳。 1.1 SERVLET容器 负责处理客户请求。当客户请求来到时,SERVLET容器获取请求,然后调用某个SERVLET,并把SERVLET的执行结果返回给客户。 当客户请求某个资源时,SERVLET容器使用SERVLETREQUEST对象把客户的请求信息封装起来,然后调用JAVA SERVLET API中定义的SERVLET的一些生命周期方法,完成SERVLET的执行,接着把SERVLET执行的要返回给客户的结果封装到SERVLETRESPONSE对象中,最后SERVLET容器把客户的请求发送给客户,完成为客户的一次服务过程。 1.2 TOMCAT的工作模式 1.2.1 独立的SERVLET容器 TOMCAT的默认工作模式,作为独立的SERVLET容器,是内置在WEB服务器中的一部分,是指使用基于JAVA的WEB服务器的情形。 其他两种方式是TOMCAT与其他服务器集成的方式: 1.2.2 进程内的SERVLET容器 SERVLET容器作为WEB服务器的插件和JAVA容器的实现。WEB服务器的插件在内部地址空间打
How Tomcat Works中文版 介绍 概要 欢迎阅读《How Tomcat Works》这本书。这本书解剖了Tomcat4.1.12和5.0.18版本,解释了它的servlet容器的内部运行机制,那是一个免费的,开源的,最受欢迎的servlet容器,代号为Catalina。Tomcat是一个复杂的系统,由许多不同的组件构成。那些想要学习Tomcat运行机制的朋友大部分知道从何入手。这本书会提供一个蓝图,然后为每一个组件构造一个简化版本,使得可以更加容易的理解这些组件。在这之后才会对真实的组件进行解释。 你应该从这份简介开始阅读,因为它解释了这本书的结构,同时给你勾画了这个项目构造的简洁轮廓。“准备前提软件”这一节会给你一些指示,例如你需要下载什么样的软件,如何为你的代码创建目录结构等等。 本书为谁而作 这本书是为任何一个使用Java技术进行工作的人而准备的。 ?假如你是一个servlet/jsp程序员或者一个Tomcat用户,而且对一个servlet容器是如何工作这个问题你感兴趣的话,这本书就是为你准备 的。 ?假如你想加入Tomcat的开发团队的话,这本书就是为你准备的,因为你首先需要学习那些已存在的代码是如何工作的。 ?假如你从未涉及web开发,但你对一般意义上的软件开发感兴趣的话,你可以在这本书学到一个像Tomcat一样的大型项目是如何进行设计和开发 的。 ?假如你想配置和自定义Tomcat,你也应该读读这本书。
为了理解书中的讨论,你需要了解Java面向对象编程技术以及servlet编程。假如你对这些不熟悉的话,这里有很多书籍可以参考,包括Budi的《Java for the Web with Servlets, JSP, and EJB》。为了让这些材料更容易理解,每一章开始都会有便于理解所讨论主题的必要的背景资料介绍。 Servlet容器是如何工作的 servlet容器是一个复杂的系统。不过,一个servlet容器要为一个servlet 的请求提供服务,基本上有三件事要做: ?创建一个request对象并填充那些有可能被所引用的servlet使用的信息,如参数、头部、cookies、查询字符串、URI等等。一个 request对 象是javax.servlet.ServletRequest或 javax.servlet.http.ServletRequest 接口的一个实例。 ?创建一个response对象,所引用的servlet使用它来给客户端发送响应。 一个response对象 javax.servlet.ServletResponse或 javax.servlet.http.ServletResponse接口的一个实例。 ?调用servlet的service方法,并传入request和response对象。在这里servlet会从request对象取值,给 response写值。 当你读这些章节的时候,你将会找到关于catalina servlet容器的详细讨论。 Catalina架构图 Catalina是一个非常复杂的,并优雅的设计开发出来的软件,同时它也是模块化的。基于“Servlet容器是如何工作的”这一节中提到的任务,你可以把Catalina看成是由两个主要模块所组成的:连接器(connector)和容器(container)。在Figure I.1中的架构图,当然是简化了。在稍后的章节里边,你将会一个个的揭开所有更小的组件的神秘面纱。 现在重新回到Figure I.1,连接器是用来“连接”容器里边的请求的。它的工作是为接收到每一个HTTP请求构造一个request和response对象。然后它把流程传递给容器。容器从连接器接收到requset和response对象之后调用servlet的service方法用于响应。谨记,这个描述仅仅是冰山一角而已。这里容器做了相当多事情。例如,在它调用servlet的service方法之前,它必须加载这个servlet,验证用户(假如需要的话),更新用户会话等等。一个容器
第1章 Java语言概述与面向对象思想 1 1.1 Java语言的发展 1 1.1.1 Java语言的产生 1 1.1.2 Java语言的发展 1 1.2 Java语言的特点 2 1.3 面向对象与面向过程的差异 3 1.3.1 面向过程思想回顾 4 1.3.2 面向对象思想介绍 4 1.4 面向对象程序设计中的主要概念和特征 4 1.4.1 主要概念 5 1.4.2 主要特征 5 *1.5 Java与C++的差异 5 1.6本章小结5 习题 5 第2章 Java语言开发环境 6 2.1 JDK 6 2.1.1 JDK的简介6 2.1.2 JDK的构成6 2.1.3 JDK的使用6 2.2 IDE 8 2.2.1 IDE简介8 2.2.2 JBuilder 9 2.2.3 Eclipse 9 2.2.4 相关资源9 2.3 Project管理9 2.3.1 Project的含义9 2.3.2 可行的Project组织模式9 2.3.3 主要开发工具的Project目录10 2.4 本章小结10 习题10 第1章 Java语言概述与面向对象思想 1.1 Java语言的发展 1.1.1 Java语言的产生以介绍面向对象编程的基本概念、基本理论为重点,结合Java语言的语法规则、编程特点和设计思想、强调容易发生错误和编程应注意的地方,使学生能对Java 技术有一个总体了解,通过本课程学习,使学生掌握Java语言的基础知识,理解和掌握面向对象程序设计的基本思想,熟练地使用Java语言进行程序的编写、编译以及调试工作 上世纪90年代初期,Sun公司在研究一种适用于未来的智能设备的编程语言,该语言要具有一些新的特性,以避免C++的一些不足。 该语言起初命名为Oak,来源于语言作者Gosling办公室窗外的一棵橡树(Oak)。后来在注册时候遇到了冲突,于是就从手中的热咖啡联想到了印度尼西亚一个盛产咖啡的岛屿,中文名叫爪哇,Java语言得名于此。 随着Internet的迅速发展,Web应用日益广泛,Java语言也得到了迅速发展。1994年,Gosling
用Servlet 进行文件上传的原理和实现 Servlet 是用 Java 编写的、协议和平台都独立的服务器端组件,使用请求/响应的模式,提供了一个基于 Java 的服务器解决方案。使用 Servlet 可以方便地处理在 HTML 页面表单中提交的数据,但 Servlet 的 API 没有提供对以 mutilpart/form-data 形式编码的表单进行解码的支持,因而对日常应用中经常涉及到到文件上传等事务无能为力。 如何用 Servlet 进行文件的上传,必须编程实现。 一、基本原理 通过 HTML 上载文件的基本流程如下图所示。 浏览器端提供了供用户选择提交内容的界面(通常是一个表单),在用户提交请求后,将文件数据和其他表单信息编码并上传至服务器端,服务器端(通常是一个 cgi 程序)将上传的内容进行解码了,提取出 HTML 表单中的信息,将文件数据存入磁盘或数据库。 二、各过程详解 A)填写表单并提交
通过表单提交数据的方法有两种,一种是 GET 方法,另一种是 POST 方法,前者通常用于提交少量的数据,而在上传文件或大量数据时,应该选用 POST 方法。在 HTML 代码中,在