Servlet开发基础笔记

来源:互联网 发布:凶暴的男人知乎 编辑:程序博客网 时间:2024/05/01 05:51

Servlet开发基础

一、        Servlet的相关概念与前置知识

    1.       什么是动态网页

    n 如果浏览器在不同时刻或不同条件下访问WEB服务器上的某个页面,浏览器所获得的页面内容可以发生变化,那么这个页面就称之为动态网页。

    n 要想让浏览器访问某一WEB页面时,能够查询出一些动态变化的实时信息,例如,某日某次列车的车票剩余状况,浏览器在不同时刻所得的Web页面的内容必须随着车票的生育状况进行变化,这就必须采用动态网页来实现。

    n 浏览器只关心如何显示和处理WEB服务器所返回的内容,浏览器处理动态网页的方式与它处理静态网页的方式完全相同,并无差异。

    n WEB服务器发送的静态内容直接来自于文本或数据文件,而动态内容需要依靠一个程序来历史产生。

    2.       动态网页程序与引擎

    n 动态网页内容的创建过程包括两个步骤:

                    i.首先使用某种编程语言编写相应的动态网页程序;

                    ii.然后由一个专门的WEB服务器程序模块来解释执行该动态网页程序。

        n  在动态网页程序的代码中可以完成各种程序逻辑控制、获取客户端传递的数据、对数据库进行操作、创建输出内容等功能,Web程序开发就是指使用某种编程语言来编写完成上述功能的动态网页程序。

    n  动态网页程序需要有一个专门的WEB服务器程序模块来解释执行,专门解释和执行某种动态网页程序的WEB服务器程序模块习惯上被称为引擎,譬如ASP引擎、Servlet引擎、JSP引擎等等。

    n  只有引擎会与浏览器直接进行信息交换,动态网页程序不直接与浏览器进行信息交换,动态网页程序只与引擎进行信息交换,由引擎将浏览器的信息传递给动态网页程序和将动态网页程序生成的结果回送给浏览器。

        n  引擎提供的API有两个基本的作用:一些API用于将访问请求的相关信息传递给动态网页程序;另一些API将动态网页程序产生的结果传递给引擎。

浏览器、引擎、API和动态网页程序之间的关系

        n  客户端想WEB服务器请求的URL资源路径,不仅可以指向服务器端的一个静态HTML文件,还可以指向服务器端的某种被解释运行的程序文件。

        n  如果客户端请求的URL后缀名符合某种引擎所处理的资源名的特征,WEB服务器将把请求转交给相应的引擎去处理,然后由引擎去调用某个程序文件,并将程序动态产生的内容返回给客户端。

        n  动态网页程序文件中的代码不仅可以创建出用于返回给浏览器的动态变化内容,还可以实现对数据库的插入、修改、删除和查询等操作、从而让网站可以实现论坛交流,产品订购、问卷调查、甚至是企业的整个管理信息系统等功能。

        n  目前有不少公司提供了动态网页的解决方案,称之服务器端的WEB编程技术,常见的技术有CGIISAPIASP.NETServlet/JSPPHP等,这些技术分别使用不同的编程语言。

     3.Servlet技术简介

             n  Servlet技术是Sun公司提供的一种实现动态网页的解决方案,它是基于Java编程语言的WEB服务器端编程技术。

             n  Servlet技术也是JSP技术(另外一种动态网页开发技术)的基础。

    n  一个Servlet程序就是一个实现了特殊接口的Java类,它由支持Servlet(具有Servlet引擎)的WEB服务器调用和启动运行。一个Servlet程序负责处理它所对应的一个或一组URL地址的访问请求,并接受客户端发出的服务请求信息和产生响应内容。

             n  Applet是用于浏览器端的Java小程序,Servlet是用于WEB服务器端的Java小程序。

             n  Servlet程序可以完成普通Java程序所能完成的大多数任务:

                    i. 获取客户端通过HTMLFORM表单提交的数据和URL后面的参数信息

                    ii.创建对客户端的响应消息内容

                    iii.访问服务器端的文件系统

                    iv.连接数据库并开发基于数据库的应用

                    v.调用其他的Java

    4.       B/S系统结构与C/S系统结构

    n 企业信息管理软件系统的一个重要特点就是:要使用多台计算机作为操作终端,而系统的数据信息集中存放在网络上的数据库服务器中。

    n 在开发企业信息管理软件时,人们通常需要在两种系统结构之间进行选择,即C/S架构和B/S架构。

    n C/S架构是Client/Server的简写,也是客户机/服务器架构,它是早期出现的一种分布式架构。

    n B/S架构是Browser/Server的简写,也就是浏览器/服务器架构,它是随着Internet技术的兴起,对C/S架构的一种变化和改进的架构。

