|
2006年7月4日
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
|