https://tomcat.apache.org/tomcat-8.5-doc/jndi-resources-howto.html
IntroductionTomcat为在其下运行的每个web应用程序提供了一个JNDI InitialContext(class)实现实例,其方式与Java企业版应用服务器提供的方式兼容。
Java EE标准在/WEB-INF/web.xml文件中提供了一组标准元素来引用/定义资源。
web.xml configuration以下元素可以在web应用程序的web应用程序部署描述符(/web-inf/web.xml)中用于定义资源
- Environment entry, a single-value parameter that can be used to configure how the application will operate. (环境键值,一个单值参数,配置应用程序如何执行,感觉像是环境变量) - Resource reference, which is typically to an object factory for resources such as a JDBC DataSource, a JavaMail Session, or custom object factories configured into Tomcat. (资源引用,通常是个对象工厂,数据源,JavaMail或者自定义对象工厂配置 - Resource environment reference, a new variation of resource-ref added in Servlet 2.4 that is simpler to configure for resources that do not require authentication information.(资源环境引用)
如果tomcat不能识别resource factory或者需要额外的配置。需要在 $CATALINA_BASE/conf/server.xml 或者每个项目的 (META-INF/context.xml) 中进行配置
Tomcat specific resource configuration is performed using the following elements in the
element:
: 相当于 :相当于 :资源链接,访问 : 添加一个资源工厂,用于实例化UserTransaction对象实例,该实例可在java:comp/UserTransaction上使用。
如果一个资源已经在context.xml中定义,那么不需要在web.xml中进行定义。
建议在web.xml中进行定义,记录web程序的需要的资源。
- 如果相同的配置在
和 都有定义,只有在 中的override设置为true,web.xml中的 才会生效
InitialContext 在web初始化部署时配置,并且对web应用只读访问。所有资源都放在 java:comp/env 下。
// Obtain our environment naming context
Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
// Look up our data source
DataSource ds = (DataSource)
envCtx.lookup("jdbc/EmployeeDB");
// Allocate and use a connection from the pool
Connection conn = ds.getConnection();
... use this connection to access the database ...
conn.close();
Tomcat Standard Resource Factories 标准资源工厂配置
Generic JavaBean Resources
这个资源工厂可以用来创建任何符合标准javabean命名约定的Java类的对象(例如,它有一个无参数构造函数,并且有符合setFoo()命名模式的属性设置器)。如果工厂的singleton属性设置为false,则资源工厂只会在每次对该条目进行lookup()时创建相应bean类的新实例。
- Create Your JavaBean Class
public class MyBean {
private String foo = "Default Foo";
public String getFoo() {
return (this.foo);
}
public void setFoo(String foo) {
this.foo = foo;
}
private int bar = 0;
public int getBar() {
return (this.bar);
}
public void setBar(int bar) {
this.bar = bar;
}
}
- 在 web.xml中定义
Object factory for MyBean instances. bean/MyBeanFactory com.webapp.domain.MyBean
- 配置context.xml 的BeanFactory Resource
- JNDI 查找
try {
Context context = new InitialContext();
Context env = (Context) context.lookup("java:comp/env");
MyBean myBean = (MyBean) env.lookup("bean/MyBeanFactory");
System.out.println(myBean); // MyBean{foo='JNDI FOO', bar=23}
} catch (NamingException e) {
e.printStackTrace();
}
forceStringMyBean会在初始化时调用setter方法进行赋值
有些bean具有不能从字符串值自动转换为类型的属性。使用Tomcat BeanFactory设置这些属性将会失败,并出现一个NamingException。如果这些bean提供了从字符串值设置属性的方法,则可以配置Tomcat BeanFactory来使用这些方法。配置是通过forceString属性完成的。
对于String类型或原始类型或其关联的原始包装类的属性,不需要使用forceString。
- JavaBean
public class MyBean2 {
private InetAddress local = null;
public InetAddress getLocal() {
return local;
}
public void setLocal(InetAddress ip) {
local = ip;
}
// 通过String转换为InetAddress 类型
public void setLocal(String localHost) {
try {
local = InetAddress.getByName(localHost);
} catch (UnknownHostException ex) {
}
}
private InetAddress remote = null;
public InetAddress getRemote() {
return remote;
}
public void setRemote(InetAddress ip) {
remote = ip;
}
public void hostName(String remoteHost) {
try {
remote = InetAddress.getByName(remoteHost);
} catch (UnknownHostException ex) {
}
}
@Override
public String toString() {
return "MyBean2{" +
"local=" + local +
", remote=" + remote +
'}';
}
}
- context.xml
- 可以指定JavaBean中的方法名remote=hostName
... ...
- JNDI
try {
Context context = new InitialContext();
Context env = (Context) context.lookup("java:comp/env");
MyBean myBean = (MyBean) env.lookup("bean/MyBeanFactory");
MyBean2 myBean2 = (MyBean2) env.lookup("bean/MyBeanFactory2");
System.out.println(myBean);
System.out.println(myBean2); // MyBean2{local=localhost/127.0.0.1, remote=/127.0.0.1}
} catch (NamingException e) {
e.printStackTrace();
}
JNDI配置数据源
- MySQL依赖
mysql mysql-connector-java 8.0.23
- context.xml配置
- JNDI
try {
DataSource dataSource = (DataSource) env.lookup("jdbc/DataSource");
Connection connection = dataSource.getConnection();
System.out.println(connection); // jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai, UserName=root@localhost, MySQL Connector/J
} catch (Exception e) {
e.printStackTrace();
}
Adding Custom Resource Factories 自定义资源工厂
Write A Resource Factory Class
-
定义类实现 javax.naming.spi.ObjectFactory 接口,每次进行lookup时,会调用getObjectInstance方法
-
Object obj - ( 对于Tomcat,这将始终是一个类型对象 javax.naming.Reference )
-
Name name - 该工厂绑定到的相对于nameCtx的名称,如果没有指定名称,则为空。
-
Context nameCtx - 指定name参数的相对上下文,如果name相对于默认初始上下文,则为空。
-
Hashtable environment - 用于创建此对象的环境(可能为空)。这在Tomcat对象工厂中通常被忽略。
public class MyBeanFactory implements ObjectFactory {
@Override
public Object getObjectInstance(Object obj, Name name2, Context nameCtx, Hashtable, ?> environment) throws Exception {
// Acquire an instance of our specified bean class
MyBean bean = new MyBean();
// Customize the bean properties from our attributes
Reference ref = (Reference) obj;
Enumeration addrs = ref.getAll();
while (addrs.hasMoreElements()) {
RefAddr addr = (RefAddr) addrs.nextElement();
String name = addr.getType();
String value = (String) addr.getContent();
if (name.equals("foo")) {
bean.setFoo(value);
} else if (name.equals("bar")) {
try {
bean.setBar(Integer.parseInt(value));
} catch (NumberFormatException e) {
throw new NamingException("Invalid 'bar' value " + value);
}
}
}
// Return the customized instance
return (bean);
}
}
Declare Your Resource Requirements
Code Your Application’s Use Of This ResourceObject factory for MyBean instances. bean/MyBeanFactory3 com.webapp.domain.MyBean
// 自定义资源工厂
MyBean myBean3 = (MyBean) env.lookup("bean/MyBeanFactory3");
System.out.println(myBean3);
Configure Tomcat’s Resource Factory



