用环境变量定制应用部署
有时,当我们编写j2ee web应用时,我们想要为应用部署人员提供一些灵活性。例如,或许你想要提供几个不同的应用版本,每一个版本满足特定的用户的需要。或许代码的有些部分需要主机名称和端口信息,这些只有在部署时才知道。或许,你只想在如何显示数据方面给应用部署人员一些灵活性。
你可以用环境变量增加这种灵活性。环境变量是可以在组件的部署描述符文件中定义的参数。应用组件通过jndi按名称查找环境变量,用环境变量的值定制应用的行为或表示。
所有类型的应用组件都可以使用环境变量。servlet、企业bean、jsp
页面和用户tag都可以使用环境变量。环境变量必须在组件的适当部署描述符文件中定义,例如,web组件在web.xml文件中定义,企业bean在ejb-jar.xml文件中定义。
例如,假定你要为电子商务应用编写一个servlet。这个servlet发送email给客户,通知客户收到了一个订单。你的servlet需要授权的smtp服务器的主机明、端口、登录名和口令。作为组件(servlet)开发者,你不必知道这些信息,只要部署者知道就行了。但是eamil功能要求这些信息,如何向servle提供这些信息呢?
一个方法是使用servlet部署描述符文件(web.xml)中的环境变量。首先,为主机名、端口、登录名、口令定义环境变量。然后,编写代码通过jndi从环境中得到这些环境变量的值,在代码中使用这些环境变量的值。部署者在部署时利用部署工具为这些环境变量填上适当的值。程序运行时提取部署者设置的这些值,使用这些值访问要访问的服务器。
定义环境变量
用xml在组件的部署描述符文件中定义环境变量。如果使用部署工具(例如j2ee参考实现所带的部署工具程序),你就可以用gui方式确定部署描述符。但是下面我们还是假定用文本编辑器手工编辑部署描述符。
环境变量有四个部分:
? 描述: 定义在scription> tag 内的一个串。
? 名称:定义在<env-entry-name> tag内的一个串。
? 值:定义在<env-entry-value> tag内的一个值。
? 类名:定义在<env-entry-type> tag内的环境变量的类型
描述是可选的文字描述,出现在部署工具的用户界面上。它告诉部署者在确定环境实体引用时做什么。换句话说,它是一个可读描述,告诉部署者如何填写其他值。它也告诉部署者这个环境变量是否是可选的。
环境变量的名称是相对于jndi上下文名“jndi:comp/env”的,组件用名称查找环境变量。所有环境变量都由它们的容器在jndi上下文中注册。
环境变量的值是环境变量应取的值,格式是字符串。除了表示单个字符的类型java.lang.character以外,允许作为环境变量的所有类型都有以串作为参数的构造函数。env-entry-value tag包含了用于值的构造函数的串。
环境变量的类型是环境变量值的类型类名。必须是下面的类型之一:
l java.lang.boolean
l java.lang.byte
l java.lang.character
l java.lang.double
l java.lang.float
l java.lang.integer
l java.lang.long
l java.lang.short
l java.lang.string
smtp主机例子中的环境变量可以象下面这样:
<env-entry>
<description>
enter the host name for sending email
</description>
<env-entry-name>smtp host name</env-entry-name>
<env-entry-value>
homer.springfield.ma.us
</env-entry-value>
<env-entry-type>java.lang.string</env-entry-type>
</env-entry>
<env-entry>
<description>smtp port number for email
</description>
<env-entry-name>smtp port</env-entry-name>
<env-entry-value>2101</env-entry-value>
<env-entry-type>java.lang.integer</env-entry-type>
</env-entry>
<env-entry>
<description>
user authentication for smtp server
</description>
<env-entry-name>smtp user</env-entry-name>
<env-entry-value>bart</env-entry-value>
<env-entry-type>java.lang.string</env-entry-type>
</env-entry>
<env-entry>
<description>
password for smtp user
</description>
<env-entry-name>smtp password</env-entry-name>
<env-entry-value>d'oh!</env-entry-value>
<env-entry-type>java.lang.string</env-entry-type>
</env-entry>
使用环境变量
要在代码中使用环境变量很简单,用jndi查找环境变量就行了。注意要使方法context.lookup的结果与适当的类型相配。如下所示:
try {
initialcontext ic = new initialcontext();
context ctx = ic.lookup("java:comp/env");
string hostname =
(string)(ctx.lookup("smtp host"));
integer port = (integer)(ctx.lookup("smtp port"));
string user = (string)(ctx.lookup("smtp user"));
string password =
(string)(ctx.lookup("smtp password"));
sendemail(
emailtext, port, hostname, user, password);
} catch (namingexception nex) {
...
}
环境变量与servlet初始化参数
在web应用中,可以用servlet初始化参数代替环境变量定制servlet的行为。servlet开发者在web.xml中用init-param tag定义servlet初始化参数,在servlet代码中用方法javax.servlet.genericservlet.getinitparameter访问servlet初始化参数。servlet初始化参数的使用范围是定义它的servlet。
那么,对于具体的定制来说,如何在环境变量和servlet初始化参数之间做出选择呢?这个问题的答案依赖于定制的自然范围。就象全局变量的作用范围是程序的名称空间一样,环境变量的作用范围是jndi名称空间。这将会导致组件之间的不必要的依赖。当定制只影响一个servlet时,servlet初始化参数是最好的选择。当定制涉及多个组件时,考虑使用环境变量。
代码示例
这个技巧的代码示例有两个部分。第一部分是servlet,打印应用的所有环境变量。这个servlet的最后用context.listbindings方法列出了所有绑定在jndi上下文java:com/env中的环境变量。下面的代码片断摘选于这个servlet的源代码:
public void printenventries(httpservletrequest req,
httpservletresponse res)
throws ioexception, servletexception {
res.setcontenttype("text/html");
printwriter out = res.getwriter();
try {
initialcontext ic = new initialcontext();
namingenumeration ne =
ic.listbindings("java:comp/env");
out.println(
"<html><head><title>environment entries</title></head>");
out.println(
"<body><table border=1><tr><th>entry</th>" +
"<th>value</th></tr>");
while (ne.hasmore()) {
binding ncp = (binding)ne.next();
string objname = ncp.getname();
object objobj = ncp.getobject();
out.println("<tr><td>" + objname + "</td>");
out.print(
"<td>" + objobj.tostring() + "</td></tr>");
}
out.println("</table></body></html>");
} catch (exception e) {
throw new servletexception(e);
}
}
这个方法对java:com/env中的每个对象迭代,用table的形式打印出每个环境变量的名称和文字表示。试一试部署这个应用,看一看定义在部署描述符文件中的环境变量。“运行示例代码”一节指导你如何部署应用。
这个技巧的代码示例的第二部分是一个定制tag,datetag.java。说明了如何利用环境变量使组件(本例中是定制tag)可以定制。
datatag是一个简单的tag,页面开发者可以用这个tag打印服务器的日期和时间。单独使用时(“<t:date/>” ),它用标准格式打印出日期和时间。如果用tag的格式属性定义了格式,打印时就使用所定义的格式。(标准类simpledateformat定义了格式语法)。
部署者可以通过符号名用环境变量定义一列日期/时间格式。如果datetag的格式属性值以$开始,那么,这个tag就查找这个属性命名的环境变量值的格式。例如,下面的环境变量就是在web.xml中定义的:
<env-entry>
<env-entry-name>longtimedateformat</env-entry-name><
闽公网安备 35060202000074号