zoukankan      html  css  js  c++  java
  • jboss7搭载EJB3之简单会话BEAN与依赖注入jboss数据源

         记录学习的脚步 以备不时之需


    主要涉及到有状态会话Bean与无状态会话Bean ,本地接口与远程接口,依赖注入EJB服务与数据源

      理论方面知识简单提一下吧 毕竟我也说的不是特别精辟

       会话Bean一般用于处理业务层操作,有状态Bean与无状态Bean的区别在于是否记录用户的状态信息  ,有状态Bean记录用户的状态信息,采用(写回(不使用时,将Bean的状态写入硬盘)-激活(需要使用时,从硬盘中恢复其状态信息)机制进行控制),而无状态Bean采用实力池方式控制,类似于数据库连接池

       本地接口与远程接口的区别在于,想要使用本地接口,本地接口与想要使用的业务类代码必须处于一个JVM中,例如部署在一个jboss容器中,本地接口的出现是为了减少远程接口的网络开销、协议解析开销之类的,总之就是加快速度

       依赖注入--都很熟悉了 不解释了

    好吧 用一个HelloWorld展现吧  

      从一个无状态HelloWorld类开始吧

    package com.undergrowth.hello.impl;
    
    import java.sql.Connection;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    
    import javax.annotation.Resource;
    import javax.ejb.EJB;
    import javax.ejb.Local;
    import javax.ejb.Remote;
    import javax.ejb.Stateless;
    import javax.sql.DataSource;
    
    import com.undergrowth.hello.HelloWorldLocal;
    import com.undergrowth.hello.HelloWorldRemote;
    import com.undergrowth.hello.Other;
    
    
    
    /**
     * Session Bean implementation class HelloWorld
     */
    @Stateless
    @Remote(HelloWorldRemote.class)
    @Local({HelloWorldLocal.class})
    public class HelloWorld implements HelloWorldRemote,HelloWorldLocal {
    
    	//依赖注入其他EJB服务
    	@EJB(beanName="OtherBean") Other other;
    	//注入数据源
    	@Resource(mappedName="java:/myDataSource") DataSource dataSource;
    	/**
         * Default constructor. 
         */
        public HelloWorld() {
            
        }
    
        /**
         * EJB测试方法
         */
    	@Override
    	public String sayHello(String what) {
    		// TODO Auto-generated method stub
    		//通过数据源 获取信息
    		String name=connDb(Integer.valueOf(what));
    		return "你好,"+what+",我是EJB HELLO WORLD!!"+"
    "+other.sayOther(what)+"
    "+"我知道你叫"+name;
    	}
    	
    	/**
    	 * 本该单独分开写的
    	 * 简单处理 就在这写了
    	 * @param id
    	 * @return
    	 */
    	private String connDb(int id)
    	{
    		String str=null;
    		Connection conn = null;
            try {
                conn = dataSource.getConnection();
                Statement stmt = conn.createStatement();
                ResultSet rs = stmt.executeQuery("SELECT st.name from student st WHERE st.id="+id);
                if (rs.next())  str = rs.getString(1);  
                rs.close();
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }finally{
                try {
                    if(null!=conn && !conn.isClosed()) conn.close();
                } catch (SQLException e) {
                 	e.printStackTrace();
                }
            }
            
            return str;
    	}
    }

    看到他有两个实现接口,一个本地,一个远程

    远程接口

    package com.undergrowth.hello;
    
    import javax.ejb.Local;
    import javax.ejb.Remote;
    
    /**
     * 远程接口
     * HelloWorld Remote interface
     */
    
    public interface HelloWorldRemote {
         public String sayHello(String what);
    }
    本地接口

    package com.undergrowth.hello;
    
    /**
     * 本地接口
     * @author Administrator
     *
     */
    public interface HelloWorldLocal {
    	public String sayHello(String what);
    }
    


    哦 还有一个依赖注入的EJB服务 使用@EJB注解

    Other接口

    package com.undergrowth.hello;
    
    /**
     * 测试接口
     * @author Administrator
     *
     */
    public interface Other {
    
    	public  String sayOther(String what);
    }
    

    有状态的Bean 

    package com.undergrowth.hello.impl;
    
    import javax.ejb.Stateless;
    
    import com.undergrowth.hello.Other;
    
    /**
     * 测试@EJB 依赖注入 使用其他EJB服务
     * Other不写Remote或者Local的话 默认为本地接口
     * @author Administrator
     *
     */
    
    @Stateless
    public class OtherBean implements Other {
    
    	@Override
    	public String sayOther(String what) {
    		// TODO Auto-generated method stub
    		return what+",我是other";
    	}
    
    }
    

    好吧  到目前为止 准备了三个接口 一个远程 两个本地  

    还有两个会话Bean,一个有状态  ,一个没有状态

    哦 对了  还有使用了@Resource 注入了jboss数据源 得去配置一下

    在 

    jbossjboss-as-7.1.1.Finalstandaloneconfiguration
    下的standalone.xml中 在

     <subsystem xmlns="urn:jboss:domain:datasources:1.0">
                <datasources>
    元素下添加数据源  修改后如下

    <datasources>
                    <datasource jndi-name="java:jboss/datasources/ExampleDS" pool-name="ExampleDS" enabled="true" use-java-context="true">
                        <connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1</connection-url>
                        <driver>h2</driver>
                        <security>
                            <user-name>sa</user-name>
                            <password>sa</password>
                        </security>
                    </datasource>
                    <datasource jta="true" jndi-name="java:/myDataSource" pool-name="OraclesqlDS" enabled="true" use-java-context="true" use-ccm="true">
                        <connection-url>jdbc:oracle:thin:@localhost:1521:orcl</connection-url>
                        <driver>oracle</driver>
                        <transaction-isolation>TRANSACTION_READ_COMMITTED</transaction-isolation>
                        <pool>
                            <min-pool-size>10</min-pool-size>
                            <max-pool-size>100</max-pool-size>
                            <prefill>true</prefill>
                            <use-strict-min>false</use-strict-min>
                            <flush-strategy>FailingConnectionOnly</flush-strategy>
                        </pool>
                        <security>
                            <user-name>u1</user-name>
                            <password>u1</password>
                        </security>
                    </datasource>
                    <drivers>
                        <driver name="h2" module="com.h2database.h2">
                            <xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
                        </driver>
                        <driver name="oracle" module="com.oracle.ojdbc6">
                            <xa-datasource-class>oracle.jdbc.xa.client.OracleXADataSource</xa-datasource-class>
                        </driver>
                    </drivers>
                </datasources>

    因为jboss7的模块化管理     详情可参考  http://vase.iteye.com/blog/1299425

    哦  现在剩下的就是将上面的会话Bean打包 发布到JBOSs中  好的  来个ant的build.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <!-- ================================================ -->
    <!-- Sample buildfile for jar components -->
    <!-- -->
    <!-- ================================================ -->
    <project name="HelloWorld"  basedir=".">
        <!-- 定义属性 -->
        <property name="src.dir" value="${basedir}src" />
        <property environment="env"  />
        <property name="jboss.home" value="${env.JBOSS_HOME}"/>
        <property name="jboss.server.home" value="standalone"  />
        <property name="dep" value="deployments"  />
        <property name="build.dir" value="${basedir}uild"  />
    
        <path id="build.classpath">
        	<fileset dir="${basedir}lib">
        		<include name="*.jar" />
        	</fileset>
        	<pathelement location="${build.dir}" />
        </path>
    
    	<!-- - - - - - - - - - - - - - -->
    	<!-- target: init -->
    	<!-- - - - - - - - - - - - - - -->
    	<target name="init">
    		<delete dir="${build.dir}"></delete>
    		<mkdir dir="${build.dir}"></mkdir>
    	</target>
    
    	<!-- ========================= -->
    	<!-- target: compile -->
    	<!-- ========================= -->
    	<target name="compile" depends="init"
    		description="--> compile  this component" >
    
    		<javac srcdir="${src.dir}" destdir="${build.dir}" includes="com/**">
    			<classpath refid="build.classpath" />
    		</javac>
    	</target>
    	
    	<!-- 打包 -->
    	<target name="ejbjar" depends="compile" description="打包ejb">
    	   <jar jarfile="${basedir}${ant.project.name}.jar">
    	   	<fileset dir="${build.dir}">
    	   		<include name="**/*.class"></include>
    	   	</fileset>
    	   	<metainf dir="${src.dir}META-INF"></metainf>
    	   </jar>
    	</target>
    
        <!-- 部署 -->
        <target name="delopy" depends="ejbjar" description="部署ejb">
        	<copy file="${basedir}${ant.project.name}.jar"  todir="${jboss.home}${jboss.server.home}${dep}" />
        </target>
        
        <!-- 卸载ejb -->
        <target name="undeploy" description="卸载ejb">
          <delete file="${jboss.home}${jboss.server.home}${dep}${ant.project.name}.jar"></delete>
        </target>
        
    	<!-- 打包接口 -->
    	<target name="package_inter" depends="compile" description="打包接口">
    		<jar jarfile="${basedir}${ant.project.name}Interface.jar">
    			   	<fileset dir="${build.dir}">
    			   		<exclude name="**/impl/*.class"></exclude>
    			   	</fileset>
    			   </jar>
    	</target>
    	
    	
    
    </project>
    

    运行ant的deploy 之后 在jboss看到部署信息  

    23:52:03,775 INFO  [org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service thread 1-2) JNDI bindings for session bean named OtherBean in deployment unit deployment "HelloWorld.jar" are as follows:
    
    	java:global/HelloWorld/OtherBean!com.undergrowth.hello.Other
    	java:app/HelloWorld/OtherBean!com.undergrowth.hello.Other
    	java:module/OtherBean!com.undergrowth.hello.Other
    	java:global/HelloWorld/OtherBean
    	java:app/HelloWorld/OtherBean
    	java:module/OtherBean
    23:52:03,792 INFO  [org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service thread 1-2) JNDI bindings for session bean named HelloWorld in deployment unit deployment "HelloWorld.jar" are as follows:
    
    	java:global/HelloWorld/HelloWorld!com.undergrowth.hello.HelloWorldRemote
    	java:app/HelloWorld/HelloWorld!com.undergrowth.hello.HelloWorldRemote
    	java:module/HelloWorld!com.undergrowth.hello.HelloWorldRemote
    	java:jboss/exported/HelloWorld/HelloWorld!com.undergrowth.hello.HelloWorldRemote
    	java:global/HelloWorld/HelloWorld!com.undergrowth.hello.HelloWorldLocal
    	java:app/HelloWorld/HelloWorld!com.undergrowth.hello.HelloWorldLocal
    	java:module/HelloWorld!com.undergrowth.hello.HelloWorldLocal
    


    看到HelloWorld既有远程接口又有本地接口  而Other只有本地接口


    好了 服务已经在JBOSS的JNDI中了 现在使用客户端进行调用

    运行 ant 的 package_inter  打包接口

    将打包好的接口 拷贝到 客户端测试项目  HelloWorldWeb 中 在index.jsp中 加入一段代码

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
    <%@ page import="javax.naming.*,com.undergrowth.hello.*,com.undergrowth.ejb3.client.*" %>
    <%
    String path = request.getContextPath();
    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
    %>
    
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
        <base href="<%=basePath%>">
        
        <title>My JSP 'index.jsp' starting page</title>
    	<meta http-equiv="pragma" content="no-cache">
    	<meta http-equiv="cache-control" content="no-cache">
    	<meta http-equiv="expires" content="0">    
    	<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    	<meta http-equiv="description" content="This is my page">
    	<!--
    	<link rel="stylesheet" type="text/css" href="styles.css">
    	-->
      </head>
      
      <body>
        <%
        try {
        //本地接口的使用  需要本地接口与EJB应用在一个JVM里面  本地接口才能找到对应部署的EJB应用
    			HelloWorldLocal helloWorld=HelloWorldClient.lookupRemoteHelloWorldBean();
    			out.println(helloWorld.sayHello("1"));;
    		} catch (NamingException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		
    		
    		
         %>
      </body>
    </html>
    


    这里调用本地接口 因为测试客户端与服务在一个JBOSS中

    JBOSS7的查找JNDI的方法 与之前的版本稍微不一样  如下

    public static HelloWorldLocal lookupRemoteHelloWorldBean() throws NamingException {
    	        final Hashtable jndiProperties = new Hashtable();
    	        jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
    	        final Context context = new InitialContext(jndiProperties);
    	        // The app name is the application name of the deployed EJBs. This is typically the ear name
    	        // without the .ear suffix. However, the application name could be overridden in the application.xml of the
    	        // EJB deployment on the server.
    	        // Since we haven't deployed the application as a .ear, the app name for us will be an empty string
    	        final String appName = "";
    	        // This is the module name of the deployed EJBs on the server. This is typically the jar name of the
    	        // EJB deployment, without the .jar suffix, but can be overridden via the ejb-jar.xml
    	        // In this example, we have deployed the EJBs in a jboss-as-ejb-remote-app.jar, so the module name is
    	        // jboss-as-ejb-remote-app
    	        final String moduleName = "HelloWorld";
    	        // AS7 allows each deployment to have an (optional) distinct name. We haven't specified a distinct name for
    	        // our EJB deployment, so this is an empty string
    	        final String distinctName = "";
    	        // The EJB name which by default is the simple class name of the bean implementation class
    	        final String beanName = "HelloWorld";
    	        // the remote view fully qualified class name
    	       // final String viewClassName = HelloWorldRemote.class.getName();
    	        final String viewClassName = HelloWorldLocal.class.getName();
    	        // let's do the lookup
    	        return (HelloWorldLocal) context.lookup("ejb:" + appName + "/" + moduleName + "/" + distinctName + "/" + beanName + "!" + viewClassName);
    	        
    	 }

    哦 还有一个 jboss客户端访问jboss服务器的参数文件 文件名为:jboss-ejb-client.properties   放在src目录下即可

    endpoint.name=client-endpoint  
    remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false  
       
    remote.connections=default  
       
    remote.connection.default.host= localhost
    remote.connection.default.port = 4447
    remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false  
      
    remote.connection.default.username=qq     
    remote.connection.default.password=q  


     参考文档  :jboss官方参考手册   https://docs.jboss.org/author/display/AS71/EJB+invocations+from+a+remote+client+using+JNDI


    发布测试客户端 访问index.jsp  输出如下

    你好,1,我是EJB HELLO WORLD!! 1,我是other 我知道你叫Eason 

    即可看到 这里获取JBOSS的JNDI树中发布的服务获取到会话Bean  并转给本地接口 本地接口 进行调用相应的服务 完成功能


    对于JBOSS  真的要赞一下 很好用


  • 相关阅读:
    教程:在 Visual Studio 中开始使用 Flask Web 框架
    教程:Visual Studio 中的 Django Web 框架入门
    vs2017下发现解决python运行出现‘No module named "XXX""的解决办法
    《sqlite权威指南》读书笔记 (一)
    SQL Server手工插入标识列
    hdu 3729 I'm Telling the Truth 二分图匹配
    HDU 3065 AC自动机 裸题
    hdu 3720 Arranging Your Team 枚举
    virtualbox 虚拟3台虚拟机搭建hadoop集群
    sqlserver 数据行统计,秒查语句
  • 原文地址:https://www.cnblogs.com/liangxinzhi/p/4275554.html
Copyright © 2011-2022 走看看