JNDI基本应用----摘自javaweb邮件开发详解

本文介绍了JNDI(Java Naming and Directory Interface)的基本概念及应用,包括命名与目录原理、如何利用JNDI进行资源绑定与查找,以及通过示例展示如何在JavaMail和DNS查询中使用JNDI。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

     

JNDI基本应用

         JNDIjava naming and directory interface(JAVA命名和目录接口)的英文缩写,它是为java应用程序提供命名和目录访问的服务器API

 

1.       命名的概念与应用

JNDI中的命名(Naming),就是将java对象以某个名称的形式绑定(binding)到一个容器环境(Context)中,以后调用容器环境(Context)的查找(lookup)方法又可以查出某个名称所绑定的java对象。在实际项目中,通常是由系统程序或框架程序先将资源对象绑定到JNDI环境中,以后在该系统或框架中运行的模块程序就可以从JNDI环境中找到这些资源对象了。例如:Tomcat服务器在启动时可以创建一个连接到某种数据库系统的数据源(DataSource)对象,并将该数据源对象绑定到JNDI环境中,以后再这个Tomcat服务器中运行的Servletjsp程序就可以从JNDI环境中查出这个数据源(DataSource)对象,并进行使用,而不需要再关心这个数据源对象是如何创建出来的,这种方式极大第增强了系统的维护性,当数据库的连接发生变更时,这只是Tomcat服务器管理员一个人需要关心的事,而所有开发人员无需关心。

容器环境(Context)本身是一个java对象,它可以通过一个名称绑定到另一个容器环境中。将一个Context对象绑定到另一个Context对象中,这就形成了一种父子级联的关系,多个Context对象最终可以级联成一种树状结构,书中的每个Context对象中可以绑定若干个java对象。如下图所示:

图中的每个方框分别代表一个Context对象,他们绑定的名称分为a,b,c,d,e,  bca的子Context, db的子Contexte又是d的子Context.图中各个方框内的每个小椭圆分别表示一个java对象,它们也都有一个绑定的名称,这些绑定名称分别为dog, pig, sheep等。在同一个Context中不能绑定两个相同的名称的java对象,在不同的Context中可以出现同名的绑定对象。可见,Context树的级联结构于文件系统中的目录结构非常相似,Context与其中绑定的java对象的关系也非常类似于文件系统中的目录与文件的关系。

从图中还可以看到,要想得到Context树中的一个java对象,首先要得到所在的Context对象,只要得到了一个Context对象,就可以调用它的lookup查询方法来获得其绑定的java对象。另外,调用某个Context对象的lookup方法也可以获得Context树中的任意一个Context对象,这只需要在lookup方法中指定相应的Context路径即可。在JNDI中不存在着”Context的概念,也就是说进行JNDI操作不是从一个根Context对象开始的,而是可以从树中任意一个Context开始。无论如何,程序必须获得一个作为操作入口的Context对象后才能执行各种JNDI命名操作,为止,JNDI API中提供了一个InitialContext类来创建用作JNDI命名操作入口的Context对象。Context是一个接口,Context对象实际上是其某个实现类的实例对象,选择这个具体的Context实现类并创建其实例对象的过程是由一个Context工厂类来完成的,这个工厂类的类名可以通过JNDI的环境属性java.naming.factory.initial指定,也可以根据Context的操作方法的url参数的Scheme来选择。

2.      目录的概念与应用

