一.在Tomcat中配置JNDI对象
解决方案:在servlet.xml或表示web应用程序的XML文件中创建Resource和ResourceParam元素。然后向web.xml
中添加一个resource-env-ref元素。
tomcat的jndi对象在conf/server.xml文件,就要在这个xml文件中配置jndi对象。
例:配置jndi对象的server.xml元素
<Resource name="bean/pricebean" type=
"com.jspservletcookbook.StockPriceBean" auth="Container" description=
"A web harvesting bean"/>
<ResourceParams name="bean/pricebean">
<parameter>
<name>factory</name>
<value>org.apache.naming.factory.BeanFactory</value>
</parameter>
</ResourceParams>
该例包括一个Resource元素和一个使用名("bean/pricebean")应用该Resource的ResourceParams元素。这个名是
Java代码用来通过JNDI API访问bean实例的地址。
下面的例子将展示卫使web应用程序代码访问该JNDI对象,必须出现在部署描述文件(web.xml)中的resource-env-ref
元素。将com.jsperveltcookbook.StockPriceBean类存储在WEB-INFO/classes或位于WEB-INF/lib的JAR文件中。
例:将此元素放在部署描述文件web.xml中
<!-- 部署描述文件开始部分r -->
<resource-env-ref>
<description>
A factory for StockPriceBean
</description>
<resource-env-ref-name>
bean/pricebean
</resource-env-ref-name>
<resource-env-ref-type>
com.jspservletcookbook.StockPriceBean
</resource-env-ref-type>
</resource-env-ref>
<!-- 部署描述文件的其余部分 -->
下面将展示使用JNDI API 的代码段,只是让你了解该配置如何应用于有关JNDI的代码。
例:访问一个Tomcat JNDI资源的代码片段
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
//此代码可以放在servlet的init()方法,或者doGet()或doPos t()中
Context env = null;
StockPriceBean spbean = null;
try{
env = (Context) new InitialContext( ).lookup("java:comp/env");
spbean = (StockPriceBean) env.lookup("bean/pricebean");
if (spbean == null)
throw new ServletException(
"bean/pricebean is an unknown JNDI object");
//如果不再使用,关闭InitialContext
env.close( );
} catch (NamingException ne) {
//close the Context if you're not using it again
try{ env.close( ); } catch(NamingException nex) {}
throw new ServletException(ne);
}
在servlet中访问Tomcat JNDI资源
进行如下步骤之后,servlet就可以作为JNDI注册资源来访问JavaBean:
1.开发该JavaBean类,并将其存储在WEB-INF/classes或WEB-INF/lib下的JAR中。
2.为将该对象绑定与Tomcat JNDI 树,要如前面所述,修改服务器配置文件和web.xml。
下面将在其init()方法中创建一个javax.naming.InitialContext,然后查找一个JavaBean:com.jspservletcookbook.StockPriceBean.
这个bean用名"bean/pricebean"绑定于JNDI实现。init()方法只是在servlet容器创建servlet实例时才被调用,因此该servlet只访问
一个StockPriceBean的实例。
例:在servlet中使用Tomcat JNDI对象
package com.jspservletcookbook;
import java.io.IOException;
import java.io.PrintWriter;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.*;
import javax.servlet.http.*;
public class BeanServlet extends HttpServlet {
private StockPriceBean spbean;
public void init( ) throws ServletException {
Context env = null;
try{
env = (Context) new InitialContext( ).lookup("java:comp/env");
spbean = (StockPriceBean) env.lookup("bean/pricebean");
//关闭InitialContext,除非代码将用它来进行另一次查找
env.close( );
if (spbean == null)
throw new ServletException(
"bean/pricebean is an unknown JNDI object");
} catch (NamingException ne) {
try{ env.close( );} catch (NamingException nex) { }
throw new ServletException(ne);
}//try
}//init
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, java.io.IOException {
//设置响应的MIME类型:"text/html"
response.setContentType("text/html");
//使用PringWriter向客户端发送文本数据
java.io.PrintWriter out = response.getWriter( );
//开始组装HTML内容
out.println("<html><head>");
out.println("<title>Stock Price Fetcher</title></head><body>");
out.println("<h2>Please submit a valid stock symbol</h2>");
//确保method="POST",这样servlet服务方法在响应此表单提交时会调用doPost
//calls doPost in the response to this form submit
out.println(
"<form method=/"POST/" action =/"" + request.getContextPath( ) +
"/namingbean/" >");
out.println("<table border=/"0/"><tr><td valign=/"top/">");
out.println("Stock symbol: </td> <td valign=/"top/">");
out.println("<input type=/"text/" name=/"symbol/" size=/"10/">");
out.println("</td></tr><tr><td valign=/"top/">");
out.println(
"<input type=/"submit/" value=/"Submit Info/"></td></tr>");
out.println("</table></form>");
out.println("</body></html>");
} //doGet
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws java.io.IOException{
String symbol;//这将保存股票代号
float price = 0f;
symbol = request.getParameter("symbol");
boolean isValid = (symbol == null || symbol.length( ) < 1) ?
false : true;
//set the MIME type of the response, "text/html"
response.setContentType("text/html");
//use a PrintWriter send text data to the client
java.io.PrintWriter out = response.getWriter( );
//Begin assembling the HTML content
out.println("<html><head>");
out.println("<title>Latest stock value</title></head><body>");
if ((! isValid) || spbean == null){
out.println(
"<h2>Sorry, the stock symbol parameter was either "+
"empty or null</h2>");
} else {
out.println("<h2>Here is the latest value of "+ symbol +"</h2>");
spbean.setSymbol(symbol);
price = spbean.getLatestPrice( );
out.println( (price==0?
"The symbol is probably invalid." : ""+price) );
}
out.println("</body></html>");
}//doPost
}//BeanServlet
下面的例子将展示Tomcat在存储为JNDI对象的bean(即上面使用的bean).
例:存储为JNDI对象的bean
package com.jspservletcookbook;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.MalformedURLException;
import javax.swing.text.html.HTMLEditorKit.ParserCallback;
import javax.swing.text.MutableAttributeSet;
import javax.swing.text.html.parser.ParserDelegator;
public class StockPriceBean {
private static final String urlBase =
"http://finance.yahoo.com/q?d=t&s=";
private BufferedReader webPageStream = null;
private URL stockSite = null;
private ParserDelegator htmlParser = null;
private MyParserCallback callback = null;
private String htmlText = "";
private String symbol = "";
private float stockVal = 0f;
public StockPriceBean( ) {}//该bean的不带参数的构造函数
public void setSymbol(String symbol){
this.symbol = symbol;
}
public String getSymbol( ){
return symbol;
}
//提供回掉的内部类
class MyParserCallback extends ParserCallback {
private boolean lastTradeFlag = false;
private boolean boldFlag = false;
public MyParserCallback( ){
if (stockVal != 0)
stockVal = 0f;
}
public void handleStartTag(javax.swing.text.html.HTML.Tag t,
MutableAttributeSet a,int pos) {
if (lastTradeFlag && (t == javax.swing.text.html.HTML.Tag.B )){
boldFlag = true;
}
}//handleStartTag
public void handleText(char[] data,int pos){
htmlText = new String(data);
if (htmlText.indexOf("No such ticker symbol.") != -1){
throw new IllegalStateException(
"Invalid ticker symbol in handleText( ) method.");
} else if (htmlText.equals("Last Trade:")){
lastTradeFlag = true;
} else if (boldFlag){
try{
stockVal = new Float(htmlText).floatValue( );
} catch (NumberFormatException ne) {
try{
//使用NumberFormat去掉数字中的所有逗号
java.text.NumberFormat nf = java.text.NumberFormat.
getInstance( );
Double f = (Double) nf.parse(htmlText);
stockVal = (float) f.doubleValue( );
} catch (java.text.ParseException pe){
throw new IllegalStateException(
"The extracted text " + htmlText +
" cannot be parsed as a number!");
}//inner try
}//outer try
lastTradeFlag = false;
boldFlag = false;
}//if
} //handleText
}//MyParserCallback
public float getLatestPrice( ) throws IOException,MalformedURLException {
stockSite = new URL(urlBase + symbol);
webPageStream = new BufferedReader(new InputStreamReader(stockSite.
openStream( )));
htmlParser = new ParserDelegator( );
callback = new MyParserCallback( );//ParserCallback
synchronized(htmlParser){
htmlParser.parse(webPageStream,callback,true);
}//sychronized
//reset symbol
setSymbol("");
return stockVal;
}//getLatestPrice
}//StockPriceBean
注意:ParserDelegator.parse()方法是同步的,因此在用以时间只允许一个线程解析该Web叶面并提供股票价格
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
在JSP中访问Tomcat JNDI资源
解决方案:使用过滤器将对象放置在请求或会话范围中。在JSP中使用c:set和c:out JSTL标记访问该对象
过滤器的一个好的任务是访问JNDI对象,然后将对象的引用放置在会话中,交给JSP使用。
下面是通过JNDI和JSP使用过滤器所需的步骤:
1.开发并编辑过滤器,包括一个不带参数的构造函数。
2.在过滤其中使用JNDI API和javax.naming包来设置一个使用JNDI对象的会话属性。
3.将过滤器放置在WEB-INF/classes或WEB-INF/lib的jar中。
4.向web.xml中添加filter和filter-mapping元素,将过滤器映射到使用JNDI对象的JSP。
5.创建使用该会话属性的JSP。
例:过滤器访问JNDI对象并将此对象设置为会话属性
package com.jspservletcookbook;
import java.io.IOException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.*;
import javax.servlet.http.*;
public class JndiTFilter implements Filter {
private FilterConfig config;
private Context env;
//不带参数的构造函数对于过滤器是必需的
//虽然在缺少这样或其他的构造函数时,编译器回创建一个,但这里仍然显式地生成这个构造函数
public JndiTFilter( ) {}
public void init(FilterConfig filterConfig) throws ServletException {
this.config = filterConfig;
try {
env = (Context) new InitialContext( ).lookup("java:comp/env");
env.close( );
} catch (NamingException ne) {
try{ env.close( ); } catch (NamingException nex) {}
throw new ServletException(ne);
}
}
public void doFilter(ServletRequest request,
ServletResponse response, FilterChain chain) throws IOException,
ServletException {
StockPriceBean spbean = null;
try {
spbean = (StockPriceBean) env.lookup("bean/pricebean");
} catch (NamingException ne) { }
HttpServletRequest hRequest = null;
if (request instanceof HttpServletRequest)
hRequest = (HttpServletRequest) request;
HttpSession hSession = hRequest.getSession( );
if (hSession != null)
hSession.setAttribute("MyBean",spbean);
chain.doFilter(request,response);
}// doFilter
public void destroy( ){
/*在web窗口将该过滤器实例从服务器中移除前调用*/
}
}//Filter
过滤器的doFilter()方法将在每次客户端请求JSP时调用,所以每个客户端都与不同 的bean实例关联。也就是说,
每个会话都存储其自己的bean实例 。
下面将展示添加到部署描述文件中的filter和filter-mapping元素。这将使得servlet容器创建该过滤器的一个实例(调用
过滤器的init()方法)。这样,在每次接收到与filter-mapping元素中所关联的URL相同的请求时,容器将调用过滤器的
doFilter()方法。
例:用于与JNDI相关过滤器的filter和filter-mapping元素
<!-- start of web.xml -->
<filter>
<filter-name>JndiTFilter</filter-name>
<filter-class>com.jspservletcookbook.JndiTFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>JndiTFilter</filter-name>
<url-pattern>/jndiJsp.jsp</url-pattern>
</filter-mapping>
<!-- rest of web.xml -->
下面将JndiTFilter映射到URL为/jndiJsp.jsp的Web组件。
例:JSP使用一个作为JNDI对象生成的会话属性
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
<html>
<head><title>Jndi Bean</title></head>
<body>
<h2>Getting a StockPriceBean object via JNDI...</h2>
<c:set var="priceBean" value="${MyBean}"/>
<%-- 设置symbol特性为股票代号 --%>
<c:set target="${priceBean}" property="symbol" value="${param.symbol}"/>
<%-- 通过调用该bean对象的getLatestPrice()或的最新价格 --%>
The latest price: <c:out value="${priceBean.latestPrice}" />
</body>
</html>
二.在Weblogic种配置JNDI资源
下面是将javax.mail.Session对象绑定于Weblogic的JNDI实现所需的步骤。
1.登陆Weblogic管理控制台,包括使用浏览器URL,如http://localhost:7001/console.
2.使用在左侧栏中Your-domain-name Services Mail菜单。
3.单击"Configure a new Mail Session...".
4.在生成的窗口种填写文本域。为Session对象赋予一个JNDI名(在"jndiname"下),这将是代码用来查找该对象的名。
5.输入Session的所有特性:健入特性名,一个等号(=)和特性值。
6.单击Apply按钮,然后选择Targets标签。生成的屏幕允许将JNDI对象与一个或多个服务器相关联。
为本技巧的 Session JNDI对象设置的JavaMail特性
特性名描述示例
mail.host默认的邮件服务器mail.comcastl.net
mail.smtp.host特定协议的邮件主机,默认mail.comcast.net
情况为mail.host的值
mail.user连接邮件服务器的用户名bruceperry
mail.from发送邮件时使用的返回地址[email protected]
在servlet种访问Weblogic JNDI资源
下面是一个包含Weblogic的JNDI实现中javax.mail.Session对象的HttpServlet.
该servlet使用此对象构建一个电子邮件消息。该servlet在其init()方法中查找以名"MyEmail"绑定的对象。servlet
容器在创建该servlet实例时调用init()一次
例:从Weblogic的JNDI实现中获取一个javax.mail.Session 对象并构建电子邮件消息的servlet
package com.jspservletcookbook;
import java.io.IOException;
import java.io.PrintWriter;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.mail.*;
import javax.mail.internet.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class EmailJndiServlet extends HttpServlet {
private Session mailSession;
public void init( ) throws ServletException {
Context env = null;
try{
env = (Context) new InitialContext( );
mailSession = (Session) env.lookup("MyEmail");
if (mailSession == null)
throw new ServletException(
"MyEmail is an unknown JNDI object");
//close the InitialContext
env.close( );
} catch (NamingException ne) {
try{ env.close( );} catch (NamingException nex) { }
throw new ServletException(ne);
}
}//init
public void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException,
java.io.IOException {
response.setContentType("text/html");
java.io.PrintWriter out = response.getWriter( );
out.println(
"<html><head><title>Email message sender</title></head><body>");
String to = request.getParameter("to");
String from = request.getParameter("from");
String subject = request.getParameter("subject");
String emailContent = request.getParameter("emailContent");
try{
sendMessage(to,from,subject,emailContent);
} catch(Exception exc){
throw new ServletException(exc.getMessage( ));
}
out.println(
"<h2>The message was sent successfully</h2></body></html>");
out.println("</body></html>");
} //doPost
public void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException,
java.io.IOException {
//doGet( ) calls doPost( )
doPost(request,response);
}
private void sendMessage(String to, String from, String subject,
String bodyContent) throws Exception {
Message mailMsg = null;
mailMsg = new MimeMessage(mailSession);//a new email message
InternetAddress[] addresses = null;
try {
if (to != null) {
//如果to电子邮件地址违反RFC822语法,则抛出AddressException
addresses = InternetAddress.parse(to, false);
mailMsg.setRecipients(Message.RecipientType.TO, addresses);
} else {
throw new MessagingException(
"The mail message requires a 'To' address.");
}
if (from != null)
mailMsg.setFrom(from);
if (subject != null)
mailMsg.setSubject(subject);
if (bodyContent != null)
mailMsg.setText(bodyContent);
//最后,发送该邮件消息,如果消息的任何一个接收地址无效,则抛出一个"SendFailException
Transport.send(mailMsg);
} catch (Exception exc) {
throw exc;
}//sendMessage
}//EmailJndiServlet
对该servlet的典型请求如下:
http://localhost:7001/[email protected]&
[email protected]&subject=hello&
emailContent=A web message
在JSP中访问Weblogic JNDI 资源
例:过滤器将Weblogic JNDI对象存储于会话属性
package com.jspservletcookbook;
import java.io.IOException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.*;
import javax.servlet.http.*;
public class JndiFilter implements Filter {
private FilterConfig config;
private Context env;
public JndiFilter( ) {}
public void init(FilterConfig filterConfig) throws ServletException {
this.config = filterConfig;
try {
env = (Context) new InitialContext( );
} catch (NamingException ne) {
throw new ServletException(ne);
}
}//init
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
javax.mail.Session mailSession = null;
try {
mailSession = (javax.mail.Session) env.lookup("MyEmail");
} catch (NamingException ne) { }
HttpServletRequest hRequest = null;
if (request instanceof HttpServletRequest){
hRequest = (HttpServletRequest) request;
HttpSession hSession = hRequest.getSession( );
if (hSession != null)
hSession.setAttribute("MyEmail",mailSession);
}//if
chain.doFilter(request,response);
}// doFilter
public void destroy( ){
/*在web窗口将该过滤器实例从服务器中移除前调用*/
}
}
下面展示了该过滤器在部署描述文件中的配置,此部署描述文件必须伴随一个已被你或另外的部署人员安装于
Weblogic服务器的web应用程序。
例:过滤器在Weblogic 中访问JNDI对象
<!-- start of web.xml -->
<filter>
<filter-name>JndiFilter</filter-name>
<filter-class>com.jspservletcookbook.JndiFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>JndiFilter</filter-name>
<url-pattern>/jndiJsp.jsp</url-pattern>
</filter-mapping>
<!-- rest of web.xml -->
下面将展示一个访问该JNDI对象的JSP.
例:JSP作为会话属性访问JavaMail对象
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
<html>
<head><title>Jndi Email</title></head>
<body>
<h2>Getting a javax.mail.Session object via JNDI...</h2>
<c:set var="mSession" value="${MyEmail}" />
<c:out value="${mSession.class.name}" />
</body>
</html>
________________________________________________________________________________________________
使用Weblogic JNDI树访问EJB
解决方案:找到该EJB的JNDI名,使用javax.naming包获得对该EJBObject或远程接口的引用,这样可以调用该EJB的方法
例:无状态会话EJB
package com.jspservletcookbook;
import javax.ejb.*;
import java.util.Map;
import java.util.HashMap;
public class AbbrevBean implements SessionBean{
private SessionContext context;
private Map abbrevMap;
public AbbrevBean( ){ //the bean's no-arguments constructor
//包含各州名和所写的Map
abbrevMap = new HashMap( );
abbrevMap.put("ALABAMA","AL");
abbrevMap.put("ALASKA","AK");
abbrevMap.put("AMERICAN SAMOA","AS");
abbrevMap.put("ARIZONA","AZ");
abbrevMap.put("ARKANSAS","AR");
abbrevMap.put("CALIFORNIA","CA");
abbrevMap.put("COLORADO","CO");
abbrevMap.put("CONNECTICUTT","CT");
abbrevMap.put("DELAWARE","DE");
abbrevMap.put("DISTRICT OF COLUMBIA","DC");
abbrevMap.put("FEDERATED STATES OF MICRONESIA","FM");
abbrevMap.put("FLORIDA","FL");
abbrevMap.put("GEORGIA","GA");
abbrevMap.put("GUAM","GU");
abbrevMap.put("HAWAII","HI");
abbrevMap.put("IDAHO","ID");
abbrevMap.put("ILLINOIS","IL");
abbrevMap.put("INDIANA","IN");
abbrevMap.put("IOWA","IA");
abbrevMap.put("KANSAS","KS");
abbrevMap.put("KENTUCKY","KY");
abbrevMap.put("LOUISIANA","LA");
abbrevMap.put("MAINE","ME");
abbrevMap.put("MARSHALL ISLANDS","MH");
abbrevMap.put("MARYLAND","MD");
abbrevMap.put("MASSACHUSETTS","MA");
abbrevMap.put("MICHIGAN","MI");
abbrevMap.put("MINNESOTA","MN");
abbrevMap.put("MISSISSIPPI","MS");
abbrevMap.put("MISSOURI","MO");
abbrevMap.put("MONTANA","MT");
abbrevMap.put("NEBRASKA","NE");
abbrevMap.put("NEVADA","NV");
abbrevMap.put("NEW HAMPSHIRE","NH");
abbrevMap.put("NEW JERSEY","NJ");
abbrevMap.put("NEW MEXICO","NM");
abbrevMap.put("NEW YORK","NY");
abbrevMap.put("NORTH CAROLINA","NC");
abbrevMap.put("NORTH DAKOTA","ND");
abbrevMap.put("NORTHERN MARIANA ISLANDS","MP");
abbrevMap.put("OKLAHOMA","OK");
abbrevMap.put("OREGON","OR");
abbrevMap.put("PALAU","PW");
abbrevMap.put("PENNSYLVANIA","PA");
abbrevMap.put("PUERTO RICO","PR");
abbrevMap.put("RHODE ISLAND","RI");
abbrevMap.put("SOUTH CAROLINA","SC");
abbrevMap.put("SOUTH DAKOTA","SD");
abbrevMap.put("TENNESSEE","TN");
abbrevMap.put("TEXAS","TX");
abbrevMap.put("UTAH","UT");
abbrevMap.put("VERMONT","VT");
abbrevMap.put("VIRGIN ISLANDS","VI");
abbrevMap.put("VIRGINIA","VA");
abbrevMap.put("WASHINGTON","WA");
abbrevMap.put("WEST VIRGINIA","WV");
abbrevMap.put("WISCONSIN","WI");
abbrevMap.put("WYOMING","WY");
}//constructor
public void setSessionContext(SessionContext ctx) throws
EJBException {
context = ctx;
}//setSessionContext
public Map getAbbrevMap( ){
return abbrevMap;
}
//这个bean的业务方法
public String getAbbreviation(String state){
return (String) abbrevMap.get(state);
}
//javax.ejb.SessionBean方法,必须在会话bean中实现,但与无状态会话bean无关
//bean, but is not relevant to Stateless session beans.
public void ejbActivate( ){}
//javax.ejb.SessionBean方法,必须在会话bean中实现,但与无状态会话bean无关
//bean, but is not relevant to stateless session beans.
public void ejbPassivate( ){}
//javax.ejb.SessionBean方法;
public void ejbRemove( ) {}
}
下面的ejb-jar.xml文件指定EJB类型和与其相关的java类的完全限定名。
例:ejb-jar.xml文件
<?xml version="1.0"?>
<!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.
//DTD Enterprise JavaBeans 2.0//EN"
"http://java.sun.com/dtd/ejb-jar_2_0.dtd"
>
<ejb-jar>
<enterprise-beans>
<session>
<ejb-name>AbbreviationEjb</ejb-name>
<home>com.jspservletcookbook.AbbrevHome</home>
<remote>com.jspservletcookbook.Abbrev</remote>
<local-home>com.jspservletcookbook.AbbrevLocalHome</local-home>
<local>com.jspservletcookbook.AbbrevLocal</local>
<ejb-class>com.jspservletcookbook.AbbrevBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
</session>
</enterprise-beans>
</ejb-jar>
包括此EJB并不属于应用程序服务器的包,是一个名为myejb.jar的jar文件
注意:"主"对象(home object)是"主"接口的实现,"本地主"对象(local home object)是本地主接口的实现。这些
对象是EJB对象的"工厂",这回将业务方法调用委托给部署于服务器的EJB.工厂是生成各种Java类对象的Java类。在
本技巧中,客户端使用JNDI获得对主对象的引用,这将创建一个EJB对象。然后servlet(客户端)调用EJB对象的
getAbbreviation()方法;该EJB对象是一个将此方法调用委托给存储在服务其中的最初的EJB的远程对象或"跟"(stub)
注意:当使用管理控制台在Weblogic中部署EJB时,Weblogic自动使用weblogic-ejb-jar.xml部署描述文件指定的名
将主对象和本地主对象绑定于Weblogic JNDI 树。
下面将展示用于这里无状态会话bean的weblogic-ejb-jar.xml部署描述文件。
例:weblogic-ejb-jar.xml文件
<!DOCTYPE weblogic-ejb-jar PUBLIC
'-//BEA Systems, Inc.//DTD WebLogic 7.0.0 EJB//EN'
'http://www.bea.com/servers/wls700/dtd/weblogic-ejb-jar.dtd'>
<weblogic-ejb-jar>
<weblogic-enterprise-bean>
<ejb-name>AbbreviationEjb</ejb-name>
<stateless-session-descriptor>
<pool>
<initial-beans-in-free-pool>1</initial-beans-in-free-pool>
</pool>
</stateless-session-descriptor>
<jndi-name>AbbrevHome</jndi-name>
<local-jndi-name>AbbrevLocalHome</local-jndi-name>
</weblogic-enterprise-bean>
</weblogic-ejb-jar>
例:ejb-jar.xml文件的内容
H:/book/cookbook/code/chap27/src/ejbs/ejbjar>jar tvf myejb.jar
META-INF/
META-INF/MANIFEST.MF
com/
com/jspservletcookbook/
com/jspservletcookbook/Abbrev.class
com/jspservletcookbook/AbbrevBean.class
com/jspservletcookbook/AbbrevHome.class
com/jspservletcookbook/AbbrevLocal.class
com/jspservletcookbook/AbbrevLocalHome.class
META-INF/ejb-jar.xml
META-INF/weblogic-ejb-jar.xml
例:在weblogic中使用JNDI访问EJB的sevelt
package com.jspservletcookbook;
import java.io.IOException;
import java.io.PrintWriter;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.rmi.PortableRemoteObject;
import javax.servlet.*;
import javax.servlet.http.*;
public class WebJndiServlet extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, java.io.IOException {
//请求参数如state=Messachusetts
String state = request.getParameter("state");
Context env = null;
Abbrev abbrev = null;
AbbrevHome home = null;
try{
env = (Context) new InitialContext( );
//在weblogic JNDI树中查找主对象或工厂对象
Object localH = env.lookup("AbbrevHome");
//这个方法调用对于使用RMI-IIOP技术的EJB代码来讲是必需的
home = (AbbrevHome) PortableRemoteObject.narrow(localH,
AbbrevHome.class);
//close the InitialContext
env.close( );
if (home == null)
throw new ServletException(
"AbbrevHome is an unknown JNDI object");
//通过调用主对象的create()方法获得远程接口
abbrev = (Abbrev) PortableRemoteObject.narrow(home.create( ),
Abbrev.class);
} catch (NamingException ne) {
try{ env.close( );} catch (NamingException nex) { }
throw new ServletException(ne);
} catch (javax.ejb.CreateException ce) {
throw new ServletException(ce);
}
//set the MIME type of the response, "text/html"
response.setContentType("text/html");
java.io.PrintWriter out = response.getWriter( );
out.println("<html><head>");
out.println("<title>State abbreviations</title></head><body>");
out.println("<h2>Here is the state's abbreviation</h2>");
//调用EJBObject的getAbbreviation()方法
//该EJBObject将这个方法调用委托给会话bean
//将所有请求参数变为大写,因为这是会话bean的java.util.Map存储Map的键
//即州名的方式
if (state != null)
out.println( abbrev.getAbbreviation(state.toUpperCase( )) );
try{
//该servlet结束使用此EJBObject;调用其remove()方法
abbrev.remove( );
} catch (javax.ejb.RemoveException re){}
out.println("</body></html>");
}//doGet
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, java.io.IOException {
doGet(request, response);
}//doPost
}//WebJndiServlet
一个请求该servlet的URL:http://localhost:7001/webjndi?state=Oregon.