上篇博客详细介绍了jboss5.0配置数据源,这篇博客讨论关于如何访问这个数据源。
如何获得这个数据源,其实总结而来,就两种,一是自己手写查找;另一个是使用注解依赖注入,由容器来查找。
就如spring来管理action时,可以自己new action,也可以通过spring来注入。
首先:手动查找相应的JNDI
第一步:按照上篇博客配置了相应的数据源。
注意:需要在jboss-5.1.0\server\default\lib添加相应的数据库驱动包,jboss不像weblogic,weblogic可以不添加数据库驱动包,因为默认自带了部分数据库驱动包。
第二步:启动jboss服务,或者启动eclispe中的jboss服务器,就会发现jndi已经绑定:
Bound ConnectionManager 'jboss.jca:service=DataSourceBinding,name=firstds' to JNDI name 'java:firstds'
第三步:直接通过InitialContext来查找JNDI名称。
一般情况我们知道,查找JNDI时,需要在JNDI名称前加上java:/
代码如下:
package com.datasource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import javax.annotation.Resource;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;
//测试jboss管理数据源
public class TestDS {
public void test()throws Exception{
Context ctx=new InitialContext();
DataSource ds=(DataSource)ctx.lookup("java:/firstds");
//获取数据库连接
Connection conn=ds.getConnection();
String sql="select * from test";
PreparedStatement pst=conn.prepareStatement(sql);
ResultSet rs=pst.executeQuery();
while(rs.next()){
System.out.print("测试通过。。。");
}
rs.close();
pst.close();
conn.close();
}
public static void main(String[] args) throws Exception{
TestDS ts=new TestDS();
ts.test();
}
}
这段是测试代码,主要测试数据源是否可连接。
第四步:测试第三步的代码,若出现以下问题:
Exception in thread "main" javax.naming.NoInitialContextException : 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
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:645)
at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:288 )
at javax.naming.InitialContext.getURLOrDefaultInitCtx(InitialContext.java:325)
at javax.naming.InitialContext.lookup(InitialContext.java:392 )
at com.datasource.TestDS.main( TestDS.java:16)
则需要指明java.naming.factory.initial等信息,可以直接在src下引入
jndi.properties
文件:
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.provider.url=localhost
java.naming.factory.url.pkgs=org.jboss.naming
也可以在代码中:
//得到一个JNDI初始化上下文–‡
Properties props= new Properties();
props.setProperty( "java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory" );
props.setProperty( "java.naming.provider.url", "localhost:1099");
props.setProperty( "java.naming.factory.url.pkgs", "org.jboss.naming");
InitialContext ctx= new InitialContext(props);
但是引入后,还继续报错,错误如下:
Exception in thread "main" javax.naming.NameNotFoundException: firstds not bound
at org.jnp.server.NamingServer.getBinding(NamingServer.java:771 )
at org.jnp.server.NamingServer.getBinding(NamingServer.java:779 )
at org.jnp.server.NamingServer.getObject(NamingServer.java:785 )
at org.jnp.server.NamingServer.lookup(NamingServer.java:443 )
at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:726 )
at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:686 )
at javax.naming.InitialContext.lookup(InitialContext.java:392 )
at com.datasource.TestDS.main( TestDS.java:16)
第二步已经启动服务,显示已经绑定了JDNI,但是客户端访问时,还是出现没有绑定的错误。
把JNDI名称改成如下: DataSource ds=(DataSource)ctx.lookup("firstds");
启动服务后,依然是服务显示绑定,但是客户端访问时提示未绑定。
上网查了好长的资料,发现一篇文章解释了问题的来源以及解决方案:
<use-java-context> - A boolean indicating if the jndi-name should be prefixed with java: which causes the DataSource to only be accessible from within the jboss server vm. The default is true.
Configuring a DataSource for remote usage
As of jboss-4.0.0 there is support for accessing a DataSource from a remote client. The one change that is necessary for the client to be able to lookup the DataSource from JNDI is to specify use-java-context=false as shown here:
<datasources> <local-tx-datasource> <jndi-name>GenericDS</jndi-name> <use-java-context>false</use-java-context> <connection-url>...</connection-url>...
This results in the DataSource being bound under the JNDI name "GenericDS" instead of the default of "java:/GenericDS" which restricts the lookup to the same VM as the jboss server.
当你指定<use-java-context>的值为false时,你就可以在jboss运行的VM外的VM上查找到这个DataSource.
这个属性默认.为true 即,默认情况下你是不可以在JBOSS的VM外来查找这个数据源.
上一篇博客中,在可视化界面新建并且jboss自动生成的**-ds.xml中的user-java-context标签默认为true。
那如何在jbossvm外访问jboss数据源?
首先把user-java-context标签更改为false;然后把 java:/ 去掉。如下:
DataSource ds=(DataSource)ctx.lookup("firstds");
若是在jbossvm内访问呢?默认是在jboss进程中访问,则可以使用上述方式
DataSource ds=(DataSource)ctx.lookup("firstds");把user-java-context标签为false。
当然也可以:
DataSource ds=(DataSource)ctx.lookup("java:/firstds");默认为true,把user-java-context标签为true或者删除此标签。
在jboss5.0提供的数据源模板中,没有此标签。可以参考上篇博客中数据源模板。
比如:界面jsp中:
<%@ page language ="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import ="java.sql.*,javax.naming.*,javax.sql.*" %>
<%
Context ctx=new InitialContext();
//jboss中实际JNDI名字必须在配置的JNDI之前加上java:/前缀
DataSource ds=(DataSource)ctx.lookup("java:/firstds");
//获取数据库连接
Connection conn=ds.getConnection();
String sql="select * from test";
PreparedStatement pst=conn.prepareStatement(sql);
ResultSet rs=pst.executeQuery();
while(rs.next()){
out.print("测试通过。。。");
}
rs.close();
pst.close();
conn.close();
%>
<html>
<head>
<meta http-equiv= "Content-Type" content ="text/html; charset=UTF-8">
<title> Insert title here</ title>
</head>
<body>
</body>
</html>
其中界面中调用时,可以不用jndi.properties文件。jboss自动默认初始化。
至于上述提到jboss5.0 服务器vm内或vm外,如何判断呢?我自己判断如下:在eclispe中运行程序时,
比如:用jsp,肯定使用jboss来运行。但是main方法,肯定是运行java application。因此两个不同的vm,当然eclispe中也可以观察出:
第二种:使用依赖注入方式。
依赖注入方式,J2EE提供了EJB组件注入,和资源的注入Resource
依赖注入,在sessionBean中的可以使用Resource注入。
//使用数据源注入方式
@Resource
(mappedName=
"java:/
firstds
"
)
private
DataSource
ds
;
但是在java 客户端则使用这种方式,则不可以。
即使我更改上述user-java-context标签,更改mappedName="java:/firstds" 或mappedName="firstds"。
若继续使用依赖注入,则可以使用spring的注入方式。
package com.datasource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import javax.sql.DataSource;
//测试jboss管理数据源
public class TestDSpring {
//java客户端则不可以使用resource注解
DataSource ds;
public DataSource getDs() {
return ds;
}
public void setDs(DataSource ds) {
this. ds = ds;
}
public void test()throws Exception{
//Context ctx =new InitialContext();
//DataSource ds =(DataSource)ctx.lookup("firstds");
//获取数据库连接
Connection conn= ds.getConnection();
String sql= "select * from test";
PreparedStatement pst=conn.prepareStatement(sql);
ResultSet rs=pst.executeQuery();
while(rs.next()){
System. out.print( "测试通过。。。" );
}
rs.close();
pst.close();
conn.close();
}
}
搭建spring的环境,不再讲解,则spring配置文件如下:
<bean name ="testDS"
class= "com.datasource.TestDSpring"
scope= "prototype">
<property name ="ds" ref="ds"></ property>
</bean >
<bean name ="ds" class= "org.springframework.jndi.JndiObjectFactoryBean" >
<property name ="jndiName" value="firstds"></ property>
</bean >
其中value="firstds"还是java:/firstds,还是依赖配置文件中的标签,上述已经讲解。
客户端测试如下:
package com.datasource;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) throws Exception {
AbstractApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext-beans.xml" );
System. out.println( "--------");
TestDSpring ps = (TestDSpring)ctx.getBean( "testDS");
ps.test();
}
}