关于为什么要使用LDAP去访问MQ, 而不是直接访问,其理由我就不啰嗦了,有兴趣的可以去Google下。最直接的原因有至少如下两条(欢迎补充):
1. 客户端不需要去记MQ的账号,密码,只要有一个LDAP目录的访问权限,其下面所有的资源都可以访问。
2. MQ躲在LDAP Server后面,可以随时变化,对客户端这种变化是透明的。
下面说下具体实施步骤,
1. 安装LDAP Server。 我使用的是OpenLDAP2.4.26 可以到官方网站下载。具体安装方法略,网上很多,推荐一篇http://blog.chinaunix.net/space.php?uid=20652253&do=blog&id=1906570。
如果想让其随机器自启动,可以在/etc/rc.local加入一行
su root -lc "/usr/local/openldap/libexec/slapd &"
2. 加入Java schema,
We must edit the slapd.conf file. After the line:
include /usr/local/etc/openldap/schema/core.schema
add the schema for java objects:
include /usr/local/etc/openldap/schema/java.schema
注意:
a. 具体在那个目录要看OpenLDAP的安装目录,以及其版本。
b. 必须要改下 java.schema, 否则会有错误 LDAP: error code 65 - object class 'javaContainer' requires attribute 'cn']
objectclass ( 1.3.6.1.4.1.42.2.27.4.2.1
NAME 'javaContainer'
DESC 'Container for a Java object'
SUP top
STRUCTURAL
MUST cn )
用#号将“MUST cn )” 注释掉,用MAY ( o $ cn) )替换它
替换后类似以下内容:
objectclass ( 1.3.6.1.4.1.42.2.27.4.2.1
NAME 'javaContainer'
DESC 'Container for a Java object'
SUP top
STRUCTURAL
MAY ( o $ cn) )
3. 安装 Sonic MQ server。我装的是比较老的6.1, 官网可以下载。安装配置简单。Windows下就是Next, Next..
4. 增加一个object 到 LDAP Server, 我使用Java 代码做的,
import javax.naming.Context; import javax.naming.NameAlreadyBoundException; import javax.naming.directory.*; import java.util.*; public class MakeRootContext { final static String rootCtx = "o=SonicMQ,dc=cyber,dc=com"; public static void main(String[] args) { // set up environment to connect to LDAP Properties env = new Properties(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.PROVIDER_URL, "ldap://192.168.0.23:389/"); env.put(Context.SECURITY_PRINCIPAL, "cn=admin,dc=stony,dc=zhang"); env.put(Context.SECURITY_CREDENTIALS, "12345"); try { // obtain initial directory context using the environment DirContext initialctx = new InitialDirContext(env); initialctx.createSubcontext(rootCtx); } catch (NameAlreadyBoundException nabe) { System.err.println(rootCtx + " has already been bound!"); } catch (Exception e) { System.err.println(e); } } }
5. 必须在Sonic MQ控制台,把ConnectionFaction,以及Destination注册到LDAP Server, 过程如下,
第一步:
第二步,
第三步:
6.最后,我们用代码验证一下。能通过LDAP得到ConnectionFactotry, 以及Queue, 并且能发送消息到MQ.
import java.util.Hashtable; import javax.jms.Message; import javax.jms.Queue; import javax.jms.QueueConnection; import javax.jms.QueueSender; import javax.jms.QueueSession; import javax.naming.Context; import javax.naming.NamingException; import javax.naming.directory.DirContext; import javax.naming.directory.InitialDirContext; import progress.message.jclient.QueueConnectionFactory; public class LDAPConnect { public LDAPConnect() throws Exception { // Obtain a JNDI connection Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.PROVIDER_URL, "ldap://192.168.0.23:389/o=SonicMQ,dc=stony,dc=zhang"); env.put(Context.SECURITY_PRINCIPAL, "cn=admin,dc=stony,dc=zhang"); env.put(Context.SECURITY_CREDENTIALS, "12345"); DirContext ctx = null; try { ctx = new InitialDirContext(env); // Lookup a JMS connection factory QueueConnectionFactory conFactory = (QueueConnectionFactory) ctx.lookup("cn=cltQCF"); QueueConnection connection = conFactory.createQueueConnection(); QueueSession session=connection.createQueueSession(true, 10); Queue queue= (Queue)ctx.lookup("cn=wfacRCAccess"); QueueSender sender=session.createSender(queue); Message msg = session.createTextMessage("test"); sender.send(msg); session.commit(); connection.close(); System.out.println("connected"); // System.exit(0); } catch (Exception e) { e.printStackTrace(); } finally { if (ctx != null) { try { ctx.close(); } catch (NamingException e) { e.printStackTrace(); } } } } public static void main(String[] args) { try { LDAPConnect simpleConnect = new LDAPConnect(); } catch (Exception e) { e.printStackTrace(); } } }
检查MQ Server是否收到消息,
测试完成。
----------------------------------------------------------------------
张瑜,Mybeautiful, [email protected].