




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、Servlet 工作原理解析许令波, Java 工程师, 淘宝网简介Web技术成为当今主流的互联网Web应用技术之一,而Servlet是Java Web技术的核心基础。因而掌握Servlet的工作原理是成为一名合格的Java Web技术开发人员的基本要求。本文将带你认识Java Web技术是如何基于Servlet工作,你将知道:以Tomcat为例了解Servlet容器是如何工作的?一个Web工程在Servlet容器中是如何启动的?Servlet容器如何解析你在web.xml中定义的Servlet?用户的请求是如何被分配给指定的Servlet的?Servlet容器如何管理Servlet生命周期?
2、你还将了解到最新的Servlet的API的类层次结构,以及Servlet中一些难点问题的分析。从Servlet容器说起要介绍Servlet必须要先把Servlet容器说清楚,Servlet与Servlet容器的关系有点像枪和子弹的关系,枪是为子弹而生,而子弹又让枪有了杀伤力。虽然它们是彼此依存的,但是又相互独立发展,这一切都是为了适应工业化生产的结果。从技术角度来说是为了解耦,通过标准化接口来相互协作。既然接口是连接Servlet与Servlet容器的关键,那我们就从它们的接口说起。前面说了Servlet容器作为一个独立发展的标准化产品,目前它的种类很多,但是它们都有自己的市场定位,很难说谁优
3、谁劣,各有特点。例如现在比较流行的Jetty,在定制化和移动领域有不错的发展,我们这里还是以大家最为熟悉Tomcat为例来介绍Servlet容器如何管理Servlet。Tomcat本身也很复杂,我们只从Servlet与Servlet容器的接口部分开始介绍,关于Tomcat的详细介绍可以参考我的另外一篇文章Tomcat系统架构与模式设计分析。Tomcat的容器等级中,Context容器是直接管理Servlet在容器中的包装类Wrapper,所以 Context容器如何运行将直接影响Servlet的工作方式。图1. Tomcat容器模型从上图可以看出Tomcat的容器分为四个等级,真正管理Serv
4、let的容器是Context容器,一个Context对应一个Web工程,在Tomcat的配置文件中可以很容易发现这一点,如下:清单 1 Context 配置参数 下面详细介绍一下Tomcat解析Context容器的过程,包括如何构建Servlet的过程。Servlet容器的启动过程Tomcat7也开始支持嵌入式功能,增加了一个启动类org.apache.catalina.startup.Tomcat。创建一个实例对象并调用start方法就可以很容易启动Tomcat,我们还可以通过这个对象来增加和修改Tomcat的配置参数,如可以动态增加Context、Servlet等。下面我们就利用这个Tom
5、cat类来管理新增的一个Context容器,我们就选择Tomcat7自带的examples Web工程,并看看它是如何加到这个Context容器中的。清单2. 给Tomcat增加一个Web工程Tomcat tomcat = getTomcatInstance(); File appDir = new File(getBuildDirectory(), webapps/examples); tomcat.addWebapp(null, /examples, appDir.getAbsolutePath(); tomcat.start(); ByteChunk res = getUrl(http:
6、/localhost: + getPort() + /examples/servlets/servlet/HelloWorldExample); assertTrue(res.toString().indexOf(Hello World!) 0); 清单1的代码是创建一个Tomcat实例并新增一个Web应用,然后启动 Tomcat 并调用其中的一个 HelloWorldExample Servlet,看有没有正确返回预期的数据。Tomcat 的addWebapp方法的代码如下:清单3. Tomcat.addWebapppublic Context addWebapp(Host host, St
7、ring url, String path) silence(url); Context ctx = new StandardContext(); ctx.setPath( url ); ctx.setDocBase(path); if (defaultRealm = null) initSimpleAuth(); ctx.setRealm(defaultRealm); ctx.addLifecycleListener(new DefaultWebXmlListener(); ContextConfig ctxCfg = new ContextConfig(); ctx.addLifecycl
8、eListener(ctxCfg); ctxCfg.setDefaultWebXml(org/apache/catalin/startup/NO_DEFAULT_XML); if (host = null) getHost().addChild(ctx); else host.addChild(ctx); return ctx; 前面已经介绍了一个Web应用对应一个Context容器,也就是Servlet运行时的Servlet容器,添加一个Web 应用时将会创建一个StandardContext容器,并且给这个Context容器设置必要的参数,url和path分别代表这个应用在Tomcat中的
9、访问路径和这个应用实际的物理路径,这个两个参数与清单1中的两个参数是一致的。其中最重要的一个配置是ContextConfig,这个类将会负责整个Web应用配置的解析工作,后面将会详细介绍。最后将这个Context容器加到父容器Host中。接下去将会调用Tomcat的start方法启动Tomcat,如果你清楚Tomcat的系统架构,你会容易理解Tomcat的启动逻辑,Tomcat的启动逻辑是基于观察者模式设计的,所有的容器都会继承Lifecycle接口,它管理者容器的整个生命周期,所有容器的的修改和状态的改变都会由它去通知已经注册的观察者(Listener),关于这个设计模式可以参考Tomcat
10、的系统架构与设计模式,第二部分:设计模式。Tomcat启动的时序图可以用图 2 表示。上图描述了Tomcat启动过程中,主要类之间的时序关系,下面我们将会重点关注添加examples应用所对应的StandardContext容器的启动过程。当Context容器初始化状态设为init时,添加在Contex容器的Listener将会被调用。ContextConfig继承了 LifecycleListener接口,它是在调用清单3时被加入到StandardContext容器中。ContextConfig类会负责整个 Web应用的配置文件的解析工作。ContextConfig的init方法将会主要完成
11、以下工作:创建用于解析xml配置文件的contextDigester对象读取默认context.xml配置文件,如果存在解析它读取默认Host配置文件,如果存在解析它读取默认Context自身的配置文件,如果存在解析它设置Context的 DocBaseContextConfig的init方法完成后,Context容器的会执行startInternal方法,这个方法启动逻辑比较复杂,主要包括如下几个部分:创建读取资源文件的对象创建ClassLoader对象设置应用的工作目录启动相关的辅助类如:logger、realm、resources 等修改启动状态,通知感兴趣的观察者(Web 应用的配置)
12、子容器的初始化获取ServletContext 并设置必要的参数初始化“load on startup”的ServletWeb应用的初始化工作Web应用的初始化工作是在ContextConfig的configureStart方法中实现的,应用的初始化主要是要解析 web.xml文件,这个文件描述了一个Web应用的关键信息,也是一个Web应用的入口。Tomcat首先会找globalWebXml这个文件的搜索路径是在engine的工作目录下寻找以下两个文件中的任一个org/apache/catalin/startup/NO_DEFAULT_XML或conf/web.xml。接着会找hostWebX
13、ml这个文件可能会在 System.getProperty(catalina.base)/conf/$EngineName/$HostName/web.xml.default,接着寻找应用的配置文件 examples/WEB-INF/web.xml。web.xml文件中的各个配置项将会被解析成相应的属性保存在WebXml对象中。如果当前应用支持Servlet3.0,解析还将完成额外9项工作,这个额外的9项工作主要是为Servlet3.0新增的特性,包括jar包中的META-INF/web-fragment.xml的解析以及对annotations的支持。接下去将会将WebXml对象中的属性设置
14、到Context容器中,这里包括创建Servlet对象、filter、listener等等。这段代码在WebXml的configureContext方法中。下面是解析Servlet的代码片段:清单4. 创建Wrapper实例for (ServletDef servlet : servlets.values() Wrapper wrapper = context.createWrapper(); String jspFile = servlet.getJspFile(); if (jspFile != null) wrapper.setJspFile(jspFile); if (servlet.
15、getLoadOnStartup() != null) wrapper.setLoadOnStartup(servlet.getLoadOnStartup().intValue(); if (servlet.getEnabled() != null) wrapper.setEnabled(servlet.getEnabled().booleanValue(); wrapper.setName(servlet.getServletName(); Map params = servlet.getParameterMap(); for (Entry entry : params.entrySet()
16、 wrapper.addInitParameter(entry.getKey(), entry.getValue(); wrapper.setRunAs(servlet.getRunAs(); Set roleRefs = servlet.getSecurityRoleRefs(); for (SecurityRoleRef roleRef : roleRefs) wrapper.addSecurityReference( roleRef.getName(), roleRef.getLink(); wrapper.setServletClass(servlet.getServletClass(
17、); MultipartDef multipartdef = servlet.getMultipartDef(); if (multipartdef != null) if (multipartdef.getMaxFileSize() != null & multipartdef.getMaxRequestSize()!= null & multipartdef.getFileSizeThreshold() != null) wrapper.setMultipartConfigElement(new MultipartConfigElement( multipartdef.getLocatio
18、n(), Long.parseLong(multipartdef.getMaxFileSize(), Long.parseLong(multipartdef.getMaxRequestSize(), Integer.parseInt( multipartdef.getFileSizeThreshold(); else wrapper.setMultipartConfigElement(new MultipartConfigElement( multipartdef.getLocation(); if (servlet.getAsyncSupported() != null) wrapper.s
19、etAsyncSupported( servlet.getAsyncSupported().booleanValue(); context.addChild(wrapper); 这段代码清楚的描述了如何将Servlet包装成Context容器中的StandardWrapper,这里有个疑问,为什么要将Servlet包装成StandardWrapper而不直接是Servlet对象。这里StandardWrapper是Tomcat容器中的一部分,它具有容器的特征,而Servlet为了一个独立的web开发标准,不应该强耦合在Tomcat中。除了将Servlet包装成StandardWrapper并作
20、为子容器添加到Context中,其它的所有web.xml属性都被解析到Context中,所以说Context容器才是真正运行Servlet的Servlet容器。一个Web应用对应一个Context容器,容器的配置属性由应用的web.xml指定,这样我们就能理解web.xml到底起到什么作用了。创建Servlet实例前面已经完成了Servlet的解析工作,并且被包装成StandardWrapper添加在Context容器中,但是它仍然不能为我们工作,它还没有被实例化。下面我们将介绍Servlet对象是如何创建的,以及如何被初始化的。创建Servlet对象如果Servlet的load-on-sta
21、rtup配置项大于0,那么在Context容器启动的时候就会被实例化,前面提到在解析配置文件时会读取默认的globalWebXml,在conf下的web.xml文件中定义了一些默认的配置项,其定义了两个Servlet,分别是: org.apache.catalina.servlets.DefaultServlet和org.apache.jasper.servlet.JspServlet它们的load-on-startup分别是1和3,也就是当Tomcat启动时这两个Servlet就会被启动。创建Servlet实例的方法是从Wrapper.loadServlet开始的。loadServlet方法
22、要完成的就是获取servletClass然后把它交给InstanceManager去创建一个基于servletClass.class的对象。如果这个Servlet配置了jsp-file,那么这个servletClass就是conf/web.xml中定义的org.apache.jasper.servlet.JspServlet了。创建Servlet对象的相关类结构图如下:图3. 创建 Servlet 对象的相关类结构初始化Servlet初始化Servlet在StandardWrapper的initServlet方法中,这个方法很简单就是调用Servlet的init 的方法,同时把包装了Stand
23、ardWrapper对象的StandardWrapperFacade作为ServletConfig传给Servlet。Tomcat容器为何要传StandardWrapperFacade给Servlet对象将在后面做详细解析。如果该Servlet关联的是一个jsp文件,那么前面初始化的就是JspServlet,接下去会模拟一次简单请求,请求调用这个jsp文件,以便编译这个jsp文件为class,并初始化这个class。这样Servlet对象就初始化完成了,事实上Servlet从被web.xml中解析到完成初始化,这个过程非常复杂,中间有很多过程,包括各种容器状态的转化引起的监听事件的触发、各种访
24、问权限的控制和一些不可预料的错误发生的判断行为等等。我们这里只抓了一些关键环节进行阐述,试图让大家有个总体脉络。下面是这个过程的一个完整的时序图,其中也省略了一些细节。图 4. 初始化 Servlet 的时序图Servlet体系结构我们知道Java Web应用是基于Servlet规范运转的,那么Servlet本身又是如何运转的呢?为何要设计这样的体系结构。图5. Servlet顶层类关联图从上图可以看出Servlet规范就是基于这几个类运转的,与Servlet主动关联的是三个类,分别是 ServletConfig、ServletRequest和ServletResponse。这三个类都是通过容
25、器传递给Servlet的,其中 ServletConfig是在Servlet初始化时就传给Servlet了,而后两个是在请求达到时调用Servlet时传递过来的。我们很清楚ServletRequest和ServletResponse在Servlet运行的意义,但是ServletConfig和ServletContext对Servlet有何价值?仔细查看ServletConfig接口中声明的方法发现,这些方法都是为了获取这个Servlet的一些配置属性,而这些配置属性可能在Servlet运行时被用到。而ServletContext又是干什么的呢?Servlet 的运行模式是一个典型的“握手型的交
26、互式”运行模式。所谓“握手型的交互式”就是两个模块为了交换数据通常都会准备一个交易场景,这个场景一直跟随个这个交易过程直到这个交易完成为止。这个交易场景的初始化是根据这次交易对象指定的参数来定制的,这些指定参数通常就会是一个配置类。所以对号入座,交易场景就由ServletContext 来描述,而定制的参数集合就由 ServletConfig 来描述。而 ServletRequest 和 ServletResponse 就是要交互的具体对象了,它们通常都是作为运输工具来传递交互结果。ServletConfig 是在 Servlet init 时由容器传过来的,那么 ServletConfig
27、到底是个什么对象呢?下图是 ServletConfig 和 ServletContext 在 Tomcat 容器中的类关系图。图 6. ServletConfig 在容器中的类关联图上图可以看出StandardWrapper和StandardWrapperFacade都实现了ServletConfig接口,而 StandardWrapperFacade是 StandardWrapper门面类。所以传给Servlet的是StandardWrapperFacade对象,这个类能够保证从StandardWrapper中拿到ServletConfig所规定的数据,而又不把ServletConfig不关
28、心的数据暴露给Servlet。同样ServletContext也与ServletConfig有类似的结构,Servlet中能拿到的ServletContext的实际对象也是ApplicationContextFacade对象。ApplicationContextFacade同样保证ServletContex只能从容器中拿到它该拿的数据,它们都起到对数据的封装作用,它们使用的都是门面设计模式。通过ServletContext可以拿到Context 容器中一些必要信息,比如应用的工作路径,容器支持的 Servlet 最小版本等。Servlet中定义的两个ServletRequest和Servlet
29、Response它们实际的对象又是什么呢?,我们在创建自己的 Servlet类时通常使用的都是HttpServletRequest和HttpServletResponse,它们继承了ServletRequest 和 ServletResponse。为何Context容器传过来的ServletRequest、ServletResponse 可以被转化为 HttpServletRequest 和 HttpServletResponse呢?图7. Request相关类结构图上图是Tomcat创建的Request和Response的类结构图。Tomcat一接受到请求首先将会创建 org.apache.
30、coyote.Request和org.apache.coyote.Response,这两个类是Tomcat内部使用的描述一次请求和相应的信息类它们是一个轻量级的类,它们作用就是在服务器接收到请求后,经过简单解析将这个请求快速的分配给后续线程去处理,所以它们的对象很小,很容易被JVM回收。接下去当交给一个用户线程去处理这个请求时又创建org.apache.catalina.connector.Request和org.apache.catalina.connector.Response对象。这两个对象一直穿越整个Servlet容器直到要传给Servlet,传给Servlet的是Request和Re
31、sponse的门面类RequestFacade和RequestFacade,这里使用门面模式与前面一样都是基于同样的目的封装容器中的数据。一次请求对应的Request和Response的类转化如下图所示:图8. Request和Response的转变过程Servlet如何工作我们已经清楚了Servlet是如何被加载的、Servlet是如何被初始化的,以及Servlet的体系结构,现在的问题就是它是如何被调用的。当用户从浏览器向服务器发起一个请求,通常会包含如下信息:http:/hostname:port/contextpath/servletpath,hostname和port是用来与服务器建
32、立TCP连接,而后面的URL才是用来选择服务器中那个子容器服务用户的请求。那服务器是如何根据这个URL来达到正确的Servlet容器中的呢?Tomcat7.0中这件事很容易解决,因为这种映射工作有专门一个类来完成的,这个就是org.apache.tomcat.util.http.mapper,这个类保存了Tomcat的Container容器中的所有子容器的信息,当org.apache.catalina.connector.Request类在进入Container容器之前,mapper会根据这次请求的hostnane和contextpath将host和context容器设置到Request的ma
33、ppingData 属性中。所以当Request进入Container容器之前,它要访问那个子容器这时就已经确定了。图 9.Request 的 Mapper 类关系图可能你有疑问,mapper中怎么会有容器的完整关系,这要回到图2中19步MapperListener 类的初始化过程,下面是MapperListener的init方法代码 :清单 5. MapperListener.initpublic void init() findDefaultHost(); Engine engine = (Engine) connector.getService().getContainer(); eng
34、ine.addContainerListener(this); Container conHosts = engine.findChildren(); for (Container conHost : conHosts) Host host = (Host) conHost; if (!LifecycleState.NEW.equals(host.getState() host.addLifecycleListener(this); registerHost(host); 这段代码的作用就是将MapperListener类作为一个监听者加到整个Container容器中的每个子容器中,这样只要任
35、何一个容器发生变化,MapperListener都将会被通知,相应的保存容器关系的MapperListener 的 mapper属性也会修改。for循环中就是将host及下面的子容器注册到mapper中。图 10.Request 在容器中的路由图上图描述了一次Request请求是如何达到最终的Wrapper容器的,我们现正知道了请求是如何达到正确的Wrapper容器,但是请求到达最终的Servlet还要完成一些步骤,必须要执行Filter链,以及要通知你在web.xml中定义的listener。接下去就要执行Servlet的service方法了,通常情况下,我们自己定义的servlet并不是直
36、接去实现javax.servlet.servlet接口,而是去继承更简单的HttpServlet类或者GenericServlet类,我们可以有选择的覆盖相应方法去实现我们要完成的工作。Servlet的确已经能够帮我们完成所有的工作了,但是现在的web应用很少有直接将交互全部页面都用 servlet来实现,而是采用更加高效的MVC框架来实现。这些MVC框架基本的原理都是将所有的请求都映射到一个Servlet,然后去实现service方法,这个方法也就是MVC框架的入口。当Servlet从Servlet容器中移除时,也就表明该Servlet的生命周期结束了,这时Servlet的destroy方法
37、将被调用,做一些扫尾工作。Session与Cookie前面我们已经说明了Servlet如何被调用,我们基于Servlet来构建应用程序,那么我们能从Servlet获得哪些数据信息呢?Servlet能够给我们提供两部分数据,一个是在Servlet初始化时调用init方法时设置的ServletConfig,这个类基本上含有了Servlet本身和Servlet所运行的Servlet容器中的基本信息。根据前面的介绍ServletConfig的实际对象是StandardWrapperFacade,到底能获得哪些容器信息可以看看这类提供了哪些接口。还有一部分数据是由ServletRequest类提供,它的
38、实际对象是RequestFacade,从提供的方法中发现主要是描述这次请求的 HTTP 协议的信息。所以要掌握Servlet的工作方式必须要很清楚HTTP协议,如果你还不清楚赶紧去找一些参考资料。关于这一块还有一个让很多人迷惑的Session与Cookie。Session与Cookie不管是对Java Web的熟练使用者还是初学者来说都是一个令人头疼的东西。Session与Cookie的作用都是为了保持访问用户与后端服务器的交互状态。它们有各自的优点也有各自的缺陷。然而具有讽刺意味的是它们优点和它们的使用场景又是矛盾的,例如使用Cookie来传递信息时,随着Cookie个数的增多和访问量的增加
39、,它占用的网络带宽也很大,试想假如Cookie占用200个字节,如果一天的PV有几亿的时候,它要占用多少带宽。所以大访问量的时候希望用Session,但是Session的致命弱点是不容易在多台服务器之间共享,所以这也限制了Session的使用。不管Session和Cookie有什么不足,我们还是要用它们。下面详细讲一下,Session如何基于Cookie来工作。实际上有三种方式能可以让Session正常工作:基于URL Path Parameter,默认就支持基于Cookie,如果你没有修改Context容器个cookies标识的话,默认也是支持的基于SSL,默认不支持,只有connector
40、.getAttribute(SSLEnabled)为TRUE时才支持第一种情况下,当浏览器不支持Cookie功能时,浏览器会将用户的SessionCookieName重写到用户请求的URL参数中,它的传递格式如/path/Servlet;name=value;name2=value2?Name3=value3,其中“Servlet;”后面的 K-V 对就是要传递的Path Parameters,服务器会从这个Path Parameters中拿到用户配置的 SessionCookieName。关于这个SessionCookieName,如果你在web.xml中配置session-config配置
41、项的话,其cookie-config下的 name 属性就是这个SessionCookieName值,如果你没有配置session-config配置项,默认的SessionCookieName就是大家熟悉的“JSESSIONID”。接着Request根据这个SessionCookieName到Parameters拿到Session ID并设置到request.setRequestedSessionId中。请注意如果客户端也支持Cookie的话,Tomcat仍然会解析Cookie中的Session ID,并会覆盖URL中的Session ID。如果是第三种情况的话将会根据javax.servle
42、t.request.ssl_session属性值设置Session ID。有了Session ID服务器端就可以创建HttpSession对象了,第一次触发是通过request.getSession()方法,如果当前的Session ID还没有对应的HttpSession对象那么就创建一个新的,并将这个对象加到 org.apache.catalina.Manager的sessions容器中保存,Manager类将管理所有Session的生命周期,Session过期将被回收,服务器关闭,Session 将被序列化到磁盘等。只要这个HttpSession对象存在,用户就可以根据 Session I
43、D来获取到这个对象,也就达到了状态的保持。图 11.Session 相关类图上从图中可以看出从request.getSession中获取的HttpSession对象实际上是StandardSession对象的门面对象,这与前面的Request和Servlet是一样的原理。下图是Session工作的时序图:图 12.Session 工作的时序图还有一点与Session关联的Cookie与其它Cookie没有什么不同,这个配置的配置可以通过web.xml中的session-config配置项来指定。Servlet中的Listener整个Tomcat服务器中Listener使用的非常广泛,它是基于观
44、察者模式设计的,Listener的设计对开发Servlet 应用程序提供了一种快捷的手段,能够方便的从另一个纵向维度控制程序和数据。目前Servlet中提供了5种两类事件的观察者接口,它们分别是:4 个 EventListeners类型的,ServletContextAttributeListener、ServletRequestAttributeListener、ServletRequestListener、HttpSessionAttributeListener 和2个 LifecycleListeners 类型的,ServletContextListener、HttpSessionLis
45、tener。如下图所示:图 13.Servlet 中的 Listener它们基本上涵盖了整个Servlet生命周期中,你感兴趣的每种事件。这些Listener的实现类可以配置在web.xml中的标签中。当然也可以在应用程序中动态添加Listener,需要注意的是ServletContextListener在容器启动之后就不能再添加新的,因为它所监听的事件已经不会再出现。掌握这些Listener的使用,能够让我们的程序设计的更加灵活。总结本文涉及到内容有点多,要把每个细节都说清楚,似乎不可能,本文试着从Servlet容器的启动到Servlet的初始化,以及Servlet的体系结构等这些环节中找出
46、一些重点来讲述,目的是能读者有一个总体的完整的结构图,同时也详细分析了其中的一些难点问题,希望对大家有所帮助。文章来源 HYPERLINK /developerworks/cn/java/j-lo-servlet/ /developerworks/cn/java/j-lo-servlet/附录资料:JAVA工程师EJB面试题集JAVA工程师EJB面试题集 HYPERLINK /phrase/200604241156485.html t _new EJB ( HYPERLINK /phrase/200603091138035.html t _new Enterprise JavaBean)是 H
47、YPERLINK /phrase/200603091447335.html t _new J2EE的一部分,定义了一个用于开发基于 HYPERLINK /phrase/200603302222545.html t _new 组件的企业多重应用 HYPERLINK /phrase/200604232224305.html t _new 程序的标准。其特点包括网络服务支持和核心开发工具(SDK)。 在J2EE里,Enterprise Java Beans(EJB)称为Java 企业柄,是Java的核心代码,分为整体柄和片段柄和 HYPERLINK /phrase/200603090938465.h
48、tml t _new 消息柄三个部分,其中的消息柄将在以后再作讨论。现在我们来看看什么是整体柄和片段柄。 整体柄是一种 HYPERLINK /phrase/200603090845215.html t _new 对象: 标准Java对象由创建它的程序创建,当程序终止时,对象也随之丢失,这就意味着当再次运行些程序时,将无法找到先前创建的柄,而整体柄会一直存在着直到它被删除。 一个程序可以创建一个整体柄,并且这个程序可以在被保存后随时停止和重启。整体柄将会依然存在。重启后,程序可以找到与之相对应的整体柄,并且会继续使用这个整体柄。 EJB实际上是SUN的J2EE中的一套规范,并且规定了一系列的 H
49、YPERLINK /phrase/200604241228185.html t _new API用来实现把EJB概念转换成EJB产品.EJB是BEANS,BEANS是什么概念,那就是得有一个容纳她,让她可劲造腾的地方,就是得有容器.EJB必须生存在EJB容器中.这个容器可是功能强大之极!她首先要包装你BEAN,EJB的客户程序实际上从来就不和你编写的EJB直接打交道,他们之间是通过HOME/REMOTE接口来发生关系的.它负责你的BEAN的所有的吃喝拉萨睡,比如BEAN的持续化,安全性,事务管理. 一.什么是 EJB?一个技术规范:EJB 从技术上而言不是一种产品EJB 是一种标准描述了构建应
50、用组件要解决的:可扩展 (Scalable)分布式 (Distributed)事务处理 (Transactional)数据存储 (Persistent)安全性 (Secure)二.Sun 对 EJB 的期望提供一个标准的分布的、基于 HYPERLINK /phrase/200604231401365.html t _new OO 的组件 HYPERLINK /phrase/200604241328115.html t _new 架构屏蔽复杂的系统级功能 HYPERLINK /phrase/200603101518295.html t _new 需求Write once, run anywher
51、e与非 Java 应用之间的互操作能力兼容 HYPERLINK /phrase/200604031336425.html t _new CORBA 标准三.为什么选择 EJB?EJB 服务器完成繁杂的工作:应用开发人员关注于业务逻辑的实现而不是底层的实现机制( HYPERLINK /phrase/200603090857555.html t _new 类似于 4GL 语言设计的目标)支持事务处理多个业务操作同时成功,或全部失败可以通过在代码外的描述来定义事务处理级别可扩展性EJB 可以根据您应用的增长而扩展EJB 服务器往往还提供了负载均衡和安全性:由 EJB 服务器提供资源的访问权限控制四.
52、EJB 架构为了满足架构的目标,规范中描述了服务器 (Server)容器 (Container)类 ( HYPERLINK /phrase/200604231359565.html t _new Class) 和实例 (Instance)Home 和 Remote 接口 HYPERLINK /phrase/200603082208195.html t _new 客户端 ( HYPERLINK /phrase/200604231337375.html t _new Client)五. 简化的编程模型关注于业务逻辑实现:EJB 负责生命周期 (lifecycle), 数据存储 (persisten
53、ce), 事务处理语义 (transactional semantic), 安全(security), .通用的编程模型:各种服务的高层 APIJava 是其编程语言1.EJB 特点由一个 EJB 容器在运行时创建和管理 EJB在部署 EJB 时定制其运行方式由 EJB 容器和服务器来协调客户端的访问可以部署到任何兼容的 EJB 容器中客户端对 EJB 的 HYPERLINK /phrase/200603141659315.html t _new 视图是由 Bean 开发人员决定的2.EJB 服务器管理 EJB 容器 (它管理 Bean)提供对 HYPERLINK /phrase/200602
54、281634075.html t _new 操作系统服务的存取提供 Java 相关的服务,尤其是通过 JNDI 访问命名空间基于 OTS 的事务处理服务3.EJB 容器管理 Bean 生命周期:将 EJB 服务器提供的服务传递给 Bean生成代码来实现对 Bean 的存取访问强制事务处理的限制创建、初始化和回收 Bean管理持久数据的存储对客户端而言 EJB 容器是透明的4.在一个 EJB 服务器中的容器目前容器通常是由 EJB 服务器本身提供的在 EJB 1.0 或 1.1 规范中没有定义容器-到-服务器的接口各厂商可以根据他们的见解来实现服务器和容器的各自责任5.容器提供服务: 数据存储容
55、器决定何时载入/储存状态Container-Managed Persistence(容器管理存储/CMP)容器负责存储您的 Bean容器生成必要的类和代码Bean-Managed Persistence(Bean 管理存储/BMP)Bean 开发人员提供存储代码开发人员决定 如何存储, 容器仍然决定 何时进行6.容器提供服务: 事务处理可以由容器代理来实现容器将得到业务逻辑方法的事务处理需求容器提供事务控制代码也可以由程序员通过代码实现7.容器提供服务: 其它服务其它服务包括命名 (Naming)安全 (Security) HYPERLINK /phrase/200603091754305.h
56、tml t _new 线程管理 ( HYPERLINK /phrase/200604231348385.html t _new Thread management)这些服务由容器代理完成将减少应用开发人员的负担8.分布式对象运算远程对象被作为本地对象来处理:传递信息的方式不变,但开销更大Enterprise JavaBeans 永远运行在服务器上:对 Bean 的访问永远是远程调用9.Stub 和 Skeleton由 EJB 生成:Stub 对要传递出去的信息编码Tie/Skel 将接受到的信息解码并传递给目标对象10.分类: Enterprise HYPERLINK /phrase/2006
57、04251741535.html t _new JavaBeans+-Entity Beans-CMP/BMPEjb-|+-Session Beans-Stateful/Stateless会话 Bean (Session Bean):根据 EJB 规范,一个会话 Bean 是:代表单个客户端来执行可以参与到事务处理中不直接代表共享于 HYPERLINK /phrase/200602271218062.html t _new 数据库中的数据,但它能访问和更新这些数据相对而言是短暂存在的当 EJB 容器失效后就不存在客户端需要重新建立一个信新的会话对象来继续运算实体 Bean (Entity Be
58、an):根据 EJB 规范,一个实体 Bean 是:提供在数据库中数据的对象视图允许被多个用户共享存取访问可以是长期存在 (只要它存在于数据库中)实体 Bean, 它的主键对象, 以及它的远程引用将能跨 EJB 容器的宕机而存在11.EJB 类和实例构建 EJB 应用包括来自三方的代码开发人员编写的代码由 EJB API 定义的类和接口由容器自动生成的代码开发人员编写的代码包括Bean 类 (定义了业务逻辑)Home 接口 (如何查找或创建 bean)Remote 接口 (如何存取 bean)其它组件,根据 bean 实际要求12.EJB Home 接口每个 bean 有一个用于:创建新的 b
59、ean 实例、查找现存的 bean (只能是实体 bean)Remote 接口:定义 bean 的公共接口只有在 Remote 接口中定义的方法才能被客户端访问EJB 客户端可以为 HYPERLINK /phrase/200603091005185.html t _new servlet, JSP, 应用程序或其它 bean通过 JNDI 来查找 EJB home 接口,步骤为:创建一个 JNDI Context (initial context)使用 JNDI Context 来查找 bean home 接口使用 bean home 接口来创建/查找 bean 实例使用 bean 实例完成业
60、务操作实际的存取 (对 EJB) 是通过容器生成的类来完成EJB 架构客户端对 bean 访问永远不是直接的EJBObject (tie) 是由容器自身提供的:用来帮助管理 bean 的生命周期EJB 中的角色EJB 服务器供应商: 开发并销售 EJB 服务器EJB 容器供应商: 开发并销售 EJB 容器Enterprise bean 开发人员: 开发并销售 EJB应用组装人员: 将不同的 EJB 搭建成应用六、EJB的 HYPERLINK /phrase/200603122156385.html t _new 体系结构 目前,EJB最新的标准是2.1,EJB3.0规范正在讨论中,预计将于明年
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025广告工程合同
- 2025标准版上海仓库租赁合同书
- 2025租赁合同(先付租金后使用)
- 一般承揽合同
- 彩票人工缩水服务合同范本
- 2025二级建造师建设工程施工管理考点知识:合同变更与现场签证与合同价款期中支付
- 2025年度装修合同范本
- 2025(范本)设备采购合同
- 广东房屋借住协议书
- 避险安置协议书范文
- 湖南省炎德英才名校联考联合体2024-2025学年高二下学期3月月考-数学+答案
- 蔬菜水果食材配送服务投标方案(技术方案)
- 中医内科学知到课后答案智慧树章节测试答案2025年春浙江中医药大学
- 第二单元第10课《小型网络的搭建》教学设计 2023-2024学年浙教版(2023)初中信息技术七年级上册
- 《高效能NLP沟通技巧》课件
- 电力应急物资储备与管理
- 中国公民健康素养-基本知识与技能(2024年版)试题及答案
- 【语文】第三单元整本书阅读《骆驼祥子》圈点、批注、做笔记课件-2024-2025学年统编版语文七年级下册
- 新目录监理规划2025
- 2024年天翼云认证运维工程师考试复习题库(含答案)
- 储能项目竣工报告
评论
0/150
提交评论