C/S架构

C/S系统架构的特点

            缺点:

                             i.数据库系统支持的并发连接数有限,限制了同时运行的客户端程序的数目。

                            ii.业务逻辑处理和界面显示都由客户端程序负责出来,一旦业务逻辑或者显示界面要发生变化,则需要对整个客户端程序进行修改,不利于软件的维护和功能扩展。

                           iii.每个客户机上都需要安装客户端程序,对于大一点的企业来说,如果客户端程序发生了修改,则需要系统管理人员到几百甚至上千台客户机上去重新安装客户端程序。

            优点:

                客户端程序就是计算机上的一个桌面程序,功能可以做到非常强大,例如,在数据库服务器不可用时仍可以独立运行,可以将事务记录保存在本地桌面数据库中后再集中向数据库服务器,很容易对数据库中的数据进行实时监控和实现报警功能。

B/S系统架构

B/S系统架构的优点

        • B/S架构将程序中的界面显示和业务逻辑处理都移动到了WEB服务器中来实现,其应用全部集中到了WEB服务器端,客户端只需要具有浏览器就可以作为B/S架构的操作终端,而不用安装和部署如何程序。

        • B/S架构中的用户操作界面是由WEB服务器创建的,当要修改系统提供的用户操作界面时,只需要在WEB服务器端修改相应的网页文档,整个系统的更新部署不需要在客户机上进行任何操作和设置,在用户的不知不觉中就迅速完成,可以做到快速服务响应。

        • 客户端不直接与数据库建立连接,而是只有Web服务器端的程序需要与数据库建立连接,所以数据库并发连接数量有限的问题也得到了解决。

        • B/S架构应作为各类信息管理系统的首选体系架构,它基本上已全面取代了C/S架构。

        Servlet应用入门

  • Servlet API介绍

  • Servlet APIServlet Application Programming Interface)是Sun公司定义的一套专门用于开发Servlet程序的Java类和接口。

  • 早期包装Servlet APIjar包被称之为JSDKJava Servlet Development Kit,即Java Servlet开发工具包),最新版本的Java Servlet开发工具包已经被集成到Sun公司的Java EEJ2EE升级后的名称,即Java企业级版本)开发工具包中。

  • 应结合Servlet API 帮助文档来学习和应用Servlet API,边学边查,边用边查。必须了解HTTP协议和WEB服务器的内部运行方式、以及Servlet引擎的一些实现机制后,才能够在看懂帮助文档中的英文单词的基础上去了解和掌握一些Servlet API的用途与用法,才能够使用Servlet来实现一些特殊的WEB功能。

  • 编写与编译Servlet程序

  • 一个Servlet程序就是一个实现了Javax.servlet.Servlet接口的Java类,Servlet接口定义了Servlet引擎与Servlet程序之间通信的协议约定。

  • Javax.servlet.GenericServlet类实现了Servlet接口,它实现了Servlet程序的基本特征和功能。

  • Javax.servlet.http.HttpServlet类是GenericServlet的子类,它在GenericServlet类的基础上进行了一些针对HTTP特点的扩充。

  • 客户端每次访问一个支持HTTPServlet程序事Servlet引擎都将调用Servletservice方法来进行处理。Service方法接受两个参数,一个是用于封装HTTP请求消息的对象,其类型为HttpServletRequest,另一个是代表HTTP响应消息的对象,其类型为HttpServletResponse

  • 调用HttpResponse对象的getWriter方法可以获得一个文本输出流对象,向这个流对象中写入的数据将作为HTTP响应消息的实体内容部分发送给客户端。

import java.io.*;

import javax.servlet.*;