JNDI中的目录(Directory)与文件系统中的目录概念上有很大的不同,JNDI中的目录是指一个对象的所有信息保存到一个容器环境中。JNDI的目录(Directory)原理与JNDI的命名(Naming)原理非常相似,主要区别在于目录容器环境中保存的是对象的属性信息,而不是对象本身,所以,目录提供的是对属性的各种操作。事实上,JNDI的目录(Directory)与命名往往是结合在一起使用的,JNDI API中提供的代表目录容器环境的类为DirContext, 它是Context的子类,显然除了能完成目录相关操作外,也能完成所有命名(Naming)操作。DirContext是对Context的扩展,它在Context的基础上增加了对目录属性的操作功能,可以在其中绑定对象的属性信息和查找对象属性信息。JNDI中的目录结构示意图如下所示:

         图中的每个最外层的方框分别代表一个DirContext对象,它们绑定的名称分别为啊,吧, b是a的子DirContext。图中的各个最外层的方框内的每个小椭圆分别代表一个java对象,各个里层的方框分别代表一个对象的属性。从名称为a的DirContext中的内容可以看到,一个DirContext容器环境中可以绑定对象自身,也可以绑定对象的属性信息,绑定对象和绑定的属性是完全独立的两个事物,即使它们的绑定名称相同,它们的操作也是完全独立的。另外一个属性可以有多个属性值,如dog对象的category属性值设置了两个属性值,meat和pet.从名称为b的DirContext中的内容可以看到,一个DirContext容器环境中也可以只绑定对象的属性信息,而不绑定任何对象自身。与Context的操作原理类似,JNDI API中提供了一个InitialContext类来创建用做JNDI命名与目录属性操作的入口DirContext对象。

         下面是一个javamail邮件开发中,将会话信息存放到JNDI容器环境中的示例:

import cn.itcast.domain.User;

public class RegisterServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		try{
			String username = request.getParameter("username");
			String password = request.getParameter("password");
			String email = request.getParameter("email");
			
			User user = new User();
			user.setEmail(email);
			user.setPassword(password);
			user.setUsername(username);
			
			
			System.out.println("把用户信息注册到数据库中");
			Sendmail send = new Sendmail(user);
			send.start();//起一个定时器,发送一封邮件,目的是避免因网络延时导致用户注册体验差
			
			
			request.setAttribute("message", "恭喜您,注册成功,我们已经发了一封带了注册信息的电子邮件,请查收,如果没有收到,可能是网络原因,过一会儿就收到了!!");
			request.getRequestDispatcher("/message.jsp").forward(request, response);
		
		}catch (Exception e) {
			e.printStackTrace();
			request.setAttribute("message", "注册失败!!");
			request.getRequestDispatcher("/message.jsp").forward(request, response);
		}
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		doGet(request, response);
	}

}


 

public class Sendmail extends Thread {

	private String from = "itcast1111@sohu.com";
	private String username = "itcast1111";
	private String password = "123456";
	private String host = "smtp.sohu.com";
	
	private User user;  //aaa@sina.com
	public Sendmail(User user){
		this.user = user;
	}
	
