ejb一些杂的代码

来源:互联网 发布:golang程序员工资 编辑:程序博客网 时间:2024/06/07 17:09

sessionbean

(一)无状态SessionBean(Statless)

(1) 无状态Session Bean单个方法调用就能完成一个完整的业务流程

(2) 无状态Session是可以被重用,不能被客户端并发共享,只可以串行共享,并不保留客户端方法调用后的的状态,而是直接返回。

(3) 无状态的SessionBean是可以池化的(pooling),以优化性能,用以被多个客户共享。

无状态SessionBean的生命周期

如果实例不存在,就会调用构造方法,然后调用资源注入方法,接着会调用有@PostConstruct标注的方法,在销毁时会调用有@PerDestroy标注的方法,

然后销毁对象,如果实例存在就会从Bean实例池中取出实例并调用方法(而不是重新生成实例)。回调方法是基于事件机制的。

接口:

package senssic.ejb.bean;public interface StatlessSession {public void doSomething();}

实现:

package senssic.ejb.bean.impl;import javax.annotation.PostConstruct;import javax.ejb.Remote;import javax.ejb.Stateless;import javax.persistence.PostRemove;import senssic.ejb.bean.StatlessSession;@Stateless@Remote(StatlessSession.class)public class SLSession implements StatlessSession {private int num = 0;@Overridepublic void doSomething() {System.out.println("说说说说,说我爱你,说了:" + num + "次");num++;}@PostConstruct// 创建实例自动被调用的方法public void beforStart() {System.out.println("今天中秋哦,我被实例化了呀");}@PostRemove// 销毁对象时回调此函数public void afterDestory() {System.out.println("连月饼都没有,我被销毁了");}}

打包jar部署到jboss的相应目录下

客户端:

package senssic.test;import java.util.Properties;import javax.naming.InitialContext;import javax.naming.NamingException;import senssic.ejb.bean.StatlessSession;public class Client {public static void main(String[] args) {Properties p = new Properties();p.setProperty("java.naming.factory.initial","org.jnp.interfaces.NamingContextFactory");p.setProperty("java.naming.provider.url", "localhost:1099");try {InitialContext cxt = new InitialContext(p);StatlessSession slSession = (StatlessSession) cxt.lookup("SLSession/remote");slSession.doSomething();// 获取第二份无状态bean通过打印的num可以判定只实例化一次被容器放入池中,多个客户端共享一个实例InitialContext cxt2 = new InitialContext(p);StatlessSession slSession2 = (StatlessSession) cxt2.lookup("SLSession/remote");slSession2.doSomething();} catch (NamingException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}

打印结果:

11:45:26,453 INFO  [STDOUT] 今天中秋哦,我被实例化了呀


11:45:26,484 INFO  [STDOUT] 说说说说,说我爱你,说了:0次


11:45:26,531 INFO  [STDOUT] 说说说说,说我爱你,说了:1次

(二)有状态的SessionBean(Statful)

有状态的SessionBean只为一个客户端服务,不能共享,并且会保留方法调用后的状态。

  (1) 多个方法调用才能完成一个业务处理流程;

  (2) 需要保留客户端的状态

  (3) 不被多个客户共享。

当有状态的SessionBean暂时不被使用时,就会被存储到缓存当中,也就是被存到虚拟内存或者是将信息同步到Session数据��库是应用服务器所提共的小型数据库,用来保存Session的信息,多应用服务器共享Session数据库,同步Bean的信息,达到集群处理)。

实现类的@Stateless改为@Stateful就行了运行结果:

12:13:36,203 INFO  [STDOUT] 今天中秋哦,我被实例化了呀
12:13:36,546 INFO  [STDOUT] 说说说说,说我爱你,说了:0次
12:13:36,578 INFO  [STDOUT] 今天中秋哦,我被实例化了呀
12:13:36,609 INFO  [STDOUT] 说说说说,说我爱你,说了:0次

由此可见有状态会话bean每次调用时候容器都会实例化一个新的,就是每个客户端对应一个会话bean

注意:对有状态的SessionBean中有transient属性时,就需要在Bean中提供激活的方法

代码:

package senssic.ejb.bean.impl;import javax.annotation.PostConstruct;import javax.ejb.PostActivate;import javax.ejb.Remote;import javax.ejb.Stateful;import javax.persistence.PostRemove;import senssic.ejb.bean.StatlessSession;@Stateful@Remote(StatlessSession.class)public class SLSession implements StatlessSession {private int num = 0;

transient private String str;

@Overridepublic void doSomething() {System.out.println("说说说说,说我爱你,说了:" + num + "次!" + "transient属性:" + str);num++;}@PostConstruct// 创建实例自动被调用的方法public void beforStart() {System.out.println("今天中秋哦,我被实例化了呀");}@PostRemove// 销毁对象时回调此函数public void afterDestory() {System.out.println("连月饼都没有,我被销毁了");}@PostActivate// 使用transient属性时侯使用此注解调用此方法激活public void activate() {str = "我是transient属性因为不能被序列化,所以每次自动调用此方法实例化我";}}

实体bean

实体beanuser:

package senssic.ejb.bean;import javax.persistence.CascadeType;import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.GenerationType;import javax.persistence.Id;import javax.persistence.JoinColumn;import javax.persistence.ManyToOne;import javax.persistence.Table;/** * 用户实体 *  * @author Senssic@163.com *  */@Entity@Table(name = "US")public class User {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)@Column(length = 35, name = "US_num")private int num;@Column(length = 35, nullable = false, unique = true, name = "US_name")private String username;@Column(length = 35, nullable = false, name = "US_password")private String password;@Column(length = 45, nullable = false, name = "US_email")private String email;@Column(length = 20, name = "US_relname")private String relname;@Column(length = 35, name = "US_department")private String department;@Column(length = 60, name = "US_address")private String address;@Column(length = 10, name = "US_postcode")private int postcode;@Column(length = 35, name = "US_phone")private String phone;@ManyToOne(cascade = CascadeType.REFRESH)@JoinColumn(name = "AU_num", nullable = false)private Privilege au_num;public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public String getEmail() {return email;}public void setEmail(String email) {this.email = email;}public int getNum() {return num;}public void setNum(int num) {this.num = num;}public String getRelname() {return relname;}public void setRelname(String relname) {this.relname = relname;}public String getDepartment() {return department;}public void setDepartment(String department) {this.department = department;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}public int getPostcode() {return postcode;}public void setPostcode(int postcode) {this.postcode = postcode;}public String getPhone() {return phone;}public void setPhone(String phone) {this.phone = phone;}public Privilege getAu_num() {return au_num;}public void setAu_num(Privilege au_num) {this.au_num = au_num;}}
实体beanprivilege:
package webwork.senssic.bean.base;import java.util.Set;import javax.persistence.CascadeType;import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.GenerationType;import javax.persistence.Id;import javax.persistence.OneToMany;import javax.persistence.Table;@Entity@Table(name = "AU")public class Privilege {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)@Column(length = 35, name = "AU_num")private int num;@Column(length = 35, nullable = false, name = "AU_name")private String name;@Column(length = 50, nullable = false, name = "AU_info")private String info;@OneToMany(mappedBy = "au_num", cascade = CascadeType.ALL)private Set<User> users;public Set<User> getUsers() {return users;}public void setUsers(Set<User> users) {this.users = users;}public int getNum() {return num;}public void setNum(int num) {this.num = num;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getInfo() {return info;}public void setInfo(String info) {this.info = info;}}
会话bean
接口:
package senssic.ejb.bean;import java.util.List;public interface Manager {public void save(User user);public void update(User user);public void delete(Integer userid);public User getUser(Integer userid);public List<User> getAllUser();public Privilege getPri(Integer pid);}
实现:
package senssic.ejb.bean.impl;import java.util.List;import javax.ejb.Remote;import javax.ejb.Stateless;import javax.persistence.EntityManager;import javax.persistence.PersistenceContext;import senssic.ejb.bean.Manager;import senssic.ejb.bean.Privilege;import senssic.ejb.bean.User;@Stateless@Remote(Manager.class)public class ManagrImpl implements Manager {// 指定持久化单元的名字,如果只有一个可以不做修改,容器已实例化好,注入即可@PersistenceContext(unitName = "senssic")EntityManager em;@Overridepublic void save(User user) {em.persist(user);}@Overridepublic void update(User user) {em.merge(user);}@Overridepublic void delete(Integer userid) {em.remove(em.getReference(User.class, userid));}@Overridepublic User getUser(Integer userid) {return em.find(User.class, userid);}@SuppressWarnings("unchecked")@Overridepublic List<User> getAllUser() {return em.createQuery("select o from Person o").getResultList();}@Overridepublic Privilege getPri(Integer pid) {return em.find(Privilege.class, pid);}}
persistence.xml
<?xml version="1.0"?><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="senssic" transaction-type="JTA"><jta-data-source>java:senssicDS</jta-data-source></persistence-unit></persistence>
mysql-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 97536 2009-12-08 14:05:07Z 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>senssicDS</jndi-name>    <connection-url>jdbc:mysql://localhost:3306/senssic</connection-url>    <driver-class>com.mysql.jdbc.Driver</driver-class>    <user-name>root</user-name>    <password>qiyu0126</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>
测试类:
package senssic.ejb.bean;import static org.junit.Assert.fail;import java.util.Properties;import java.util.Random;import javax.naming.InitialContext;import org.junit.BeforeClass;import org.junit.Test;public class ManagerTest {private static Manager manager;@BeforeClasspublic static void setUpBeforeClass() throws Exception {Properties p = new Properties();p.setProperty("java.naming.factory.initial","org.jnp.interfaces.NamingContextFactory");p.setProperty("java.naming.provider.url", "localhost:1099");InitialContext cxt = new InitialContext(p);manager = (Manager) cxt.lookup("ManagrImpl/remote");}@Testpublic void testSave() {User user = new User();Privilege privilege = manager.getPri(1);user.setUsername("煜");user.setEmail("43349267@qq.com");user.setPassword("qiyu");user.setAddress("安徽池州---池州学院");user.setDepartment("池州学院数学系部门");user.setPhone("1325946667");user.setPostcode(1 + new Random().nextInt(10) + 396);user.setRelname("qiyuyu" + new Random().nextInt(100));user.setAu_num(privilege);manager.save(user);}@Testpublic void testUpdate() {fail("Not yet implemented");}@Testpublic void testDelete() {fail("Not yet implemented");}@Testpublic void testGetUser() {fail("Not yet implemented");}@Testpublic void testGetAllUser() {fail("Not yet implemented");}}

jms消息bean

一条消息有三部分组成,头,属性,主体,消息有以下几种类型,都是派生自Message接口
StreamMessage:一种主体中包含java基元流的消息。其填充和读取均按顺序进行
MapMessage:一种主体中包含一组名-值对的消息,没有定义条目顺序
TextMessage:一种主体中包含java字符串的消息,例如xml消息
ObjectMessage:一种主体中包含序列化java对象的消息
BytesMessage:一种主体中包含连续字节流的消息

Point-to-Point(PTP)点对点模型

① 消息服务器上用Queue队列来存放消息

② 允许多个消息的生产者发送消息到Queue,但是消息只允许一个消息消费者消费。一旦消息被消费,MOM会把消息从Queue中删除。

修改server\default\deploy\hornetq\hornetq-jms.xml文件添加如下代码:注:因为使用的是6.0的和5.0的配置不一样

       <queue name="senssic">      <entry name="/queue/senssic"/>   </queue>
发送端:
package senssic.mq;import java.util.Properties;import javax.jms.Queue;import javax.jms.QueueConnection;import javax.jms.QueueConnectionFactory;import javax.jms.QueueSender;import javax.jms.QueueSession;import javax.jms.TextMessage;import javax.naming.InitialContext;public class PtoPTo {public static void main(String[] args) {Properties p = new Properties();p.setProperty("java.naming.factory.initial","org.jnp.interfaces.NamingContextFactory");p.setProperty("java.naming.provider.url", "localhost:1099");try {InitialContext cxt = new InitialContext(p);QueueConnectionFactory qFactory = (QueueConnectionFactory) cxt.lookup("ConnectionFactory");//此处的QueueConnectionFactory为全局的jndi名称,不能随意更改由jms的各个实现厂商默认提供QueueConnection connection = qFactory.createQueueConnection();QueueSession qSession = connection.createQueueSession(false,QueueSession.AUTO_ACKNOWLEDGE);Queue queue = (Queue) cxt.lookup("queue/senssic");TextMessage msg = qSession.createTextMessage("今年的中秋节没有月饼吃,艹");QueueSender sender = qSession.createSender(queue);sender.send(msg);qSession.close();connection.close();System.out.println("月饼已发送。");} catch (Exception e) {e.printStackTrace();}}}

接受监听结果:
package senssic.mq;import javax.ejb.ActivationConfigProperty;import javax.ejb.MessageDriven;import javax.jms.JMSException;import javax.jms.Message;import javax.jms.MessageListener;import javax.jms.TextMessage;@MessageDriven(activationConfig = {@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),@ActivationConfigProperty(propertyName = "destination", propertyValue = "queue/senssic"),@ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge") })public class PtoPFrom implements MessageListener {@Overridepublic void onMessage(Message arg0) {TextMessage textMessage = (TextMessage) arg0;try {System.out.println(textMessage.getText());} catch (JMSException e) {e.printStackTrace();}}}

部署运行后结果:
20:55:43,843 INFO  [org.jboss.ejb3.proxy.impl.jndiregistrar.JndiSessionRegistrarBase] Binding the following Entries in Global JNDI:


SLSession/remote - EJB3.x Default Remote Business Interface
SLSession/remote-senssic.ejb.bean.StatlessSession - EJB3.x Remote Business Interface


20:56:01,968 INFO  [STDOUT] 今年的中秋节没有月饼吃,艹

Publish/Subscribe(pub/sub) 发布/订阅模型

 ① 用Topic存放消息

 ② 允许有多个生产者和消费者,同一个消息可被多个消费者消费,且在Topic中不会因消费而删除。

在同样的配置文件下配置如下:

       <topic name="qiyu">      <entry name="/topic/qiyu"/>   </topic>
发送端:

package senssic.mq;import java.util.Properties;import javax.jms.TextMessage;import javax.jms.Topic;import javax.jms.TopicConnection;import javax.jms.TopicConnectionFactory;import javax.jms.TopicPublisher;import javax.jms.TopicSession;import javax.naming.InitialContext;public class TopicTo {public static void main(String[] args) {Properties p = new Properties();p.setProperty("java.naming.factory.initial","org.jnp.interfaces.NamingContextFactory");p.setProperty("java.naming.provider.url", "localhost:1099");try {InitialContext cxt = new InitialContext(p);TopicConnectionFactory tFactory = (TopicConnectionFactory) cxt.lookup("ConnectionFactory");TopicConnection connection = tFactory.createTopicConnection();TopicSession tSession = connection.createTopicSession(false,TopicSession.AUTO_ACKNOWLEDGE);Topic topic = (Topic) cxt.lookup("topic/qiyu");TextMessage msg = tSession.createTextMessage("今年的中秋节没有月饼吃,那我就群发月饼………………");TopicPublisher tPublisher = tSession.createPublisher(topic);tPublisher.send(msg);tSession.close();connection.close();System.out.println("月饼已分发。");} catch (Exception e) {e.printStackTrace();}}}

接受端监听结果(可以有多个监听接受):

package senssic.mq;import javax.ejb.ActivationConfigProperty;import javax.ejb.MessageDriven;import javax.jms.JMSException;import javax.jms.Message;import javax.jms.MessageListener;import javax.jms.TextMessage;@MessageDriven(activationConfig = {@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Topic"),@ActivationConfigProperty(propertyName = "destination", propertyValue = "topic/qiyu"),@ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge") })public class TopicFrom implements MessageListener {@Overridepublic void onMessage(Message arg0) {TextMessage tMessage = (TextMessage) arg0;try {System.out.println(tMessage.getText());} catch (JMSException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}

ejb定时服务

定时器接口:

package senssic.ejb.time;public interface MyTimer {public void setScheduleTimer(long milliseconds);}
定时器实现:

package senssic.ejb.time;import java.util.Date;import javax.annotation.Resource;import javax.ejb.Remote;import javax.ejb.Stateless;import javax.ejb.Timeout;import javax.ejb.Timer;import javax.ejb.TimerService;@Stateless@Remote(MyTimer.class)public class MyTimerBean implements MyTimer {private static int count = 0;@ResourceTimerService tService;@Overridepublic void setScheduleTimer(long milliseconds) {if (count == 0) {count = 1;tService.createTimer(new Date(new Date().getTime() + milliseconds),milliseconds, "定时分发月饼器。");}}// 每隔指定的时间回调函数@Timeoutpublic void timerout(Timer timer) {System.out.println("-----发了第" + count + "个月饼了------");System.out.println("定时发月饼事件发生传递的月饼为:" + timer.getInfo());if (count > 100) {System.out.println("月饼分发完毕了,亲记得明年早点来哦!");timer.cancel();count = 0;} else {System.out.println("恭喜还有月饼,月饼剩余:" + (100-count) + "个");count++;}}}

测试类:

package senssic.ejb.time;import java.util.Properties;import javax.naming.InitialContext;public class MyTimeTest {/** * @param args */public static void main(String[] args) {Properties p = new Properties();p.setProperty("java.naming.factory.initial","org.jnp.interfaces.NamingContextFactory");p.setProperty("java.naming.provider.url", "localhost:1099");try {InitialContext cxt = new InitialContext(p);MyTimer mTimer = (MyTimer) cxt.lookup("MyTimerBean/remote");mTimer.setScheduleTimer(1000);} catch (Exception e) {e.printStackTrace();}}}
打印结果:

21:49:56,968 WARN  [org.jboss.ejb3.TimerServiceContainer] EJBTHREE-2193: using deprecated TimerServiceFactory for restoring timers
21:50:16,781 INFO  [STDOUT] -----发了第1个月饼了------


21:50:16,781 INFO  [STDOUT] 定时发月饼事件发生传递的月饼为:定时分发月饼器。


21:50:16,812 INFO  [STDOUT] 恭喜还有月饼,月饼剩余:99个


21:50:17,765 INFO  [STDOUT] -----发了第2个月饼了------


21:50:17,765 INFO  [STDOUT] 定时发月饼事件发生传递的月饼为:定时分发月饼器。


21:50:17,765 INFO  [STDOUT] 恭喜还有月饼,月饼剩余:98个


21:50:18,750 INFO  [STDOUT] -----发了第3个月饼了------


21:50:18,750 INFO  [STDOUT] 定时发月饼事件发生传递的月饼为:定时分发月饼器。


21:50:18,750 INFO  [STDOUT] 恭喜还有月饼,月饼剩余:97个


21:50:19,765 INFO  [STDOUT] -----发了第4个月饼了------


21:50:19,765 INFO  [STDOUT] 定时发月饼事件发生传递的月饼为:定时分发月饼器。


21:50:19,765 INFO  [STDOUT] 恭喜还有月饼,月饼剩余:96个


21:50:20,765 INFO  [STDOUT] -----发了第5个月饼了------


21:50:20,765 INFO  [STDOUT] 定时发月饼事件发生传递的月饼为:定时分发月饼器。


21:50:20,765 INFO  [STDOUT] 恭喜还有月饼,月饼剩余:95个


21:50:21,750 INFO  [STDOUT] -----发了第6个月饼了------


21:50:21,750 INFO  [STDOUT] 定时发月饼事件发生传递的月饼为:定时分发月饼器。


21:50:21,750 INFO  [STDOUT] 恭喜还有月饼,月饼剩余:94个


21:50:22,765 INFO  [STDOUT] -----发了第7个月饼了------


21:50:22,765 INFO  [STDOUT] 定时发月饼事件发生传递的月饼为:定时分发月饼器。


21:50:22,765 INFO  [STDOUT] 恭喜还有月饼,月饼剩余:93个


21:50:23,781 INFO  [STDOUT] -----发了第8个月饼了------


21:50:23,781 INFO  [STDOUT] 定时发月饼事件发生传递的月饼为:定时分发月饼器。


21:50:23,781 INFO  [STDOUT] 恭喜还有月饼,月饼剩余:92个


21:50:24,781 INFO  [STDOUT] -----发了第9个月饼了------


21:50:24,781 INFO  [STDOUT] 定时发月饼事件发生传递的月饼为:定时分发月饼器。


21:50:24,781 INFO  [STDOUT] 恭喜还有月饼,月饼剩余:91个


21:50:25,781 INFO  [STDOUT] -----发了第10个月饼了------


21:50:25,781 INFO  [STDOUT] 定时发月饼事件发生传递的月饼为:定时分发月饼器。


21:50:25,781 INFO  [STDOUT] 恭喜还有月饼,月饼剩余:90个


21:50:26,781 INFO  [STDOUT] -----发了第11个月饼了------


21:50:26,781 INFO  [STDOUT] 定时发月饼事件发生传递的月饼为:定时分发月饼器。


21:50:26,781 INFO  [STDOUT] 恭喜还有月饼,月饼剩余:89个


21:50:27,781 INFO  [STDOUT] -----发了第12个月饼了------


21:50:27,781 INFO  [STDOUT] 定时发月饼事件发生传递的月饼为:定时分发月饼器。


21:50:27,781 INFO  [STDOUT] 恭喜还有月饼,月饼剩余:88个