JNDI实践简介

这篇博客先介绍JNDI的概念,再配上本人JNDI一次练习的代码:

JDNI全称The Java Naming and Directory Interface™,是java提供的命名和目录服务。命名和目录服务就是一种映射功能,你能够根据一个名称获取这个名称对应的实际对象。比如,域名和ip就是一种映射。文件目录和文件也是一种映射。

1、JNDI的结构体系

在这里插入图片描述
由图看出,JNDI由一套JNDI的API和SPI组成。我们的java应用使用api操纵一系列目录服务,比如添加目录,删除目录等等。但是java提供的JNDI只是一套接口,具体实现需要实际的服务提供者,而服务提供者实现spi接口即可。这样JNDI接口就实现了独立于任何具体JNDI实现。

2、基本接口简介(重要)

Context:此接口表示一个命名上下文,它由一组名称到对象的绑定组成。它包含检查和更新这些绑定的一些方法。这是一个核心接口,目录一切命名操作都由这个接口操作。由这个接口可以实现对象创建、销毁、查找、绑定、重命名等操作。
这个接口有以下一些常用方法:详见java api

Lookup():该方法通过名称获取对象
bind()/rebind():该方法实现名称和对象的绑定/重绑定
unbind():该方法实现名称和对象的解绑
listBindings()/list()。该方法返回上下文指定名称对象的绑定

InitialContext:执行命名操作的初始上下文。JNDI一切的目录操作都是通过上面的context对象来的。而这个初始上下文实现 Context 接口并提供解析名称的起始点。

Name:JNDI对于绑定的名称的接口定义,也就是说绑定时要传该接口实现类对象。当然了,JNDI接口对于名称一般都提供了String类型的重载形式,直接用String类对象表示名称也可以。

References:在JNDI里,你需要将名称和对象绑定。在java里我们都知道对象传的其实是个引用。这个类定义了你绑定的对象引用的类型。也就是说,和名称绑定的对象只能是References对象或者实现Referenceable接口的类。

3、实现过程:

由上可知,我们配置好java环境后,只需要配置JNDI服务spi服务提供者即可。一般由WEB容器作为服务提供者的角色。比如tomcat,jboss,weblogic等。关于tomcat实现JNDI功能,tomcat官网有非常详细的教程:tomcat如何实现JNDI 大家可以前往查看。

这边贴一下使用sun的FSSP(File System Service Provider)文件系统作为服务提供者。这样就不需要使用容器了,直接使用操作系统的文件系统作为JNDI提供者实现名称和对象的绑定。
该实现需要导入两个jar包:fscontext.jar && providerutil.jar

4、FSSP实现

这边实现的是用JNDI实现MQ根据名称查找实现类的代码。

JNDI初始化上下文:

接口

package demo.jndi;

import javax.jms.QueueConnectionFactory;

public interface JmsConnInterface {
    QueueConnectionFactory getConnFactory();
}

实现类:这边实现了Referenceable接口,以便作为绑定对象。

package demo.jndi;

import demo.config.MyConfig;

import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.QueueConnectionFactory;
import javax.naming.*;

public class JmsConnService implements  Referenceable, JmsConnInterface {

    @Override
    public Reference getReference() throws NamingException {
        return new Reference(getClass().getName(),JmsConnServiceFactory.class.getName(),null);
    }

    @Override
    public QueueConnectionFactory getConnFactory() {
        // Create the object to be bound
        QueueConnectionFactory queueConnectionFactory = null;
        queueConnectionFactory = new ActiveMQConnectionFactory(MyConfig.ACTIVEMQ_URL);
        System.out.println("queueConnectionFactory = " + queueConnectionFactory);
        return queueConnectionFactory;
    }
}

实现类的工厂类:在实现Refrence接口时需要工厂类。内部会用工厂类生成对象实例。

package demo.jndi;

import javax.naming.Context;
import javax.naming.Name;
import javax.naming.Reference;
import javax.naming.spi.ObjectFactory;
import java.util.Hashtable;

public class JmsConnServiceFactory implements ObjectFactory {
    @Override
    public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) throws Exception {
        if(obj instanceof Reference){
            return new JmsConnService();
        }
        return null;
    }
}

初始化上下文类:这个list()方法,仅仅用来打印绑定对象。

package demo.jndi;

import javax.naming.*;
import java.util.Properties;

public class JNDIContainer {
    private Context ctx = null;

    public void init() throws Exception {
        Properties env = new Properties();
        env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory");
        env.put(Context.PROVIDER_URL, "file:///d:/ttt/");
        ctx = new InitialContext(env);
        ctx.rebind("factoryAddByHand", new JmsConnService());
        NamingEnumeration list = ctx.list("/");
        while (list.hasMore()) {
            NameClassPair nc = (NameClassPair) list.next();
            System.out.println("1111" + nc);
        }
    }

    public void close() throws NamingException {
        ctx.close();
    }

    public Context getContext() {
        return ctx;
    }
}

jms使用JNDI

JNDI初始化连接工厂

