- 浏览: 125779 次
最新评论
-
arthur8:
看标题还以为怎么对value排序~
对Map按key和value分别排序 -
xiaohuafyle:
无耻了,这么简单的东西也上首页,无耻了, 无耻呀,恶心
Apache的安装与配置 -
bestchenwu:
这种文章自己谢谢看看,就好了,为什么要置顶?况且还是装在Win ...
Apache的安装与配置 -
y90055015:
请问,如果需要结合cas sso,应该如何调整配置?org.s ...
Spring Security3 十五日研究 -
Wentasy:
我的CSDN博客:http://blog.csdn.net/w ...
CSDN博客评论插入表情
J2EE学习笔记
J2EE学习笔记
J2EE模式
ValueObject(值对象)用于把数据从某个对象/层传递到其他对象/层的任意Java对象。
通常不包含任何业务方法。
也许设计有公共属性,或者提供可以获取属性值的get方法。
JSP
1.JSP的基础知识
__
_____|directive(指令)
||--scripting(脚本)
JSP-------||__action(动作)
|
|_____Templatedata:除JSP语法外,JSP引擎不能解读的东西
1)在JSP中使用的directive(指令)主要有三个:
a)page指令
b)include指令
c)taglib指令
在JSP的任何地方,以任何顺序,一个页面可以包含任意数量的page指令
2)Scripting(脚本)包括三种类型
a)<%!declaraction%>
b)<%scriptlet%>
c)<%=expression%>
3)action(动作)
标准的动作类型有:
a)<jsp:useBean>
b)<jsp:setProperty>
d)<jsp:getProperty>
e)<jsp:param>
f)<jsp:include>
g)<jsp:forward>
h)<jsp:plugin>
1.注释:<%-----jspcomment-------%>
<!-----htmlcomment-------%>
2.<%@pagesession=“true”import=”java.util.*”%>
session可以不赋值,默认为true,如果session=”false”,则在JSP页面中,隐含的变量session就不能使用。
3.请求控制器结构(RequestController)
也被称之为JSPModel2Architecture
这种途径涉及到使用一个Servlet或一个JSP作为一个应用程序或一组页面的入口点。
为创建可维护的JSP系统,RequestController是最有用的方式之一。
不是JSP,而是Java类才是放置控制逻辑的正确的地方。
请求控制器的命名模式为:xxxController.jsp
请求控制器类的命名模式为:xxxRequestController
2.JSP中的JavaBean
JSP三种bean的类型
1)页面bean
2)会话bean
3)应用bean
大多数的系统会使用一个会话bean来保持状态,而对每一个页面使用一个页面bean来对复杂的数据进行表示。
页面bean是一个模型,而JSP是一个视图。
3.Customtag
bean是信息的携带者,
而tag更适用于处理信息。
标记库包含一个标记库描述符(TLD)和用于实现Customtag的Java类
在翻译阶段,JSP容器将使用TLD来验证页面中的所有的tag是否都被正确的使用。
标记处理程序只是一个简单的适配器,而真正的逻辑是在另一个类中实现的,标记处理程序只是提供了一个供其他的可复用的类的JSP接口
Servlet
1.ServletConfig
l一个ServletConfig对象是servletcontainer在servletinitialization的时候传递给servlet的。
ServletConfig包涵ServletContext和一些Name/Valuepair(来自于deploymentdescriptor)
lServletContext接口封装了Web应用程序的上下文概念。
2.会话跟踪
1)Session
l当一个Client请求多个Servlets时,一个session可以被多个servlet共享。
l通常情况下,如果serverdetect到browser支持cookie,那么URL就不会重写。
2)cookie
l在JavaServlet中,如果你光Cookiecookie=newCookie(name,value)
那么当用户退出Browser时,cookie会被删除掉,而不会被存储在客户端的硬盘上。
如果要存储cookie,需加一句cookie.setMaxAge(200)
lcookie是跟某一个server相关的,运行在同一个server上的servlet共享一个cookie.
3)URLRewriting
在使用URLRewriting来维护SessionID的时候,每一次HTTP请求都需要EncodeURL()
典型的用在两个地方
1)out.print(“formaction=\””);
out.print(response.encodeURL(“sessionExample”));
out.print(“formaction=\””);
out.print(“method=GET>”);
2)out.print(“<p><ahref=\””);
out.print(response.encodeURL(“SessionExample?database=foo&datavalue=bar”));
out.println(“\”>URLencoded</a>”);
3.SingleThreadModel
默认的,每一个servletdefinitioninacontainer只有一个servletclass的实例。
只有实现了SingleThreadModel,container才会让servlet有多个实例。
Servletspecification上建议,不要使用synchronized,而使用SingleThreadModel。
SingleThreadModel(没有方法)
保证servlet在同一时刻只处理一个客户的请求。
SingleThreadModel是耗费资源的,特别是当有大量的请求发送给Servlet时,SingleThreadModel的作用是使包容器以同步时钟的方式调用service方法。
这等同于在servlet的service()方法种使用synchronized.
SingleThreadModel一般使用在需要响应一个heavyrequest的时候,比如是一个需要和数据库打交道的连接。
1.在重载Servlet地init()方法后,一定要记得调用super.init();
2.theclient通过发送一个blankline表示它已经结束request
而theserver通过关闭thesocket来表示response已结束了。
3.一个HttpServlet可以送三种东西给Client
1)asinglestatuscode
2)anynumberofhttpheaders
3)aresponsebody
4.Servlet之间信息共享的一个最简单的方法就是
System.getProperties().put(“key”,”value”);
5.Post和Get
Post:将form内各字段名称和内容放置在htmlheader内传送给server
Get:?之后的查询字符串要使用URLEncode,经过URLEncode后,这个字符串不再带有空格,以后将在server上恢复所带有的空格。
Get是Web上最经常使用的一种请求方法,每个超链接都使用这种方法。
6.Web.xml就是WebApplicatin的deploymentdescriptor
作用有:组织各类元素
设置initparam
设置安全性
7.RequestDispatcher用来把接收到的requestforwardprocessing到另一个servlet
要在一个response里包含另一个servlet的output时,也要用到RequestDispatcher.
8.Servlet和Jsp在同一个JVM中,可以通过ServeltContext的
setAttribute()
getAttribute()
removeAttribute()
来共享对象
9.利用request.getParameter()得到的String存在字符集问题。
可以用strTitle=request.getParameter(“title”);
strTitle=newString(strTitle.getBytes(“8859-1”),”gb2312”);
如果你希望得到更大得兼容性
Stringencoding=response.getCharacterEncoding();
//确定Applicationserver用什么编码来读取输入的。
strTitle=newString(strTitle.getBytes(encoding),”gb2312”);
XML
1.XML基础知识
1.一个xml文档可以分成两个基本部分:
首部(header)
内容(content)
2.xml名字空间规范中指定:
xml文档中的每一个元素都处在一个名字空间中;如果没有指定的名字空间,缺省的名字空间就是和该元素相关联的名字空间。
3.Adocumentthatiswell-formedobeysalloftherulesofXMLdocuments(nestedtags,etc.)
"Ifawell-formeddocumentusesaDocumentTypeDefinition(moreontheseinaminute),anditfollowsalltherulesoftheDTD,thenitisalsoavaliddocument
4.Atagisthetextbetweenthe<anglebrackets>
"Anelementisthestarttag,theendtag,andeverything(includingotherelements)inbetween
5.标签(tags)实际上包含了“元素”(elements)和“属性”(attributes)两部分。
用元素(elements)来描述有规律的数据。
用属性(attributes)来描述系统数据。
如果你有一些数据要提供给某个应用程序,该数据就可能要用到一个元素。
如果该数据用于分类,或者用于告知应用程序如何处理某部分数据,或者该数据从来没有直接对客户程序公开,那么它就可能成为一种属性。
6.CDATA(读作:Cdata)C是character的缩写。
7.org.xml.sax.Reader
/|\
org.xm.l.sax.XMLReader
/|\
org.apche.xerces.parsers.SAXParser
2.WebService
2.1WebService的基本概念
WebService是一种可以接收从Internet或者Intranet上的其它系统中传递过来的请求,轻量级的独立的通讯技术。
这种技术允许网络上的所有系统进行交互。随着技术的发展,一个Web服务可以包含额外的指定功能并且可以在多个B2B应用中协作通讯。
Web服务可以理解请求中上下文的关系,并且在每一个特定的情况下产生动态的结果。这些服务会根据用户的身份,地点以及产生请求的原因来改变不同的处理,用以产生一个唯一的,定制的方案。这种协作机制对那些只对最终结果有兴趣的用户来说,是完全透明的。
UDDI
在用户能够调用Web服务之前,必须确定这个服务内包含哪些商务方法,找到被调用的接口定义,还要在服务端来编制软件。所以,我们需要一种方法来发布我们的Web服务。
UDDI(UniversalDescription,Discovery,andIntegration)是一个主要针对Web服务供应商和使用者的新项目。UDDI项目中的成员可以通过UDDIBusinessRegistry(UBR)来操作Web服务的调用,UBR是一个全球性的服务。
Web服务供应商可以在UBR中描述并且注册他们的服务。
用户可以在UBR中查找并定位那些他们需要的服务。
UDDI是一种根据描述文档来引导系统查找相应服务的机制。
UDDI包含标准的“白皮书”类型的商业查询方式,
“黄皮书”类型的局部查找,以及
“绿皮书”类型的服务类型查找。
UDDI利用SOAP消息机制(标准的XML/HTTP)来发布,编辑,浏览以及查找注册信息。它采用XML格式来封装各种不同类型的数据,并且发送到注册中心或者由注册中心来返回需要的数据。
WSDL
对于商业用户来说,要找到一个自己需要使用的服务,他必须知道如何来调用。
WSDL(WebServicesDescriptionLanguage)规范是一个描述接口,语义以及Web服务为了响应请求需要经常处理的工作的XML文档。这将使简单地服务方便,快速地被描述和记录。
以下是一个WSDL的样例:
<?xmlversion="1.0"?>
<definitionsname="StockQuote"
targetNamespace="http://example.com/stockquote.wsdl"
xmlns:tns="http://example.com/stockquote.wsdl"
xmlns:xsd1="http://example.com/stockquote.xsd"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns="http://schemas.xmlsoap.org/wsdl/">
<types>
<schematargetNamespace=http://example.com/stockquote.xsd
xmlns="http://www.w3.org/2000/10/XMLSchema">
<elementname="TradePriceRequest">
<complexType>
<all>
<elementname="tickerSymbol"type="string"/>
</all>
</complexType>
</element>
<elementname="TradePrice">
<complexType>
<all>
<elementname="price"type="float"/>
</all>
</complexType>
</element>
</schema>
</types>
<messagename="GetLastTradePriceInput">
<partname="body"element="xsd1:TradePriceRequest"/>
</message>
<messagename="GetLastTradePriceOutput">
<partname="body"element="xsd1:TradePrice"/>
</message>
<portTypename="StockQuotePortType">
<operationname="GetLastTradePrice">
<inputmessage="tns:GetLastTradePriceInput"/>
<outputmessage="tns:GetLastTradePriceOutput"/>
</operation>
</portType>
<bindingname="StockQuoteSoapBinding"
type="tns:StockQuotePortType">
<soap:bindingstyle="document"
transport="http://schemas.xmlsoap.org/soap/http"/>
<operationname="GetLastTradePrice">
<soap:operation
soapAction="http://example.com/GetLastTradePrice"/>
<input>
<soap:bodyuse="literal"/>
</input>
<output>
<soap:bodyuse="literal"/>
</output>
</operation>
</binding>
<servicename="StockQuoteService">
<documentation>Myfirstservice</documentation>
<portname="StockQuotePort"binding="tns:StockQuoteBinding">
<soap:addresslocation="http://example.com/stockquote"/>
</port>
</service>
</definitions>
它包含了以下的关键信息:
消息的描述和格式定义可以通过XML文档中的<types>和<message>标记来传送。
<portType>标记中表示了消息传送机制。(e.g.request-only,request-response,response-only)。
<binding>标记指定了编码的规范。
<service>标记中表示服务所处的位置(URL)。
WSDL在UDDI中总是作为一个接口描述文档。因为UDDI是一个通用的用来注册WSDL规范的地方,UDDI的规范并不限制任何类型或者格式描述文档。这些文档可能是一个WSDL文档,或者是一个正规的包含导向文档的Web页面,也可能只是一个包含联系信息的电子邮件地址。
现在Java提供了一个JavaAPIforWSDL(JWSDL)规范。它提供了一套能快速处理WSDL文档的方法,并且不用直接对XML文档进行操作,它会比JAXP更方便,更快速。
SOAP
当商业用户通过UDDI找到你的WSDL描述文档后,他通过可以SimpleObjectAccessProtocol(SOAP)调用你建立的Web服务中的一个或多个操作。
SOAP是XML文档形式的调用商业方法的规范,它可以支持不同的底层接口,象HTTP(S)或者SMTP。
之所以使用XML是因为它的独立于编程语言,良好的可扩展性以及强大的工业支持。之所以使用HTTP是因为几乎所有的网络系统都可以用这种协议来通信,由于它是一种简单协议,所以可以与任何系统结合,还有一个原因就是它可以利用80端口来穿越过防火墙。
SOAP的强大是因为它简单。SOAP是一种轻量级的,非常容易理解的技术,并且很容易实现。它有工业支持,可以从各主要的电子商务平台供应商那里获得。
从技术角度来看,SOAP详细指明了如何响应不同的请求以及如何对参数编码。一个SOAP封装了可选的头信息和正文,并且通常使用HTTPPOST方法来传送到一个HTTP服务器,当然其他方法也是可以的,例如SMTP。SOAP同时支持消息传送和远程过程调用。以下是一个SOAP请求。
POST/StockQuoteHTTP/1.1
Host:www.stockquoteserver.com
Content-Type:text/xml;charset="utf-8"
Content-Length:nnnn
SOAPAction:"Some-URI"
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
<SOAP-ENV:Header>
<t:Transactionxmlns:t="some-URI"SOAP-ENV:mustUnderstand="1">
5
</t:Transaction>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<m:GetLastTradePricexmlns:m="Some-URI">
<symbol>SUNW</symbol>
</m:GetLastTradePrice>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
JAXR
为了支持UDDI在Java平台上的功能,JavaAPIsforXMLRegistries(JAXR)允许开发者来访问注册中心。
值得注意的是,JAXR并不是建立Web服务必需的,你可以利用其他常用的XMLAPIs来直接集成这些协议。
JAXR是一个方便的API,它提供了JavaAPI来发布,查找以及编辑那些注册信息。它的重点在于基于XML的B2B应用,复杂的地址本查找以及对XML消息订阅的支持等Web服务。
它也可以用来访问其他类型的注册中心,象ebXML注册中心。
这些对Web服务的注册信息进行的操作,可以使用当前的一些Web服务工具来完成(例如第三方的SOAP和ebXML消息工具)。另外,当JAXP提供了一致并具有针对性的API来完成这些操作,这将使开发变得更加容易。
JAX/RPC
为了使开发人员专注于建立象SOAP那样的基于XML的请求,JCP正在开发基于RPC(JAX/RPC)的JavaAPI。JAX/RPC是用来发送和接收方法调用请求的,它基于XML协议,象SOAP,或者其他的象XMLP(XMLProtocol,要了解更多可以参考http://www.w3.org/2000/xp/)。JAX/RPC使你不用再关注这些协议的规范,使应用的开发更快速。不久,开发人员就不用直接以XML表示方法调用了。
目前有很多第三方实现了SOAP,开发人员可以在不同的层次上调用SOAP,并选择使用哪一种。将来,JAX/RPC会取代这些APIs并提供一个统一的接口来构造以及处理SOAPRPC请求。
在接收一个从商业伙伴那里过来的SOAP请求的时候,一个Javaservlet用JAX/RPC来接收这个基于XML的请求。一旦接收到请求后,servlet会调用商务方法,并且把结果回复给商业伙伴。
JAXM
当从商业合作伙伴那里接收一个Web服务的请求时,我们需要JavaAPI实现一个Servlet来处理ebXML消息,就象我们用JAX/RPC来处理SOAP请求一样。
JavaAPIforXMLMessaging(JAXM)是集成XML消息标准(象ebXML消息或者SOAP消息)的规范。
这个API是用来推动XML消息处理的,它检测那些预定单的消息格式以及约束。它控制了所有的消息封装机制,用一种直观的方式分割了消息中的信息,象路由信息,发货单。这样,开发人员只要关注消息的有效负载,而不用去担心那些消息的重复处理。
目前的开发人员用JAXP来实现JAXM将要提供的功能,JAXM将会提供一套非常具有针对性的API来处理基于XML的消息传送。这将大大简化开发人员的代码,并使它们具有统一的接口。
JAXM和JAX/RPC的差别在于处理消息导向的中间件以及远程过程调用的不同。JAXM注重于消息导向,而JAX/RPC是用来完成远程过程调用的。以下是图解。
请注意,在JAXM和JAX/RPC技术成熟之前,开发人员还是依赖于第三方的SOAPAPIs,象ApacheSOAP,IdooXOAP,以及GLUE。当JAXM和JAX/RPC正式发布后,它将为当前不同的SOAP和ebXML消息提供统一的接口。就象JDBC位多种不同的数据库提供统一的接口。
JAXB
XML绑定技术可以把XML文档和Java对象进行自由转换。
用JAXB,你可以在后台的EJB层,把XML文档转换成Java对象。同样你也可以把从EJB中取出的Java对象转换成XML文档返回给用户。
JAXB接口提供了比SAX和DOM更高级的方法来处理XML文档。它提供的特性可以在XML数据和Java类之间互相映射,提供了一个简单的方法来转换XML数据。它比逐个解析标记更简单。
2.2建立WeService的步骤
在建立WeService的时候,有三个主要步骤:
1.建立客户端联接
为了允许Applets,Applications,商业合作伙伴,浏览器和PDAs使用Web服务。
2.实现Web服务
包括工作流,数据传送,商业逻辑以及数据访问。这些功能是隐藏在Web服务后,并且为客户端工作的。
3.联接后台系统
这个系统可能包括一个或多个数据库,现存的企业信息系统,商业合作伙伴自己的系统或者Web服务,以及在多个系统中共享的数据。
基于J2EE的Web服务的核心构架:
RMI
1.RMI-IIOP
2.RMI是在java中使用remotemethodinvocation的最初的方法,RMI使用java.rmi包
RMI-IIOP是RMI的一个特殊版本,RMI-IIOP可以和CORBA兼容,RMI-IIOP使用java.rmi包和javax.rmi
JAF(Java活动构架)
开发者可以使用JAF来决定任意一块数据的类型、封装对数据的访问、寻找合适的操作、实例化相关的bean来执行这些操作等。
例如,JavaMail就是使用JAF根据MIME类型来决定实例化那一个对象。
EJB
1.EJB组件实现代码的限制
EJB组件的约束
EJB的开发者并不需要在EJB的组件实现代码中编写系统级的服务,EJB提供商/开发
者需知道并且严格地遵守一些限制,这些限制与开发稳定的和可移植的EJB组件的利益有
关。
以下是你应该回避使用的一些Java特色,并且在你的EJB组件的实现代码中要严格限
制它们的使用:
1.使用static,非final字段。建议你在EJB组件中把所有的static字段都声明为final型的。这样可以保证前后一致的运行期语义,使得EJB容器有可以在多个Java虚拟机之间分发组件实例的灵活性。
2.使用线程同步原语来同步多个组件实例的运行。避免这个问题,你就可以使EJB容器灵活的在多个Java虚拟机之间分发组件实例。
3.使用AWT函数完成键盘的输入和显示输出。约束它的原因是服务器方的商业组件意味着提供商业功能而不包括用户界面和键盘的I/O功能。
4.使用文件访问/java.io操作。EJB商业组件意味着使用资源管理器如JDBC来存储和检索数据而不是使用文件系统API。同时,部署工具提供了在部署描述器(descriptor)中存储环境实体,以至于EJB组件可以通过环境命名上下文用一种标准的方法进行环境实体查询。所以,使用文件系统的需求基本上是被排除了。
5.监听和接收socket连接,或者用socket进行多路发送。EJB组件并不意味着提供网络socket服务器功能,但是,这个体系结构使得EJB组件可以作为socket客户或是RMI客户并且可以和容器所管理的环境外面的代码进行通讯。
6.使用映象API查询EJB组件由于安全规则所不能访问的类。这个约束加强了Java平台的安全性。
7.欲创建或获得一个类的加载器,设置或创建一个新的安全管理器,停止Java虚拟机,改变输入、输出和出错流。这个约束加强了安全性同时保留了EJB容器管理运行环境的能力。
8.设置socket工厂被URL'sServerSocket,Socket和Streamhandler使用。避免这个特点,可以加强安全性同时保留了EJB容器管理运行环境的能力。
9.使用任何方法启动、停止和管理线程。这个约束消除了与EJB容器管理死锁、线程
和并发问题的责任相冲突的可能性。
通过限制使用10-16几个特点,你的目标是堵上一个潜在的安全漏洞:
10.直接读写文件描述符。
11.为一段特定的代码获得安全策略信息。
12.加载原始的类库。
13.访问Java一般角色所不能访问的包和类。
14.在包中定义一个类。
15.访问或修改安全配置对象(策略、安全、提供者、签名者和实体)。
16.使用Java序列化特点中的细分类和对象替代。
17.传递this引用指针作为一个参数或者作为返回值返回this引用指针。你必须使用
SessionContext或EntityContext中的getEJBObject()的结果。
Java2平台的安全策略
以上所列的特点事实上正是Java编程语言和Java2标准版中的标准的、强有力的特色。EJB容器允许从J2SE中使用一些或全部的受限制的特色,尽管对于EJB组件是不可用的,但需通过J2SE的安全机制来使用而不是通过直接使用J2SE的API。
Java2平台为EJB1.1规范中的EJB容器所制定的安全策略定义了安全许可集,这些许可在EJB组件的编程限制中出现。通过这个策略,定义了一些许可诸如:java.io.FilePermission,java.net.NetPermission,java.io.reflect.ReflectPermission,java.lang.security.SecurityPermission,以便加强先前所列出的编程限制。
许多EJB容器没有加强这些限制,他们希望EJB组件开发者能遵守这些编程限制或者是带有冒险想法违背了这些限制。违背这些限制的EJB组件,比标准方法依赖过多或过少的安全许可,都将很少能在多个EJB容器间移植。另外,代码中都将隐藏着一些不确定的、难以预测的问题。所有这些都足以使EJB组件开发者应该知道这些编程限制,同时也应该认真地遵守它们。
任何违背了这些编程限制的EJB组件的实现代码在编译时都不能检查出来,因为这些特点都是Java语言和J2SE中不可缺少的部分。
对于EJB组件的这些限制同样适用于EJB组件所使用的帮助/访问(helper/access)类,J2EE应用程序使用Java文档(jar)文件格式打包到一个带.ear(代表EnterpriseArchive)扩展名的文件中,这个ear文件对于发送给文件部署器来说是标准的格式。ear文件中包括在一个或多个ejb-jar文件中的EJB组件,还可能有ejb-jar所依赖的库文件。所有ear文件中的代码都是经过深思熟虑开发的应用程序并且都遵守编程限制和访问许可集。
未来版本的规范可能会指定通过部署工具来定制安全许可的能力,通过这种方法指定了一个合法的组件应授予的许可权限,也指定了一个标准方法的需求:如从文件系统中读文件应有哪些要求。一些EJB容器/服务器目前在它们的部署工具中都提供了比标准权限或多或少的许可权限,这些并不是EJB1.1规范中所需要的。
理解这些约束
EJB容器是EJB组件生存和执行的运行期环境,EJB容器为EJB组件实例提供了一些服务如:事务管理、安全持久化、资源访问、客户端连接。EJB容器也负责EJB组件实例整个生命期的管理、扩展问题以及并发处理。所以,EJB组件就这样寄居在一个被管理的执行环境中--即EJB容器。
因为EJB容器完全负责EJB组件的生命期、并发处理、资源访问、安全等等,所以与容器本身的锁定和并发管理相冲突的可能性就需要消除,许多限制都需要使用来填上潜在的安全漏洞。除了与EJB容器责任与安全冲突的问题,EJB组件还意味着仅仅聚焦于商务逻辑,它依赖于EJB容器所提供的服务而不是自己来直接解决底层的系统层的问题。
可能的问题
通常,EJB组件在容器之间的移植不可避免地与如下问题相关:
1.它需要依靠的受限制的特点在特定EJB容器中没有得到加强。
2.它需要依靠的非标准的服务从容器中可获得。
为了保证EJB组件的可移植性和一致的行为,你应该使用一个具有与Java2平台安全
策略集相一致的策略集的容器来测试EJB组件,并且其加强了前述的编程限制。
总结
EJB组件开发者应该知道这些推荐的关于EJB组件的编程限制,明白它们的重要性,并且从组件的稳定性和可移植性利益方面考虑来遵循它们。因为这些编程限制能阻止你使用标准的Java语言的特点,违背了这些编程限制在编译时不会知道,并且加强这些限制也不是EJB容器的责任。所有这些原因都使你应很小心地遵守这些编程限制,这些限制在组件的合同中已经成为了一个条款,并且它们对于建造可靠的、可移植的组件是非常重要的。
2.优化EJB
entitybean为在应用程序和设计中描述持久化商业对象(persistentbusinessobjects)提供了一个清晰的模型。在java对象模型中,简单对象通常都是以一种简单的方式进行处理但是,很多商业对象所需要的事务化的持久性管理没有得到实现。entitybean将持久化机制封装在容器提供的服务里,并且隐藏了所有的复杂性。entitybean允许应用程序操纵他们就像处理一个一般的java对象应用。除了从调用代码中隐藏持久化的形式和机制外,entitybean还允许EJB容器对对象的持久化进行优化,保证数据存储具有开放性,灵活性,以及可部署性。在一些基于EJB技术的项目中,广泛的使用OO技术导致了对entitybean的大量使用,SUN的工程师们已经积累了很多使用entityBean的经验,这篇文章就详细阐述的这些卡发经验:
*探索各种优化方法
*提供性能优化和提高适用性的法则和建议
*讨论如何避免一些教训。
法则1:只要可以,尽量使用CMP
CMP方式不仅减少了编码的工作量,而且在Container中以及container产生的数据库访问代码中包括了许多优化的可能。Container可以访问内存缓冲中的bean,这就允许它可以监视缓冲中的任何变化。这样的话就在事物没有提交之前,如果缓存的数据没有变化就不用写到数据库中。就可以避免许多不必要的数据库写操作。另外一个优化是在调用find方法的时候。通常情况下find方法需要进行以下数据库操作:
查找数据库中的纪录并且获得主键
将纪录数据装入缓存
CMP允许将这两步操作优化为一步就可以搞定。[具体怎么做我也没弄明白,原文没有具体阐述]
法则2:写代码时尽量保证对BMP和CMP都支持
许多情况下,EJB的开发者可能无法控制他们写的bean怎么样被部署,以及使用的container是不是支持CMP.
一个有效的解决方案是,将商业逻辑的编码完全和持久化机制分离。再CMP类中实现商业逻辑,然后再编写一个BMP类,用该类继承CMP类。这样的话,所有的商业逻辑都在CMP类中,而持久化机制在BMP中实现。[我觉得这种情况在实际工作中很少遇到,但是作者解决问题的思路值得学习]
法则3:把ejbStore中的数据库访问减小到最少。
如果使用BMP,设置一个缓存数据改变标志dirty非常有用。所有改变数据库中底层数据的操作,都要设置dirty,而在ejbStore()中,首先检测dirty的值,如果dirty的值没有改变,表明目前数据库中的数据与缓存的一致,就不必进行数据库操作了,反之,就要把缓存数据写入数据库。
法则4:总是将从lookup和find中获得的引用进行缓存。(cache)
引用缓存对sessionbean和entitybean都是适用的。
通过JNDIlookup获得EJB资源。比如DataSource,bean的引用等等都要付出相当大的代价。因此应该避免多余的lookup.可以这样做:
将这些引用定义为实例变量。
从setEntityContext(sessionBean使用setSessionContext)方法查找他们。SetEntityContext方法对于一个bean实例只执行一次,所有的相关引用都在这一次中进行查找,这样查找的代价就不是那么昂贵了。应该避免在其他方法中查找引用。尤其是访问数据库的方法:ejbLoad()和ejbStore(),如果在这些频繁调用的方法中进行DataSource的查找,势必造成时间的浪费。
调用其他entitybean的finder方法也是一种重量级的调用。多次调用finder()方法的代价非常高。如果这种引用不适合放在setEntityContext这样的初始化时执行的方法中执行,就应该在适当的时候缓存finder的执行结果。只是要注意的是,如果这个引用只对当前的entity有效,你就需要在bean从缓冲池中取出来代表另外一个实体时清除掉这些引用。,这些操作应该在ejbActivate()中进行。
法则5:总是使用preparestatements
这条优化法则适用于所有访问关系数据库的操作。
数据库在处理每一个SQLStatement的时候,执行前都要对Statement进行编译。一些数据库具有缓存statement和statement的编译后形式的功能。数据库可以把新的Statement和缓存中的进行匹配。然而,如果要使用这一优化特性,新的Statement要必须和缓存中的Statement完全匹配。
对于Non-preparedStatement,数据和Statement本身作为一个字符串传递,这样由于前后调用的数据不同而不能匹配,就导致无法使用这种优化。而对于preparedStatement,数据和Statement是分开传递给数据库的,这样Statement就可以和cache中已编译的Statement进行匹配。Statement就不必每次都进行编译操作。从而使用该优化属性。
这项技术在一些小型的数据库访问中能够减少Statement将近90%的执行时间。
法则6:完全关闭所有的Statement
在编写BMP的数据库访问代码时,记住一定要在数据库访问调用之后关闭Statement,因为每个打开的Statement对应于数据库中的一个打开的游标。
Security
1.加密
对称加密
(1)分组密码
(2)流密码
常用的对称加密算法:
DES和TripleDES
Blowfish
RC4
AES
非对称加密
常用的非对称加密算法
RSA
ElGamal
会话密钥加密(对称加密和非对称加密一起使用)
常用的会话密钥加密协议
S/MIME
PGP
SSL和TLSSSL是在Applicationlevelprotocal和Transportprotocal之间的。
比如:Http和TCP/IP之间
SSL提供了服务器端认证和可选的客户端认证,保密性和数据完整性。
提供基于SSL方式的传输加密和认证,确保以下三种安全防护:
数据的机密性和准确性、
服务器端认证
客户端认证。
客户端认证比服务器端认证不很普遍的原因是每一个要被认证的客户都必须有一张Verisign这样的CA签发的证书。
通常,在进行身份认证的时候,应当只接受一个CA,这个CA的名字包含在客户证书中。
由于不可能随意创建一个由指定CA签发的证书,所以这可以有效的防御通过伪造证书来进行的攻击尝试。
2.认证(Authentication)
认证就是确定一条消息或一个用户的可靠性的过程。
1.消息摘要
MD5
SHA和SHA-1
2.消息认证码(MessageAuthienticationCodes,MAC)
3.数字签名
用户可以用自己的密钥对信息加以处理,由于密钥仅为本人所有,这样就产生了别人无法生成的文件,也就形成了数字签名
数字签名可以
1)保证数据的完整性
2)验证用户的身份
数字签名采用一个人的私钥计算出来,然后用公钥去检验。
hash算法私钥加密
原报文――――――>报文摘要(MessageDigest)―――――>数字签名
原报文和数字签名一起被发送到接受者那里,接受者用同样的hash算法得到报文摘要,然后用发送者的公钥解开数字签名。
比较是否相同,则可以确定报文确定来自发送者。
验证数字签名必须使用公钥,但是,除非你是通过安全的方式直接得到,否则不能保证公钥的正确性。(数字证书可以解决这个问题)
一个接受者在使用公钥(publickey)检查数字签名(digitalsignature)的可信度时,通常先要检查收到的公钥(publickey)是否可信的。
因此发送方不是单单地发送公钥(publickey),而是发送一个包含公钥(publickey)的数字证书(cetificate)。
4.数字证书
数字证书是一个经证书授权中心数字签名的包含公开密钥所有者信息以及公开密钥的文件。
数字证书Cetificate中包括:
I.用户的公钥(publickey)
II.用户的一些信息,如姓名,email
III.发行机构的数字签名(digitalsignature),用于保证证书的可信度
IV.发行机构的一些信息
数字证书的格式遵循X.509国际标准。
注意:一个数字证书certificate并不适用于多种browser,甚至一种Browser的多个版本。
数字标识由公用密钥、私人密钥和数字签名三部分组成。
当在邮件中添加数字签名时,您就把数字签名和公用密钥加入到邮件中。数字签名和公用密钥统称为证书。您可以使用OutlookExpress来指定他人向您发送加密邮件时所需使用的证书。这个证书可以不同于您的签名证书。
收件人可以使用您的数字签名来验证您的身份,并可使用公用密钥给您发送加密邮件,这些邮件必须用您的私人密钥才能阅读。
要发送加密邮件,您的通讯簿必须包含收件人的数字标识。这样,您就可以使用他们的公用密钥来加密邮件了。当收件人收到加密邮件后,用他们的私人密钥来对邮件进行解密才能阅读。
在能够发送带有数字签名的邮件之前,您必须获得数字标识。如果您正在发送加密邮件,您的通讯簿中必须包含每位收件人的数字标识。
数字证书,可以是个人证书或Web站点证书,用于将身份与"公开密钥"关联。只有证书的所有者才知道允许所有者"解密"或进行"数字签名"的相应"私人密钥"。当您将自己的证书发送给其他人时,实际上发给他们的是您的公开密钥,这样他们就可以向您发送只能由您使用私人密钥解密和读取的加密信息。
通过浏览器使用数字证书,必须先要设置浏览器软件InternetExplorer或NetScape使用此证书,才能开始发送加密或需要数字签名的信息。访问安全的Web站点(以"https"打头的站点)时,该站点将自动向您发送他们的Web站点证书。
3.CA(证书授证中心)
CA机构,又称为证书授证(CertificateAuthority)中心,作为电子商务交易中受信任的第三方,承担公钥体系中公钥的合法性检验的责任。CA中心为每个使用公开密钥的用户发放一个数字证书,数字证书的作用是证明证书中列出的用户合法拥有证书中列出的公开密钥。CA机构的数字签名使得攻击者不能伪造和篡改证书。在SET交易中,CA不仅对持卡人、商户发放证书,还要对获款的银行、网关发放证书。它负责产生、分配并管理所有参与网上交易的个体所需的数字证书,因此是安全电子交易的核心环节。
对证书的信任基于对根证书的信任.例如在申请SHECA的个人数字证书前,需要先下载根证书,然后再进行各类证书的申请。
下载根证书的目的:
网络服务器验证(S);安全电子邮件(E)
申请个人数字证书可以为Internet用户提供发送电子邮件的安全和访问需要安全连接(需要客户证书)的站点。
1)个人数字证书
a.个人身份证书
个人身份证书是用来表明和验证个人在网络上的身份的证书,它确保了网上交易和作业的安全性和可靠性。可应用于:网上炒股、网上理财、网上保险、网上缴费、网上购物、网上办公等等。个人身份证书可以存储在软盘或IC卡中。
b.个人安全电子邮件证书
个人安全电子邮件证书可以确保邮件的真实性和保密性。申请后一般是安装在用户的浏览器里。用户可以利用它来发送签名或加密的电子邮件。
用户在申请安装完安全安全电子邮件数字证书后,就可以对要发送的邮件进行数字签名。收信人收到该邮件后,就可以看到数字签名的标记,这样就可以证明邮件肯定来自发信者本人,而不是别人盗用该帐号伪造信件,同时也保证该邮件在传送过程中没被他人篡改过任何数据。
安全电子邮件中使用的数字证书可以实现:
保密性通过使用收件人的数字证书对电子邮件加密。如此以来,只有收件人才能阅读加密的邮件,在Internet上传递的电子邮件信息不会被人窃取,即使发错邮件,收件人也无法看到邮件内容。
认证身份在Internet上传递电子邮件的双方互相不能见面,所以必须有方法确定对方的身份。利用发件人数字证书在传送前对电子邮件进行数字签名即可确定发件人身份,而不是他人冒充的。
完整性利用发件人数字证书在传送前对电子邮件进行数字签名不仅可确定发件人身份,而且传递的电子邮件信息也不能被人在传输过程中修改。
不可否认性由于发件人的数字证书只有发件人唯一拥有,故发件人利用其数字证书在传送前对电子邮件进行数字签名,发件人就无法否认发过这个电子邮件。
OutLookExpress中的个人安全电子邮件证书
签名邮件带有签名邮件图标。
签名邮件可能出现的任何问题都将在本信息之后可能出现的“安全警告”中得到描述。如果存在问题,您应该认为邮件已被篡改,或并非来自所谓的发件人。
当收到一封加密邮件时,您应该可以自信地认为邮件未被任何第三者读过。OutlookExpress会自动对电子邮件解密,如果在您的计算机上装有正确的数字标识。
2)企业数字证书
a.企业身份证书
企业身份证书是用来表明和验证企业用户在网络上身份的证书,它确保了企业网上交易和作业的安全性和可靠性。可应用于:网上证券、网上办公、网上交税、网上采购、网上资金转帐、网上银行等。企业身份证书可以存储在软盘和IC卡中。
b.企业安全电子邮件证书
企业安全电子邮件证书可以确保邮件的真实性和保密性。申请后一般是安装在用户的浏览器里。企业可以利用它来发送签名或加密的电子邮件。
可使用Windows2000中的证书服务来创建证书颁发机构(CA),它负责接收证书申请、验证申请中的信息和申请者的身份、颁发证书、吊销证书以及发布证书吊销列表(CRL)。
通常,当用户发出证书申请时,在其计算机上的加密服务提供程序(CSP)为用户生成公钥和私钥对。用户的公钥随同必要的识别信息发送至CA。如果用户的识别信息符合批准申请的CA标准,那么CA将生成证书,该证书由客户应用程序检索并就地存储。
4.SET
安全接口层协议——SSL(SecureSocketsLayer),并且已经几乎成为了目前WWW世界的事实标准。这一标准使用公共密钥编码方案来对传输数据进行加密,在双方之间建立一个Internet上的加密通道,从而使第三方无法获得其中的信息,其思路与目前流行的VPN方案大致相同,目的都是要保护数据不被未经授权的第三方所,或即使到也不知所云。但就象VPN一样,SSL在认证方面没有任何作为,它们都需要通过另外的手段来确认身份和建立双方彼此间的信任,然后再通过SSL进行交易。
正是由于SSL标准在认证方面的缺憾,所以SET才有存在的必要。SET(SecureElectronicTransactions)规范由Mastercard和Visa公司于1996年发布,专家们认为SET是保证用户与商家在电子商务与在线交易中免受欺骗的重要手段。传统的信用卡交易者总在担心不诚实的店员会将自己的信用卡号码透露给他人,而在线交易也是如此,持卡者总在担心服务器端的管理员会将信用卡号码泄露出去,或者担心黑客会在管理员不知情的情况下盗取信用卡号码。事实上这些担心都是必要的,而SET标准则可以保证用户的信用卡号码只传送给信用卡公司进行认证,不会被系统管理员看到,也不会留在交易服务器的硬盘上给黑客以可乘之机。
5.PKI
PKI是一种易于管理的、集中化的网络安全方案。它可支持多种形式的数字认证:数据加密、数字签字、不可否认、身份鉴别、密钥管理以及交叉认证等。PKI可通过一个基于认证的框架处理所有的数据加密和数字签字工作。PKI标准与协议的开发迄今已有15年的历史,目前的PKI已完全可以向企业网络提供有效的安全保障。
PKI是一种遵循标准的密钥管理平台,它能够为所有网络应用透明地提供采用加密和数字签名等密码服务所必需的密钥和证书管理。PKI必须具有
1)CA、
2)证书库、
3)密钥备份及恢复系统、
4)证书作废处理系统、
5)客户端证书处理系统
等基本成分,构建PKI也将围绕着这五大系统来构建
一个PKI由众多部件组成,这些部件共同完成两个主要功能:
1)为数据加密
2)创建数字认证。
服务器(即后端)产品是这一系统的核心,这些数据库管理着数字认证、公共密钥及专用密钥(分别用于数据的加密和解密)。
CA数据库负责发布、废除和修改X.509数字认证信息,它装有用户的公共密钥、证书有效期以及认证功能(例如对数据的加密或对数字签字的验证)。为了防止对数据签字的篡改,CA在把每一数字签字发送给发出请求的客户机之前,需对每一个数字签字进行认证。一旦数字认证得以创建,它将会被自动存储于X.500目录中,X.500目录为树形结构。LDAP(LightweightDirectoryAccessProtocol)协议将响应那些要求提交所存储的公共密钥认证的请求。CA为每一用户或服务器生成两对独立的公共和专用密钥。其中一对用于信息的加密和解密,另一对由客户机应用程序使用,用于文档或信息传输中数字签字的创建。
大多数PKI均支持证书分布,这是一个把已发布过的或续延生命期的证书加以存储的过程。这一过程使用了一个公共查询机制,X.500目录可自动完成这一存储过程。影响企业普遍接受PKI的一大障碍是不同CA之间的交叉认证。假设有两家公司,每一家企业分别使用来自不同供应商的CA,现在它们希望相互托管一段时间。如果其后援数据库支持交叉认证,则这两家企业显然可以互相托管它们的CA,因而它们所托管的所有用户均可由两家企业的CA所托管。
*认证机关
CA是证书的签发机构,它是PKI的核心。众所周知,构建密码服务系统的核心内容是如何实现密钥管理,公钥体制涉及到一对密钥,即私钥和公钥,私钥只由持有者秘密掌握,无须在网上传送,而公钥是公开的,需要在网上传送,故公钥体制的密钥管理主要是公钥的管理问题,目前较好的解决方案是引进证书(certificate)机制。
证书是公开密钥体制的一种密钥管理媒介。它是一种权威性的电子文档,形同网络计算环境中的一种身份证,用于证明某一主体(如人、服务器等)的身份以及其公开密钥的合法性。在使用公钥体制的网络环境中,必须向公钥的使用者证明公钥的真实合法性。因此,在公钥体制环境中,必须有一个可信的机构来对任何一个主体的公钥进行公证,证明主体的身份以及他与公钥的匹配关系。CA正是这样的机构,它的职责归纳起来有:
1、验证并标识证书申请者的身份;
2、确保CA用于签名证书的非对称密钥的质量;
3、确保整个签证过程的安全性,确保签名私钥的安全性;
4、证书材料信息(包括公钥证书序列号、CA标识等)的管理;
5、确定并检查证书的有效期限;
6、确保证书主体标识的唯一性,防止重名;
7、发布并维护作废证书表;
8、对整个证书签发过程做日志记录;
9、向申请人发通知。
其中最为重要的是CA自己的一对密钥的管理,它必须确保其高度的机密性,防止他方伪造证书。CA的公钥在网上公开,整个网络系统必须保证完整性。
*证书库
证书库是证书的集中存放地,它与网上"白页”类似,是网上的一种公共信息库,用户可以从此处获得其他用户的证书和公钥。
构造证书库的最佳方法是采用支持LDAP协议的目录系统,用户或相关的应用通过LDAP来访问证书库。系统必须确保证书库的完整性,防止伪造、篡改证书。
*密钥备份及恢复系统
*证书作废处理系统
*PKI应用接口系统
PKI的价值在于使用户能够方便地使用加密、数字签名等安全服务,因此一个完整的PKI必须提供良好的应用接口系统,使得各种各样的应用能够以安全、一致、可信的方式与PKI交互,确保所建立起来的网络环境的可信性,同时降低管理维护成本。最后,PKI应用接口系统应该是跨平台的。
许多权威的认证方案供应商(例如VeriSign、Thawte以及GTE)目前都在提供外包的PKI。外包PKI最大的问题是,用户必须把企业托管给某一服务提供商,即让出对网络安全的控制权。如果不愿这样做,则可建造一个专用的PKI。专用方案通常需把来自Entrust、BaltimoreTechnologies以及Xcert的多种服务器产品与来自主流应用程序供应商(如Microsoft、Netscape以及Qualcomm)的产品组合在一起。专用PKI还要求企业在准备其基础设施的过程中投入大量的财力与物力。
7.JAAS
扩展JAAS实现类实例级授权
“Java认证和授权服务”(JavaAuthenticationandAuthorizationService,JAAS)
在JAAS下,可以给予用户或服务特定的许可权来执行Java类中的代码。在本文中,软件工程师CarlosFonseca向您展示如何为企业扩展JAAS框架。向JAAS框架添加类实例级授权和特定关系使您能够构建更动态、更灵活并且伸缩性更好的企业应用程序。
大多数Java应用程序都需要某种类实例级的访问控制。例如,基于Web的、自我服务的拍卖应用程序的规范可能有下列要求:
任何已注册(经过认证)的用户都可以创建一个拍卖,但只有创建拍卖的用户才可以修改这个拍卖。
这意味着任何用户都可以执行被编写用来创建Auction类实例的代码,但只有拥有该实例的用户可以执行用来修改它的代码。通常情况下,创建Auction实例的用户就是所有者。这被称为类实例所有者关系(classinstanceownerrelationship)。
该应用程序的另一个要求可能是:
任何用户都可以为拍卖创建一个投标,拍卖的所有者可以接受或拒绝任何投标。
再一次,任何用户都可以执行被编写用来创建Bid类实例的代码,但只有拥有该实例的用户会被授予修改该实例的许可权。而且,Auction类实例的所有者必须能够修改相关的Bid类实例中的接受标志。这意味着在Auction实例和相应的Bid实例之间有一种被称为特定关系(specialrelationship)的关系。
不幸的是,“Java认证和授权服务”(JAAS)—它是Java2平台的一部分—没有考虑到类实例级访问控制或者特定关系。在本文中,我们将扩展JAAS框架使其同时包含这两者。推动这种扩展的动力是允许我们将访问控制分离到一个通用的框架,该框架使用基于所有权和特定关系的策略。然后管理员可以在应用程序的生命周期内更改这些策略。
在深入到扩展JAAS框架之前,我们将重温一下Java2平台的访问控制机制。我们将讨论策略文件和许可权的使用,并讨论SecurityManager和AccessController之间的关系。
Java2平台中的访问控制
在Java2平台中,所有的代码,不管它是本地代码还是远程代码,都可以由策略来控制。策略(policy)由不同位置上的代码的一组许可权定义,或者由不同的签发者定义、或者由这两者定义。许可权允许对资源进行访问;它通过名称来定义,并且可能与某些操作关联在一起。
抽象类java.security.Policy被用于表示应用程序的安全性策略。缺省的实现由sun.security.provider.PolicyFile提供,在sun.security.provider.PolicyFile中,策略被定义在一个文件中。清单1是一个典型策略文件示例:
清单1.一个典型的策略文件
//Grantthesepermissionstocodeloadedfromasample.jarfile
//intheCdriveandifitissignedbyXYZ
grantcodebase"file:/C:/sample.jar",signedby"XYZ"{
//Allowsocketactionstoanyhostusingport8080
permissionjava.net.SocketPermission"*:8080","accept,connect,
listen,resolve";
//Allowsfileaccess(read,write,execute,delete)in
//theuser'shomedirectory.
Permissionjava.io.FilePermission"${user.home}/-","read,write,
execute,delete";
};
SecurityManager对AccessController
在标准JDK分发版中,控制代码源访问的机制缺省情况下是关闭的。在Java2平台以前,对代码源的访问都是由SecurityManager类管理的。SecurityManager是由java.security.manager系统属性启动的,如下所示:
java-Djava.security.manager
在Java2平台中,可以将一个应用程序设置为使用java.lang.SecurityManager类或者java.security.AccessController类管理敏感的操作。AccessController在Java2平台中是新出现的。为便于向后兼容,SecurityManager类仍然存在,但把自己的决定提交AccessController类裁决。SecurityManager和AccessController都使用应用程序的策略文件确定是否允许一个被请求的操作。清单2显示了AccessController如何处理SocketPermission请求:
清单2.保护敏感操作
PublicvoidsomeMethod(){
Permissionpermission=
newjava.net.SocketPermission("localhost:8080","connect");
AccessController.checkPermission(permission);
//Sensitivecodestartshere
Sockets=newSocket("localhost",8080);
}
在这个示例中,我们看到AccessController检查应用程序的当前策略实现。如果策略文件中定义的任何许可权暗示了被请求的许可权,该方法将只简单地返回;否则抛出一个AccessControlException异常。在这个示例中,检查实际上是多余的,因为缺省套接字实现的构造函数也执行相同的检查。
在下一部分,我们将更仔细地看一下AccessController如何与java.security.Policy实现共同合作安全地处理应用程序请求。
运行中的AccessController
AccessController类典型的checkPermission(Permissionp)方法调用可能会导致下面的一系列操作:
AccessController调用java.security.Policy类实现的getPermissions(CodeSourcecodeSource)方法。
getPermissions(CodeSourcecodeSource)方法返回一个PermissionCollection类实例,这个类实例代表一个相同类型许可权的集合。
AccessController调用PermissionCollection类的implies(Permissionp)方法。
接下来,PermissionCollection调用集合中包含的单个Permission对象的implies(Permissionp)方法。如果集合中的当前许可权对象暗示指定的许可权,则这些方法返回true,否则返回false。
现在,让我们更详细地看一下这个访问控制序列中的重要元素。
PermissionCollection类
大多数许可权类类型都有一个相应的PermissionCollection类。这样一个集合的实例可以通过调用Permission子类实现定义的newPermissionCollection()方法来创建。java.security.Policy类实现的getPermissions()方法也可以返回Permissions类实例—PermissionCollection的一个子类。这个类代表由PermissionCollection组织的不同类型许可权对象的一个集合。Permissions类的implies(Permissionp)方法可以调用单个PermissionCollection类的implies(Permissionp)方法。
CodeSource和ProtectionDomain类
许可权组合与CodeSource(被用于验证签码(signedcode)的代码位置和证书)被封装在ProtectionDomain类中。有相同许可权和相同CodeSource的类实例被放在相同的域中。带有相同许可权,但不同CodeSource的类被放在不同的域中。一个类只可属于一个ProtectionDomain。要为对象获取ProtectionDomain,请使用java.lang.Class类中定义的getProtectionDomain()方法。
许可权
赋予CodeSource许可权并不一定意味着允许所暗示的操作。要使操作成功完成,调用栈中的每个类必须有必需的许可权。换句话说,如果您将java.io.FilePermission赋给类B,而类B是由类A来调用,那么类A必须也有相同的许可权或者暗示java.io.FilePermission的许可权。
在另一方面,调用类可能需要临时许可权来完成另一个拥有那些许可权的类中的操作。例如,当从另一个位置加载的类访问本地文件系统时,我们可能不信任它。但是,本地加载的类被授予对某个目录的读许可权。这些类可以实现PrivilegedAction接口来给予调用类许可权以便完成指定的操作。调用栈的检查在遇到PrivilegedAction实例时停止,有效地将执行指定操作所必需的许可权授予所有的后继类调用。
使用JAAS
顾名思义,JAAS由两个主要组件组成:认证和授权。我们主要关注扩展JAAS的授权组件,但开始我们先简要概述一下JAAS认证,紧接着看一下一个简单的JAAS授权操作。
JAAS中的用户认证
JAAS通过添加基于subject的策略加强了Java2中定义的访问控制安全性模型。许可权的授予不仅基于CodeSource,还基于执行代码的用户。显然,要使这个模型生效,每个用户都必须经过认证。
JAAS的认证机制建立在一组可插登录模块的基础上。JAAS分发版包含几个LoginModule实现。LoginModules可以用于提示用户输入用户标识和密码。LoginContext类使用一个配置文件来确定使用哪个LoginModule对用户进行认证。这个配置可以通过系统属性java.security.auth.login.config指定。一个示例配置是:
java-Djava.security.auth.login.config=login.conf
下面是一个登录配置文件的样子:
Example{
com.ibm.resource.security.auth.LoginModuleExamplerequired
debug=trueuserFile="users.xml"groupFile="groups.xml";
};
认识您的主体
Subject类被用于封装一个被认证实体(比如用户)的凭证。一个Subject可能拥有一个被称为主体(principal)的身份分组。例如,如果Subject是一个用户,用户的名字和相关的社会保险号可能是Subject的某些身份或主体。主体是与身份名关联在一起的。
Principal实现类及其名称都是在JAAS策略文件中指定的。缺省的JAAS实现使用的策略文件与Java2实现的策略文件相似—除了每个授权语句必须与至少一个主体关联在一起。javax.security.auth.Policy抽象类被用于表示JAAS安全性策略。它的缺省实现由com.sun.security.auth.PolicyFile提供,在com.sun.security.auth.PolicyFile中策略定义在一个文件中。清单3是JAAS策略文件的一个示例:
清单3.示例JAAS策略文件
//Examplegrantentry
grantcodeBase"file:/C:/sample.jar",signedby"XYZ",
principalcom.ibm.resource.security.auth.PrincipalExample"admin"{
//Allowsocketactionstoanyhostusingport8080
permissionjava.net.SocketPermission
"*:8080","accept,connect,listen,resolve";
//Allowsfileaccess(read,write,execute,delete)in
//theuser'shomedirectory.
Permissionjava.io.FilePermission
"${user.home}/-","read,write,execute,delete";
};
这个示例与清单1中所示的标准Java2策略文件相似。实际上,唯一的不同是主体语句,该语句声明只有拥有指定主体和主体名字的subject(用户)被授予指定的许可权。
再一次,使用系统属性java.security.auth.policy指出JAAS策略文件驻留在何处,如下所示:
java-Djava.security.auth.policy=policy.jaas
Subject类包含几个方法来作为特殊subject执行工作;这些方法如下所示:
publicstaticObject
doAs(Subjectsubject,java.security.PrivilegedActionaction)
publicstaticObject
doAs(Subjectsubject,java.security.PrivilegedActionaction)
throwsjava.security.PrivilegedActionException
注意,用来保护敏感代码的方法与“Java2代码源访问控制”(Java2CodeSourceAccessControl)概述中描述的方法相同。请参阅参考资料部分以了解更多关于JAAS中代码源访问控制和认证的信息。
JAAS中的授权
清单4显示一个授权请求的结果,该请求使用清单3中显示的JAAS策略文件。假设已经安装了SecurityManager,并且loginContext已经认证了一个带有名为“admin”的com.ibm.resource.security.auth.PrincipalExample主体的Subject。
清单4.一个简单的授权请求
publicclassJaasExample{
publicstaticvoidmain(String[]args){
...
//whereauthenticatedUserisaSubjectwith
//aPrincipalExamplenamedadmin.
Subject.doAs(authenticatedUser,newJaasExampleAction());
...
}
}
publicclassJaasExampleActionimplementsPrivilegedAction{
publicObjectrun(){
FileWriterfw=newFileWriter("hi.txt");
fw.write("Hello,World!");
fw.close();
}
}
这里,敏感代码被封装在JaasExampleAction类中。还要注意,调用类不要求为JaasExampleAction类代码源授予许可权,因为它实现了一个PrivilegedAction。
扩展JAAS
大多数应用程序都有定制逻辑,它授权用户不仅仅在类上执行操作,而且还在该类的实例上执行操作。这种授权通常建立在用户和实例之间的关系上。这是JAAS的一个小缺点。然而,幸运的是,这样设计JAAS使得JAAS可以扩展。只要做一点工作,我们将可以扩展JAAS,使其包含一个通用的、类实例级的授权框架。
在文章开头处我已经说明了,抽象类javax.security.auth.Policy被用于代表JAAS安全性策略。它的缺省实现是由com.sun.security.auth.PolicyFile类提供。PolicyFile类从JAAS格式的文件(象清单3中显示的那个一样)中读取策略。
我们需要向这个文件添加一个东西为类实例级授权扩展策略定义:一个与许可权语句相关的可选关系参数。
缺省JAAS许可权语句的格式如下:
permission<permissionimplementationclass>[name],[actions];
我们在这个许可权语句的末尾添加一个可选的关系参数来完成策略定义。下面是新许可权语句的格式:
permission<permissionimplementationclass>
[name],[actions],[relationship];
在为类实例级授权扩展JAAS时要注意的最重要的一点是:许可权实现类必须有一个带三个参数的构造函数。第一个参数是名称参数,第二个是行为参数,最后一个是关系参数。
解析新文件格式
既然文件格式已经改变,就需要一个新的javax.security.auth.Policy子类来解析文件。
为简单起见,我们的示例使用了一个新的javax.security.auth.Policy子类com.ibm.resource.security.auth.XMLPolicyFile,来从XML文件读取策略。在实际的企业应用程序中,关系数据库更适合执行这个任务。
使用XMLPolicyFile类代替缺省的JAAS访问控制策略实现的最容易的方法是向java.security属性文件添加auth.policy.provider=com.ibm.resource.security.auth.XMLPolicyFile条目。java.security属性文件位于Java2平台运行时的lib/security目录下。清单5是与XMLPolicyFile类一起使用的样本XML策略文件:
清单5.一个XML策略文件
<?xmlversion="1.0"?>
<policy>
<grantcodebase="file:/D:/sample_actions.jar">
<principalclassname=
"com.ibm.resource.security.auth.PrincipalExample"name="users">
<permissionclassname=
"com.ibm.resource.security.auth.ResourcePermission"
name="com.ibm.security.sample.Auction"
actions="create"/>
<permissionclassname=
"com.ibm.resource.security.auth.ResourcePermission"
name="com.ibm.security.sample.Auction"
actions="read"/>
<permissionclassname=
"com.ibm.resource.security.auth.ResourcePermission"
name="com.ibm.security.sample.Auction"
actions="write"
relationship="owner"/>
<permissionclassname=
"com.ibm.resource.security.auth.ResourcePermission"
name="com.ibm.security.sample.Bid"
actions="create"/>
<permissionclassname=
"com.ibm.resource.security.auth.ResourcePermission"
name="com.ibm.security.sample.Bid"
actions="read"/>
<permissionclassname=
"com.ibm.resource.security.auth.ResourcePermission"
name="com.ibm.security.sample.Bid"
actions="write"
relationship="owner"/>
<permissionclassname=
"com.ibm.resource.security.auth.ResourcePermission"
name="com.ibm.security.sample.Bid"
actions="accept"
relationship="actionOwner"/>
</principal>
</grant>
</policy>
在这个示例策略文件中,任何与名为PrincipalExample的用户有关的用户(Subject)都可以创建并读取一个Auction.class实例。但是,只有创建该实例的用户才可以更新(写)它。这是第三个permission元素定义的,该元素包含值为owner的relationship属性。Bid.class实例也是一样,除了相应Auction.class实例的所有者可以更改投标接受标志。
Resource接口
要求类实例级访问控制的类必须实现Resource接口。该接口的getOwner()方法返回类实例的所有者。fulfills(Subjectsubject,Stringrelationship)方法被用于处理特定关系。另外,这些类使用com.ibm.resource.security.auth.ResourcePermission类保护敏感代码。例如,Auction类拥有下列构造函数:
publicAuction(){
Permissionpermission=
newResourcePermission("com.ibm.security.sample.Auction","create");
AccessController.checkPermission(permission);
}
所有者关系
ResourcePermission类的implies(Permissionp)方法是这个框架的关键。implies()方法就等同性比较名称和行为属性。如果定义了一个关系,那么必须把受保护的类实例(Resource)传递到ResourcePermission构造函数中。ResourcePermission类理解所有者关系。它将类实例的所有者与执行代码的subject(用户)进行比较。特定关系被委托给受保护类的fulfills()方法。
例如,在清单5中所示的XML策略文件中,只有Auction类实例的所有者可以更新(写)文件。该类的setter方法使用清单6中显示的保护代码:
清单6.运行中的implies(Permission)方法
publicvoidsetName(StringnewName){
Permissionpermission=
newResourcePermission("com.ibm.security.sample.Auction","write",this);
AccessController.checkPermission(permission);
//sensitivecode
this.name=newName;
}
被传递到ResourcePermission构造函数中的this引用代表Auction类实现的Resource接口。由于策略文件中列出的关系是owner,所以ResourcePermission类使用这个引用检查当前Subject(用户)是否拥有与实例所有者相匹配的主体。如果指定了另一个关系,那么ResourcePermission类调用Auction类的fulfills(Subjectsubject,Stringrelationship)方法。由Resource实现类提供fulfills()方法中的逻辑。
XML策略文件中列出的Bid类拥有清单7中所示的方法(假设Bid类实例有一个对相应Auction类实例的引用—auction)。
清单7.处理特定关系
publicvoidsetAccepted(booleanflag){
Permissionpermission=
newResourcePermission("com.ibm.security.sample.Auction","accept",this);
AccessController.checkPermission(permission);
//sensitivecode
this.accepted=flag;
}
publicbooleanfulfills(Subjectuser,Stringrelationship){
if(relationship.equalsIgnoreCase("auctionOwner")){
StringauctionOwner=auction.getOwner();
IteratorprincipalIterator=user.getPrincipals().iterator();
while(principalIterator.hasNext()){
Principalprincipal=(Principal)principalIterator.next();
if(principal.getName().equals(auctionOwner))
returntrue;
}
}
returnfalse;
}
传递到fulfills()方法中的关系字符串是策略文件中列出的关系。在这个案例中,我们使用了“auctionOwner”字符串。
缺省情况下,XMLPolicyFile类在当前工作目录中查找名为ResourcePolicy.xml的文件。系统属性com.ibm.resource.security.auth.policy可以用于指定另一个不同的文件名和位置。
WebSphereApplicationServer示例
除命令行示例之外,您可能还想运行这个简单的程序,该程序为了IBMWebSphereApplicationServer,version4.0.2而被优化。
一个可运行的示例
综合这些信息,我们将运行一个简单的命令行示例。该示例程序包含三个jar文件:
resourceSecurity.jar
example.jar
exampleActions.jar
resourceSecurity.jar文件包含允许实例级访问控制的JAAS扩展框架。它还包含一个LoginModuleExample类,这个类从XML文件读取用户认证信息。用户标识和密码存储在users.xml文件中。用户组存储在groups.xml文件中。关于LoginModuleExample的更多信息,请参阅参考资料部分。
该示例包含四个附加的文件:
login.conf
policy
resourcePolicy.xml
run.bat
在试图运行这个示例程序之前,请确保更新了run.bat、policy和resourcePolicy.xml文件中的路径。缺省情况下,所有的密码都是“passw0rd”。
示例如何工作
该示例程序提示输入用户标识和密码。它用users.xml文件中的条目核对所提供的用户标识和密码。在认证了用户之后,程序设法创建一个UserProfile类实例,修改它并从中读取。缺省情况下,UserProfile类的所有者是Jane(jane)。当Jane登录时,三个操作全部成功。当John(john)登录时,只有创建操作成功。当Jane的经理Lou(lou)登录时,只有第一个和最后一个操作成功。当系统管理员(admin)登录时,操作全部成功。当然,只有当提供的ResourcePolicy.xml文件未被修改时,上述这些才都是真的。
示例安装
下面的安装指导假设您正在使用JDK1.3并且已经把文件解压缩到d:\JaasExample目录。通过将文件解压缩到这个目录,您可以省去一些工作;否则您就必须使用正确的路径名修改policy和ResourceSecurity.xml策略文件。
下面是运行该示例需要做的工作:
下载这个示例的源文件。
把jaas.jar和jaasmod.jar复制到JDKjre\lib\ext目录(即D:\JDK1.3\jre\lib\ext)。
向位于JDK的jre\lib\security目录(即D:\JDK1.3\jre\lib\security)中的java.security文件的末尾添加下面的字符串:auth.policy.provider=com.ibm.resource.security.auth.XMLPolicyFile。
执行run.bat文件。
结束语
类实例级授权把访问控制分离到一个通用框架(该框架使用基于所有权和特定关系的策略)中。然后管理员可以在应用程序的生命周期内更改这些策略。用这种方法扩展JAAS减少了您或另一个程序员必须在应用程序生命周期内业务规则发生更改时重写代码的可能性。
通过将关系字符串抽象为类可以进一步扩展特定关系这个概念。不调用Resource实现类的fulfills(Subjectuser,Stringrelationship)方法,而只要调用Relationship实现类中定义的新fulfills(Subjectuser,Resourceresource)方法。这样就会允许许多Resource实现类使用相同的关系逻辑。
6.Java的安全性
1.thesecuritymanager是一个application-wideobject(java.lang.SecurityManager)
每个JavaApplication都可以有自己地SecurityManager,但是默认地JavaApplication没有一个SecurityManager
可以通过下面地代码得到一个SecurityManager
try
{
System.setSecurityManager(newSecurityManager(“--”));
}
catch()
{}
2.
JDBC
在JDBC2开发的过程中,SQL99还处在一种变化不定的情况下。现在规范已经完成了,而且数据库厂商已经采用了部分标准。所以自然地,JDBC规范就跟着将自己与SQL99功能的一部分相统一。最新的JDBC规范已经采用了SQL99标准中那些已经被广泛支持的功能,还有那些在五年内可能会获得支持的功能。
1.DataSource
在JDBC2.0OptionalPackage中,提供了透明的连接池(Connectionpooling)。
一旦配置了J2EE应用服务器后,只要用DataSource获取连接(Connection),连接池(Connectionpooling)就会自动的工作。
如果用户希望建立一个数据库连接,通过查询在JNDI服务中的DataSource,可以从DataSource中获取相应的数据库连接。
DataSource被认为是从JNDI中获取的网络资源。
DataSource在池中保存的对象都实现了PooledConnection接口。
当应用程序向DataSource请求一个Connection时,它会找到一个可用的PooledConnection对象。
如果连接池空了,它就向ConnectionPoolecDataSource请求一个新的PooledConnection对象
通过使用DataSource接口(JDBC2.0)或DriverManager(JDBC1.0)接口,J2EE组件可以获得物理数据库连接对象(Connection)。要获得逻辑(合用的)连接,J2EE组件必须使用以下这些JDBC2.0合用管理器接口:
javax.sql.ConnectionPoolDataSource接口,该接口充当合用的java.sql.Connection对象的资源管理器连接factory。每家数据库服务器供应商都提供该接口的实现
(例如,Oracle实现oracle.jdbc.pool.OracleConnectionPoolDataSource类)。
javax.sql.PooledConnection接口,该接口封装到数据库的物理连接。同样,数据库供应商提供其实现。
对于那些接口和XA连接的每一个,都存在一个XA(X/Open规范)等价定义。
2.ResultSet
在JDBC2.0中,为了获得一个UptatableResult,在Query语句里必须包含Primarykey,并且查询的内容里必须来自一个table
ava.sql.ResultSet接口中定义了三种类型的结果集
TYPE_FORWARD_ONLY
TYPE_SCROLL_INSENSITIVE这种类型的结果集支持双向滚动
TYPE_SCROLL_SENSITIVE
如果要建立一个双向滚动的ResultSet,一定要在建立Statement的时候使用如下参数
Statementstmt=conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
3.JDBC驱动程序
连通oracle8.1.6的JDBC
把oracle8.1.6/lib/jdbc/*.zipcopy到%JAVA_HOME%/jre/lib/ext/*.jar
如果光copy不ren为.jar是没有用的。
4.事务处理
本地事务
java.sql.Connection接口可以控制事务边界(即开始和结束)。
在事务开始的时候调用setAutoCommit(false),而在中止事务时调用rollback或commit()方法。这类事务叫本地事务。
分布式事务
但是,在特定的情况下,可能有多个客户(例如两个不同的servlet或EJB组件)参与了同一个事务。
或者,客户在同一个事务中可能会执行跨越多个数据库的数据库操作。
JDBC2.0OptionalPackage同JTA一起来实现分布式样事务。
5.一些技巧
检索自动产生的关键字
为了解决对获取自动产生的或自动增加的关键字的值的需求,JDBC3.0API现在将获取这种值变得很轻松。要确定任何所产生的关键字的值,只要简单地在语句的execute()方法中指定一个可选的标记,表示您有兴趣获取产生的值。您感兴趣的程度可以是Statement.RETURN_GENERATED_KEYS,也可以是Statement.NO_GENERATED_KEYS。在执行这条语句后,所产生的关键字的值就会通过从Statement的实例方法getGeneratedKeys()来检索ResultSet而获得。ResultSet包含了每个所产生的关键字的列。清单1中的示例创建一个新的作者并返回对应的自动产生的关键字。
清单1.检索自动产生的关键字
Statementstmt=conn.createStatement();
//Obtainthegeneratedkeythatresultsfromthequery.
stmt.executeUpdate("INSERTINTOauthors"+
'(first_name,last_name)"+
"VALUES('George','Orwell')",
Statement.RETURN_GENERATED_KEYS);
ResultSetrs=stmt.getGeneratedKeys();
if(rs.next()){
//Retrievetheautogeneratedkey(s).
intkey=rs.getInt();
}
JTA/JTS
1.JTA/JTS基本知识
服务器实现JTS是否对应用程序开发人员来说不是很重要的。
对你来说,应该把JTA看作是可用的API。
JTA是用来开发distributedtansaction的API.
而JTS定义了支持JTA中实现TransactionManager的规范。
JavaTransactionService(JTS)specifiestheimplementationofaTransactionManagerwhichsupportstheJavaTransactionAPI(JTA)1.0Specificationatthehigh-levelandimplementstheJavamappingoftheOMGObjectTransactionService(OTS)1.1Specificationatthelow-level.JTSusesthestandardCORBAORB/TSinterfacesandInternetInter-ORBProtocol(IIOP)fortransactioncontextpropagationbetweenJTSTransactionManagers.
AJTSTransactionManagerprovidestransactionservicestothepartiesinvolvedindistributedtransactions:theapplicationserver,theresourcemanager,thestandalonetransactionalapplication,andtheCommunicationResourceManager(CRM).
2.JTA
1.1事务处理的概念
JTA实际上是由两部分组成的:一个高级的事务性客户接口和一个低级的X/OpenXA接口。
我们关心的是高级客户接口,因为bean可以访问它,而且是推荐的客户应用程序的事务性接口。
低级的XA接口是由EJB服务器和容器使用来自动协调事务和资源(如数据库)的
1.1.1事务划分
a.程序划分
使用UserTransaction启动JTA事务
TheUserTransactioninterfacedefinesthemethodsthatallowanapplicationtoexplicitlymanagetransactionboundaries.(fromj2eeAPIdocument)
b.声明划分
EJB容器使用TransactionManager启动JTA事务
TheTransactionManagerinterfacedefinesthemethodsthatallowanapplicationservertomanagetransactionboundaries.(fromj2eeAPIdocument)
1.1.2事务上下文及其传播
事务上下文是一种对资源上的事务操作之间和调用操作的组件之间的联系。
1.1.3资源加入
资源加入(resourceenlistment)是一个过程,在这个过程中资源管理器通知事务管理器它要参与事务。
1.1.4两阶段提交
两阶段提交是事务管理器和所有加入到事务中的资源之间的协议,确保要么所有的资源管理器都提交了事务,要么都撤销了事务。
如果在一个事务内部只是访问一个单一资源管理器,不需要执行一个两阶段提交。
如果在一个事务内部只是访问多个资源管理器,两阶段提交是有益的。
1.2事务处理系统中的构件模块
应用组件
资源管理器
资源管理器管理持久和稳定的数据存储系统,并且与事务管理器一起参与两阶段提交和恢复协议。典型的资源管理器如数据库系统和消息队列。
事务管理器
3.JTS
JTS是一个组件事务监视器(componenttransactionmonitor)。
这是什么意思?在第1部分,我们介绍了事务处理监视器(TPM)这个概念,TPM是一个程序,它代表应用程序协调分布式事务的执行。
TPM与数据库出现的时间长短差不多;在60年代后期,IBM首先开发了CICS,至今人们仍在使用。经典的(或者说程序化)TPM管理被程序化定义为针对事务性资源(比如数据库)的操作序列的事务。随着分布式对象协议,如CORBA、DCOM和RMI的出现,人们希望看到事务更面向对象的前景。将事务性语义告知面向对象的组件要求对TPM模型进行扩展—在这个模型中事务是按照事务性对象的调用方法定义的。
JTS只是一个组件事务监视器(有时也称为对象事务监视器(objecttransactionmonitor)),或称为CTM。
JTS和J2EE的事务支持设计受CORBA对象事务服务(CORBAObjectTransactionService,OTS)的影响很大。实际上,JTS实现OTS并充当Java事务API(JavaTransactionAPI)—一种用来定义事务边界的低级API—和OTS之间的接口。使用OTS代替创建一个新对象事务协议遵循了现有标准,并使J2EE和CORBA能够互相兼容。
乍一看,从程序化事务监视器到CTM的转变好像只是术语名称改变了一下。然而,差别不止这一点。当CTM中的事务提交或回滚时,与事务相关的对象所做的全部更改都一起被提交或取消。但CTM怎么知道对象在事务期间做了什么事?象EJB组件之类的事务性组件并没有commit()或rollback()方法,它们也没向事务监视器注册自己做了什么事。那么J2EE组件执行的操作如何变成事务的一部分呢?
透明的资源征用
当应用程序状态被组件操纵时,它仍然存储在事务性资源管理器(例如,数据库和消息队列服务器)中,这些事务性资源管理器可以注册为分布式事务中的资源管理器。在第1部分中,我们讨论了如何在单个事务中征用多个资源管理器,事务管理器如何协调这些资源管理器。资源管理器知道如何把应用程序状态中的变化与特定的事务关联起来。
但这只是把问题的焦点从组件转移到了资源管理器—容器如何断定什么资源与该事务有关,可以供它征用?请考虑下面的代码,在典型的EJB会话bean中您可能会发现这样的代码:
清单1.bean管理的事务的透明资源征用
InitialContextic=newInitialContext();
UserTransactionut=ejbContext.getUserTransaction();
ut.begin();
DataSourcedb1=(DataSource)ic.lookup("java:comp/env/OrdersDB");
DataSourcedb2=(DataSource)ic.lookup("java:comp/env/InventoryDB");
Connectioncon1=db1.getConnection();
Connectioncon2=db2.getConnection();
//performupdatestoOrdersDBusingconnectioncon1
//performupdatestoInventoryDBusingconnectioncon2
ut.commit();
注意,这个示例中没有征用当前事务中JDBC连接的代码—容器会为我们完成这个任务。我们来看一下它是如何发生的。
资源管理器的三种类型
当一个EJB组件想访问数据库、消息队列服务器或者其它一些事务性资源时,它需要到资源管理器的连接(通常是使用JNDI)。而且,J2EE规范只认可三种类型的事务性资源—JDBC数据库、JMS消息队列服务器和“其它通过JCA访问的事务性服务”。后面一种服务(比如ERP系统)必须通过JCA(J2EEConnectorArchitecture,J2EE连接器体系结构)访问。对于这些类型资源中的每一种,容器或提供者都会帮我们把资源征调到事务中。
在清单1中,con1和con2好象是普通的JDBC连接,比如那些从DriverManager.getConnection()返回的连接。我们从一个JDBCDataSource得到这些连接,JDBCDataSource可以通过查找JNDI中的数据源名称得到。EJB组件中被用来查找数据源(java:comp/env/OrdersDB)的名称是特定于组件的;组件的部署描述符的resource-ref部分将其映射为容器管理的一些应用程序级DataSource的JNDI名称。
隐藏的JDBC驱动器
每个J2EE容器都可以创建有事务意识的池态DataSource对象,但J2EE规范并不向您展示如何创建,因为这不在J2EE规范内。浏览J2EE文档时,您找不到任何关于如何创建JDBC数据源的内容。相反,您不得不为您的容器查阅该文档。创建一个数据源可能需要向属性或配置文件添加一个数据源定义,或者也可以通过GUI管理工具完成,这取决于您的容器。
每个容器(或连接池管理器,如PoolMan)都提供它自己的创建DataSource机制,JTA魔术就隐藏在这个机制中。连接池管理器从指定的JDBC驱动器得到一个Connection,但在将它返回到应用程序之前,将它与一个也实现Connection的虚包包在一起,将自己置入应用程序和底层连接之间。当创建连接或者执行JDBC操作时,包装器询问事务管理器当前线程是不是正在事务的上下文中执行,如果事务中有Connection的话,就自动征用它。
其它类型的事务性资源,JMS消息队列和JCA连接器,依靠相似的机制将资源征用隐藏起来,使用户看不到。如果要使JMS队列在部署时对J2EE应用程序可用,您就要再次使用特定于提供者的机制来创建受管JMS对象(队列连接工厂和目标),然后在JNDI名称空间内发布这些对象。提供者创建的受管对象包含与JDBC包装器(由容器提供的连接池管理器添加)相似的自动征用代码。
透明的事务控制
两种类型的J2EE事务—容器管理的和bean管理的—在如何启动和结束事务上是不同的。事务启动和结束的地方被称为事务划分(transactiondemarcation)。清单1中的示例代码演示了bean管理的事务(有时也称为编程(programmatic)事务)。Bean管理的事务是由组件使用UserTransaction类显式启动和结束的。通过ejbContext使UserTransaction对EJB组件可用,通过JNDI使其对其它J2EE组件可用。
容器根据组件的部署描述符中的事务属性代表应用程序透明地启动和结束容器管理的事务(或称为宣告式事务(declarativetransaction))。通过将transaction-type属性设置为Container或Bean您可以指出EJB组件是使用bean管理的事务性支持还是容器管理的事务性支持。
使用容器管理的事务,您可以在EJB类或方法级别上指定事务性属性;您可以为EJB类指定缺省的事务性属性,如果不同的方法会有不同的事务性语义,您还可以为每个方法指定属性。这些事务性属性在装配描述符(assemblydescriptor)的container-transaction部分被指定。清单2显示了一个装配描述符示例。trans-attribute的受支持的值有:
Supports
Required
RequiresNew
Mandatory
NotSupported
Never
trans-attribute决定方法是否支持在事务内部执行、当在事务内部调用方法时容器会执行什么操作以及在事务外部调用方法时容器会执行什么操作。最常用的容器管理的事务属性是Required。如果设置了Required,过程中的事务将在该事务中征用您的bean,但如果没有正在运行的事务,容器将为您启动一个。在这个系列的第3部分,当您可能想使用每个事务属性时,我们将研究各个事务属性之间的区别。
清单2.EJB装配描述符样本
<assembly-descriptor>
...
<container-transaction>
<method>
<ejb-name>MyBean</ejb-name>
<method-name>*</method-name>
</method>
<trans-attribute>Required</trans-attribute>
</container-transaction>
<container-transaction>
<method>
<ejb-name>MyBean</ejb-name>
<method-name>updateName</method-name>
</method>
<trans-attribute>RequiresNew</trans-attribute>
</container-transaction>
...
</assembly-descriptor>
功能强大,但很危险
与清单1中的示例不同,由于有宣告式事务划分,这段组件代码中没有事务管理代码。这不仅使结果组件代码更加易读(因为它不与事务管理代码混在一起),而且它还有另一个更重要的优点—不必修改,甚至不必访问组件的源代码,就可以在应用程序装配时改变组件的事务性语义。
尽管能够指定与代码分开的事务划分是一种非常强大的功能,但在装配时做出不好的决定会使应用程序变得不稳定,或者严重影响它的性能。对容器管理的事务进行正确分界的责任由组件开发者和应用程序装配人员共同担当。组件开发者需要提供足够的文档说明组件是做什么的,这样应用程序部署者就能够明智地决定如何构建应用程序的事务。应用程序装配人员需要理解应用程序中的组件是怎样相互作用的,这样就可以用一种既强制应用程序保持一致又不削弱性能的方法对事务进行分界。在这个系列的第3部分中我们将讨论这些问题。
透明的事务传播
在任何类型的事务中,资源征用都是透明的;容器自动将事务过程中使用的任意事务性资源征调到当前事务中。这个过程不仅扩展到事务性方法使用的资源(比如在清单1中获得的数据库连接),还扩展到它调用的方法(甚至远程方法)使用的资源。我们来看一下这是如何发生的。
容器用线程与事务相关联
我们假设对象A的methodA()启动一个事务,然后调用对象B的methodB()(对象B将得到一个JDBC连接并更新数据库)。B获得的连接将被自动征调到A创建的事务中。容器怎么知道要做这件事?
当事务启动时,事务上下文与执行线程关联在一起。当A创建事务时,A在其中执行的线程与该事务关联在一起。由于本地方法调用与主调程序(caller)在同一个线程内执行,所以A调用的每个方法也都在该事务的上下文中。
橱中骸骨
如果对象B其实是在另一个线程,甚至另一个JVM中执行的EJB组件的存根,情况会怎样?令人吃惊的是,远程对象B访问的资源仍将在当前事务中被征用。EJB对象存根(在主调程序的上下文中执行的那部分)、EJB协议(IIOP上的RMI)和远端的骨架对象协力要使其透明地发生。存根确定调用者是不是正在执行一个事务。如果是,事务标识,或者说Xid,被作为IIOP调用的一部分与方法参数一起传播到远程对象。(IIOP是CORBA远程-调用协议,它为传播执行上下文(比如事务上下文和安全性上下文)的各种元素而备;关于RMIoverIIOP的更多信息,请参阅参考资料。)如果调用是事务的一部分,那么远程系统上的骨架对象自动设置远程线程的事务上下文,这样,当调用实际的远程方法时,它已经是事务的一部分了。(存根和骨架对象还负责开始和提交容器管理的事务。)
事务可以由任何J2EE组件来启动—一个EJB组件、一个servlet或者一个JSP页面(如果容器支持的话,还可以是一个应用程序客户机)。这意味着,应用程序可以在请求到达时在servlet或者JSP页面中启动事务、在servlet或者JSP页面中执行一些处理、作为页面逻辑的一部分访问多个服务器上的实体bean和会话bean并使所有这些工作透明地成为一个事务的一部分。图1演示了事务上下文怎样遵守从servlet到EJB,再到EJB的执行路径。
图1.单个事务中的多个组件
最优化
让容器来管理事务允许容器为我们做出某些最优化决定。在图1中,我们看到一个servlet和多个EJB组件在单个事务的上下文中访问一个数据库。每个组件都获得到数据库的Connection;很可能每个组件都在访问同一个数据库。即使多个连接是从不同的组件到同一个资源,JTS也可以检测出多个资源是否和事务有关,并最优化该事务的执行。您可以从第1部分回忆起来,单个事务要包含多个资源管理器需要使用两阶段提交协议,这比单个资源管理器使用的单阶段提交代价要高。JTS能够确定事务中是不是只征用了一个资源管理器。如果它检测出所有与事务相关的资源都一样,它可以跳过两阶段提交并让资源管理器自己来处理事务。
结束语
这个虑及透明事务控制、资源征用和透明传播的魔术不是JTS的一部分,而是J2EE容器如何在幕后代表J2EE应用程序使用JTA和JTS服务的一部分。在幕后有许多实体合力使这个魔术透明地发生;EJB存根和骨架、容器厂商提供的JDBC驱动器包装器、数据库厂商提供的JDBC驱动器、JMS提供器和JCA连接器。所有这些实体都与事务管理器进行交互,于是应用程序代码就不必与之交互了。
4.事务的特性ACID
原子性(automic)
事务内部的操作必须被看作一个单一的,原子性的单元。
这意味着,如果在其中的每个操作都被成功的执行,事务就能被认为是完整的并且允许提交。
一致性(consistent)
当作为一个整体执行一个事务的操作时,这些操作必须把它们处理的数据从一个一致性的状态转移到另一个一致性的状态
隔离性(isolated)
隔离对资源的访问
事务应该与其他事务的效用隔离。
隔离级别描述了通过并发事务对一个资源的访问被隔离的程度。
如果你熟悉Java中的线程同步或是关系数据库中的行锁设计的概念,隔离性与这样的概念类似。
在EJB1.1中,如果容器管理事务,配置器设置事务隔离层
如果bean管理事务,bean配置器设置事务隔离层
事务隔离可用隔离条件来定义,这些条件有:
A.dirtyread(脏读,不清楚的读)
B.repeatableread(可重复的读)
C.phantomread(幻影,有名无实的读·)
四种隔离层
a.ReadUncommitted
b.ReadCommitted
c.RepeatableRead
d.Serializable
这些隔离层和JDBC定义的隔离层相同,在java.sql.Connection类中定义了相应的静态变量。
Serializable的隔离层确保数据不被事务并发访问,这样可以确保数据永远是一致的。
get方法的隔离层的等级可以非常低,如ReadUncommited
set方法所作的修改必须防止其他事务的不清楚的读取,因此将使用最大约束的隔离层Serializable
通常来说,随着隔离层变得更有约束,系统的性能也将降低。
持久性(durable)
当提交事务时,该事务所作的任何数据更新必须是“耐久性”的。
这意味着不管它结束之后发生任何错误,被提交事务的结果必须保留。
更通俗的说法是:所有再事务过程中所作的数据修改必须在事务成功完成之前写入某种类型的物理介质。
理解:
1.事务系统通过确保事务是原子的,隔离的和持久的来实现事务的一致性
现实程序中主要考虑的是原子性
JCA(J2EE连接体系结构)
J2EEConnectorArchitecture基础
J2EE连接体系结构,目前正在修改,将期盼着包括J2EE未来版本的规范,这个连接
体系结构定义了标准的资源适配器和依附于连接、事务、安全管理的合同,所以应用服务器将以标准和统一的方式插入各种企业信息系统,包括ERP(如SAPR/3),主框架事务处理系统和数据库系统。
理想的做法是内置一个可用于任何资源类型和所有连接管理功能(包括合用)的通用连接接口。这就是即将出现的J2EEConnectorArchitecture1.0规范的目标之一。
图显示了体系结构内部的主要概念,资源适配器。应用服务器所支持的每一种资源类型的可插入组件,资源适配器,都在应用服务器地址空间中执行。访问那些适配器的客户机API可以是CommonClientInterface(CCI)或(为了向后兼容)特定于资源的API(例如JDBC2.0)。
例如,CCI定义javax.resource.cci.ConnectionFactory和javax.resource.cci.Connection,分别作为连接factory和连接的接口--与JDBC2.0接口类似。
JDBC和JCA关系
大多数应用程序开发人员不需要知道JDBC和J2EE连结器体系结构之间的关系,就可以很好地使用JDBCAPI。但是,由于JDBC3.0规范已经考虑到这项新的体系结构,这使得开发人员能更好地理解JDBC在哪里适合J2EE标准,以及这个规范的发展方向是什么。
JCA指定了一组协议,允许企业的信息系统以一种可插入的方式连接到应用服务器上。这种体系结构定义了负责与外部系统连接的资源适配器。连接器服务提供者接口(TheConnectorsServiceProviderInterface,SPI)恰好和JDBC接口提供的服务紧密配合。
JDBCAPI实现了连结器体系结构定义的三个协议中的两个。
第一个是将应用程序组件与后端系统相连接的连接管理,它是由DataSource和ConnectionPoolDataSource接口来实现的。
第二个是支持对资源的事务性访问的事务管理,它是由XADataSource来处理的。
第三个是支持后端系统的安全访问的安全性管理,在这点上,JDBC规范并没有任何对应点。尽管有最后那个不足,JDBC接口仍能映射到连接器SPI上。
如果一个驱动程序厂商将其JDBC驱动程序映射到连接器系统协议上,它就可以将其驱动程序部署为资源适配器,并立刻享受可插性、封装和在应用服务器中部署的好处。这样,一个标准的API就可以在不同种类的的企业信息系统中,供企业开发人员使用。
JMS
THEbasicbuildingblocksofaJMSapplicationareasfollows:
•Administeredobjects(connectionfactoriesanddestinations)
•Connections
•Sessions
•Messageproducers
•Messageconsumers
•Messages
消息系统允许分开的未耦合的应用程序之间可靠地异步通信。类同邮件系统.
通常有两种消息类型。
1.发布/订阅(publish/subscribe)
发布/订阅消息系统支持一个事件驱动模型,消息产生者和使用者都参与消息的传递。产生者发布事件,而使用者订阅感兴趣的事件,并使用事件。产生者将消息和一个特定的主题(Topic)连在一起,消息系统根据使用者注册的兴趣,将消息传给使用者。
2.点对点(Peertopeer)
在点对点的消息系统中,消息分发给一个单独的使用者。它维持一个"进入"消息队列。消息应用程序发送消息到一个特定的队列,而客户端从一个队列中得到消息JMS和EJB一样是WEBLOGIC提供的服务,客户端通过JNDI名字查找。
在控制台先创建一个JMS的主题,设定一个JNDI(参照提示做啊,跟前边的介绍雷同)
一个典型的JMS客户端由下面的几个基本步骤来创建:
创建一个到消息系统提供者的连接(Connection)
创建一个Session,用于接收和发送消息
创建MessageProducer和MessageConsumer来创建和接收消息
当完成了上述步骤后,一个消息产生者客户端将创建并发布消息到一个主题,(JNDI)
而消息使用者客户端会接收与一个主题相关的消息。
1.创建一个Connection
AconnectionencapsulatesavirtualconnectionwithaJMSprovider.ItcouldrepresentanopenTCP/IPsocketbetweenaclientandaproviderservicedaemon.Youuseaconnectiontocreateoneormoresessions.
一个Connection提供客户端对底层的消息系统的访问。并实现资源的分配和管理。通过使用一个ConnectionFactory来创建一个Connection,通常用JDNI来指定:
Connectionmessage=newinitialContext();
TopicConnectionFactorytopicConnectionFactory=(TopicConnectionFactory);
topic=(Topic)jndiContext.lookup(topicName);
topicConnection=topicConnectionFactory.createTopicConnection();
2.创建一个Session
Asessionisasingle-threadedcontextforproducingandconsumingmessages.Youusesessionstocreatemessageproducers,messageconsumers,andmessages.
Session是一个比较大的JMS对象,他提供了生产和消费消息的手段。
用于创建消息使用者和消息产生者。
topicSession=
topicConnection.createTopicSession(false,Session.AUTO_ACKNOWLEDGE);
两个参数用于控制事务和消息确认。
3.定位一个Topic
用JDNI来定位一个Topic,Topic用于识别发送或接收的消息,在发布/订阅系统中。
订阅者订阅一个给定的Topic,而发布者将它发布的消息与一个Topic相连。
下面是创建一个Topic"WeatherReport"
TopicweatherTopic=messaging.lookup("WeatherReport");
4.启动Connection
在上面的初始化步骤之后,消息流是禁止的,用于防止在初始化时发生不可预料的行为。
一旦初始化结束,必须让Connection启动消息系统。
topicConnection.start();
5.创建一个消息产生者
在发布/订阅里,一个产生者发布消息到一个指定的Topic。
下面的代码显示创建一个产生者,以及后续的建立和发布一个简单文本消息。
TopicPublisherpublisher=session.createPublisher(weatherTopic);
TexeMessagemessage=session.createMessage();
message.setText("ssss");
publisher.publish(message);
下面是一个消息使用者的代码
topicConnection=topicConnectionFactory.createTopicConnection();
topicSession=topicConnection.createTopicSession(false,Session.AUTO_ACKNOWLEDGE);
topicSubscriber=topicSession.createSubscriber(topic);
topicListener=newMsgListener();
topicSubscriber.setMessageListener(this);
topicConnection.start();
JNDI
1.JNDI的基本知识
JNDI――Java的命名和目录接口
命名服务是一种应用程序,该程序包含一个对象集合或对象引用的集合,还对每个对象关联了一个对用户友好的名称。
目录服务只是命名服务所提供的一个扩展功能。
在JDK1.3中,JNDI支持以下三种ServiceProvider
LDAP
CORBA的COSNamingService
RMIRegistry
目录服务实现的常见的功能
LDAP
NDS
NIS+
X.500
2.避免在程序中显式的设置JNDIFactory
Contextctx=null;
try
{
Hashtableenv=newHashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"weblogic.jndi.WLInitialContextFactory");
env.put(Context.PROVIDER_URL,"t3://localhost:7001");
ctx=newInitialContext(env);
System.out.println("成功创建Initialcontext");
}
catch(Exceptione)
{
e.printStackTrace();
}
可以在jndi.properties文件中添加如下两行
java.naming.factory.initial=weblogic.jndi.WLInitialContextFactory
java.naming.provider.url=t3://localhost:7001
其他的如文件系统访问的例子参看《EJB2.0企业级应用程序开发》
3.关闭InitialContext
在结束InitialContext对象的使用后,总要关闭该对象。
这类似于关闭其他的有限资源,比如JDBC连接。
即使抛出了某个异常,也要保证关闭InitialConext对象
ApplicationServer
1.WebSphere
1.1初步安装
6.29.2002
安装developerWorkstoolboxsampleCD(disk1)上的
Websphereapplicationserveradvancedsingleserver
在server机器上进行“典型安装”,安装很顺利,比websphereapplicationserver3.0要好很多
由于wingate可能使用了7000端口,第一次启动WAS没有成功,把wingatestop掉,就可以启动WAS了(后来修改server-config.xml,把7000端口改为别的端口,即使wingatestarting,也可以启动WAS)
现在WAS典型安装的时候自动安装了IBMHttpServer,比以前方便多了(以前还要担心IBMHttpServer的安装问题,况且这次我是安装在win2000prefessional上面的,本来机器上就没有IIS)。
可以使用http://server:9090/admin进行管理
在gu机器上进行“定制安装”,不安装IBMHttpServer,也顺利搞定。
安装忘了可以在IE中访问以下网址测试
http://localhost:9080/webapp/examples/
http://localhost:9080/estore/
http://localhost:9080/estore/是不需要配置就可以使用的,况且用到了数据库,根据petstore.ear中的customerEjb.jar中的ibm-web-bnd.xmi中看来,使用的数据源为
jdbc/EstoreDataSource
说明在WAS安装完后,这个DataSource就是可用的,可供测试
1.2配置样本
可以通过“样本”(http://localhost/WSsamples/index.html)来学习WAS
DatabaseConfiguration
选择“StartSamples.earSQLServerwithMerantDatabaseConfiguration”
JDBC驱动程序(MicrosoftSQLServerviaMerantSequeLinkJDBCDriver)
服务器类路径:${WAS_ROOT}/lib/sljc.jar;${WAS_ROOT}/lib/sljcx.jar
1.3部署示例应用(MyBank)
根据“将应用安装到WebSphere4.0高级单服务器版(AEs).pdf”的指导,可以顺利的部署应用程序
1.3.1停止WAS服务
可以在命令行下用stopserver。
1.3.2db2的JDBC版本
WhenIBMDB2UniversalDatabaseVersion7isfirstinstalled,itusestheJDBC1.0APIforconnections.WebSphereV4.0andJ2EErequireJDBC2.0.StoptheDB2JDBCAppletServer,thenrunabatchfiletochangefromJDBC1.0toJDBC2.0.
__ClicktheWindowsStartbutton,andselectSettings-->ControlPanel.
__IntheControlPanel,double-clickServices.
__IntheServiceswindow,selecttheDB2JDBCAppletServer,andclickStop.
__ClickYes,youaresureyouwanttostoptheDB2JDBCAppletServerservice.
__VerifytheWebSphereServerisstopped.InaCommandwindow,type:stopserver.
__InaCommandwindow,changedirectoriestowhereDB2isinstalled.
Forexample:cdC:\SQLLIB(CouldbeC:\ProgramFiles\SQLLIBonyoursystem.)
__IntheCommandwindow,type:cdjava12
__IntheCommandwindow,type:usejdbc2
Sixfilesarecopied,andafilenamedinuseisupdated.
__IntheCommandwindow,type:typeinuse.
Thisshoulddisplay:JDBC2.0
__IntheControlPanel,double-clickServices.
__IntheServiceswindow,selecttheDB2JDBCAppletServer,andclickStart.
1.3.3设置DataSource
WhenyoucreatedtheDataSource,youspecifiedthattheDefaultUserIDfortheapplicationdatabaseisUSERID,andtheDefaultPasswordisPASSWORD.YouneedtocreatethisUserIDintheoperatingsystemregistry.
1.4开发和部署自己的应用
成功的在WAS4.0中部署bidding2.ear,使用的是通过Web页面部署,而不是通过SEAppInstall命令行方式
看来JBuilder7和WAS4.0集成开发还是比较方便的。
简单的还行,复杂一点就不行了,例如开发WebApplication的时候,ibm-web-bnd.xmi和ibm-web-ext.xmi根本不知道怎么写,也没有资料可以查
看来,开发WebSphere的东西,还是要使用WSAD.
可以在Jbuilder中开发后,使用“应用程序组装工具”(assembly.bat)来配置程序,然后再安装到WebSphere中去。
也可以不使用“应用程序组装工具”,不管ibm-web-bnd.xmi和ibm-web-ext.xmi,直接通过http:localhost:9090/admin来安装应用程序的时候,会提示你输入对应的实际的jndi资源名
在WebSphere中部署了bidding2企业应用程序后,关闭重新启动WAS还是不行,bidding2还是无法运行,结果,重新启动一下计算机就可以了,这一点不如Weblogic
1.4.1JSP中的访问DataSource和EJB
(1)在WebApplication程序的javabean里有这样一句
DataSourcesource=(DataSource)initCtx.lookup("java:comp/env/jdbc/sample");
注意:红字部分是和web.xml中的红字部分对应的
(2)在web.xml中有这样
<resource-refid="ResourceRef_1">
<res-ref-name>jdbc/sample</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>CONTAINER</res-auth>
</resource-ref>
(3)在ibm-web-bnd.xmi中有这样
<resRefBindingsxmi:id="ResourceRefBinding_1"jndiName="jdbc/sample">
<bindingResourceRefhref="WEB-INF/web.xml#ResourceRef_1"/>
</resRefBindings>
注意:绿字部分是和web.xml中的绿字部分对应的
至于ibm-web-bnd.xmi中jndiName="jdbc/sample",这个指向的是具体的WAS中已定义的DataSource的JNDI名字,可以是任何名字,只要有效。
可以顺利找到DataSource
(1)在WebApplication程序的javabean里有这样一句
CustomerManagerHomehome=
(CustomerManagerHome)initCtx.lookup("java:comp/env/ejb/CustomerManager");
CustomerManagerCustomerManager=home.create();
注意:红字部分是和web.xml中的红字部分对应的
(2)在web.xml中有这样
<ejb-refid="EjbRef_1">
<ejb-ref-name>ejb/CustomerManager</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type><home>com.hmautomation.bidding2.controller.CustomerManagerHome</home><remote>com.hmautomation.bidding2.controller.CustomerManager</remote>
</ejb-ref>
(3)在ibm-web-bnd.xmi中有这样
<ejbRefBindingsxmi:id="EjbRefBinding_1"jndiName="CustomerManager">
<bindingEjbRefhref="WEB-INF/web.xml#EjbRef_1"/>
</ejbRefBindings>
注意:绿字部分是和web.xml中的绿字部分对应的
至于ibm-web-bnd.xmi中jndiName="CustomerManager",这个指向的是具体的WAS中已有的EJB的JNDI名字,可以是任何名字,只要有效。
可以顺利找到EJB
1.4.2launchClient.bat
在开发j2ee应用时,如果你的客户端程序是javaClient形式的,你应该通过客户端程序的容器来执行客户端程序。在WebSpheread4.0中,你应该用launchClient.bat来执行你的程序
j2ee客户端程序有两种形式,web形式和java客户端形式。java客户端形式是你自己编写的拥有main函数的类。WebSphere的launchClient.bat在WebSphere安装目录/AppServer/bin下
1.4.3WebSphere中的JNDI
参看《WebSphereVersion4ApplicationDevelopmentHandbook》
Chapter13:GuidelinesforcodingWebSphereapplications
UsingJNDI
参考infocenter中的信息,轻易解决这个问题,在jndi.properties中写
java.naming.factory.initial=com.ibm.websphere.naming.WsnInitialContextFactory
java.naming.provider.url=iiop://localhost:900
实例代码片断:
ctx=newInitialContext();
System.out.println("成功创建Initialcontext");
Objectobjref=ctx.lookup("jdbc/sample");//这里的jdbc/sample就是WAS安装
//已有的instantDB的sampledatasource
System.out.println("成功找到DataSourcesample");
1.4.4WebSphere中的重新安装ear
很麻烦!
“应用程序安装”向导
Application或Application目录已存在。
与所选应用程序同名的目录已存在。
目录中的文件可能已由应用程序服务器锁定。
要安装此应用程序,您将需要执行下列步骤:
1.如果您还未卸载此应用程序,则现在卸载它。
2.保存此配置。
3.停止应用程序服务器进程。
4.删除与要安装的应用程序相应的目录(在installedApps目录下)。
5.重新启动应用程序服务器并返回到管理应用程序。
6.再次安装应用程序。
1.4.5WebSphere中的UserProfile
《IBMWebsphereandVisualAgeforJavaDatabaseIntegrationwithDB2,OracleandSQLServer》有一章专门讲如何使用UserProfile
1.5WebSphere实现的一些服务
WebSpher是OMGSpecification的一个LightImplenentation
而ComponetBroker是一个CompleteImplementation
1.4.3DirectoryService
LDAPDirectory可以通过存储userID和password而被用作一个authientication的centralizedpoint
IBMSecurewayDirectory是LDAP的一个实现,它使用IBMDB2作为后端存储。
1.6WebSphere的文档
Web上的文档
要获取提供了所有支持语言的整个文档集,请参阅:
http://www.ibm.com/software/webservers/appserv/infocenter.html
当您进入此Web页面时,可在线浏览信息中心,或将它下载到您的机器上。
在信息中心中,您会找到下列信息:
发行说明
此文档包括问题描述和解决方法,以及产品限制。在开始产品安装之前,请阅读此文件。发行说明的最新版本在产品Web站点上。
“欢迎”页面
“欢迎”页面突出显示了所有用户特别关注的信息(包括从版本3.5迁移到版本4.0,以及用于通过教程和代码样本的“边干边学”的实践指示。)
步进式安装文档
此安装文档为安装和配置此产品提供了说明性、步进式的帮助。每个PDF文档涉及到不同的操作系统和数据库组合,如在安装有IBMDB2数据库的WindowsNT上安装此产品。
内容更深入的文档
这些主题包括编程、安全性、管理、迁移和多机器环境(不适用于高级单服务器版)。
帮助文件更新
与此产品一起安装的帮助文件已更新版本在信息中心中提供。各种界面的帮助主题按管理部分下面的对象类型(如“Web模块”)组织。特别地,请参阅章节6.7。
1.7WebSphere和SQLServer
1.7.1使用MerantDriver
1.安装sqlserver2000;完毕后安装sqlserver2000sp2;
(注:我没有安装sqlserver2000SP2,安装merantdriver的时候,它提示我要MDAC-MicrosoftDataAccessComponent,我又下载了一个MDAC2.6)
2.安装MerantSequeLinkServer5.1(这是装在SQLServer的那台机器上的),命令行下输入setup/v”IPE=NO”,按提示直至安装完毕
问OEM/SerialNumber的时候,敲入1111,但是敲入1111似乎是evaluation,只能用一个月,server上可以用到2002.8.10
3.配置DataSource
我作了如下填写:
JDBC驱动程序(MicrosoftSQLServerviaMerantSequeLinkJDBCDriver)
服务器类路径:${WAS_ROOT}/lib/sljc.jar;${WAS_ROOT}/lib/sljcx.jar
(后来程序又说WAS4.01带这两个jar文件和MerantSequeLinkServer5.1不匹配,IBM老是出这样的问题,我用eFixPQ62295Update中sequelink.zip的两个jar文件取代才解决了问题,但还是有中文问题)
但是程序告诉我找不到文件,一发狠,就把这两个文件拷到WAS所带的JDK的ext目录中去,结果javax.sql.DataSource又找不到,只能把j2ee.jar也拷到WAS所带的JDK的ext目录中去,OK。(有待改进)
com.merant.sequelink.jdbc.SequeLinkDriver.class
Jdbc:sequelink//hostname:19996
总结:Merant似乎已经放弃了JDBCDriver这一块,已有另一个新的公司在作这个产品(http://www.datadirect-technologies.com/)
IBM也意识到了这一点,在eFixPQ62295Update中提供了它自己的JDBCDriver
1.7.2使用MicroSoft的Driver
com.microsoft.jdbcx.sqlserver.SQLServerDataSource
基本是不行的,IBM的程序不能实例化上面的类。
2.Weblogic
1)Weblogic安装
在startWeblogic.cmd里找到下面这句,写上你的密码即可。
setWLS_PW=
或在startWeblogic.cmd同级目录下加一个文件password.ini
里面写一句话,就是你的密码即可,(只是密码字串,不要别的)
有关weblogic在jb6中调用出错的一点添加:
安装上面的方法可能会出现java.lang.NullException(可能)。只要你把工程中jdk换成weblogic自带的jdk即可消除这个问题。
weblogic和jb6自带的jdk,虽然版本一样,可能存在差异!
大家还是装个7.0来用吧,好象没有时间限制,只不过是有连接限制,呵
2)Weblogic中的安全问题
配置SSL
a.每个需要配置SSL的WeblogicServerDeployment,你需要一个私钥和一个数字证书
私钥和数字证书生成存放在PEM或者DefiniteEncodingRules(DER)格式的文件中。.
PEM文件是文本的。
DER文件是二进制的。
b.
相关推荐
**J2EE学习笔记概述** J2EE(Java 2 Platform, Enterprise Edition)是一个由Sun Microsystems(现已被Oracle收购)开发的平台,主要用于构建企业级的分布式应用系统。它提供了服务器端组件模型、服务和API,支持...
### J2EE 笔记概览 #### 一、J2EE基础知识介绍 J2EE(Java 2 Platform, Enterprise Edition)是Sun Microsystems为简化企业级应用开发而提出的一套技术标准,它提供了构建分布式系统的基础框架。在J2EE环境中,...
在这个J2EE学习笔记中,我们将重点讨论Value Object(值对象)模式以及JSP、JavaBean和Servlet的相关知识点。 **Value Object(值对象)模式**是一种常见的设计模式,在J2EE应用中用于数据传输和状态保持。值对象不...
**J2EE学习笔记概述** J2EE,全称为Java 2 Platform, Enterprise Edition,是Java平台上用于构建企业级分布式应用程序的框架。它为开发者提供了丰富的功能,包括Web服务、事务处理、安全控制以及数据库连接等,使得...
【J2EE学习笔记概述】 J2EE(Java 2 Platform, Enterprise Edition)是Java平台的一个版本,专门针对企业级应用开发。它提供了一个全面的框架,用于构建、部署和管理分布式多层企业应用程序。J2EE的核心在于其组件...
本篇学习笔记将聚焦于四个核心的J2EE框架:JDBC、Hibernate、Struts和Spring,这些框架在现代企业应用开发中扮演着重要角色。 **JDBC(Java Database Connectivity)**是Java语言访问数据库的标准API,它是连接Java...
《软件工程师学习笔记J2EE》是一份针对Java企业级应用开发(J2EE)的详尽学习资源,对于想要深入理解和掌握J2EE技术体系的软件工程师来说,具有极高的参考价值。这份笔记不仅全面覆盖了J2EE的基础概念,还深入探讨了...
本文主要围绕J2EE的学习笔记进行详细解析。 首先,我们来看看J2EE模式中的Value Object(值对象)。Value Object是一个Java对象,它的主要职责是承载数据,常用于不同对象或层次之间的数据传递。它们通常不含业务...
【J2EE学习笔记 by dream】是一份详细记录了作者dream在J2EE技术领域学习过程和经验的文档集合。J2EE(Java 2 Platform, Enterprise Edition)是Oracle公司提供的一个用于构建企业级分布式应用的平台,它包含了多种...
**J2EE学习笔记概述** J2EE(Java 2 Platform, Enterprise Edition)是Java平台的一个版本,专门针对企业级应用开发。它提供了一个全面的框架来构建、部署和管理多层、分布式、跨平台的企业应用程序。J2EE学习笔记...
这份“J2EE学习笔记”涵盖了该技术领域的核心概念、架构和关键组件,对于初学者和进阶者都是宝贵的参考资料。文档以58页的篇幅深入浅出地讲解了J2EE的各个方面,包括基础理论和实际应用。 在J2EE的体系结构中,主要...
**J2EE学习笔记概述** J2EE(Java 2 Platform, Enterprise Edition)是Java平台的一个版本,专门针对企业级应用开发。它提供了一个全面的框架,用于构建、部署和管理分布式多层企业应用程序。本笔记主要围绕J2EE的...
J2EE学习笔记主要涵盖了Java企业级开发的关键概念和技术,特别是关于JSP、JavaBean以及Servlet的使用。首先,J2EE模式中的Value Object(值对象)是一个关键概念,它是一个不含业务逻辑的Java对象,通常用于在不同...
【J2EE学习笔记概述】 J2EE,全称为Java 2 Platform, Enterprise Edition,是Java平台上用于构建企业级应用的框架。它提供了一个统一的标准和可扩展的平台,允许开发人员创建分布式、多层的企业应用程序。J2EE的...
一份很好的j2ee学习笔记,希望对大家有用
这份“J2EE学习笔记”文档很可能是为了帮助初学者或有经验的开发者深入理解J2EE的核心概念和技术。在本文中,我们将详细探讨J2EE的关键组成部分、其工作原理以及在实际开发中的应用。 1. **J2EE架构**:J2EE架构...