为什么在一个.java文件中不能直接获取tomcat的jndi?而在 jsp文件中可以?

时间:2022-11-26 14:26:29
我有一个问题感到很疑惑,希望能得到大家的指点

环境:
IDE :myeclipse 我的tomcat是在myeclipse中设置启动的
tomcat6.0

问题是这样,我写了一个class,当然是在.java文件中,我的目的是通过tomcat的jndi来获取数据源,但是我 没有在Jsp中实例化这个类,然后去调用它的方法,而是在main()方法中来运行,代码如下:

public class ExtAsis {

/**
 * @param args
 */
public static void main(String[] args) {
ExtAsis asis=new ExtAsis();
asis.queryDataBase();
}

public void queryDataBase(){
try {
Context initCon=new InitialContext();
//Context envCon=(Context)initCon.lookup("java:comp/env");
DataSource ds= (DataSource)initCon.lookup("java:comp/env/jdbc/LiferayPool");
Connection conn=ds.getConnection();
PreparedStatement ps=conn.prepareStatement("insert into custom t values('y','109','csdn','y@163.com')");
ResultSet rs=ps.executeQuery();
rs.close();
} catch (NamingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}


}

写完这个类以后,我就启动了tomcat,然后使用myeclipse run 来运行。

毫无疑问,报错了, Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file:  java.naming.factory.initial

但是如果我像普通的做法那样——在Jsp中实例化这个类,然后去调用它的方法,就可以成功

现在问题来了,
问题一:
我们知道jsp实际上是被转化为一个servlet——也就是一个.class文件来执行的——和java文件一样,那么为什么直接在java文件执行中会失败呢?

根据错误提示,找不到java.naming.factory.initial这个property,于是,我对main()作修改,看看这个property有没有被加入
public static void main(String[] args) {
System.out.println(System.getProperty("java.naming.factory.initial"));

}

结果毫无疑问:null

问题二:
我们知道tomcat要在jvm中运行,java.naming.factory.initial是在tomcat启动时加载的。因为我是在我本机上开发,tomcat就部署在我现在的机器上,而我运行的main()的java文件也是在我本机上运行的,我是在启动tomcat后来运行这个java文件的,那么这个java.naming.factory.initial应该已经被加载到tomcat了,为什么java文件会找不到呢?
莫非运行这个java文件的jvm和运行tomcat的jvm不是同一个?那如何才能指定同一个jvm呢?

希望大家能给出答案

4 个解决方案

#1


肯定是有差别的..
最大的可能是,InitialContext 是为服务器环境准备的,
也就是生成一个默认的系统环境,这个是由JNDI提供商(vendor)实现的。JNDI提供商通常与EJB,WEB提供商是同一的。
比如BEA的Weblogic就是这样一个提供商,你调用new   InitialContext()就会调用Weblogic的JNDI   Provider.不同的JNDI提供商对JNDI有不同的实现。
那么,这里应当是对应于Tomcat的吧..

另外JSP编译是由服务器进行动态编译的,必须有服务器软件才可以,而application则是由JVM直接编译..这个过程应当是有很大差别的,
我也是不明白...

#2


补充一点,如果说,InitialContext 在服务器环境下,是可以自动获取得到JNDI Provider.
那么,在application模式,可以手动添加进去:
Properties pro = new Properties();
pro.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.fscontext.RefFSContextFactory");
pro.put(Context.PROVIDER_URL,"file:C:\temp");

Context initCon=new InitialContext(pro); 

#3


lz是通过数据源获得连接的。这个数据源是和应用服务器绑定一起的。你把它放到main()方法中当然是不行了,因为在main()方法的上下文中是找不到你的数据源的。原因是你已经把你的正个工程发布成了web应用,jsp是在Tomcat容器的管理范围内的,所以成生的servlet是可以获得服务器的上下文,但是在main()方法中是不可以的。

#4


要想在main()中获得需要手动添加上下文。呵呵,2楼给了一个例子。

#1


肯定是有差别的..
最大的可能是,InitialContext 是为服务器环境准备的,
也就是生成一个默认的系统环境,这个是由JNDI提供商(vendor)实现的。JNDI提供商通常与EJB,WEB提供商是同一的。
比如BEA的Weblogic就是这样一个提供商,你调用new   InitialContext()就会调用Weblogic的JNDI   Provider.不同的JNDI提供商对JNDI有不同的实现。
那么,这里应当是对应于Tomcat的吧..

另外JSP编译是由服务器进行动态编译的,必须有服务器软件才可以,而application则是由JVM直接编译..这个过程应当是有很大差别的,
我也是不明白...

#2


补充一点,如果说,InitialContext 在服务器环境下,是可以自动获取得到JNDI Provider.
那么,在application模式,可以手动添加进去:
Properties pro = new Properties();
pro.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.fscontext.RefFSContextFactory");
pro.put(Context.PROVIDER_URL,"file:C:\temp");

Context initCon=new InitialContext(pro); 

#3


lz是通过数据源获得连接的。这个数据源是和应用服务器绑定一起的。你把它放到main()方法中当然是不行了,因为在main()方法的上下文中是找不到你的数据源的。原因是你已经把你的正个工程发布成了web应用,jsp是在Tomcat容器的管理范围内的,所以成生的servlet是可以获得服务器的上下文,但是在main()方法中是不可以的。

#4


要想在main()中获得需要手动添加上下文。呵呵,2楼给了一个例子。