package demo.jms;

import demo.config.MyConfig;
import demo.jndi.JNDIContainer;
import demo.jndi.JmsConnInterface;
import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.JMSException;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.util.Hashtable;

public class JmsFactory {
    private static QueueConnectionFactory queueConnectionFactory;

    public static QueueConnectionFactory CreatJmsFactory() {

        JNDIContainer container = new JNDIContainer();
        try {
            container.init();
            //JNDI客户端使用标准JNDI接口访问命名服务。
            Context ctx = container.getContext();
            JmsConnInterface conn = (JmsConnInterface) ctx.lookup("factoryAddByHand");
            System.out.println("JmsConnInterface  is:" + conn.getConnFactory());
            queueConnectionFactory = conn.getConnFactory();

        } catch (NamingException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {

        }
        return queueConnectionFactory;
    }

}

jms连接工厂类

package demo.jms;

import org.slf4j.ILoggerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.jms.*;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;

public class JmsConnFactory {
    private static Logger log = LoggerFactory.getLogger(JmsConnFactory.class);
    private static QueueConnectionFactory queueConnectionFactory;

    static {
        // ConnectionFactory :连接工厂,JMS 用它创建连接
        queueConnectionFactory = JmsFactory.CreatJmsFactory();
        System.out.println("queueConnectionFactory "+queueConnectionFactory );

    }

    public QueueConnection initializeJMSConnection() {

        QueueConnection queueConnection = null;
        try {
            queueConnection = queueConnectionFactory.createQueueConnection();
            return queueConnection;

        } catch (JMSException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static QueueSession getQueueSession() throws Exception {
        // Connection :JMS 客户端到JMS Provider 的连接
        JmsConnFactory jmsConnFactory = new JmsConnFactory();
        QueueConnection queueConnection = jmsConnFactory.initializeJMSConnection();
        // Connection 启动
        queueConnection.start();
        log.info("connect is started!");
        QueueSession queueSession = queueConnection.createQueueSession(true, Session.AUTO_ACKNOWLEDGE);
        return queueSession;
    }

}

MQ接收者

package demo.jms;

import demo.config.MyConfig;

import javax.jms.*;

public class MessageReceiver {
    public static void main(String[] args) throws Exception {
        // Session: 一个发送或接收消息的线程
        QueueSession qSession  = JmsConnFactory.getQueueSession();
        // Session: 一个发送或接收消息的线程
        Queue destination = qSession.createQueue(MyConfig.QUEUE_NAME);
        // Destination :消息的目的地;消息发送给谁.
        QueueReceiver qReceiver = qSession.createReceiver(destination);
        qReceiver.setMessageListener(new MessageListener(){//有事务限制
            @Override
            public void onMessage(Message message) {
                try {
                    TextMessage textMessage=(TextMessage)message;
                    System.out.println(textMessage.getText());
                } catch (JMSException e1) {
                    e1.printStackTrace();
                }
                try {
                    qSession.commit();
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }
        });
        /*  另外一种接受方式
 *    while (true) {
              //设置接收者接收消息的时间,为了便于测试,这里谁定为100s
              TextMessage message = (TextMessage) consumer.receive(100000);
              if (null != message) {
                  System.out.println("收到消息" + message.getText());
              } else {
                  break;
              }
          }*/
    }
}



MQ发送者

package demo.jms;

import demo.config.MyConfig;

import javax.jms.*;
import javax.naming.Context;
import javax.naming.InitialContext;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;

public class MessageSender {

    //Queue(点对点)方式  生存者Producer
    public static void main(String[] args) throws Exception {
       
        QueueSession qSession = JmsConnFactory.getQueueSession();
   
        // Queue :消息的目的地;消息发送给谁.
        Queue destination = qSession.createQueue(MyConfig.QUEUE_NAME);
        // MessageProducer:消息发送者
        QueueSender qSender = qSession.createSender(destination);
        // 设置不持久化,此处学习,实际根据项目决定
        qSender.setDeliveryMode(DeliveryMode.PERSISTENT);
        // 构造消息,此处写死,项目就是参数,或者方法获取
        sendMessage(qSession, qSender);
        qSession.commit();
        System.out.println("message is send successfully!!!");

    }

    public static void sendMessage(Session session, MessageProducer producer)
            throws Exception {
        for (int i = 1; i <= 5; i++) {//有限制,达到1000就不行
            TextMessage message = session.createTextMessage("ActiveMq 用JMS配合JNDI 发送的消息" + i+"号");
            // 发送消息到目的地方
            System.out.println("发送消息:" + "ActiveMq 发送的消息" + i+"号");
            producer.send(message);
        }
    }

}

MQ服务器接口配置

package demo.config;

public class MyConfig {
    //定义ActiveMQ的连接地址
    public static final String ACTIVEMQ_URL = "tcp://xxx.xxx.x.x:xxxxx";
    //p2p 队列名称
    public static final String QUEUE_NAME = "queue_01";
    //topic 队列名称
    public static final String TOPIC_NAME = "topic_01";
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值