import javax.servlet.http.*;

public class HelloServlet extends HttpServlet {

         public void service(HttpServletRequest request, HttpServletResponse response)

                            throws IOException, ServletException {

                   PrintWriter out = response.getWriter();

                   out.println("<html>");

                   out.println("<font size=30 color=red>www.baidu.com</font><br>");

                   out.println("<marquee>" + new java.util.Date() + "</marquee>");

                   out.println("</html>");

         }

}

  1. 3.       Servlet的注册与运行

  2. n Servlet程序必须通过Servlet引擎来启动运行,并且储存目录有特殊要求,通常需要存储在<WEB应用程序目录>\WEB-INF\classes\目录中。

  3. n Servlet程序必须在WEB应用程序的web.xml文件中进行注册和映射其访问路径,才可以被Servlet引擎加载和被外界访问。

  4. n 一个<Servlet>元素用于注册一个Servlet,它包含有两个主要的子元素:<servlet-name><servlet-class>,分别用于设置Servlet的注册名称和Servlet的完整类名。

  5. n 一个<servlet-mapping>元素用于映射一个已注册的Servlet的一个对外访问路径,它包含有两个子元素:<servlet-name><servlet-pattern>,分别用于指定Servlet的注册名称和Servlet的对外访问路径。

Servlet映射的细节

  • 同一个Servlet可以被映射到多个URL上,即多个<servlet-mapping>元素的<servlet-name>子元素的设置值可以是同一个Servlet的注册名。

  • Servlet映射到的URL中也可以使用*通配符,但是只能杨浦两种固定的格式:一种格式是“*.扩展名”,另一种是以正斜杠(/)开头并以“/*”结尾。

Servlet映射的最具体匹配原则

对于如下的一些映射关系:

  • /abc/*      映射到 Servlet1

  • /*               映射到 Servlet2

  • /abc          映射到 Servlet3

  • *.do          映射到 Servlet4

将发生如下一些行为:

  • 当请求URL为“/abc/a.html”,“/abc/*”和“/*”都可以匹配这个URLServlet引擎将调用Servlet1

  • 当请求URL为“/abc”时,“/abc/*”和“/abc”都可以匹配这个URLServlet引擎将调用Servlet3

  • 当请求URL为“/abc/a.do”时,“/abc/*”和“*.do”都可以匹配这个URLServlet引擎将调用Servlet1。(“*.扩展名”的匹配优先级最低)

  • 当请求URL为“/a.do”时,“/*”和“*.do”都可以匹配这个URLServlet引擎将调用Servlet2

  • 当请求URL为“/xxx/yyy/a.do”时,“/*”和“*.do”都可以匹配这个URLServlet引擎将调用Servlet2

特别提醒:

  • 映射URL不能设置为“/action/*.xx

  • Servlet程序不能被设置为Web应用程序的目录默认网页文档

  • 缺省Servlet

  • 如果某个Servlet的映射路径仅仅为一个正斜杠(/),那么这个Servlet就成为当前Web应用程序的缺省Servlet

  • 凡是在web.xml文件中找不到匹配的<sservlet-mapping>元素的URL,它们的访问请求都将交给缺省Servlet处理,也就是说,缺省Servlet用于处理所有其他Servlet都不处理的访问请求。

  • <tomcat的安装目录>\conf\web.xml文件中,注册了一个名称为org.apache.actalina.servlets.DefaultServletServlet,并将这个Servlet设置为缺省Servlet

  • 当访问Tomcat服务器中的某个静态HTML文件和图片时,实际上是在访问这个缺省Servlet

  • Servlet的类装载器

  • Java虚拟机使用每一个类的第一件事情就是将该类的字节码装载进来,装载类字节码的功能由类装载器完成的,类装载器负责根据一个类的名称来定位和生成类的字节码数据后返回给Java虚拟机。

  • 类装载器本身也是一个Java类,Java虚拟机也允许开发人员编写自己的类装载器,以便通过其他各种特殊方式来产生类字节码。

  • 不管类装载器采用什么方式,只要能够在内存中制造出给Java虚拟机调用类字节码即可,所以,把类装载器描述为类字节码的制造器更容易让人理解。

  • 当一个类被加载后,Java虚拟机将其编译为可执行代码存储在内存中,并将索引信息存储进一个HashTable中,其索引关键字为与之相对应的类名。

  • Java程序中的类本身也是一种事物,它也可以用一个Java类描述,这个特殊的类名就叫Class、类装载器装载某个类的字节码呃过程实际上就是在创建Class类的一个实例对象,这个Class类的实例对象的内容正好是当前加载的类的字节码数据。

  • 要想在程序中获得代表某个类的字节码数据的Class实例对象,可以采用下面三种方式:

  • 类名.class,例如,Syetem.class

  • 对象.getClass(),例如,new Date().getClass()

  • Class.forName(“类名”),例如,Class.forName(“java.util.Date”)

  • Java类库中提供了一个java.lang.ClassLoader来作为类装载器的基类,Java虚拟机和程序都调用ClassLoader类的loadClass方法来加载类,ClassLoader是一个抽象类,真正的类装载器必须是ClassLoader的子类。

  • Class类中定义了一个getClassLoader方法,用于返回它所描述的类的类装载器对象,这个返回对象的类型就是ClassLoader

类装载器的基本策略

  • 一个类装载器本身也是一个Java类,所以,类装载器自身也需要被另一个类装载器装载。

  • Java虚拟机中内嵌了一个成为Bootstrap的类装载器,它属于Java虚拟机的内核,不用类装载器。Bootstrap类装载器负责加载Java核心包中的类(即rt.jar文件中的类),这些类的Class.getClassLoader方法返回值为null,即表示是Bootstrap类装载器。

  • ExtClassLoader类装载器负责加载存放在<JAVA_HOME>/jre/lib/ext目录下的jar包中的类,AppClassLoader负责加载应用程序的启动执行类。

类装载器的委托模式

  • 一个Java虚拟机中的所有类装载器采用具有父子关系的树形结构进行组织,在实例化每个类装载器对象是,需要为其指定一个父级类装载器对象,如果没有指定的话,则以ClassLoader.getSystemClassLoader()方法返回的系统类装载器作为其父级类装载器对象。

  • 系统类装载器通常被设置为启动应用程序的AppC,可以通过java.system.class.loader系统属性来将系统类装载器设置为其他类装载器。ExtClassLoaderAppClassLoader父级类装载器,ExtClassLoader没有父级类装载器。

  • 每个ClassLoader本身只能分别加载特定位置和目录的类,但是,ClassLoader被设计成了一种委托模式,使得某一个ClassLoader可以委托它的父级类装载器去加载类,从而让应用程序可以借助某一个子级的ClassLoader去多个位置和目录中进行了的加载。

  • 当药加载一个类时,ClassLoaderloadClass方法先查找这个类是否已被加载,如果没有加载则委托其父级类装载器去加载这个类,如果父级的类装载器无法加载这个类,子级类装载器才调用自己内部的findClass方法去进行真正的加载。委托过程会一直追溯到Bootstrap类装载器,如果委托过程中的所有类装载器都不能完成类的装载,最终就会报告ClassNotFoundException异常。

  • 一个类装载器只能创建某个类的一份字节码数据,即只能为某个类创建一个与之对应的Class实例对象。在一个Java虚拟机智能光可以存在对个类装载器,每个类装载器都拥有自己的名称空间,对于同一个类,每个类装载器都可以创建出它的一个Class实例对象。

  • 采用委托模式避免了一个Java虚拟机中的多个类装载器为同一个类创建多份字节码数据的情况。只要开发人员自定义的类装载器不覆盖ClassLoaderloadClass方法,而是覆盖其findClass方法,这样就可以继续采用委托模式。

线程中的类装载器

  • 如果在类A中使用new关键字创建类BJava虚拟机将使用加载类A的类装载器来加载类B。如果在一个类中调用Class.forName方法来动态加载另外一个类,可以通过传递给Class.forName方法的一个参数来指定另外那个类的类装载器,如果没有指定该参数,则使用加载当前类的类装载器。

  • 依据一个类的存放位置,这个类最终只能由一个特定的类装载器装载。对于一个已被父级类装载器装载的类来说,Java虚拟机默认也使用这个父级类装载器去装载它所调用的其他类,由于父级类装载器不会委托子级类装载器去装载类,所以,在一般情况下,一个人已被父级类装载器装载的类无法调用那些只能被子级类装载器发现和装载的其他类。

  • 每个运行中的线程都有一个关联的上下文类装载器,可以使用Tread.setContexrClassLoader()方法设置线程的上下文类装载器。

  • 每个线程默认的上下文类装载器是其父线程的上下文类装载器,而主线程的类装载器初始被设置为ClassLoader.getSystemClassLoader()方法返回的系统类装载器。

  • 当线程运行的代码需要使用某个类时,它使用上下文类装载器来装载这个类,上下文类装载器首先会委托它的父级类装载器来装载这个类,如果父级的类装载器无法装载时,上下文类装载器才自己进行装载。

Tomcat中的类装载器(6.0版本后没有commonshare文件)

                           

  • BootstrapJava虚拟机内嵌的类装载器与ExtClassLoader的总称,负责加载Java核心包中的类和存放在<JAVA_HOME>/jre/lib/ext目录下的类。

  • System即系统类装载器,通常情况下就是AppClassLoader,负责加载CLASSPATH环境变量设置的目录中的类。Tomcat不会继承操作系统上原来设置好的CLASSPATH环境变量的内容,而是将CLASSPATH环境变量重新设置为仅包含如下两个jar包:

  • <CATALINA_HOME>/bin/bootstrap.jar

  • <JAVA_HOME>/lib/tools.jar

  • Common类装载器负责从<CATALINA_HOME>/common/classes中的.class类文件和<CATALINA_HOME>/common/lib中的jar包加载类。

  • Catalina类装载器负责从<CATALINA_HOME>/server/classes中的.class类文件和<CATALINA_HOME>/server/lib中的jar包加载类。

  • Shared类装载器负责<CATALINA_HOME>/share/classes中的.class类文件和<CATALINA_HOME>/share/lib中的jar包加载类。

  • WebappX类装载器负责从当前Web应用程序的/WEB-INF/classes中的.class类文件和/WEB-INF/lib中的jar包加载类。

  • Servlet的特点及运行过程

  • Servlet的特点

  • Servlet是一个供其他Java程序(Servlet引擎)调用的Java类,它不能独立运行,它的运行完全由Servlet引擎来控制和调度。

  • Servlet引擎是一种容器程序,它负责管理和维护所有Servlet对象的生命周期。Servlet的加载、执行流程、以及如何接受客户端发送的数据和如何将数据传输到客户端等具体的底层事务,都是由Servlet引擎来实现的。Servlet引擎负责将客户端的请求信息转交给Servlet和将Servlet生成的响应信息返回给客户端。

  • Servlet属于一种插件,它是一个提供了一些约定方法供容器去调用的类,它只负责在自身的方法中接受并处理容器传递进来的数据,以及生成并返回给容器去使用的数据和状态信息。

  • Servlet的最常见应用在于读取WEB浏览器传递给WEB服务器的参数和生成Web服务器返回给WEB浏览器的动态网页文档内容;Servlet也能获取WEB浏览器发送的HTTP请求消息中的各个请求头和请求行信息,以及生成用于WEB服务器发送的HTTP响应消息中的状态行和响应头信息;Servlet还能获取WEB服务器和Servlet引擎自身的一些环境和状态信息。

  • Servlet程序的运行过程就是它与Servlet引擎的交互过程,Servlet程序只与Servlet引擎打交道,它并不与WEB服务器和客户端进行任何直接的交互。

  • Servlet本身就是Java语言的一个应用,具有Java语言的所以优势,能完成普通Java程序所能完成的所有功能。

  • Web服务器上可以布置多个功能各不相同的Servlet,每个Servlet都应该宣称它可以处理何种样式的URL,当符合样式的URL请求到达时,Servlet引擎调用相应的Servlet进行处理。

Servlet程序查询数据库的工作工程

  1. 2.       Servlet的运行过程

  2. 1)        Servlet引擎检查是否已经装载并创建了该Servlet的实例对象。如果是,则直接执行第4)步,否则,执行第2)步。

  3. 2)        装载并创建该Servlet的一个实例对象。

  4. 3)        调用Servlet实例对象的init()方法。

  5. 4)        创建一个用于封装HTTP请求消息的HttpServletRequest对象和一个代表HTTP响应消息的HttpServletResponse对象,然后调用Servletservice()方法并将请求和响应对象作为参数传递进去。

  6. 5)        Web应用程序被停止或重新启动之前,Servlet引擎将卸载Servlet,并在卸载之前调用Servletdestroy()方法。

特殊说明:

  • <servlet>元素中嵌套一个<load-on-startup>子元素,WEB应用程序在启动时就可以装载并创建Servlet的实例对象、以及调用Servlet实例对象的init()方法。

  • Servlet的整个生命周期内,它的init方法只被调用一次,而对一个Servlet的每次访问请求都导致Servlet引擎调用一次Servletservice方法。对于每次访问请求,Servlet引擎都会创建一个新的HttpServletRequest请求对象和一个新的Htt响应对象,然后将这两个对象作为参数传递个它调用的Servletservice()方法。

  • Tomcat也提供了是否自动重新装载被修改的Servlet的配置选项。在<Tomcat安装目录>/conf/server.xml文件中,可以将<Context>元素的reloadable属性设置为true,这样,Tomcat将监视该WEB应用程序的/WEB-INF/classes/WEB-INF/lib目录下的类是否发生了改变,然后自动重新装载那些发生了改变的类。

举例:

<Context path=”/test” docBase=”d:\myweb” debug=”0” reloadable=”true” />

  1. 3.       Servlet的线程安全问题

  2. l Servlet引擎采用多线程模式运行,它为并发的每个访问请求都使用一个独立的线程来进行响应,但带来了线程安全的问题。

  3. l 如果某个Servlet实现了SingleThreadModel接口(荒废了),那么Servlet引擎将以单线程模式来调用其service方法。

  4. l SingleThreadModel接口中没有定义任何方法,只要在Servlet类的定义中增加实现SingleThreadModel接口的声明即可。

  5. l 对于实现了SingleThreadModel接口的ServletServlet引擎仍然支持对该Servlet的多线程并发访问,其采用的方式是产生多个Servlet实例对象,并发的每个线程分别调用一个独立的Servlet实例对象。

  6. l 实现SingleThreadModel接口并不能真正解决Servlet的线程安全问题,因为Servlet引擎会创建多个Servlet实例对象。事实上,在Servlet API 2.4中,已经将SingleThreadModel标记为Deprecated(过时的)。

  7. 四、        ServletConfig接口

  8. l Servlet在有些情况下可能需要访问Servlet容器或借助Servlet容器访问外部的资源,所以,Servlet引擎需要将表示Servlet容器的对象传递给Servlet。另外,在web.xml文件中为某个Servlet设置的友好名称和初始化参数等信息也需要传递给该Servlet

  • Servlet引擎代表Servlet容器的对象和Servlet的配置参数信息一并封装到一个称为ServletConfig的对象中,并在初始化Servlet实例对象时传递给该ServletServletConfig接口则用于定义ServletConfig对象需要对外提供的方法,以便在Servlet程序中可以调用这些方法来获取有关信息。

  • Servlet引擎调用Servlet的实例对象的init(ServletConfig config)方法将ServletConfig对象传递给ServletServlet.getServletConfig()方法必须返回init(ServletConfig config)方法传递进来的这个ServletConfig对象的引用。

  • GenericServletHttpServlet

GenericServlet类实现ServletConfig接口的目的

  • Servlet接口中定义了一个getServletConfig方法,该方法必须返回Servlet容器调用Servlet.init(ServletConfig config)方法时传递进来的那个ServletConfig对象的引用,GenericServlet类已经按此要求实现了getServletConfig方法。

  • Servlet程序中如何调用ServletConfig对象的方法

举例:String servletName=getServletConfig().getServletName();

  • GenericServlet类如何实现ServletConfig接口中的方法

举例:

Public String getServletName()

{

         return getServletConfig().getServletName();

}

  • Servlet程序中调用ServletConfig对象的方法的简单方式

举例:String servletName=getServletName();

0 0
原创粉丝点击