一、 把jboss里面的所有包导入到项目,创建接口,实现类。
1.接口类HelloWorld
publicinterface HelloWorld {
public String sayHello(Stringname);
}
2.实现类
/* @Stateful 说明这是一个有状态的会话bean
* @Stateless 说明这是一个无状态的会话bean
* @Remote(HelloWorld.class) 把接口指定为远程接口 如果没有写就是默认实现的本地接口
*/
@Stateless
@Remote(HelloWorld.class)
publicclass HelloWorldBeanimplementsHelloWorld {
public String sayHello(String name) {
return name+"说:你好,世界!";
}
}
二、 创建测试类EJBClient
设置jndi访问环境信息,两种方式,如下:
1. 硬编码设置参数
Properties props = new Properties();
props.setProperty("java.naming.factory.initial",
"org.jnp.interfaces.NamingContextFactory");
props.setProperty("java.naming.provider.url","localhost:1099");
try {
InitialContext ctx = new InitialContext(props);
//通过lookup寻找HelloWorldBean绑定的EJB代理存根对象
HelloWorld helloWorld = (HelloWorld)ctx.lookup("HelloWorldBean/remote");
System.out.println(helloWorld.sayHello("南昌"));
} catch (NamingException e) {
e.printStackTrace();
}
2. 通过新建一个jndi.properties设置参数
try {
InitialContext ctx =new InitialContext();
//通过lookup寻找HelloWorldBean绑定的EJB代理存根对象
HelloWorld helloWorld = (HelloWorld)ctx.lookup("HelloWorldBean/remote");
System.out.println(helloWorld.sayHello("南昌"));
} catch (NamingException e) {
e.printStackTrace();
}
三、 在项目底下新建ant的配置文件,build.xml
<?xml version="1.0"encoding="UTF-8" ?>
<!-- name属性是项目名,或者自定义 basedir属性是项目所在目录
.说明项目所在路径就在此xml文件的所在路径
..说明项目所在路径就在此xml文件的上级目录-->
<projectname="HelloWorld"basedir=".">
<!--说明项目源文件所在的目录 ${basedir}引用上面的属性值-->
<propertyname="src.dir"value="${basedir}\src"></property>
<!--此属性变量指向的是系统变量 -->
<propertyenvironment="env"></property>
<propertyname="jboss.home"value="${env.JBOSS_HOME}"></property>
<!--配置jboss的配项,默认的是用default-->
<propertyname="jboss.server.config"value="default"></property>
<!--编译源文件,class类存放的目录 -->
<propertyname="build.dir"value="${basedir}\build"></property>
<pathid="build.classpath">
<!--先定位到dir,然后包含dir目录下的所有jar文件-->
<filesetdir="${jboss.home}\client">
<includename="*.jar"/>
</fileset>
<pathelementlocation="${build.dir}"/>
</path>
<!--定义工作,name可以自己设置 mkdir创建目录 delete如果目录存在,删除目录-->
<targetname="prepare">
<deletedir="${build.dir}"/>
<mkdirdir="${build.dir}"/>
</target>
<!-- depends表示先执行prepare,然后再执行compile-->
<targetname="compile"depends="prepare"description="编译">
<javacsrcdir="${src.dir}"destdir="${build.dir}">
<compilerargline="-encoding GBK "/>
<classpathrefid="build.classpath"></classpath>
</javac>
</target>
<targetname="ejbjar"depends="compile"description="创建EJB发布包">
<jarjarfile="${basedir}\${ant.project.name}.jar">
<filesetdir="${build.dir}">
<includename="**/*.class"/>
</fileset>
</jar>
</target>
<targetname="deploy"depends="ejbjar"description="发布EJB">
<copyfile="${basedir}\${ant.project.name}.jar"todir="${jboss.home}\server\${jboss.server.config}\deploy"/>
</target>
<targetname="undeploy" description="卸载EJB">
<deletefile="${jboss_home}\server\${jboss.server.config}\deploy\${ant.project.name}.jar"/>
</target>
</project>
四、 通过注解的方式其他EJB或者服务
1. 创建一个新的接口 Other
publicinterface Other {
public String sayMe();
}
2. 创建一个接口实现类
@Stateless
publicclass OtherBeanimplements Other{
public String sayMe() {
return"other";
}
}
3. 在HelloWorldBean里面调用Other接口
@Stateless
@Remote(HelloWorld.class)
publicclass HelloWorldBeanimplements HelloWorld {
publicStringsayHello(String name) {
try {
InitialContext ctx = new InitialContext();
Other other = (Other)ctx.lookup("OtherBean/local");
return name+"说:你好,世界!"+other.sayMe();
} catch (NamingException e) {
e.printStackTrace();
}
returnnull;
}
}
4. 测试类里面EJBClient
publicclass EJBClient {
publicstaticvoidmain(String[]args) {
try {
InitialContext ctx = new InitialContext();
HelloWorld helloWorld = (HelloWorld)ctx.lookup("HelloWorldBean/remote");
System.out.println(helloWorld.sayHello("南昌"));
} catch (NamingException e) {
e.printStackTrace();
}
}
}
5. 或者用注入的方式:HelloWorldBean里面
@Stateless
@Remote(HelloWorld.class)
publicclass HelloWorldBeanimplements HelloWorld {
@EJBOther other;
publicStringsayHello(String name) {
return name+"说:你好,世界!"+other.sayMe();
}
}
6. 如果Other接口被多个EJB实现了,就必须指定需注入的EJB的名称,
EJB的名称默认的就是类名,也可以自定义,在@Stateless(name=”XXX”)
@EJB(beanName=”OtherBean”) Other other
Ps:@EJB注解只能够注入EJB。如果需要注入服务的话用@Resource,
同样,注入数据源也用@Resource(mappedName=””) DataSource dataSource
五、 配置数据源
一、 jBoss里面有模版,docs\examples\jca
mysql 就是mssql-ds.xml,修改里面的基本信息。
同时可以配置最高连接数和最小连接数如:
<min-pool-size>3</min-pool-size >
<max-pool-size>100</max-pool-size >
然后拷贝到server\default\deploy里面去
ps:所有数据源文件后面都必须带-ds结尾,也就是说,-ds结尾的文件会被jboss认为是数据源的配置文件,然后对他进行发布。
二、 把对应数据库的架包,比如说mysql,放进jBoss里面的server\default\lib里面去。然后重启jBoss
六、 开发单表映射的实体bean
1. 新建一个项目EntityBean,导入所有jboss里面的架包
2.新建一个META-INF文件夹,在此文件夹里面新建persistence.xml文件
<?xmlversion="1.0"encoding="UTF-8"?>
<persistencexmlns="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-unitname="crazy"transaction-type="JTA">
<jta-data-source>java:crazyDS</jta-data-sourc>
</persistence-unit>
</persistence>
Ps:其中的java:crazyDS就是前面配置的数据源的名称
2. 创建实体bean Person,创建所需的数据库,表。
@Entity
@Table(name="person")
publicclass Person implementsSerializable{
privatestaticfinallongserialVersionUID = -8070495794570698778L;
private Integerid;
private Stringpname;
public Person(){
}
public Person(String name) {
this.pname = name;
}
//auto 可以根据数据库的类型由持久化实现产品决定选用 IDENTITY SEQUENCETABLE三种中的一种
@Id@Column(name="id")@GeneratedValue(strategy=GenerationType.AUTO)
public Integer getId() {
returnid;
}
publicvoid setId(Integer id) {
this.id = id;
}
@Column(name="pname",length=20,nullable=false)
public String getPname() {
returnpname;
}
publicvoid setPname(String pname) {
this.pname = pname;
}
@Override
publicint hashCode() {
finalint prime = 31;
int result = 1;
result = prime * result + ((id ==null) ? 0 :id.hashCode());
return result;
}
@Override
publicboolean equals(Object obj) {
if (this == obj)
returntrue;
if (obj ==null)
returnfalse;
if (getClass() != obj.getClass())
returnfalse;
Person other = (Person) obj;
if (id ==null) {
if (other.id !=null)
returnfalse;
} elseif (!id.equals(other.id))
returnfalse;
returntrue;
}
}
3. 创建接口PersonService
publicinterface PersonService {
publicvoid save(Person person);
publicvoid update(Person person);
publicvoid delete(Integer personid);
public Person getPerson(Integer personid);
public List<Person> getPersons();
}
4. 创建接口实现类PersonServiceBean
@Stateless
@Remote(PersonService.class)
publicclassPersonServiceBeanimplements PersonService {
/*
* @PersistenceContext 注入实体管理器,指定持久化单元名称,对应的persistence.xml文件里面的name属性值
* 因为持久化单元可以为多个,所以必须指定,如果为一个的话,可以省略
* getReference 返回的是一个代理对象,只要还不访问方式对象的get方法的话,是不会发生数据的装载,只有调用了get属性方法的时候才会进行数据的状态,简单理解就是懒加载
* 简单来说就是相当于hibernate里面的load方法
* 如果数据库找不到相应的实体,这个方法会抛出javax.persistence.EntityNotFoundException。
*/
@PersistenceContext(unitName="crazy") EntityManagerem;
publicvoid delete(Integer personid) {
em.remove(em.getReference(Person.class, personid));
}
public Person getPerson(Integer personid) {
//如果在数据库里面没有找到的话,返回值就是null 相当于hibernate里面的get方法
returnem.find(Person.class, personid);
}
@SuppressWarnings("unchecked")
public List<Person> getPersons() {
returnem.createQuery("selecto from Person o").getResultList();
}
publicvoid save(Person person) {
em.persist(person);
}
publicvoid update(Person person) {
//person在游离状态下,对数据进行了修改,才调用merge方法,如果对象处于托管状态,对数据进行修改,只需调用set方法
em.merge(person);
}
}
5. 创建jndi.properties配置文件
6. 用JUNIT测试方法:
导入JUNIT的架包,右键PersonService选择NEW
然后再选择Junit Test Case
在对话框里面选择 Junit 4 test,修改报名junit.test
勾选setUpBeforeClass()
然后点next,勾选所有方法。点击finish
7. 第6部生成了PersonServiceTest文件
首先测试save方法:
publicclass PersonServiceTest {
privatestatic PersonServicepersonService;
@BeforeClass
publicstaticvoid setUpBeforeClass()throws Exception {
try {
InitialContext ctx = new InitialContext();
personService = (PersonService) ctx
.lookup("PersonServiceBean/remote");
} catch (Exception e) {
e.printStackTrace();
}
}
@Test
publicvoid testSave() {
personService.save(new Person("小明"));
}
@Test
publicvoid testUpdate() {
fail("Not yetimplemented");
}
@Test
publicvoid testDelete() {
fail("Not yetimplemented");
}
@Test
publicvoid testGetPerson() {
fail("Not yetimplemented");
}
@Test
publicvoid testGetPersons() {
fail("Not yetimplemented");
}
}
测试修改方法
publicvoid testUpdate() {
Person person = personService.getPerson(1);
person.setPname("小白");
personService.update(person);
}
测试删除方法
publicvoid testDelete() {
personService.delete(1);
}
测试查找方法
@Test
publicvoid testGetPerson() {
Person person = personService.getPerson(1);
System.out.println(person.getPname());
}
测试查找集合方法
@Test
publicvoid testGetPersons() {
List<Person> persons = personService.getPersons();
System.out.println(persons.size());
}
8.如果编写了bean运行之后自动创建表
在persistence.xml文件的<persistence-unit>标签里面添加
<properties>
<propertyname="hibernate.hbm2ddl.auto"value="create"/>
<!-- 在控制台打印出sql语句-->
<propertyname="hibernate.show_sql"value="true"/>
<!-- 在控制台标准化打印出sql语句-->
<propertyname="hibernate.format_sql"value="true"/>
</properties>
8. 如果在发布的时候出了错,也就是JUNIT没有打进jar包,
有两种方法解决:
第一种:如果你没有把jUnit的架包放进jboss里面的Client目录的话,
就会出现错误,所以添加进去;
第二种:过滤掉单元测试,编译的时候我们不编译单元测试类
在build.xml文件里面 修改编译动作
<targetname="compile"depends="prepare"description="编译">
<javacsrcdir="${src.dir}"destdir="${build.dir}" includes=”com/**”>
<classpathrefid="build.classpath"></classpath>
</javac>
</target>
主要是因为junit的文件夹为junit.test其他的都是以com开头。
七、 开发消息驱动bean
1. 创建一个xml文件,结尾必须为-service结尾放进jboss里面的server\default\deploy 目录下
如:crazy-service.xml
<?xmlversion="1.0" encoding="UTF-8" ?>
<server>
<mbeancode="org.jboss.mq.server.jmx.Queue"name="jboss.mq.destination:server=Queue,name=crazyQueue">
<attributename="JNDIName">queue/crazyQueue</attribute>
<dependsoptional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends>
</mbean>
</server>
Ps:红色的都是自定义的,JNDIName可以不写,不写的话就是默认的为queue/+mbean里面的那么名称
2. 新建项目MessageDrivenBean,导入所以jboss架包,
在源目录创建jndi.properties,配置以下信息。
3. 创建发送信息的类 QueueSender
publicclass QueueSender {
publicstaticvoid main(String[] args) {
try {
//得到jndi初始化上下文
InitialContext ctx = new InitialContext();
//根据上下文查找一个连接工厂QueueConnectionFactory该连接工厂有JMS提供。
QueueConnectionFactory factory =(QueueConnectionFactory)ctx.lookup("ConnectionFactory");
//从连接工厂得到一个连接
QueueConnection conn = factory.createQueueConnection();
//通过连接来建立一个会话session
QueueSession session = conn.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);
//查找目标地址
Destination destination = (Destination)ctx.lookup("queue/crazyQueue");
//根据会话和目标地址来创建消息的生产者
MessageProducer producer =session.createProducer(destination);
//调用消息发送者的send方法
producer.send(session.createTextMessage("你好,思远!"));
//关闭对应的资源
session.close();
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
4. 创建消息驱动bean MessageDrivenBean实现MessageListener接口
/*
* 通过注释可以指定消息驱动bean 监听的目标地址的类型destinationType
* 目标地址的JBDI名称是什么destination
* 并且还可以指定,当消息接收到之后,消息的确认模式是什么acknowledgeMode
* 当使用容器管理的时候默认的就是Auto-acknowledge,可以不写
*/
@MessageDriven(activationConfig=
{
@ActivationConfigProperty(propertyName="destinationType",
propertyValue="javax.jms.Queue"),
@ActivationConfigProperty(propertyName="destination",
propertyValue="queue/crazyQueue"),
@ActivationConfigProperty(propertyName="acknowledgeMode",
propertyValue="Auto-acknowledge")
})
publicclass MessageDrivenBeanimplements MessageListener {
publicvoid onMessage(Message message) {
//因为发送的消息类型为TextMessage类型
TextMessage msg = (TextMessage) message;
try {
System.out.println(msg.getText());
} catch (Exception e) {
e.printStackTrace();
}
}
}
5. 把build.xml文件复制到此项目中,发布。然后再QueueSender里面运行
控制台中就会打印出你好,思远!
6. Topic类型消息可以被多个接收方接受
创建TopicSender
publicclass TopicSender {
publicstaticvoid main(String[] args) {
try {
//得到jndi初始化上下文
InitialContext ctx = new InitialContext();
//根据上下文查找一个连接工厂QueueConnectionFactory该连接工厂有JMS提供。
TopicConnectionFactory factory =(TopicConnectionFactory)ctx.lookup("ConnectionFactory");
//从连接工厂得到一个连接
TopicConnection conn = factory.createTopicConnection();
//通过连接来建立一个会话session
TopicSession session = conn.createTopicSession(false, TopicSession.AUTO_ACKNOWLEDGE);
//查找目标地址
Destination destination = (Destination)ctx.lookup("topic/crazyTopic");
//根据会话和目标地址来创建消息的生产者
MessageProducer producer =session.createProducer(destination);
//调用消息发送者的send方法
producer.send(session.createTextMessage("你好,思远!"));
//关闭对应的资源
session.close();
conn.close();
System.out.println("消息发送完成");
} catch (Exception e) {
e.printStackTrace();
}
}
}
创建两个消息驱动bean
@MessageDriven(activationConfig=
{
@ActivationConfigProperty(propertyName="destinationType",
propertyValue="javax.jms.Topic"),
@ActivationConfigProperty(propertyName="destination",
propertyValue="topic/crazyTopic")
})
publicclass ReceiveOtherBeanimplements MessageListener {
publicvoid onMessage(Message message) {
TextMessage msg = (TextMessage) message;
try {
System.out.println(msg.getText()+this.getClass());
} catch (Exception e) {
e.printStackTrace();
}
}
}
第二个
@MessageDriven(activationConfig=
{
@ActivationConfigProperty(propertyName="destinationType",
propertyValue="javax.jms.Topic"),
@ActivationConfigProperty(propertyName="destination",
propertyValue="topic/crazyTopic")
})
publicclass ReceiveBeanimplements MessageListener {
publicvoid onMessage(Message message) {
TextMessage msg = (TextMessage) message;
try {
System.out.println(msg.getText()+this.getClass());
} catch (Exception e) {
e.printStackTrace();
}
}
}
八、 开发EJB模型的Web服务
详细见:http://blog.csdn.net/itm_hadf/article/details/7687797