花了几天的时间研究了一下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

一个基于JBoss5.1+EJB3.0 登陆应用的更多相关文章

  1. 一个基于 .NET Core 2.0 开发的简单易用的快速开发框架 - LinFx

    LinFx 一个基于 .NET Core 2.0 开发的简单易用的快速开发框架,遵循领域驱动设计(DDD)规范约束,提供实现事件驱动.事件回溯.响应式等特性的基础设施.让开发者享受到正真意义的面向对象 ...

  2. 分享一个基于 ABP(.NET 5.0) + vue-element-admin 管理后台

    1.前言 分享一个基于ABP(.NET 5.0) + vue-element-admin项目.希望可以降低新手对于ABP框架的学习成本,感兴趣的同学可以下载项目启动运行一下.对于想选型采用ABP框架的 ...

  3. 一个基于thinkphp的微信授权登陆功能

    共享一份基于thinkphp开发的用户授权登陆的功能代码,本实例使用thinkphp的第三方微信公众平台PHP-SDK,地址https://github.com/dodgepudding/wechat ...

  4. 基于Server-Sent Event的简单聊天室 Web 2.0时代,即时通信已经成为必不可少的网站功能,那实现Web即时通信的机制有哪些呢?在这门项目课中我们将一一介绍。最后我们将会实现一个基于Server-Sent Event和Flask简单的在线聊天室。

    基于Server-Sent Event的简单聊天室 Web 2.0时代,即时通信已经成为必不可少的网站功能,那实现Web即时通信的机制有哪些呢?在这门项目课中我们将一一介绍.最后我们将会实现一个基于S ...

  5. 用VSCode开发一个基于asp.net core 2.0/sql server linux(docker)/ng5/bs4的项目(1)

    最近使用vscode比较多. 学习了一下如何在mac上使用vscode开发asp.netcore项目. 这里是我写的关于vscode的一篇文章: https://www.cnblogs.com/cgz ...

  6. Asp.Net Core 2.0 项目实战(2)NCMVC一个基于Net Core2.0搭建的角色权限管理开发框架

    Asp.Net Core 2.0 项目实战(1) NCMVC开源下载了 Asp.Net Core 2.0 项目实战(2)NCMVC一个基于Net Core2.0搭建的角色权限管理开发框架 Asp.Ne ...

  7. 一个基于Net Core3.0的WPF框架Hello World实例

    目录 一个基于Net Core3.0的WPF框架Hello World实例 1.创建WPF解决方案 1.1 创建Net Core版本的WPF工程 1.2 指定项目名称,路径,解决方案名称 2. 依赖库 ...

  8. 痞子衡嵌入式:kFlashFile v1.0 - 一个基于Flash的掉电数据存取方案

    大家好,我是痞子衡,是正经搞技术的痞子.今天给大家带来的是痞子衡的个人小项目 - kFlashFile. 痞子衡最近在参与一个基于 i.MXRT1170 的项目,项目有个需求,需要在 Flash 里实 ...

  9. 开源低代码平台开发实践二:从 0 构建一个基于 ER 图的低代码后端

    前后端分离了! 第一次知道这个事情的时候,内心是困惑的. 前端都出去搞 SPA,SEO 们同意吗? 后来,SSR 来了. 他说:"SEO 们同意了!" 任何人的反对,都没用了,时代 ...

随机推荐

  1. this.$Message.success('提示信息') 少写了一个c 导致报错

    this.$Message.success('提示信息') 少写了一个c 导致报错 而且 $Message 输出还没显示,导致我以为是没有 $Message 对象了,其实全局对象直接调用即可

  2. PHP 中空字符串介绍0、null、empty和false之间的关系

    0是数字,是empty,是false,不是null,值相当于空字符串,但类型不是字符串,去空格或强制转换为字符串型时不等于空字符串 ""的值相当于0,是empty,是空字符串,是f ...

  3. luogu P1364 医院设置

    题目描述 设有一棵二叉树,如图: 其中,圈中的数字表示结点中居民的人口.圈边上数字表示结点编号,现在要求在某个结点上建立一个医院,使所有居民所走的路程之和为最小,同时约定,相邻接点之间的距离为1.如上 ...

  4. redis:哨兵集群配置

    最少配置1主2从3哨兵 一.引言 上一篇文章我们详细的讲解了Redis的主从集群模式,其实这个集群模式配置很简单,只需要在Slave的节点上进行配置,Master主节点的配置不需要做任何更改,但是有一 ...

  5. 如何用 CSS 创作一个立体滑动 toggle 交互控件

    效果预览 在线演示 按下右侧的"点击预览"按钮在当前页面预览,点击链接全屏预览. https://codepen.io/zhang-ou/pen/zjoOgX 可交互视频教程 此视 ...

  6. 高可用技术之keepalived原理简单了解

    Keepalived 工作原理 keepalived是以VRRP协议为实现基础的,VRRP全称Virtual Router Redundancy Protocol,即虚拟路由冗余协议. 虚拟路由冗余协 ...

  7. (二十)python 3 匿名函数

    匿名函数lambda Python使用lambda关键字创造匿名函数.所谓匿名,意即不再使用def语句这样标准的形式定义一个函数.这种语句的目的是由于性能的原因,在调用时绕过函数的栈分配.其语法是: ...

  8. 在Ubuntu 16.04 LTS上用g++和gcc编译C/C++代码错误提示“.../x86_64-linux-gnu/crt1.o: ELF section name out of range”

    (有一些图片我是直接从个人的CSDN博客上复制来的) 最近一个多月来,我曾经多次尝试在Ubuntu 16.04 LTS上使用g++和gcc(这俩好像合起来叫MinGW?)来编译C/C++代码,但是在解 ...

  9. python025 Python3 正则表达式

    Python3 正则表达式 正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配. Python 自1.5版本起增加了re 模块,它提供 Perl 风格的正则表达式模式. ...

  10. Leetcode 236.二叉树的最近公共祖先

    二叉树的最近公共祖先 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先. 百度百科中最近公共祖先的定义为:"对于有根树 T 的两个结点 p.q,最近公共祖先表示为一个结点 x,满足 x ...