|
2006年6月15日
System.getProperty()参数大全
java.version Java Runtime Environment version
java.vendor Java Runtime Environment vendor
java.vendor.url Java vendor URL
java.home Java installation directory
java.vm.specification.version Java Virtual Machine specification version
java.vm.specification.vendor Java Virtual Machine specification vendor
java.vm.specification.name Java Virtual Machine specification name
java.vm.version Java Virtual Machine implementation version
java.vm.vendor Java Virtual Machine implementation vendor
java.vm.name Java Virtual Machine implementation name
java.specification.version Java Runtime Environment specification version
java.specification.vendor Java Runtime Environment specification vendor
java.specification.name Java Runtime Environment specification name
java.class.version Java class format version number
java.class.path Java class path
java.library.path List of paths to search when loading libraries
java.io.tmpdir Default temp file path
java.compiler Name of JIT compiler to use
java.ext.dirs Path of extension directory or directories
os.name Operating system name
os.arch Operating system architecture
os.version Operating system version
file.separator File separator ("/" on UNIX)
path.separator Path separator (":" on UNIX)
line.separator Line separator ("\n" on UNIX)
user.name User's account name
user.home User's home directory
user.dir User's current working directory
服务类型
在axis中有4中服务类型
RPC服务采用soap rpc的标准,and also the SOAP "section 5" encoding.
Document 服务没有采用任何编码(所以你在组装时不会看到复杂对象的序列化以及soap-style数组),但是仍然作了xml和java对象的互映射。
Wrapped服务和Document服务类似
Message 服务接受和返回soap Envelope中的任意的xml而不需要mapping/data得榜定。如果你想处理来自外部的原始的xml,可以采用Message 服务。
RPC服务
这个服务是axis默认的服务。我们在前面的例子中写的就是rpc服务。<service ... provider="java:RPC"> 。rpc服务遵从soap rpc规范和编码规则,意味着来自rpc服务的xml将类似上面例子中的“echoString”--每个rpc调用被模块化为一个外部元素,匹配操作名称,并包含了很多内部元素,每一个都是操作的一个参数。axis将把这些xml转化为java对象,配送给你得服务,并将序列化来自服务的java对象为xml.因为rpc服务默认采用soap section 5规则,对象将会通过"multi-ref" 序列化来编码。
Document / Wrapped 服务
这2个服务很类似,都不需要用soap编码来处理数据。他就是一个普通的xml格式。无论哪种情况,axis还是对他们做了xml到java得榜定,所以你最终处理的还是java对象,而不是xml结构的字符串。
下面的例子来说明他们2个之间的区别。
<soap:Envelope xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<soap:Body>
<myNS:PurchaseOrder xmlns:myNS="http://commerce.com/PO">
<item>SK001</item>
<quantity>1</quantity>
<description>Sushi Knife</description>
</myNS:PurchaseOrder>
</soap:Body>
</soap:Envelope>
相关的PurchaseOrder类型定义如下:
<schema targetNamespace="http://commerce.com/PO">
<complexType name="POType">
<sequence>
<element name="item" type="xsd:string"/>
<element name="quantity" type="xsd:int"/>
<element name="description" type="xsd:string"/>
</sequence>
</complexType>
<element name="PurchaseOrder" type="POType"/>
</schema>
对于一个document服务来说,他将对应到这样的方法
public void method(PurchaseOrder po)
换句话说,整个PurchaseOrder元素将被处理为一个单一的对象,包含3个属性。
而对于wrapped服务来说,他对应于下面的方法
public void purchaseOrder(String item, int quantity, String description)
注意到,在wrapped中,PurchaseOrder元素被映射为代表了一个方法。他的参数就是他的那些元素。
他们在wsdd得使用如下
<service ... style="document"> for document style
<service ... style="wrapped"> for wrapped style
Message 服务
当你需要处理纯xml而不是java对象时,你将会用到这种服务。
message服务的方法有4中签名
public Element [] method(Element [] bodies);
public SOAPBodyElement [] method (SOAPBodyElement [] bodies);
public Document method(Document body);
public void method(SOAPEnvelope req, SOAPEnvelope resp);
发布service
有2种发布方式,一种是实例发布,一种是描述符发布
实例发布很简单
把我们的java源文件拷贝到axis目录下,改扩展名为jws
然后就可以直接访问了,例如:
java samples.userguide.example2.CalcClient -p8080 add 2 5
他将调用add方法,传递的2个变量分别为2和5。
很显然,第一种方法有很多弊端,比如需要源文件,不能有包路径等等
描述符发布
一个最简单的例子如下:
<deployment xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<service name="MyService" provider="java:RPC">
<parameter name="className" value="samples.userguide.example3.MyService"/>
<parameter name="allowedMethods" value="*"/>
</service>
</deployment>
一个服务是一个targeted chain ,可能包含下面的一些或者全部:请求Handler,pivot Handler 支点Handler,响应Handler。支点hander在服务中叫做provider,在例子中我们的provider是java:RPC,他被axis内嵌,代表了Java RPC service,具体的类是org.apache.axis.providers.java.RPCProvider.
我们告诉RPCProvider 我们要调用的服务MyService,并以参数的形式告诉他具体的目标以及可以被调用的方法。
我们也可以给我们要调用的对象设置作用范围scope,和servlet的scope一样,有request,session,application.
我们需要把这个描述符定义的内容告诉应用服务器才能真正提供我们需要的服务。
如果已经部署axis到tomcat,我们可以这样发布
org.apache.axis.client.AdminClient deploy.wsdd
这样我们的服务就可以通过soap来访问了
测试一下
java samples.userguide.example3.Client
-lhttp://localhost:8080/axis/services/MyService "test me!"
可以通过下面来查看所有已经部署的服务
java org.apache.axis.client.AdminClient list
来看看更进一步的应用,使用一下request handler
<deployment xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<!-- define the logging handler configuration -->
<handler name="track" type="java:samples.userguide.example4.LogHandler">
<parameter name="filename" value="MyService.log"/>
</handler>
<!-- define the service, using the log handler we just defined -->
<service name="LogTestService" provider="java:RPC">
<requestFlow>
<handler type="track"/>
</requestFlow>
<parameter name="className" value="samples.userguide.example4.Service"/>
<parameter name="allowedMethods" value="*"/>
</service>
</deployment>
这个例子会在客户端掉用LogTestService的时候,先调用samples.userguide.example4.LogHandler作记录操作
远程管理
默认状态下,axis只允许在axis部署的机器上使用管理请求,如果希望在其他的机器上进行管理操作可以参照下面的例子
<service name="AdminService" provider="java:MSG">
<parameter name="className" value="org.apache.axis.util.Admin"/>
<parameter name="allowedMethods" value="*"/>
<parameter name="enableRemoteAdmin" value="true"/>
</service>
注意,这样配置需要作必要的安全配置
原文见:
http://blog.csdn.net/huabingl/archive/2008/02/12/2089145.aspx
说dtree是使用最广泛的目录树javascript应该也不为过.这得意于他简单的使用方式和良好的结构.
可能这里是他最早的发源地之一http://www.destroydrop.com/javascripts/tree/
上面有他的示例和api文档.
dtree使用简单,使用起来就是引入一个dtree.js,dtree.css和一些小图片文件。.在需要显示树的地方,插入类似下面的代码
可以参照这里做些配置,观看效果.可选的选项有folderLinks, useIcons, useLines, useSelection, useStatusText, closeSameLevel
http://www.destroydrop.com/javascripts/tree/example/
你可以放置radio或者checkbox在相应的节点上,或者在节点上加上链接.
原文见
http://blog.csdn.net/huabingl/archive/2008/02/12/2088711.aspx
opencms列表显示
先准备要显示的数据。比如在站点下建立一个sports目录,里面以news的格式放入一些xmlpage.
注意给这些xmlpage准备好detail显示页面。
<%@ taglib prefix="cms" uri="http://www.opencms.org/taglib/cms" %>
<%@ page import="java.util.*"%>
<%@ page import="org.opencms.jsp.*"%>
<%
String sPageIndex=request.getParameter("pageIndex");
int iPageIndex=1;
if(sPageIndex!=null){
iPageIndex=Integer.parseInt(sPageIndex);
}
pageContext.setAttribute("pageIndex", iPageIndex+"");
%>
<cms:contentload collector="allInFolderDateReleasedDesc" param="/myfirstsite/sports/%(number)_news.html|news" pageIndex="%(pageContext.pageIndex)" pageSize="2">
<cms:contentinfo var="contentInfo" scope="request" />
<a href="<cms:link><cms:contentshow element="%(opencms.filename)"/></cms:link>" target=_blank><cms:contentshow element="Title"/> </a>
<%out.println("---");%>
</cms:contentload>
<%
CmsContentInfoBean info = (CmsContentInfoBean)request.getAttribute("contentInfo");
int totalNum=info.getResultSize();
%>
共<%=totalNum%>条数据,当前第<%=info.getPageIndex()%>/<%=info.getPageCount()%>
<a href="list_taglib?pageIndex=<%=info.getPageNavStartIndex()%>">第一页</a>
<a href="list_taglib?pageIndex=<%=(info.getPageNavStartIndex()-1)>0?(info.getPageNavStartIndex()-1):1%>">上一页</a>
<a href="list_taglib?pageIndex=<%=(info.getPageNavStartIndex()+1)>info.getPageCount()?info.getPageCount():(info.getPageNavStartIndex()+1)%>">下一页</a>
<a href="list_taglib?pageIndex=<%=info.getPageNavEndIndex()%>">最后页</a>
上面的例子力求尽可能少的使用标签。主要使用了CmsContentInfoBean ,CmsJspXmlContentBean ,I_CmsXmlContentContainer(CmsJspTagContentLoad )等多个对象。分页的关键在CmsContentInfoBean 和 CmsJspTagContentLoad的关系上。
参考资料:
http://www.javaedu.com/bbs/viewthread?thread=128
http://wangyi878750.blog.sohu.com/41725191.html
http://l--w.blog.sohu.com/47996664.html
http://wangyi878750.blog.sohu.com/41378072.html
Ruby之Blocks,Iterator -------读《Programming Ruby 2nd》
Ruby是”一种用于迅速和简便的面向对象编程的解释性脚本语言”;这意味着什么? 解释性脚本语言:
- 有直接呼叫系统调用的能力
- 强大的字符串操作和正则表达式
- 开发中快速回馈
迅速和简便:
- 无需变量声明
- 变量无类型
- 语法简单而坚实
- 自动内存管理
面向对象编程
- 任何事物都是一个对象
- 类,继承,方法,等等
- 单态方法
- 模块糅合
- 迭代器和闭包(closures)
以及:
如果你对上面的那些概念还不熟悉,继续读,别担心.Ruby的箴言是”迅速和简便”.
<script language="javascript"> //定义全局变量,用于清理工作 var word; var doc; function editFile(){ //调用word控件 word= new ActiveXObject("Word.Application"); //屏蔽“另存为”按钮 word.CommandBars("File").Controls(5).Enabled= false; word.CommandBars("File").Controls(5).visible= false; //屏蔽"另存为网页"按钮
word.CommandBars("File").Controls(6).Enabled= false; word.CommandBars("File").Controls(6).visible= false;
word.visible = true; // word.activate(); try{ //打开文件 doc=word.Documents.Open("http://212312.doc"); //痕迹保留 word.ActiveDocument.TrackRevisions =true; //切换成web视图 word.ActiveDocument.ActiveWindow.View.Type=3 }catch(e){ alert(e.message); }; } function myfinalize(){ //文档保存 doc.save(); //文档关闭 doc.close(); //把屏蔽的功能打开 word.CommandBars("File").Controls(5).Enabled= true; word.CommandBars("File").Controls(5).visible= true; //word退出 word.quit(); } //参考文档 http://bbs.hidotnet.com/712/ShowPost.aspx
原文:
http://blog.csdn.net/huabingl/archive/2008/02/11/2088477.aspx
摘要: AXIS User Guide(1) 阅读全文
摘要: Sliding into WebDAV 阅读全文
摘要: HibernateTemplate方法索引 阅读全文
最近又遇到个对js取名不帅导致错误的问题,特开此贴,以示警戒: 不要把自己的js函数取成close(),open(),start()之类的名字!!
window得resizeto和resizeby方法对模式窗口无效。
最近研究了一下webdav,关于webdav的详细信息可以在 google上搜索或者参看官方网站http://www.webdav.org. "WebDAV stands for "Web-based Distributed Authoring and Versioning". It is a set of extensions to the HTTP protocol which allows users to collaboratively edit and manage files on remote web servers. " 笔者简单的尝试了它下面的slide和mod_dav. slide是jakarta下面的子项目,分为服务端和客户端.个人认为服务端是专门为tomcat定做的一个webdav实现.关于slide,javaeye上有些讨论,可以参考http://www.javaeye.com/t/5267.html.本人涉入的不是很深,中文问题让我碰到了,slide提供2中存储方式,文件形式和数据库形式,限于时间,笔者没有对数据库形式进行测试.slide的工作目录默认在服务器bin目录下. 用mod_dav来实现相比就简单多了,如果你熟悉apache httpserver,应该很容易搞定.http://www.webdav.org/mod_dav/ 上的有部分资料.可以根据http://www.webdav.org/mod_dav/install.html 的讲解来配置.apache server1.3以后(包括1.3)在发布的时候都自带了mod_dav包.需要做的就是加载和配置它. LoadModule dav_module libexec/libdav.so AddModule mod_dav.c 笔者在配置的时候由于没有认真看文档,犯了个小小的错误.所以注意下面的文字: "In the following example, the DAV lock database will be stored in the /usr/local/apache/var directory (which must be writable by the server process). The file's name will be DAVLock when mod_dav needs to create it. (actually, mod_dav will create one or more files using this file name plus an extension)
DAVLockDB /usr/local/apache/var/DAVLock" 然后你需要配置一个webdav的工作目录,由于访问apache服务的用户会默认是nobody用户,所以你至少得让工作目录对nobody可读写.在目录的定义中加入DAV on这样的属性就 ok了 eg: "Alias /pages /home/www/davhome <Location /pages> DAV On </Location> " 测试webdav 安装完webdav后,你可以做简单的测试: IE浏览器-〉文件-〉打开,然后输入配置的url,http://127.0.0.1/pages,选上"以Web文件夹方式打开".可以看到效果。 客户端API. 如果是 java可以 采用slide的客户端.(php用户咋办?). 这个最新的客户端使用的是最新的jdom,注意哦.. 参考资料: http://www.uplinux.com/www/net/02/131.shtml
mvnforum是一个开源的论坛软件.网址如下: http://sourceforge.net/projects/mvnforum/ 本文主要研究它的权限部分,以作为使用借鉴. 这里有篇中文的文档,以作参考: http://www.cn-java.com/target/news.php?news_id=3298
权限部分的UML图如下:
数据流程: 1,系统从OnlineUserManager这个入口进入.这个部件有个Map用来存储当前的非过期用户。OnlineUserManager会先根据当前时间和最后一个用户的请求时间做对比,检查是否有刷新过期用户的必要,如果超过所设置的时间,那么先更新Map。然后OnlineUserManager根据提供的用户的 sessionid和username在这个Map中查找。如果找到,则刷新该用户的最后一次访问时间;否则,OnlineUserManager调用OnlineUserFactory部件创建该OnlineUser,并把这个OnlineUser存入Map之中。 判对用户是否过期的原理是:从OnlineUser的OnlineUserAction中取出最后一次的访问时间和当前时间做对比. 2,OnlineUserFactory负责创建OnlineUser并为该OnlineUser提供完整的权限信息.OnlineUser包括3大部分信息,一部分是用户的基本信息,一部分是用户的权限信息,一部分是用户的在线信息.在线信息由OnlineUserManager负责管理,其他2部分信息由OnlineUserFactory从持久层获得. 获得权限信息并把它设置到OnlineUser部件上,提供给OnlineUserManager管理. 3.CNMPermissionFactory类似我们常说的service.主要负责和持久层通信,最终返回一个CNMPermission部件供OnlineUserFactory合成OnlineUser部件.在下面的章节里,笔者会对他细化讨论. 权限结构: 用来实现用户权限的主要的是CNMPermission接口和他是2个子类AbstractPermission和CNMPermissionImpl.CNMPermission接口负责定义权限有关的常量和对外API.AbstractPermission设置了保存权限信息的变量并实现了CNMPermission接口中定义的抽象方法,因此,笔者把这个抽象类叫做鉴权类.CNMPermissionImpl 则负责对AbstractPermission使用的变量进行设值,因此,笔者称之为赋权类. 先看看AbstractPermission的结构。这里涉及到这么几个概念:全局权限,特定权限,单个权限,组合权限。 全局权限用true/false来设置。 特定权限是指某一个动作所作用的不同的对象。比如:某用户只能将写操作作用于1,2,4这3个论坛板块之上。表示为这个特定权限内部的ArrayList容器中只有1,2,4三个编号。 单个权限是指单个动作。比如读操作。 组合权限是为了方便设置提供的对单个权限的组合。比如对某用户一次设置某板块的“读”和“发布”2种权限。 前2种权限是一个纬度的划分,后2个是另一个纬度的划分。 如何鉴权? 鉴权的接口都会在CNMPermission中定义。对全局权限,直接返回对应的标志位的值,对于特定权限,则先判断是否特定权限全开,否,则然后判断其ArrayList中是否包含对应的对象编号。 如何赋权? 这里要承接到上述数据流程的第三步。由CNMPermissionFactory根据一定先后循序(其实无关顺序,因为采用的为真覆盖原则,即持久层返回的权限都是真值,后面的真值对前面的真值可覆盖)从持久层获得所有的全局权限和特定权限。mvnforum只有用户和角色2种概念(当然也可以扩展),因此它的顺序是:用户全局全县-〉用户特定权限-〉角色全局全县-〉角色特定权限。当然无论哪一部都是对同一个CNMPermission进行操作。 无论在设置全局权限还是特定权限的时候都可能会遇到所定义的组合权限。具体的组合权限拆分是由CNMPermissionImpl来做的. 相关的表结构: member表,存贮用户基本信息。 membergroup ,存储用户和组(角色)的对应关系。 groups表,存储组/角色的基本信息 grouppermission,存储组/角色的全局权限,字段为groupid permissionid groupforum,存储组/角色 的论坛权限, 字段为groupid ,forum,permissionid memberpermission 存贮用户的全局权限,字段为 memberid permissionid memberforum 存贮用户的论坛权限,字段为memberid ,forum,permissionid
修改于2006/12/16 晚8时
目前的很多商业和非商业的服务器中间件都默认集成了common-log甚至是log4j.因此当我门把我们的应用发布在上面的时候,都会遇到关于log方面的问题. 1.webshpere下面集成log4j. "WebSphere的类装入器方式有两种方式:PARENT_FIRST和PARENT_LAST。默认值是PARENT_FIRST,这种方式在载入当前classpath的类之前先载入其上一级classloader能够装入的类。这是标准的JVM classloader的默认策略。如果采用PARENT_LAST,则过程正好相反,即先载入当前classpath的类,再载入其上一级classloader能够装入的类,这样可以用当前classpath中更新的类覆盖其上一级classloader的相同类。受类装入器方式影响的classloader包括application classloader、WAR classloader以及共享类库的classloader。" 因为websphere在共享类库的classloader中有一套common logging,但是确没有合适配置文件.如果我们把配置正确的log4j.properties文件放在共享类库下,我们会发现log4j可以运行.但还有另外一个很通用的方式--改变webshpere的类库加载顺序.我们让他先加载我们web应用所需的类库.即我们把web应用的加栽方式改为PARENT_LAST. 哎,尽管我小心的提防,今天还是中招了,在我的配置里,log4j的配置文件只能读取一次,不能一个应用一个配置文件.为了让它加载自己的配置,可以自己写(或者用spring的)servlet/listener去手动加载这个配置文件. 2.jboss下面的集成log4j 大家可能都曾在为jboss下面配置log4j郁闷过.jboss比webshpere走的还远.无论你的项目是否使用了log4j,jboss在自己启动的时候就已经运行他了.也就是说在jboss加载自己共享类库的时候,已经读取了自己log4j.xml文件配置.这个文件在conf中可以找到.如果你需要为你的应用单独配置一个catagory,你需要直接在这里配置. 在webloader装载应用的时候,如果应用中有log4j的包,似乎总出现appender已被占用的问题.笔者把log4j的包连带应用中的log4j配置文件一并移去,世界清净了. 关于为了让应用自带的log4j配置文件生效,有人建议修改 <attribute name="Java2ClassLoadingCompliance">false</attribute> 和 <attribute name="UseJBossWebLoader">false</attribute> 这两个属性. 3.sunone下面集成log4j 距离上次用SunOne服务器已经好长时间了,似乎sunOne的log有些类似jboss,也是一个服务器的log集中管理.由于使用的不是很多,暂且在这里站个位子. 随手贴点关于log的信息: http://wiki.apache.org/jakarta-commons/Logging/FrequentlyAskedQuestionshttp://www-128.ibm.com/developerworks/cn/websphere/library/techarticles/0408_baigang/part3.html
OpenLDAP
快速上手
Ben
的项目里面要用到
OpenLDAP,
我的项目里面也要用到
LDAP,
所以这
2
天集中看了一下
LDAP
相关的内容。做了个笔记,也算是为人类知识的积累做点或有或无的贡献。
OpenLDAP
的官方站点是
http://www.openldap.org
。
上面有个
QuickStart,
我将大致按照这个来讲解。
一、
安装
在官方站点上发布的是
linux/unix
下的
OpenLDAP
源文件,当然也很容易找到
windows
系统下的版本。笔者学习安装的就是
windows
版本的。
二、
配置
OpenLDAP
有
2
个用户最关注的配置文件。
一个是
slapd.conf
,
在他里面定义了最基本的
DN
以及管理员的账号和密码。
另一个是
LDIF
的文件。在它里面可以配置所有的用户和组织。
1、
我们先来了解
LDAP
的相关概念。
我们知道
LDAP
的全称为(
Lightweight Directory Access Protocol
),即轻量级目录访问协议。
Ldap
是怎样的一个结构呢
?用官方的话说:“
In LDAP, directory entries are arranged in a hierarchical tree-like structure. Traditionally, this structure reflected the geographic and/or organizational boundaries. Entries representing countries appear at the top of the tree. Below them are entries representing states and national organizations. Below them might be entries representing organizational units, people, printers, documents, or just about anything else you can think of..
”他是一个树状的结构。每一个节点被称为一个
Entry
。这些
Entry
有着有趣的含义。
下面是他的
2
个实例。一个反映了
geographic
,一个反映了
organizational
。
传统命名
网络命名
我们来看看个个节点的定义方式。
每个
Entry
都有一个自己得一个标示
,我们把他叫
DN(Distinguished Name)
,这个
dn
包含了一个
RDN
(
Relative Distinguished Name
)。在上面的第二个图例
中,Barbara Jensen的RDN是
uid=babs,他的dn是
uid=babs,ou=People,dc=example, dc=com。
每个节点都需要一个类别
,
这个类别信息用objectClass来表示。ObjectClass就是该节点的schema,他定义了该节点该有和不该有的属性。默认的objectClass都在schema/core.schema中有定义。如果在你的配置过程中出现了关于找不到objectClass的问题,您不妨参看一下这里面有没有你用到的objectClass
. 在schema文件夹下还有其他一些schema文件,你也可以定义自己的schema.想要加载其他的schema,你可以在slapd.conf文件中用include加入.如:include ./schema/core.schema.
为了方便识别,其实我们在DN里面用的都是objectClass的简写形式。如:ou代表organizationUnit,c代表country,st代表state,dc代表??等。
2、
来看看
slapd.conf
这个文件
这个文件的主要信息是如下几行:
database bdb
suffix "dc=<MY-DOMAIN>,dc=<COM>"
rootdn "cn=Manager,dc=<MY-DOMAIN>,dc=<COM>"
rootpw secret
directory /usr/local/var/openldap-data
定义了数据库,最基本的后缀,管理员的
dn
和密码,以及数据存放路径。
编辑好这个文件,我们就可以启动了。
如果你把
ldap
安装为
windows
服务,你可以像我一样启动:
net start OpenLDAP-slapd
3、
我们主要操作的就是这个
LDIF
文件
我们需要在这个文件里面加入所需要的
dn.
注意,因为我们在
slapd.conf
中定义了一个
base dn
和一个管理员
dn
,所以我们需要首先把这
2
个
dn
加进来。
dn: dc=<MY-DOMAIN>,dc=<COM>
objectclass: dcObject
objectclass: organization
o: <MY ORGANIZATION>
dc: <MY-DOMAIN>
dn: cn=Manager,dc=<MY-DOMAIN>,dc=<COM>
objectclass: organizationalRole
cn: Manager
保存为
ldif
后缀的文件。然后我们用命令把这些信息加到
ldap
中去:
ldapadd -x -D "cn=Manager,dc=<MY-DOMAIN>,dc=<COM>" -W -f example.ldif
让我们来查看以下我们的设置是否出现问题:
ldapsearch -x -b 'dc=example,dc=com' '(objectclass=*)'
上面的是
linux/unix
下的命令,
windows
下我们需要做点更改:
ldapsearch -x -b dc=example,dc=com (objectclass=*)
对,就是去掉引号。
为了察看方便,笔者建议使用
GUI
工具来查看,比如笔者使用的
Softerra LDAP Browser 2.6
。
三、
和
java
集成
我们的
ldap Server
已经搭建起来了,我们需要在我们的
java
程序中访问这个服务。
Openldap.org
上有没有讲?有讲?下面介绍的
JLDAP
就是干这个的。
我们需要看一下“
Java LDAP Overview
”里面的内容。内容不是很多,但很实用。
要在
java
中访问
ldap
,我们需要一套
api,
你可以在下面的网站上获得:
http://developer.novell.com/wiki/index.php/LDAP_Classes_for_Java
在下在的文件里面有许多的例子,在
novell
的网站上也有很多的例子。我就不讲了。
Try yourself
。
没有华丽的Rose,也没有Togather,用JUDE的感觉也不错.刚刚把PicoContainer反向了.可惜,好东西都陆续要收费了.只能用用 Community /Free 版. JUDE的一个下载地址: http://jude.change-vision.com/jude-web/product/community.html
摘要: 一、简介 感谢“简易java框架”分享的学习心得。循着他的足迹,我把picocontainer读了一遍。源代码的版本是1.2-RC-2。 pico的官方站点:http://www.picocontainer.org/ 由于它是一个专门的ioc容器,所以使用起来没有spring那么麻烦。关于他的文档,在官方站点上有一篇《5分钟搞定pico》的文章。国人似乎也有很多的翻译版本。讲解得很详细... 阅读全文
一个简单的ThreadPool 原文来自 http://www.informit.com/articles/printerfriendly.asp?p=30483&r1=1&rl=1 项目是多线程的,所以引入了线程池这个东西。池子是个老美写的。在项目中表现的还不错。所以把它摘出来,介绍给以后或许需要用到它的同行们。 关于为什么要采用ThreadPool,原文已经提到了:创建一个线程是需要开销的;如果线程数量过大的话,cpu就会浪费很大的精力做线程切换。 ThreadPool的实现过程就是对WorkerThread的同步和通信的管理过程。 我们来看代码。 首先,在ThreadPool构造的时候,创建10个WorkerThread(size=10)并让他们运行。每个WorkerThread线程都有个ThreadPool的引用,用于查询ThreadPool的状态和获得同步锁.WorkerThread运行以后,循环调用ThreadPool的方法进行查询,如果没有发现任务,ThreadPool告诉正在查询的线程进入休眠状态,WorkerThread释放对查询方法的锁定.这样在还没有任务的时候,所有的10个WorkerThread都会进入休眠状态,进入等待ThreadPool对象的等待锁定池,只有ThreadPool对象发出notify方法(或notifyAll)后WorkerThread线程才进入对象锁定池准备获得对象锁进入运行状态。 代码片断: while ( !assignments.iterator().hasNext() ) wait(); 如果你有jprofile或者其他的观察线程的工具,你可以看到有10个线程都在休眠状态. 接着,我们向ThreadPool中加入任务,这些任务都实现了Runnable的run方法.(至于为什么把任务都做成Runnable,译者至今也有些疑问?预定俗成?TimerTask也是实现自Runnable,弄得初学者经常把真正运行的线程搞混).ThreadPool每assign一个任务,就会发出一条消息,通知它的等待锁定池中的线程.各个线程以抢占的方式获得对象锁,然后很顺利的获得一条任务.并把此任务从ThreadPool里面删除.没有抢到的继续等待. Runnable r = (Runnable)assignments.iterator().next(); assignments.remove(r); WorkerThread从ThreadPool那里获得了任务,继续向下执行。 target = owner.getAssignment(); if (target!=null) { target.run(); owner.done.workerEnd(); } 记住,这里调用的是target.run();而不是调用的线程的start()方法。也就是说在这里表现出的WorkerThread和task之间的关系仅仅是简单的方法调用的关系,并没有额外产生新线程。(这就是我上面纳闷为什么大家都实现Runnable来做task的原因) 大家可能注意到,WorkerThread并没有对异常作处理。而我们知道发生在线程上的异常会导致线程死亡。解决的办法有2中,一种是通过threadpool的管理来重新激起一个线程,一种是把异常在线程之内消灭。在项目中,我采用的是第二中,因此这个片断改称这样: if (target!=null) { try{ target.run(); } catch(Throwable t){ ....... } owner.done.workerEnd(); } 在WorkerThread完成一个task以后,继续循环作同样的流程. 在这个ThreadPool的实现里面,Jeff Heaton用了一个Done类来观察WorkerThread的执行情况.和ThreadPoool的等待锁定池不同,Done的等待锁定池里面放的是初始化ThreadPool的线程(可能是你的主线程),我们叫他母线程. 在给出的测试例子中.母线程在调用complete()方法后进入休眠(在监视中等待),一开始是waitBegin()让他休眠,在assign加入task以后,waitDone()方法让他休眠.在WorkerThread完成一个task以后,通知waitDone()起来重新检查activeThreads的数值.若不为0,继续睡觉.若为0,那么母线程走完,死亡(这个时候该做的task已经做完了).母线程走完,ThreadPool还存在吗?答案是存在,因为WorkerThread还没有消亡,他们在等待下一批任务,他们有ThreadPool的引用,保证ThreadPool依然存在.大家或许已经明白Done这个类的作用了. 细心的读者或许会发现,发生在Done实例上的notify()并不是像ThreadPool上的notify()那样每次都能完成一项工作.比如除了第一个被assign的task,其他的task在assign进去的时候,发出的notify()对于waitDone()来说是句"狼来了". 最后在ThreadPool需要被清理得时候,使每一个WorkerThread中断(这个时候或许所有的WorkerThread都在休眠)并销毁.记住这里也是一个异步的过程.等到每一个WorkerThread都已经销毁,finalize()的方法体走完.ThreadPool被销毁. for (int i=0;i<threads.length;i++) { threads[i].interrupt(); done.workerBegin(); threads[i].destroy(); } done.waitDone(); 为什么有句done.workerBegin();?不明白. 参考文章: http://www.zdnet.com.cn/developer/common/printfriend/printfriendly.htm?AT=39276905-3800066897t-20000560c
吕华兵,男,24岁。 2000-2004年,在中国民航大学读书。学习期间,笔者以技术部长身份参与了校易航工作室暨易航网站的创建和发展工作,参与和独立完成了多个项目的设计和开发。 2004年5月到2006年5月,在北京环亚时代(港新合资)天津软件中心从事Java的开发工作。参与了CMCC的OA的实施工作,主力开发了MOCHA AM的前端显示和MOCHA ITAM的报表系统。 2006年5月至今,在美国易达软件有限公司工作。设计并开发了Information Publisher的多线程后端程序。 笔者长期从事j2se,j2ee的开发工作,对各种设计模式亦有丰富的使用经验。 笔者从来重视规范的软件流程,对RUP有很深的理解。 对于javascript,dhtml,ajax,笔者有着丰富的经验。 笔者也是“拿来主义”的拥趸,不遗余力的翻译、学习、使用和宣传各种开源项目。目前使用过的开源项目有:spring、picocontainer、hibernate、ibatis、struts、webwork等框架系列,DOM系列,commons系列,Quartz,log4j,ant,oscache,proxool以及各种报表工具等等。
笔者从来重视知识的提取和积累,这也是笔者开此blog的主要原因,同时,也希望通过此blog结交更多的朋友。
译者安:你敢大胆采用最新的技术吗?你顾虑哪些方面?下面的采访将给我们提供一个参考。 原文:Interview: Real-world Experience with Google Web Toolkit (GWT) 在java中,对技术的采用是一件让人心烦的事情,因为我们获得通知的途径太多。不同的会议,不同的站点如slashdot和theserverside,而且还有数不清的个人博客如dhh和o'Reilly's Radar. 一个让人感兴趣的技术总是让业界议论纷纷,正如人们所意识到的,这个产品并不是成熟期。 为了让一个产品成为主流,早期的采用者必须足够喜欢这项产品来承担很多非常的任务以便 让更为胆怯的开发者相信这项新技术值得采用。像Hibernate和Spring Framework这样的技术花了好几年 才成为一个成熟产品。许多产品,比如maven,在版本确定之前经历了痛苦的时期因为他们早期缺乏 足够的文档或者有不同的足够强大的挑战者比如ant.本人对这个过程中的盲点很感兴趣,从议论这个产品的介绍到大范围的采用往往要经历成月上年,而且很难指定时间表。hibernate并不是暴雨似的到来,而是通过大量用户自我采用.一个失败的项目比如ojb出来的时候也是引起轰动,但是它最终没有承诺的那么好.在这种情况下,早期的hibernate使用者其实信心不足. 让我们来看Google Web Toolkit (GWT)… GWT在这个进程中处于什么位置? gwt看起来是在早期使用(early-adopter)的中期。一开始的议论声已经消去,现在陆续出现了许多关于gwt的文章和博客,表明了人们正在期待关于gwt的第一个helloworld的反馈报告。我的很多谨慎的同行都在回避他,事实上认为它是个不好的主意。风险阻碍了开发者对大多数新技术的评估直到他们在现实中看到了一个活生生的实例解决方案--就像maven被ibm使用一样。那些有能力来尝试风险的开发者正在对这个框架进行测试。他们中的某一个或许宣称gwt不适合它的组织。另外一个同行已经原则上接受了gwt的观点,但是没有时间来在他的应用中集成。所以,到底gwt处于什么时期?早期的使用人群有哪些经验呢? 关于这个问题,我专门采访了Grassroots Technologies公司的Michael Podrazik。Grassroots Technologies是一个在纽约的咨询小组。通过在Grassroots的工作,michael已经正在把gwt应用在他们的一个新的正在开发的web应用当中。在下面的采访里面,我要求他来交流他的产品经验来帮助其他人去理解gwt.我特别要求他给一些gwt客观的意见,而且细致的描述他在用gwt开发过程中遇到的挑战。幸运的是,他的信息将会帮助你决定是否gwt是你项目的正确选择。 采访内容: q:什么使你选择了gwt? a:我订阅了google的blog,所以我听说了gwt当他发布到javaone的时候。在阅读了他的文档之后我开始对这种方式很好奇,因此我把它down了下来而且开始使用它(play with it).我刚刚开始了一个项目,这个项目是把遗留的 Access/VBA的桌面应用升级为一个web应用。在UI方面有许多ajaxian特性所以我想我可以让gwt一展身手。我认为(figure)只要我保持我的架构足够抽象,我就有能力用更为传统的web应用框架来替换gwt层。gwt会很伤脑筋吗?至少目前为止我很开心。 q:gwt出现了那些挑战?你围绕着gwt设计的web框架吗?gwt是否挑战了你关于web应用开发的观点? a:你确实不能简单的认为gwt是一个webapp的框架,他更是一个有着rpc和对象序列化的ui类库。因为你需要改变你项目组织的assumptions以及包的结构。在java服务端开发rich-client用户界面我们有大量的经验,比如flash/actionscript.gwt和他们十分类似,因此可以想象有这些元素的项目--分隔的服务端和客户端而不是同一的webapp--很爽。 朝着这个方向,你需要明确区分服务端和客户端的功能。我相信一个好的哲学就是使你的客户端仅仅用于展示。 你需要思考你服务接口的设计,比如每个操作的粒度 你不能在客户端代码上用java5得语法 Q:你的意思是不能再gwt的具体类或者普通的web应用里面用java5的语法? a:你不能在客户代码里面使用java5的语法。我们在服务端代码中使用了许多java5的特性,但是所有将要被转换成javascript的代码必须是1.4的规范。 这个也包括许多事实上你用在服务端的类。因为rpc框架允许用户定义的数据类型的序列化,意思是你将在浏览器端得到一个已经被转化为javascript实例的类,这个类作为一个参数传递到服务端的实现中。在你的服务端代码中,你将操纵同一个class而且是编译过的字节码。 这个时候就出现了一个选择,domain module和gwt的耦合度怎样才合适呢? What we decided was to keep value objects implementation-agnostic so as to avoid “infecting” the API and persistence layers with beans implementing GWT’s IsSerializable interface. 举个例子,在服务端我们有个IUser接口的用户模块,这个借口继承自IPersistable.gwt的实现接受和返回实现IsSerializable接口的GwtUser的实例并把这些实例利用commons-beanutils发送到服务端。 对于这一点可能有些争论,这样做并不非必要。但是我觉得这点额外的工作将带给你更为清晰的层次划分。我们可以嵌入gwt到任何一点,而且可以转换到springmvc或者struct或者其他的地方,而不需要担心代码上 的反应。 q:你发现gwt产生的javascript不能垮浏览器的地方了吗?你发现gwt产生的javascript包含一些错误需要手动调试了吗? a:都没有,这正是令我们惊讶的地方。跨浏览器javascript的开发是PITA,而且GWT真正的把你从他那里隔离开来。 我发现了大量的在FIREFOX和IE不同的地方,但是这些最后被确认都是CSS支持的问题而于GWT无关。 我也遇到了一大队JAVASCRIPT错误,但是这些错误都是应为变量而不在初始化,这些问题很快就会找到并且不需要大量的调试。目前已经完成的大多数工作并不全是ui控件的问题,或许随着我们的深入,我们会遇到一些问题,但是目前为止,我们还没有多少麻烦。 q:你的工作组的成员是更喜欢java还是javascript呢? 显然是java,哈哈。但是我们有人对javascript和actionscript也很精通。就像译者本人。 q:一句话,对正在考虑gwt的人,你有什么建议?你会推荐他吗?你对这项技术的客观观点是什么?thumbs up or thumbs down? a:目前是thumbs up.我们目前仍然在开发的早期,而且我还不想说在它是完美的或者在以后的进程中不会咬我们一口。意思是说,你的建构要搭好。 它真的像是在作swing或者其他UI的桌面应用。 我们用基于Controller和IView实现的GWT生成了全部的ui.除了gwt模块引入以外,那里没有html。 这是对几乎所有主流web应用范例的违背,但是如果你喜欢ui编程,他完美的抽象了ajax/dhtml的行为到一个十分友好和可扩展的api. 我或许会说如果你的工作是php,asp或者其他语言,你或许需要花更多的功夫。如果你已经是一个有经验的java程序员,那么你可以很快投入其中。
java.sql.Date,java.sql.Time和java.sql.Timestamp三个都是java.util.Date的子类(包装类)。 但是为什么java.sql.Date类型的值插入到数据库中Date字段中会发生数据截取呢? java.sql.Date是为了配合SQL DATE而设置的数据类型。“规范化”的java.sql.Date只包含年月日信息,时分秒毫秒都会清零。格式类似:YYYY-MM-DD 当我们调用ResultSet的getDate()方法来获得返回值时,java程序会参照"规范"的java.sql.Date来格式化数据库中的数值。因此,如果 数据库中存在的非规范化部分的信息将会被劫取。在sun提供的ResultSet.java中这样对getDate进行注释的: Retrieves the value of the designated column in the current row of this <code>ResultSet</code> object as a “java.sql.Date” object in the Java programming language. 同理。如果我们把一个java.sql.Date值通过PrepareStatement的setDate方法存入数据库时,java程序会对传入的java.sql.Date规范化 ,非规范化的部分将会被劫取。 然而,我们java.sql.Date一般由java.util.Date转换过来,如:java.sql.Date sqlDate=new java.sql.Date(new java.util.Date().getTime()). 显然,这样转换过来的java.sql.Date往往不是一个规范的java.sql.Date. 在 http://www.thunderguy.com/semicolon/2003/08/14/java-sql-date-is-not-a-real-date/ 文章中提到,要保存java.util.Date的精确值, 我们需要利用java.sql.Timestamp. 感谢这篇文章的铺垫: http://community.csdn.net/Expert/topic/4354/4354971.xml?temp=.5256616
官方网址:
http://logging.apache.org/log4j/docs/index.html
一个中文翻译的文档:
http://www.jaxwiki.org/zh/project/logging.apache.org/log4j/docs/manual.html
我摘出黄色字体表明几条列在下面,也是笔者认为log4j最主要特点的浓缩:
1.阶层式的命名:
如果一个logger 的名字后面跟着一个点号(dot),它就是点号(dot)后面的那个logger的前辈( ancestor),是这个晚辈(descendant) 的前缀。如果在它自己和这个晚辈之间没有其它的前辈,它和这个晚辈之间就是父子关系。
2.级别继承
对于一个给定的logger C,它继承的级别等于logger阶层里,从C开始往root logger上去的第一个non-null级别。
3.执行规则
在一个级别为q(被指定的或继承的)的logger里,一个级别为p的日志请求,只有在p >= q 时才能够被执行。
4.appender添加性的规则
Logger C的log输出信息将被输出到C的所有appenders和它的前辈的 appenders。这就是"appender additivity"的意思。但是,如果logger C的前辈,比如说P,P的additivity flag被设置为 false ,那么,C的输出信息将被输出到C的所有appenders中去,以及它的前辈的——截止在P那里,包括P在内的,appenders中去,但是不会输出到P的前辈的 appenders中去。 默认情况下,Loggers的additivity flag设置为true 。
关于日志格式:暂贴几个样例:
log4j.appender.A1.layout.ConversionPattern=%d %-5p [%t] %-c (%13F:%L) %3x - %m%n
在配置文件中,log4j可以访问到系统环境变量。具体的变量参考相关资料。
一篇我很早以前在csdn写的文章:
http://blog.csdn.net/huabingl/archive/2005/02/19/293933.aspx
我承认我用mysql有很长时间了,不过似乎我仍然很白。好吧,还是写写吧。 1。1067错误,无法启动。7/3/2006 解决步骤和方案:察看日至,mysql.user表莫名其妙的弄丢了。从其他地方扒下一个放在这里就可以了。 2.非安装版mysql的安装和启动。 一般情况下,本人习惯用非安装版的软件。为了安装方便,你可以把解压后的文件拷贝到c盘根目录下,并把总目录改为mysql.然后进入windows命令 控制台,在c:/mysql/bin下面运行mysqld-nt --install把它安装为一个服务,然后调用net start mysql启动它,停止的命令是net stop mysql .想要移除这个服务,用命令mysqld-nt --remove 3.访问mysql的命令:mysql -h host -u user -p 。不过有好多好用的客户端可以使用,比如5.0自带的工具和SQLyog Enterprise 4。库表相关的命令:SHOW DATABASES;SHOW TABLES;DESCRIBE table1/desc table1; 5.察看当前配置:show variables; 6.关于中文乱码问题,到一定积累,笔者准备开专题。目前简要列下: 在mysql的一次会话中,服务器收到客户端发来的指令后,大致要执行3个动作: 1、服务器认为收到的指令是按当前character_set_client环境变量所指定的字符集编码的, 2、然后再将其转换成character_set_connection所指定的字符集编码 3、分析、执行该指令。 4、 用character_set_results变量所指定的字符集返回服务器向客户端传输的数据 解决这个问题的关键点在于设置 default-character-set 变量。 7,在创建数据库的时候,我们有时会需要提供一些编码上的参数,如: #1. Create mvnforum database with the "Create database" syntax (for unicode and others): # mysql> CREATE DATABASE mvnforum CHARACTER SET [charater_set] COLLATE [collation] # mysql> CREATE DATABASE mvnforum CHARACTER SET utf8 collate # Where charater_set and collation : @see http://dev.mysql.com/doc/refman/4.1/en/charset-mysql.html # # a, practice to view all supported character set # mysql> SHOW CHARACTER SET; # b, practice to view all supported collation: # mysql> SHOW COLLATION; # # c, Example for Unicode: # mysql> CREATE DATABASE mvnforum CHARACTER SET utf8 COLLATE utf8_general_ci #" " 未完待续。 欢迎回帖。
1。什么是异常 异常是一种状态,是程序出现了符合该异常条件的一种状态。因此,他也可以说成是一种条件。 2。为什么要捕获异常 捕获异常是为了对程序中出现的某种状况进行处理。如果有异常而没有捕获,异常将会向上一层传播,最终导致线程在此中止。 3。什么是check异常和unchecked异常 uncheck异常一般是RuntimeException.出现这类异常,编译器不会强制要用户去捕获(当然你可以捕获)。 编译器会强制要求用户对checked异常进行捕获并作出一定的处理。 4。为什么不推荐捕获顶层异常(Exception) 程序中会发生各种各样的异常。除非你的程序是个终端(一个业务的终点),否则不推荐捕获顶层异常。 在程序的中间环节捕获所有异常毫无意义,并有可能导致流程上的隐患。比如,出现某种异常后,期望线程就此结束,不去做下面的工作,但是如果在中间环节对顶层异常进行了非法处理,程序有可能会运行下去,将导致不可控的错误。 5。为什么要自定义异常 自定义异常是为了设置异常链的起点。一般情况下,我们都是允许每个程序员看到所有的异常信息,这个时候大多数都是把下一层的异常直接重掷到上一层。然而在多层次的结构中,我们有时候需要隐藏底层异常(这种异常的信息很多,很枯燥),而给消费者提供一个更为直观的异常,这个时候我们需要自定义异常。有的异常类jdk已经给我们提供,比如常用的IllegalArgumentException。如果你想在此再作包装,你可以创建自己的异常类。如此,消费者将以此异常作为异常链的起点。 6。为什么要重掷异常 重掷异常是处理异常的一种方式。在捕获了某种异常后,用户可能不希望在这一层做出裁决,或者即使做出了一定的处理,但仍然需要向上一层报告,因此需要重掷异常。 7。异常机制。 一旦某个点发生异常,这个点下面和catch语句之间的代码将不会被执行。因此,异常是一种中止流程的很有效的机制。 关于异常,在effective java中提到“异常转译”和“异常连接”的概念。本人倾向于用“异常转译”,前提是要配置log4j,并作详细的日志纪录。
XmlBeans由 BEA公司发明,后捐赠给Apache基金会的。 在项目中遇到这样的需求,根据已有的schema对xml进行格式校验,并读取出xml得数据。 在大搜一番后,我最终把目光停留在xmlbeans上面。被淘汰的是digester. 下面是一篇dev2dev得文章: http://dev2dev.bea.com/pub/a/2006/05/xmlbeans-2.html?page=4 我就不炒饭了。 好心的人给简单翻译了一下: http://dev2dev.bea.com.cn/techdoc/200403127.html 翻译得内容很少,有空本人补上。 ibm dw上也有个豆腐块: http://www-128.ibm.com/developerworks/cn/xml/x-beans1/ 关于digester的内容,只选了一篇文章:来自devx得 http://www.devx.com/Java/Article/21832/1763
关于2中方法的对比,他们的文章已经说的很详细了。
xmlbeans采用的是sax来读取数据。2004年,由bea公司发明的stax(stream API for XML)已经被jcp列为标准jsr-173,在jdk6.0中会出现。 关于stax,sax和dom的对比超出本篇范围,在此略过。 后记: 在正在完成的项目中,我采用了xmlbeans,它的引入给我带来了很大的方便.
-
You have to get noticed to get promoted.
-
You have to get noticed to get hired.
-
It really impresses people when you say “Oh, I’ve written about that, just google for XXX and I’m on the top page” or “Oh, just google my name.”
-
No matter how great you are, your career depends on communicating. The way to get better at anything, including communication, is by practicing. Blogging is good practice.
-
Bloggers are better-informed than non-bloggers. Knowing more is a career advantage.
-
Knowing more also means you’re more likely to hear about interesting jobs coming open.
-
Networking is good for your career. Blogging is a good way to meet people.
-
If you’re an engineer, blogging puts you in intimate contact with a worse-is-better 80/20 success story. Understanding this mode of technology adoption can only help you.
-
If you’re in marketing, you’ll need to understand how its rules are changing as a result of the current whirlwind, which nobody does, but bloggers are at least somewhat less baffled.
-
It’s a lot harder to fire someone who has a public voice, because it will be noticed.
from http://www.tbray.org/ongoing/When/200x/2005/03/08/BloggingIsGood
http://www.javaalmanac.com
Java开发者年鉴一书的在线版本. 要想快速查到某种Java技巧的用法及示例代码, 这是一个不错的去处.
http://www.onjava.com
O'Reilly的Java网站. 每周都有新文章
http://java.sun.com
官方的Java开发者网站 - 每周都有新文章发表
http://www.developer.com/java
由Gamelan.com 维护的Java技术文章网站
http://www.java.net
Sun公司维护的一个Java社区网站
http://www.builder.com
Cnet的Builder.com网站 - 所有的技术文章, 以Java为主.
http://www.ibm.com/developerworks/java
IBM的Developerworks技术网站; 这是其中的Java技术主页
http://www.javaworld.com
最早的一个Java站点. 每周更新Java技术文章
http://www.devx.com/java
DevX维护的一个Java技术文章网站
http://www.fawcette.com/javapro
JavaPro在线杂志网站.
http://www.sys-con.com/java
Java Developers Journal的在线杂志网站.
http://www.javadesktop.org
位于Java.net的一个Java桌面技术社区网站.
http://www.theserverside.com
这是一个讨论所有Java服务器端技术的网站.
http://www.jars.com
提供Java评论服务. 包括各种framework和应用程序
http://www.jguru.com
一个非常棒的采用Q&A形式的Java技术资源社区.
http://www.javaranch.com
一个论坛,得到Java问题答案的地方,初学者的好去处。
http://www.ibiblio.org/javafaq/javafaq.html
comp.lang.java的FAQ站点 - 收集了来自comp.lang.java新闻组的问题和答案的分类目录.
http://java.sun.com/docs/books/tutorial/
来自SUN公司的官方Java指南 - 对于了解几乎所有的java技术特性非常有帮助.
http://www.javablogs.com
互联网上最活跃的一个Java Blog网站.
http://java.about.com/
转自51cto
一般情况下,J2EE应用服务器支持JDBC事务、JTA事务、容器管理事务。这里讨论JTA和JDBC事务的区别。这2个是常用的DAO模式事务界定方式。 JDBC 事务 JDBC 事务是用 Connection 对象控制的。JDBC Connection 接口( java.sql.Connection )提供了两种事务模式:自动提交和手工提交。 ★ 在jdbc中,事务操作缺省是自动提交。也就是说,一条对数据库的更新表达式代表一项事务操作,操作成功后,系统将自动调用commit()来提交,否则将调用rollback()来回滚。 ★ 在jdbc中,可以通过调用setAutoCommit(false)来禁止自动提交。之后就可以把多个数据库操作的表达式作为一个事务,在操作完成后调用commit()来进行整体提交,倘若其中一个表达式操作失败,都不会执行到commit(),并且将产生响应的异常;此时就可以在异常捕获时调用rollback()进行回滚。这样做可以保持多次更新操作后,相关数据的一致性,示例如下:
try {
conn =
DriverManager.getConnection
("jdbc:oracle:thin:@host:1521:SID","username","userpwd";
conn.setAutoCommit(false);//禁止自动提交,设置回滚点
stmt = conn.createStatement();
stmt.executeUpdate(“alter table …”); //数据库更新操作1
stmt.executeUpdate(“insert into table …”); //数据库更新操作2
conn.commit(); //事务提交
}catch(Exception ex) {
ex.printStackTrace();
try {
conn.rollback(); //操作不成功则回滚
}catch(Exception e) {
e.printStackTrace();
}
}
JDBC 事务的一个缺点是事务的范围局限于一个数据库连接。一个 JDBC 事务不能跨越多个数据库。 JTA事务 JTA(Java Transaction API) 为 J2EE 平台提供了分布式事务服务。 要用 JTA 进行事务界定,应用程序要调用 javax.transaction.UserTransaction 接口中的方法。例如: utx.begin(); // ... DataSource ds = obtainXADataSource(); Connection conn = ds.getConnection(); pstmt = conn.prepareStatement("UPDATE MOVIES ..."); pstmt.setString(1, "Spinal Tap"); pstmt.executeUpdate(); // ... utx.commit();
让我们来关注下面的话: “用 JTA 界定事务,那么就需要有一个实现 javax.sql.XADataSource 、 javax.sql.XAConnection 和 javax.sql.XAResource 接口的 JDBC 驱动程序。一个实现了这些接口的驱动程序将可以参与 JTA 事务。一个 XADataSource 对象就是一个 XAConnection 对象的工厂。 XAConnection s 是参与 JTA 事务的 JDBC 连接。” 要使用JTA事务,必须使用XADataSource来产生数据库连接,产生的连接为一个XA连接。 XA连接(javax.sql.XAConnection)和非XA(java.sql.Connection)连接的区别在于:XA可以参与JTA的事务,而且不支持自动提交。 Note: Oracle, Sybase, DB2, SQL Server等大型数据库才支持XA, 支持分布事务。 My SQL 连本地都支持不好,更别说分布事务了。 JTA方式的实现过程: 用XADataSource产生的XAConnection它扩展了一个getXAResource()方法,事务通过这个方法把它加入到事务容器中进行管理.对于调用者来说,根本看不到事务是如果管理的,你只要声明开始事务,告诉容器我下面的操作要求事务参与了,最后告诉事务说到这儿可以提交或回滚了,别的都是黑箱操作。 在使用JTA之前,你必须首先实现一个Xid类用来标识事务(在普通情况下这将由事务管理程序来处理)。Xid包含三个元素:formatID、gtrid(全局事务标识符)和bqual(分支修饰词标识符)。 下面的例子说明Xid的实现:
import javax.transaction.xa.*; public class MyXid implements Xid { protected int formatId; protected byte gtrid[]; protected byte bqual[]; public MyXid() { } public MyXid(int formatId, byte gtrid[], byte bqual[]) { this.formatId = formatId; this.gtrid = gtrid; this.bqual = bqual; }
public int getFormatId() { return formatId; }
public byte[] getBranchQualifier() { return bqual; }
public byte[] getGlobalTransactionId() { return gtrid; }
} 其次,你需要创建一个你要使用的数据库的数据源:
public DataSource getDataSource() throws SQLException { SQLServerDataSource xaDS = new com.merant.datadirect.jdbcx.sqlserver.SQLServerDataSource(); xaDS.setDataSourceName("SQLServer"); xaDS.setServerName("server"); xaDS.setPortNumber(1433); xaDS.setSelectMethod("cursor"); return xaDS; }
例1?这个例子是用“两步提交协议”来提交一个事务分支:
XADataSource xaDS; XAConnection xaCon; XAResource xaRes; Xid xid; Connection con; Statement stmt; int ret; xaDS = getDataSource(); xaCon = xaDS.getXAConnection("jdbc_user", "jdbc_password"); xaRes = xaCon.getXAResource(); con = xaCon.getConnection(); stmt = con.createStatement(); xid = new MyXid(100, new byte[]{0x01}, new byte[]{0x02}); try { xaRes.start(xid, XAResource.TMNOFLAGS); stmt.executeUpdate("insert into test_table values (100)"); xaRes.end(xid, XAResource.TMSUCCESS); ret = xaRes.prepare(xid); if (ret == XAResource.XA_OK) { xaRes.commit(xid, false); } } catch (XAException e) { e.printStackTrace(); } finally { stmt.close(); con.close(); xaCon.close(); } 当然,实际过程中,我们不需要写这些代码,这些代码是JTA最终的实现代码。 关于“两步提交协议”,可以参看下面的文章: http://www.jspcn.net/htmlnews/11049371131251752.html
http://www.vermicelli.pasta.cs.uit.no/ipv6/students/andrer/doc/html/node18.html
选择最好的方式 用 JDBC API 进事务界定来构建 DAO 类的。这些 DAO 类可以总结如下:
事务界定代码嵌入在 DAO 类中。 DAO 类使用 JDBC API 进行事务界定。 调用者不能界定事务。 事务范围局限于单个 JDBC 连接。 JDBC 事务并不总是适合复杂的企业应用程序。如果您的事务要跨越多个 DAO 或者多个数据库,那么下列实现策略也许更合适:
事务用 JTA 界定。 事务界定代码从 DAO 中分离出来。 调用者负责界定事务。 DAO 加入一个全局事务。 JDBC 方式由于其简单性而具有吸引力,JTA 方式提供了更大的灵活性。您所选择的实现将取决于应用程序的特定需求。 XADataSource例子: <?xml version="1.0" encoding="UTF-8"?>
<!-- ===================================================================== --> <!-- --> <!-- JBoss Server Configuration --> <!-- Thanks to Horia Muntean <horia@bvb.ro> --> <!-- ===================================================================== -->
<!-- $Id: db2-xa-ds.xml,v 1.1.2.1 2003/05/30 18:25:57 d_jencks Exp $ -->
<datasources> <!-- XADatasource for DB2 V8.1 (app driver) copy $db2_install_dir/java/db2java.zip into $jboss_install_dir/server/default/lib -->
<xa-datasource> <jndi-name>DB2XADS</jndi-name> <xa-datasource-class>COM.ibm.db2.jdbc.DB2XADataSource</xa-datasource-class> <xa-datasource-property name="DatabaseName">yout_database_name</xa-datasource-property> <xa-datasource-property name="User">your_user</xa-datasource-property> <xa-datasource-property name="Password">your_password</xa-datasource-property> </xa-datasource> </datasources>
引用: http://www.jspcn.net/htmlnews/11049371131251752.html http://www-128.ibm.com/developerworks/cn/java/j-dao/ http://www.vermicelli.pasta.cs.uit.no/ipv6/students/andrer/doc/html/node18.html
|