	@Override
	public void run() {
		try{
			/*Properties prop = new Properties();
			prop.setProperty("mail.host", host);
			prop.setProperty("mail.transport.protocol", "smtp");
			prop.setProperty("mail.smtp.auth", "true");
			
			Session session = Session.getInstance(prop);*/
			//使用JNDI容器来保存session
			Context initCtx = new InitialContext();
			Context envCtx = (Context) initCtx.lookup("java:comp/env");
			Session session = (Session) envCtx.lookup("mail/Session");  //Session s = session
			session.setDebug(true);

			
			Transport ts = session.getTransport();
			ts.connect(host, username, password);
			Message message = makeMessage(session,user);
			ts.sendMessage(message, message.getAllRecipients());
			ts.close();
			
		}catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	
	public Message makeMessage(Session session,User user) throws Exception{
		
		MimeMessage message = new MimeMessage(session);
		message.setFrom(new InternetAddress(from));
		message.setRecipient(Message.RecipientType.TO, new InternetAddress(user.getEmail()));
		message.setSubject("ԃ»§ע²┊¼�		
		String info = "¹§ϲźע²ᴉ¹¦£¬źµœû§Ļ£º" + user.getUsername() + ",źµŃ݂룺" + user.getPassword() + "£¬ȫΗʆ±£¹ܣ¬ɧԐϊ͢ȫjϵθվ¿ͷ�
		message.setContent(info, "text/html;charset=UTF-8");
		message.saveChanges();
		return message;
	}
}


        下面这个示例是利用JNDI容器查询DNS域名信息。

                 

/*
		 * 第一个参数指定要查询的域或主机名,第二个参数指定查询的DNS服务器
		 */
		String[] arg = {"sohu.com"};
	
		String domain = arg[0];
		
		String dnsServer = arg.length<2 ? "":("//"+arg[1]);
		
		//通过环境属性来指定Context的工厂类
		Hashtable env = new Hashtable();
		env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.dns.DnsContextFactory");
		env.put(Context.PROVIDER_URL, "dns:"+dnsServer);
		
		DirContext ctx = new InitialDirContext(env);
		//分别获取包含所有属性和只包含Mx属性的attributes对象
		Attributes attrsAll = ctx.getAttributes(domain);
		Attributes attrsMx = ctx.getAttributes(domain, new String[]{"MX"});
		
		/*
		 * 上面这段代码可以使用下面这段代码替换,通过查询URL中的Scheme信息来自动选择Context的工厂类
		 */
	/*	DirContext ctx = new InitialDirContext();
		Attributes attrsAll = ctx.getAttributes("dns:"+dnsServer+"/"+domain);
		Attributes attrsMx = ctx.getAttributes("dns:"+dnsServer + "/"+domain, new String[]{"MX"});
	*/	
		System.out.println("打印出域"+domain + "的Attributes对象中的信息:");
		System.out.println(attrsAll);
		System.out.println("----------------------------");
		System.out.println("打印只检索域"+domain+"的MX记录的Attributes对象:");
		System.out.println(attrsMx);
		
		System.out.println("------------------------");
		System.out.println("逐一打印出Attributes对象中的各个属性:");
		
		NamingEnumeration attributes = attrsAll.getAll();
		while(attributes.hasMore()){
			System.out.println(attributes.next());
		}
		
		System.out.println("------------------------");
		//直接调用get方法从attrsMx集合检索MX属性
		System.out.println("直接检索Attributes对象中的索MX属性:");
		
		Attribute attrMx = attrsAll.get("MX");
		System.out.println(attrMx);
		
		System.out.println("------------------------");
		
		//获取Mx属性的第一个值
		System.out.println("获取Mx属性中的第一个值:");
		String recordMx = (String)attrMx.get();
		System.out.println(recordMx);
		
		//从Mx属性的第一个值中提取邮件服务器地址
		System.out.println("从MX属性值中提取邮件服务器地址: ");
		String smtpServer = recordMx.substring(
				recordMx.indexOf(" ")+1);
		System.out.println(smtpServer);


            结果:

打印出域sohu.com的Attributes对象中的信息:
{ns=NS: ns1.sohu.com., dns.sohu.com., ns4.sohu.com., ns2.sohu.com., mx=MX: 10 sohumx.h.a.sohu.com., 5 sohumx1.sohu.com., 5 sohumx2.sohu.com.}
----------------------------
打印只检索域sohu.com的MX记录的Attributes对象:
{mx=MX: 5 sohumx2.sohu.com., 10 sohumx.h.a.sohu.com., 5 sohumx1.sohu.com.}
------------------------
逐一打印出Attributes对象中的各个属性:
NS: ns1.sohu.com., dns.sohu.com., ns4.sohu.com., ns2.sohu.com.
MX: 10 sohumx.h.a.sohu.com., 5 sohumx1.sohu.com., 5 sohumx2.sohu.com.
------------------------
直接检索Attributes对象中的索MX属性:
MX: 10 sohumx.h.a.sohu.com., 5 sohumx1.sohu.com., 5 sohumx2.sohu.com.
------------------------
获取Mx属性中的第一个值:
10 sohumx.h.a.sohu.com.
从MX属性值中提取邮件服务器地址: 
sohumx.h.a.sohu.com.


 

        附录:

       JNDI 查找及其关联的引用

JNDI 查找名称 

关联的引用 

java:comp/env

应用程序环境项 

java:comp/env/jdbc

JDBC 数据源资源管理器连接工厂 

java:comp/env/ejb

EJB 引用 

java:comp/UserTransaction

UserTransaction 引用 

java:comp/env/mail

JavaMail 会话连接工厂 

java:comp/env/url

URL 连接工厂 

java:comp/env/jms

JMS 连接工厂和目标 

java:comp/ORB

应用程序组件之间共享的 ORB 实例 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值