基于EJB开发业务简介
在复杂的企业IT架构中 web模块主要用途其实在展现层,它接收到用户的请求后委托后端的 ejb 完成业务逻辑(将业务交由ejb处理,可方便地获得保障业务事务及分布式事务、多客户端调用等好处),然后将ejb的处理结果以可视化形式展现给用户,如此的分层架构可以方便地对ejb业务层实施可复用和分布式。
ejb通常都是jar文件,web通常是war文件,一般都是独立部署,但是,有的时候我们也希望将某些ejb和web打包的一起部署,这就是企业应用ear。
maven 支持 ear 的管理。
假设要完成的ear中包行一个ejb和一个web,名称分别为:ejb3和webdemo,两个模块独立开发完成后执行 install 安装到本地maven库,建立一个ear模块(其实就是普通的maven项目,只是设置pom打包类型<packaging>ear</packaging>),如果要开发一个ejb,那么就设置<packaging>ejb</packaging>。
1.开发一个ejb
名称ejb3,其pom大致为:
- <?xml version="1.0" encoding="UTF-8"?>
- <project xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <parent>
- <artifactId>eden</artifactId>
- <groupId>com.conquer.eden</groupId>
- <version>1.0</version>
- </parent>
- <modelVersion>4.0.0</modelVersion>
- <packaging>ejb</packaging>
- <artifactId>ejb3</artifactId>
- <dependencies>
- <dependency>
- <groupId>javax.ejb</groupId>
- <artifactId>ejb-api</artifactId>
- <version>3.0</version>
- <scope>provided</scope>
- </dependency>
- <!--<dependency>-->
- <!--<groupId>org.eclipse.persistence</groupId>-->
- <!--<artifactId>javax.persistence</artifactId>-->
- <!--<version>2.0.5</version>-->
- <!--<scope>provided</scope>-->
- <!--</dependency>-->
- </dependencies>
- <build>
- <finalName>${artifactId}</finalName>
- <plugins>
- <plugin>
- <!--<groupId>org.apache.maven.plugins</groupId>-->
- <artifactId>maven-ejb-plugin</artifactId>
- <version>2.5</version>
- <configuration>
- <ejbVersion>3.0</ejbVersion>
- <!--<filterDeploymentDescriptor>true</filterDeploymentDescriptor>-->
- <!-- this is false by default -->
- <generateClient>true</generateClient>
- <!--用下面的方式进行 客户端生成定制-->
- <clientIncludes>
- <!-- 包含 test 下面的所有文件和文件夹 -->
- <!--<clientInclude>test/**</clientInclude>-->
- <!-- 包含 com/example 下面所有的文件,PS:不含文件夹-->
- <!--<clientInclude>com/example/*</clientInclude>-->
- </clientIncludes>
- <clientExcludes>
- <!-- 不包含 com/example 下的所有文件-->
- <!--<clientExclude>com/example/*</clientExclude>-->
- <!-- this will exclude all files and directories with the name sparrow under com/jack -->
- <!--<clientExclude>com/jack/**/sparrow</clientExclude>-->
- </clientExcludes>
- </configuration>
- </plugin>
- </plugins>
- </build>
- </project>
以上的pom文件需要注意的点:
1.打包类型:
<packaging>ejb</packaging>
2.EJB插件
<artifactId>maven-ejb-plugin</artifactId>
3.是否生成EJB客户端jar
<generateClient>true</generateClient>
关于
<generateClient>
的介绍:
<generateClient>用于生成简单版的ejb客户端,通常只包含客户端使用到的接口而不包含实现类,
他的默认排除规则是:
- **/*Bean.class
- **/*CMP.class
- **/*Session.class
- **/package.html
当然,该规则也可以定制,可以定制需要添加和排除的文件,如下:
- <configuration>
- <clientIncludes>
- <!-- this will include all files and directories under com/foo/bar -->
- <clientInclude>com/foo/bar/**</clientInclude>
- <!-- this will include all files and directories under com/foo/acme -->
- <clientInclude>com/foo/acme/**</clientInclude>
- <!-- this will include all files under com/example -->
- <clientInclude>com/example/*</clientInclude>
- </clientIncludes>
- <clientExcludes>
- <!-- this will exclude all files under com/example -->
- <clientExclude>com/example/*</clientExclude>
- <!-- this will exclude all files and directories with the name
- sparrow under com/jack -->
- <clientExclude>com/jack/**/sparrow</clientExclude>
- </clientExcludes>
- </configuration>
最后:在模块中添加此client的依赖时候,其类型要指定为ejb-client,如
<dependency>
<groupId>com.conquer.eden</groupId>
<artifactId>xaejb</artifactId>
<version>1.0</version>
<!--<classifier>client</classifier>-->
<type>ejb-client</type>
</dependency>
官网参考:
http://maven.apache.org/plugins/maven-ejb-plugin/
http://maven.apache.org/plugins/maven-ejb-plugin/examples/generating-ejb-client.html
ejb的java代码:
- public interface TestDAOEJB {
- String insertData(String data) throws Exception;
- String insertData2(String data) throws Exception;
- String insertData3(String data) throws Exception;
- }
- import javax.ejb.*;
- import javax.naming.Context;
- import javax.naming.InitialContext;
- import javax.sql.DataSource;
- import java.io.IOException;
- import java.sql.Connection;
- import java.sql.Statement;
- import java.util.Properties;
- //@Stateless
- //@Stateless(mappedName = "TestDAOBean")
- @Stateful
- @Remote(value = TestDAOEJB.class)
- public class TestDAOBean implements TestDAOEJB {
- private static String otherNode1;
- private static String otherNode2;
- static {
- try {
- Properties properties = new Properties();
- properties.load(TestDAOBean.class.getResourceAsStream("/config.properties"));
- otherNode1 = properties.getProperty("otherNode1");
- otherNode2 = properties.getProperty("otherNode2");
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- /**
- * CREATE TABLE wangpl(name VARCHAR2(200))
- */
- @Override
- @TransactionAttribute(TransactionAttributeType.REQUIRED)//这是默认值,可以省略,或修改为其它事务策略
- public String insertData(String data) throws Exception {
- String returnString = "insertData-OK";
- Connection con = null;
- Statement statement = null;
- try {
- DataSource dataSource = (DataSource) new InitialContext().lookup("DataSource1");
- con = dataSource.getConnection();
- statement = con.createStatement();
- String sql = "INSERT INTO wangpl VALUES('" + data + ":insertData')";
- statement.execute(sql);
- } finally {
- // close xxx
- }
- // 调用远程节点
- Properties p = new Properties();
- p.put(Context.INITIAL_CONTEXT_FACTORY, "com.xxx.RemoteInitialContextFactory");
- p.put(Context.PROVIDER_URL, otherNode1);
- InitialContext ctx = new InitialContext(p);
- TestDAOEJB remote = (TestDAOEJB) ctx.lookup("TestDAOBeanRemote");
- remote.insertData2(data + "1");
- return returnString;
- }
- @Override
- @TransactionAttribute(TransactionAttributeType.SUPPORTS)
- public String insertData2(String data) throws Exception {
- String returnString = "insertData2-OK";
- Connection con = null;
- Statement statement = null;
- try {
- DataSource dataSource = (DataSource) new InitialContext().lookup("DataSource1");
- con = dataSource.getConnection();
- statement = con.createStatement();
- String sql = "INSERT INTO wangpl VALUES('" + data + ":insertData2')";
- statement.execute(sql);
- } finally {
- // close xxx
- }
- // 调用远程ejb
- Properties p = new Properties();
- p.put(Context.INITIAL_CONTEXT_FACTORY, "com.xxx.RemoteInitialContextFactory");
- p.put(Context.PROVIDER_URL, otherNode2);
- InitialContext ctx = new InitialContext(p);
- TestDAOEJB remote = (TestDAOEJB) ctx.lookup("TestDAOBeanRemote");
- remote.insertData3(data + "1");
- if (data.equals("11")) {
- throw new RuntimeException("************* Runtime Exception **************");
- }
- return returnString;
- }
- @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
- public String insertData3(String data) throws Exception {
- String returnString = "insertData3-OK";
- Connection con = null;
- Statement statement = null;
- try {
- DataSource dataSource = (DataSource) new InitialContext().lookup("DataSource1");
- con = dataSource.getConnection();
- statement = con.createStatement();
- String sql = "INSERT INTO wangpl VALUES('" + data + ":insertData3')";
- statement.execute(sql);
- } finally {
- // close xxx
- }
- if (data.equals("211")) {
- throw new RuntimeException("************* Runtime Exception **************");
- }
- return returnString;
- }
- }
2.开发web模块
其pom大致如下:
- <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
- <parent>
- <artifactId>eden</artifactId>
- <groupId>com.conquer.eden</groupId>
- <version>1.0</version>
- </parent>
- <modelVersion>4.0.0</modelVersion>
- <artifactId>webdemo</artifactId>
- <packaging>war</packaging>
- <name>webdemo</name>
- <build>
- <finalName>${artifactId}</finalName>
- </build>
- <dependencies>
- <dependency>
- <groupId>javax.servlet</groupId>
- <artifactId>javax.servlet-api</artifactId>
- <version>3.1.0</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>com.conquer.eden</groupId>
- <artifactId>ejb3</artifactId>
- <version>1.0</version>
- <!--<classifier>client</classifier>-->
- <type>ejb-client</type>
- </dependency>
- </dependencies>
- </project>
web层业务代码 ,可以使用 @EJB @Resource 的注解方式,或者手工: new InitialContext(xx)来访问ejb。
3.开发ear
其pom文件为:
- <?xml version="1.0" encoding="UTF-8"?>
- <project xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <parent>
- <artifactId>eden</artifactId>
- <groupId>com.conquer.eden</groupId>
- <version>1.0</version>
- </parent>
- <modelVersion>4.0.0</modelVersion>
- <packaging>ear</packaging>
- <artifactId>ear</artifactId>
- <dependencies>
- <dependency>
- <groupId>com.conquer.eden</groupId>
- <artifactId>ejb3</artifactId>
- <version>1.0</version>
- <type>ejb</type>
- </dependency>
- <dependency>
- <groupId>com.conquer.eden</groupId>
- <artifactId>webdemo</artifactId>
- <version>1.0</version>
- <type>war</type>
- </dependency>
- </dependencies>
- <build>
- <finalName>${artifactId}</finalName>
- <plugins>
- <plugin>
- <artifactId>maven-ear-plugin</artifactId>
- <version>2.10</version>
- <configuration>
- <!--<generateModuleId>true</generateModuleId>-->
- <!--指定打包范围,避免无用jar混乱加入-->
- <!--<packagingIncludes>META-INF/**,**/acme-*.jar,**/acme-*.war</packagingIncludes>-->
- <!--<packagingExcludes></packagingExcludes>-->
- <!--打包指定目录lib-->
- <defaultLibBundleDir>lib/</defaultLibBundleDir>
- <!--将多个war的共享包提取到父级别-->
- <skinnyWars>true</skinnyWars>
- <!--<includeLibInApplicationXml>true</includeLibInApplicationXml>-->
- <!--jboss 定制-->
- <!--<jboss>-->
- <!--<version>5</version>-->
- <!--<module-order>strict</module-order>-->
- <!--<unauthenticated-principal>guest</unauthenticated-principal>-->
- <!--<loader-repository>com.foo:loader=foo-application-1.0.ear</loader-repository>-->
- <!--</jboss>-->
- <modules>
- <!--jarModule:用于添加第三方库,配合includeInApplicationXml,可使其像一个开发的模块-->
- <jarModule>
- <!--<groupId>com.conquer.eden</groupId>-->
- <!--<artifactId>ejb3</artifactId>-->
- <!--<bundleFileName>ejb3.jar</bundleFileName>-->
- <!--<includeInApplicationXml>true</includeInApplicationXml>-->
- <!--<bundleDir>APP-INF/lib</bundleDir> 只更改位置,名称保持不变-->
- <!--<uri>APP-INF/lib/anotherName-1.2.3.jar</uri> 可定制位置和名称,需要指定名称-->
- <!--<excluded>true</excluded>-->
- <!--<moduleId>ejb3-id</moduleId>-->
- </jarModule>
- <ejbModule>
- <groupId>com.conquer.eden</groupId>
- <artifactId>ejb3</artifactId>
- <bundleFileName>ejb3.jar</bundleFileName>
- </ejbModule>
- <webModule>
- <groupId>com.conquer.eden</groupId>
- <artifactId>webdemo</artifactId>
- <bundleFileName>webdemo.war</bundleFileName>
- <!--<moduleId>webdemo-id</moduleId>-->
- </webModule>
- </modules>
- <!--<security>-->
- <!--<security-role id="SecurityRole_1234">-->
- <!--<role-name>manager</role-name>-->
- <!--</security-role>-->
- <!--<security-role id="SecurityRole_5678">-->
- <!--<description>My cool description</description>-->
- <!--<role-name id="RoleName_12">teller</role-name>-->
- <!--</security-role>-->
- <!--</security>-->
- <!--<version>6</version>-->
- <!--<env-entries>-->
- <!--<env-entry>-->
- <!--<description>A complete entry.</description>-->
- <!--<env-entry-name>complete</env-entry-name>-->
- <!--<env-entry-type>java.lang.Integer</env-entry-type>-->
- <!--<env-entry-value>4</env-entry-value>-->
- <!--</env-entry>-->
- <!--<env-entry>-->
- <!--<env-entry-name>no-type</env-entry-name>-->
- <!--<env-entry-value>4</env-entry-value>-->
- <!--</env-entry>-->
- <!--<env-entry>-->
- <!--<env-entry-name>no-value</env-entry-name>-->
- <!--<env-entry-type>java.lang.String</env-entry-type>-->
- <!--</env-entry>-->
- <!--</env-entries>-->
- </configuration>
- </plugin>
- </plugins>
- </build>
- </project>
以上pom要注意的是:
1.添加的两个依赖一个是ejb,一个是war包,指明的类型分别是:
<type>ejb</type>和<type>war</type>
2.EAR的打包插件
<artifactId>maven-ear-plugin</artifactId>
3.添加的ejb和war需要分别指明:<ejbModule> 和 <webModule> 并且都可以定制打进ear的名称,通过:<bundleFileName>
执行ear模块的package目标或执行ear模块maven的ear:ear可完成 ear的打包工作。
关于 maven-ear-plugin ,官网参考:http://maven.apache.org/plugins/maven-ear-plugin/