zoukankan      html  css  js  c++  java
  • 一个基于JBoss5.1+EJB3.0 登陆应用

    花了几天的时间研究了一下EJB的使用,一直以来都主要是在写终端中的程序,对Java框架的相关的开发非常不熟悉,中间遇到了不少麻烦,还好总算都攻克了。写篇日志记录一下。


    经验总结

    • 为什么选择JBoss5.1:

    从8開始最新的jboss已经改名为WildFly了,jboss5还是09年的东西.刚開始的时候我准备用WildFly部署EJB的,由于没有经验并且相关的资料非常少.仅仅能换用更老一点的Jboss5

    • 怎样打包公布:
      ejb的公布非常easy,仅仅要将打包好的代码(jar,ear,war ….)复制到 ==~/jboss-5.1.0.GA/server/default/deploy/==里,jboss就会自己主动检測到变动自己主动载入

    MyEclipse可保存后就自己主动公布,Eclipse-J2EE版似乎没有这个功能,只是即使是MyEclipse的自己主动公布也可能存在问题,比較稳妥的办法是自己写一个ant的自己主动编译文件.

    • ant配置文件的写法

      ant能够帮助完毕编译,复制,粘贴,打包,部署等反复的操作,以下是一份ant的模版.

    <?

    xml version="1.0" encoding="UTF-8"?

    > <project name="EJB" basedir="."> <property name="src.dir" value="${basedir}/ejbModule" /> <property name="jboss.home" value="/home/ckboss/jboss-5.1.0.GA/" /> <property name="jboss.server.config" value="default" /> <property name="build.dir" value="${basedir}/build" /> <path id="build.classpath"> <fileset dir = "${jboss.home}/client"> <include name="*.jar" /> </fileset> <pathelement location ="${build.dir}" /> </path> <target name="prepare"> <delete dir="${build.dir}" /> <mkdir dir="${build.dir}" /> </target> <target name="compile" depends="prepare" description="编译"> <javac srcdir="${src.dir}" destdir="${build.dir}"> <classpath refid = "build.classpath" /> </javac> </target> <target name = "ejbjar" depends="compile" description="创建EJB"> <jar jarfile="${build.dir}/${ant.project.name}.jar"> <fileset dir="${build.dir}"> <include name="**/*.class" /> </fileset> </jar> </target> <target name="deploy" depends="ejbjar" description="公布"> <copy file ="${build.dir}/${ant.project.name}.jar" todir = "${jboss.home}/server/${jboss.server.config}/deploy/" /> </target> <target name="undeploy" description="卸载"> <delete file="${jboss.home}/server/${jboss.server.config}/deploy/${ant.project.name}.jar" /> </target> </project>

    详解一下ant的使用:

    1.在工程文件夹下新建一个叫 build.xml 的文件填上以上内容就能够了,然后会发现xml变成了小蚂蚁的图标,这样就能够了.这个build.xml所在的位置就叫做basedir , 其它文件能够依据这个相对路径来定位.
    2.代码的解释:

    <project name="EJB" basedir=".">
        <property name="src.dir" value="${basedir}/ejbModule" />
        <property name="jboss.home" value="/home/ckboss/jboss-5.1.0.GA/" />
        <property name="jboss.server.config" value="default" />
        <property name="build.dir" value="${basedir}/build" />

    这一段主要定义了一些变量的路径,project name 就是工程的名字,也就是${ant.project.name}

    src.dir:是源代码位置

    jboss.home: jboss部署在哪

    jboss.server.config: jboss的启动配置

    build.dir: 生成的jar包的位置

    <path id="build.classpath">
            <fileset dir = "${jboss.home}/client">
                <include name="*.jar" />
            </fileset>
            <pathelement location ="${build.dir}" />
        </path>

    所须要的jar包的位置,这里包括了jboss下client的全部jar包,假设引入了别的jar包能够手动的包括进去.

    <target name="prepare">
            <delete dir="${build.dir}" />
            <mkdir dir="${build.dir}" />
        </target>

    这里定义了一个叫prepare的过程,功能是删除可能存在的build.dir,再新建一个build.dir

        <target name="compile" depends="prepare" description="编译">
            <javac srcdir="${src.dir}" destdir="${build.dir}">
                <classpath refid = "build.classpath" />
            </javac>
        </target>

    一个叫做 compile 的过程,这个过程的执行须要prepare在它前面执行.
    编译全部src里的文件,编译到build里

    <target name = "ejbjar" depends="compile"  description="创建EJB">
            <jar jarfile="${build.dir}/${ant.project.name}.jar">
                <fileset dir="${build.dir}">
                    <include name="**/*.class" />
                </fileset>
            </jar>
        </target>

    创建一个jar包到build.dir中,包括了build.dir里的class类

    <target name="deploy" depends="ejbjar" description="公布">
            <copy file ="${build.dir}/${ant.project.name}.jar" 
                    todir = "${jboss.home}/server/${jboss.server.config}/deploy/" />
        </target>
    
        <target name="undeploy" description="卸载">
            <delete file="${jboss.home}/server/${jboss.server.config}/deploy/${ant.project.name}.jar" />
        </target>
    

    公布和卸载,在jboss上的部署非常easy,公布仅仅要把jar复制到jboss里相应的deploy文件夹里就能够了,卸载就是把这个jar包移除就能够了.

    3.怎样使用ant?


    点击XML文件,选择大纲视图,选择所需的步骤,右键用ant执行

    这种界面就是执行成功了

    • jboss的 jndi

    jndi比較难以理解,各种服务器的调用也个不一样,放弃WildFly的一个原因就是不知道怎么用jndi,也找不到靠普的文档

    但jboss5中的jndi使用比較简单,

    控制台上的输出就是某个应用的jndi

    怎样获取jndi,
    外部调用ejb就要用Context找到相应的jndi,并转换成相应的接口,获取Contex的參数设置各种服务器是不一样的,jboss5中的一种调用方法是:

    Properties properties = new Properties();
                properties.put("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
                properties.put("java.naming.factory.url.pkgs", "org.jboss.naming rg.jnp.interfaces");
                properties.setProperty(Context.PROVIDER_URL, "localhost:1099");
                InitialContext ctx = new InitialContext(properties);

    为了写起来更方便,也能够直接在src下建立一个叫jndi.properties的配置文件,这样就不用写一堆properties了

    这个配置文件内容例如以下:

    java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
    java.naming.factory.url.pkgs=org.jboss.naming rg.jnp.interfaces
    java.naming.provider.url=localhost:1099

    有了这个配置文件仅仅要写一句就能够了

    InitialContext ctx = new InitialContext();

    有了ctx后就能够将相应的jndi找到并转换成接口了
    例如以下,调用一个远程接口

    AccountServerRemote asl = (AccountServerRemote) ctx.lookup("AccountServer/remote");
    • jndi的数据库使用

    用实体bean来完毕对数据库的持久化操作.由于曾经用过hibernate在处理数据库的时候就自然想到了用hibernate.于是想法设法把hibernate往EJB里弄,忙活了一下午,最后无果而终,看了JPA之后才知道JPA採用的就是hibernate的实现…..

    ejb使用数据库第一步就是连接写一个*-ds.xml文件,这个能够在jboss文件夹下 ==jboss-5.1.0.GA/docs/examples/jca/== 找到,以下是一个msql-ds.xml的文件

    <?

    xml version="1.0" encoding="UTF-8"?> <!-- See http://www.jboss.org/community/wiki/Multiple1PC for information about local-tx-datasource --> <!-- $Id: mysql-ds.xml 88948 2009-05-15 14:09:08Z jesper.pedersen $ --> <!-- Datasource config for MySQL using 3.0.9 available from: http://www.mysql.com/downloads/api-jdbc-stable.html --> <datasources> <local-tx-datasource> <jndi-name>tomysql</jndi-name> <connection-url>jdbc:mysql://localhost:3306/USERS</connection-url> <driver-class>com.mysql.jdbc.Driver</driver-class> <user-name>javaTest</user-name> <password>123456</password> <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter</exception-sorter-class-name> <!-- should only be used on drivers after 3.22.1 with "ping" support <valid-connection-checker-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLValidConnectionChecker</valid-connection-checker-class-name> --> <!-- sql to call when connection is created <new-connection-sql>some arbitrary sql</new-connection-sql> --> <!-- sql to call on an existing pooled connection when it is obtained from pool - MySQLValidConnectionChecker is preferred for newer drivers <check-valid-connection-sql>some arbitrary sql</check-valid-connection-sql> --> <!-- corresponding type-mapping in the standardjbosscmp-jdbc.xml (optional) --> <metadata> <type-mapping>mySQL</type-mapping> </metadata> </local-tx-datasource> </datasources>

    改成自己的内容后,粘贴到==jboss-5.1.0.GA/server/default/deploy/==,
    同一时候要把相应的驱动放到==/jboss-5.1.0.GA/server/default/lib/==

    同一时候在项目文件夹META-INF下要新建一个persistence.xml的文件,
    内容例如以下:

    <?

    xml version="1.0" encoding="UTF-8"?> <persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0"> <persistence-unit name="ejbdb" transaction-type="JTA"> <jta-data-source>java:tomysql</jta-data-source> <properties> <property name="hibernate.hbm2ddl.auto" value="update"/> <property name="hibernate.show_sql" value="true"/> <property name="hibernate.format_sql" value="true"/> </properties> </persistence-unit> </persistence>

    能够看到,这里直接使用hibernate的配置就能够了…..
    注意一定要保证打包后persistence.xml在META-INF中….

    ejb里实体bean开发是使用注解的,基本上和hibernate一样,可是用一个叫 @PersistenceContext private EntityManager em;的东西进行操作(就像hibernate里的session),用相似与HQL用一种叫JPQL的东西查询…..

    • 消息bean
      一个点对点的消息bean

    首先须要新建一个叫*-service.xml的文件新建一个队列,
    文件内容例如以下:

    <?xml version="1.0" encoding="UTF-8"?>    
    <server>    
        <mbean code="org.jboss.mq.server.jmx.Queue"    
            name="jboss.mq.destination:service=Queue,name=myMDB">    
            <attribute name="JNDIName">queue/myMDB</attribute>    
            <depends optional-attribute-name="DestinationManager">    
                jboss.mq:service=DestinationManager    
            </depends>    
        </mbean>     
    </server>    

    新建一个叫做queue/myMDB的jndi

    发送一个消息:

    
            InitialContext ctx = new InitialContext();
    
            QueueConnectionFactory factory = (QueueConnectionFactory)ctx.lookup("ConnectionFactory");
            QueueConnection conn = factory.createQueueConnection();
            QueueSession session = conn.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);
            Destination destination = (Destination) ctx.lookup("queue/myMDB");
            MessageProducer producer = session.createProducer(destination);
    
            producer.send(session.createTextMessage(MSG));
    
            session.close();
            conn.close();

    接受一个消息:

    @MessageDriven
    (
            mappedName = "jms/MessageDriverBean", 
            activationConfig = 
            {
                    @ActivationConfigProperty
                    (propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
                    @ActivationConfigProperty
                    (propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
                    @ActivationConfigProperty
                    (propertyName = "destination" , propertyValue = "queue/myMDB")
            }
    )
    
    //重载的onmessage方法
    @Override
        public void onMessage(Message msg) {
            TextMessage tmsg = (TextMessage)msg;
            try {
                System.out.println(tmsg.getText());
    
               FileWriter fw = new FileWriter("/home/ckboss/桌面/Log.record", true); 
               fw.append(tmsg.getText());
               fw.close();
    
            } catch (JMSException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    • EJB工程的结构

    我也不知道EJB的正确姿势是什么样的…
    公布一个EJB后,其它的java项目能够通过Jndi找到相应的bean,可是须要在源代码中包括这个bean的接口.
    为了方便,以下的登陆应用放在了一个EJB中.

    一个登陆应用

    包括了一个实体bean和一个点对点的消息驱动bean,由client包调用,假设登陆成功会通过消息驱动bean发送一条消息,并被接受到记录一条记录

    文件结构

    ➜  EJB_LogIn  tree
    
    └── ejbModule
        ├── client
        │   ├── client1.java
        │   └── LogInClient.java
        ├── db
        │   ├── Account.java
        │   ├── AccountServer.java
        │   ├── AccountServerLocal.java
        │   └── AccountServerRemote.java
        ├── jndi.properties
        ├── META-INF
        │   ├── MANIFEST.MF
        │   └── persistence.xml
        └── msg
            ├── MessageDriverBean.java
            └── QueueSender.java
    
    14 directories, 32 files
    

    EJB_LogIn.zip下载1
    EJB_LogIn.zip下载2

  • 相关阅读:
    python学习-装饰器
    python-内置函数
    HA高可用解决方案-RHCS部署
    mac安装nose,command not found:nosetests
    iPhone的home键进果汁了,按起来粘粘的感觉
    Reportng 的测试报告在 Jenkins 中显示不全
    atom markdown报错:AssertionError: html-pdf: Failed to load PhantomJS module.
    markdown的图片外链
    reportng定制修改
    运行maven build报错No goals have been specified for this build.
  • 原文地址:https://www.cnblogs.com/mfmdaoyou/p/6813317.html
Copyright © 2011-2022 走看看