ejb一些杂的代码

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;

	@Override
	public 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 block
			e.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;

@Override public 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;

	@Override
	public void save(User user) {
		em.persist(user);
	}

	@Override
	public void update(User user) {
		em.merge(user);
	}

	@Override
	public void delete(Integer userid) {
		em.remove(em.getReference(User.class, userid));
	}

	@Override
	public User getUser(Integer userid) {

		return em.find(User.class, userid);
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<User> getAllUser() {
		return em.createQuery("select o from Person o").getResultList();
	}

	@Override
	public 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;

	@BeforeClass
	public 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");
	}

	@Test
	public 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);
	}

	@Test
	public void testUpdate() {
		fail("Not yet implemented");
	}

	@Test
	public void testDelete() {
		fail("Not yet implemented");
	}

	@Test
	public void testGetUser() {
		fail("Not yet implemented");
	}

	@Test
	public 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 {

	@Override
	public 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 {

	@Override
	public void onMessage(Message arg0) {
		TextMessage tMessage = (TextMessage) arg0;
		try {
			System.out.println(tMessage.getText());
		} catch (JMSException e) {
			// TODO Auto-generated catch block
			e.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;
	@Resource
	TimerService tService;

	@Override
	public void setScheduleTimer(long milliseconds) {
		if (count == 0) {
			count = 1;
			tService.createTimer(new Date(new Date().getTime() + milliseconds),
					milliseconds, "定时分发月饼器。");
		}
	}

	// 每隔指定的时间回调函数
	@Timeout
	public 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个













  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
EJB 3.0 项目的代码结构通常如下: ``` project-name │ ├── src/main/java │ │ │ ├── com.example.ejb │ │ ├── beans │ │ ├── dao │ │ ├── entities │ │ └── services │ │ │ ├── META-INF │ │ ├── persistence.xml │ │ └── ejb-jar.xml │ │ │ └── log4j.properties │ ├── src/test/java │ │ │ └── com.example.ejb │ ├── beans │ ├── dao │ ├── entities │ └── services │ ├── WebContent │ ├── META-INF │ │ └── MANIFEST.MF │ ├── WEB-INF │ │ ├── lib │ │ ├── classes │ │ └── web.xml │ └── index.jsp │ └── pom.xml ``` 1. `src/main/java`:EJB 模块的主要 Java 代码目录,包含 EJB 组件的实现。 2. `com.example.ejb`:Java 包名,与项目名称相关。 3. `com.example.ejb.beans`:Java 包名,包含所有 EJB 组件的实现。 4. `com.example.ejb.dao`:Java 包名,包含所有数据访问组件的实现。 5. `com.example.ejb.entities`:Java 包名,包含所有实体组件的实现。 6. `com.example.ejb.services`:Java 包名,包含所有业务逻辑组件的实现。 7. `META-INF`:EJB 模块的元数据目录。 8. `persistence.xml`:JPA 的配置文件,定义实体管理器工厂和数据源等。 9. `ejb-jar.xml`:EJB 的配置文件,定义 EJB 组件的相关属性和配置信息。 10. `log4j.properties`:日志配置文件,用于配置 EJB 组件的日志记录器。 11. `src/test/java`:EJB 模块的测试 Java 代码目录,用于编写测试用例。 12. `WebContent`:Web 应用程序部署目录。 13. `META-INF/MANIFEST.MF`:Web 应用程序的主清单文件。 14. `WEB-INF/lib`:Web 应用程序所需的 JAR 包目录。 15. `WEB-INF/classes`:Web 应用程序所需的类文件目录。 16. `WEB-INF/web.xml`:Web 应用程序的部署描述符文件。 17. `index.jsp`:Web 应用程序的首页文件。 18. `pom.xml`:Maven 项目构建文件,用于管理项目依赖和构建过程。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值