JBoss 6中整合EJB3与Struts2

方祺
2023-12-01
下面是鄙人做JBoss 6整合EJB3与Struts2时遇到的一些问题,解决之后决定把它整理出来,或许能帮到某位正在为此问题困惑的同仁,若有疏漏或错误请直接扔砖。
最近在做一个Java平台下的项目,考虑到后期业务逻辑可能非常复杂,为了今后能充分利用JBoss应用服务器所提供的服务,因此决定采用EJB3实现业务逻辑,而又想充分利用Struts2作为WEB框架所带来的简洁性,因此决定采用EJB3整合Struts2,但之前的尝试发现Struts2无法在JBoss6中部署,此问题一直未能解决,于是选择了一种折中的方案,JBoss中部署EJB模块,Tomcat中部署表现层模块,由Spring为Struts2提供ObjectFactory,并负责通过JNDI查找并注入EJB远程业务对象。
原型开发完毕之后,发现性能不佳,原因也显而易见,引入了分布式——RMI,于是决定只使用JBoss6作为应用服务器,去掉Tomcat。但Struts2无法在JBoss6中部署,直接用Servlet开发WEB层又过于繁琐,于是痛下决心,看看究竟什么原因让Struts2无法与JBoss6并存,看着部署时的各种堆栈异常发呆,迟迟找不到解决方案,于是拿出最后的杀手锏——Google一番,相关资料很少,煞费苦心之后终于找到了一些参考,还是国外的——英语,勉强看吧,原来是Struts2中的Xwork包不能在JBoss6中部署,原因是由于JBoss6中增加了一种新的Jar文件前缀vfs,而XWork仅能兼容JBoss5之前的版本,只需对XWork一个类中的代码稍加修改,一切OK。
该项目采用Maven做项目管理,考虑到项目构建的跨平台性,决定将XWork源码修改后作为自己项目的一个子模块发布,修改相当简单,只需对com.opensymphony.xwork2.util.URLUtil类稍作修改即可,以下是XWork发布包中该类的部分源代码:
/*
* Copyright (c) 2002-2003 by OpenSymphony
* All rights reserved.
*/
package com.opensymphony.xwork2.util;

import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.net.URL;
import java.net.MalformedURLException;

/**
* Helper class to extract file paths from different urls
*/
public class URLUtil {

/**
* Prefix for Jar files in JBoss Virtual File System
*/
public static final String JBOSS5_VFSZIP = "vfszip";
public static final String JBOSS5_VFSMEMORY = "vfsmemory";

/**
* Check if given URL is pointing to JBoss 5 VFS resource
* @param fileUrl
* @return
*/
public static boolean isJBoss5Url(URL fileUrl) {
final String protocol = fileUrl.getProtocol();
return JBOSS5_VFSZIP.equals(protocol) || JBOSS5_VFSMEMORY.equals(fileUrl.getProtocol());
}

}

以下是修改后的源文件,仅需添加一个新的静态字符串常量"vfs"并对isJBoss5Url方法稍作修改即可:
/*
* Copyright (c) 2002-2003 by OpenSymphony
* All rights reserved.
*/
package com.opensymphony.xwork2.util;

import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.net.URL;
import java.net.MalformedURLException;

/**
* Helper class to extract file paths from different urls
*/
public class URLUtil {

/**
* Prefix for Jar files in JBoss Virtual File System
*/
public static final String JBOSS6_VFS = "vfs";
public static final String JBOSS5_VFSZIP = "vfszip";
public static final String JBOSS5_VFSMEMORY = "vfsmemory";

/**
* Check if given URL is pointing to JBoss 5 VFS resource
* @param fileUrl
* @return
*/
public static boolean isJBoss5Url(URL fileUrl) {
final String protocol = fileUrl.getProtocol();
return JBOSS6_VFS.equals(protocol) || JBOSS5_VFSZIP.equals(protocol) || JBOSS5_VFSMEMORY.equals(fileUrl.getProtocol());
}

}

OK,就这么简单,为了便于在以后的项目中重用,特意把XWork发布包的POM文件做了一番修改,将修改后的XWork作为自己项目的一个模块来使用,POM文件代码就不列出了,构建该项目时使用的是Maven3,如果哪位同仁遇到了同样的问题,而且在用Maven做项目管理,那么该模块可以直接添加到你的项目中,整个模块作为Maven项目上传在附件中:
好了,终于可以在JBoss 6中部署Struts2,但是,Spring现在用来做什么呢?JNDI查找?依赖注入?既然是在同一个容器中,那么能不能直接把EJB注入Struts中的Action呢,
只知道EJB能被注入Servlet等受管资源中,试一试再说。首先彻底将Spring移除,哇,项目发布包小了不少,给力,呵呵~~,然后直接在Struts2 Action中采用注解注入EJB,修改完成之后,部署运行,果不出所料,NullPointerException~~~,看来是不行,Google一下,找到了一个插件——strus2-ejb3-plugin,该插件是个Google开源项目,项目首页是[url]http://code.google.com/p/struts2-ejb3-plugin/[/url],大家可以看看怎么使用。相当简单,几乎是零配置,默认的配置就可以搞定,只需要把这个插件添加在你的类路径中。我的项目是打包成EAR包,如application.ear,那么仅需要在类路径下添加struts2-ejb3-plugin.properties,内容如下所示:
#struts-ejb3-plugin.properties

# ear file path, leave empty if not applicable
earFileBaseName=application

除此之外,在你的类路径下添加jndi.properties文件,如下所示:
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
java.naming.provider.url=jnp://localhost:1099

重新构建部署项目,一切OK,尽情享受EJB3与Struts2的整合吧,enjoy it!
哦,不对,还有一点小小的缺陷,既然我的项目是用Maven作项目管理的,而这个插件项目并未使用Maven,搜索过几个主要的仓库之后,都没有该构件,如果直接把该插件放在类路径中,那岂不是失去了Maven的长处?OK,这个好办,既然是开源的,那就自己用Maven构建它,和上面的XWork模块一样,将它作为自己项目的一部分,让Maven来为你做这些吧。该构件也作为Maven项目一并上传至附件中。遇到同样问题的同仁可以直接使用它,不用浪费自己宝贵的时间了。OK,就这么多,经过调整之后,性能有了明显的改善,以后若采用同样的架构,便可一劳永逸。
第一次在JavaEye上发文章,以前一直看各位大侠的文章来帮助自己解决问题,提高自己,实在不好意思写什么,因为自己很菜。昨天解决了这个困扰自己已久的问题,有点小激动,于是乎把这些问题整理出来,兴许能帮到哪位同仁!!!
 类似资料: