tarena学习EJB笔记

EJB day1 Wednesday 2007.3.28
Enterprise JavaBeans
写EJB项目步骤:
1.建立EJB项目的路径。
2.设置CLASSPATH(类路径):
 EJB目录/lib/javaee.jar //编译时
 EJB目录/lib/appserv-rt.jar //运行时
 如:liunx下配置
 export CLASSPATH=.:opt/EJB/lib/javaee.jar:opt/EJB/lib/appserv-rt.jar:$CLASSPATH
3.写bean类,需要暴露的接口:Remote,Local
 必须要有接口与实现类;远程通过接口中暴露的方法,向服务器发起调用,用服务器调用具体的实现类
 public interface BeanRemote{
  String m1(String v);
  }
  //只在服务器端有
  //无状态模式
 @Stateless
 @Remote(BeanRemote.class)
 public Bean implements BeanRemote{
  String m1(String v){
   //方法实现的代码
  };
 }
4.编译bean类。
5.打成jar包
6.部署到服务器上
7.(可选)写一个测试类测试
 public class BeanTest {   
    public BeanTest() {}
    public static void main(String[] args) throws NamingException {
      //设置远程访问的IP地址
        System.setProperty("org.omg.CORBA.ORBInitialHost","192.168.12.41");
        InitialContext context=new InitialContext();
   //在上下文中查询
        BeanRemote beanRemote=(BeanRemote) context.lookup(BeanRemote.class.getName());
        //调用BeanRemote的方法
    String s=beanRemote.m1("abc");
    }   
}
==============================================================================================


EJB day2 Thursday 2007.3.29

1.Stateless Session Bean
 特点:存入Bean pool,无成员属性保存数据
 Stateful Session Bean
 特点:存入cache中,成员属性保存数据,只供各自客户端使用

2.Lifecycle of Session Bean(生命周期)
 ------------------------------------------------
 Stateless and Stateful 注释
 @Stateless :声明该Session Bean是无状态的
 @Stateful :声明该Session Bean是有状态的
 
 *写这些注释的方法的标准:public void method()  //只有method可自己命名
 @PostConstruct :在Session Bean创建后,调用该方法
 @PreDestroy :在Session Bean销毁前,调用该方法
 @Remove :(Stateless 中无用)接口中暴露该方法,由客户端主动调用该方法,调用后会销毁Session Bean,销毁前会调用@PreDestroy(有则调用)
 
 Stateful 注释
 @PrePassivate :内存cache中Session Bean被用完时,回根据配置的策略选一个Session Bean存到磁盘中(叫遁化)前调用该方法
 @PostActivate :从磁盘中取回数据到内存cache中后,调用该方法
 
 三中策略:
 LRU:最近最少使用策略
 FIFO:先进先出策略
 NRU:(Not Recently Used)这种近似LRU算法,已经退化成一种"最近不用"的算法
 
3.NetBeans 5.5使用
 一般端口设置:
  Admin port:4848
  Domain Http port:8080
  ORB Listener Port:3700
  HTTPS port 8181
 
 用NetBeans写EJB
 选择新建项目:企业(Enterprise)->企业应用(EnterpriseApplication)[选择创建EJB模块,客户段模块]
 在EJB模块->源包(Source)中建一个会话bean(Session bean)
 1).//远程借口类session class
  @Remote
  public interface CountRemote{
   int count();
   @Remove
   void remove();
  }
 2).//接口实现类session class
  @Stateful
  //如果使用拦截器,需要在这里配置,拦截器的类
  @Interceptors({CountInterceptor.class})
  public class CountBean implements CountRemote{
   private int val;
   public int count(){//实现代码};
   
   @Remove
   public void remove(){//实现代码};
   
   /*
   //如果拦截器中有了该方法就不用写在该类中了
   @Postconstruct
   public void construct(){//实现代码};
   */
  }
 3).//拦截器(可选)java class
  public class CountInterceptor{
   @PostConstruct
   public void construct(){//实现代码};
   @preDestroy
   public void destroy(){//实现代码};
   @PrePassivate
   public void passivate(){//实现代码};
   @PostActivate
   public void activate(){//实现代码};
  }
  
 4).//测试类(可选) java main
  创建Enterprise Applicaton Client(不通用,只有sun公司提供),提供了EJB运行环境容器
 public class CountTest {
  //创建EJB Session bean
  //注入的方式创建bean,提供了运行环境容器
    @EJB
    private static CountRemote countRemote;   
    public CountTest() {
    }
    public static void main(String[] args) {
    //可以直接使用,不关心如何获得
      int i=countRemote.count();
      countRemote.remove();
      }   
  }
 5.//配置EJB配置文件下的sun-ejb-jar.xml
  Bean pool:(Stateless)
  稳定池大小:
  调整数量:
  最大池数量:
  池空闲超时秒数:
  Bean cache:(Stateful)  
  最大缓存大小:
  调整数量:
  是否允许缓存溢出:(有些不支持)
  缓存空闲超时秒数:
  删除超时秒数:>100
  牺牲者选择策略:LRU
==============================================================================================
EJB day3 Friday 2007.3.30
WebService:主要目标是跨平台的可互操作性。为了达到这一目标,WebService完全基于XML(可扩展标记语言)、XSD(XMLSchema)等独立于平台、独立于软件供应商的标准,是创建可互操作的、分布式应用程序的新平台。
 1.用EJB生成WebService
   1)写Session Bean(声明为WebService);
   @Stateless
   //声明生成WebService发布,服务名(serviceName):AdderService,(portName):AdderSerevicePort
   @WebService(serviceName="AdderService",portName="AdderServicePort")
   public class AdderBean implements AdderLocal {
      
       /** Creates a new instance of AdderBean */
       public AdderBean() {
       }
    //声明该方法在WebService中发布,如果所有的方法都不加,默认都发布
       @WebMethod
       public int add(int a, int b) {
           //TODO implement add
           return a+b;
       }  
   }
   2).部署(Deploy)到服务器上.在浏览器上获取他的地址(http://localhost:8080/AdderService/AdderBean?WSDL)
    生成的是xml文档
   3).在客户端创建Web Service Client->WSDL URL:http://localhost:8080/AdderService/AdderBean?WSDL
    创建成功会访问服务器把应用下载到本地,生成相关的java.class和*.java等文件.包括:
    AdderService.java:连接WebService的静态类,获取AdderBean的实体
    AdderBean.java:只是接口(暴露所提供的方法),以便我们调用
   4).(可选)写一个测试类,创建一个java main class
    package test;
    import java.net.MalformedURLException;
    import java.net.URL;
    import javax.xml.namespace.QName;
    import javax.xml.ws.Service;
    public class AdderTest {
        public AdderTest() {}
        public static void main(String[] args) throws MalformedURLException {
            //静态
     /获取服务对象
            AdderService service=new AdderService();
     //获得Session Bean
            AdderBean adderBean=(AdderBean)service.getAdderServicePort();
     //调用他暴露的方法
            System.out.println(adderBean.add(12,23));
            //动态
            URL wsdlURL=new URL("http://localhost:8080/AdderService/AdderBean?WSDL");
            QName serviceName=new QName("http://day03/", "AdderService");
            Service service2=Service.create(wsdlURL,serviceName);
            adderBean=(AdderBean)service.getAdderServicePort();
           System.out.println(adderBean.add(12,23));
        }   
    }
  
2.Message Service(JMS)
 创建queue message服务(点对点),发送者,接收者
 发送者->queue message->一个接收者
 1).在sun java System Application Server上创建消息转发:
  Application Server->Resources->JMS Resources->Connection Factories->new[JNDI Name=jms/cfA Type=javax.jms.ConnectionFactory{自动区别queue或topic}]
  Application Server->Resources->JMS Resources->Destination Resources->new[JNDI Name=jms/queueA Type=javax.jms.Queue name={必须有,随便输}] 
 2).客户端必须创建Enterprise Applicaton Client下创建发送者,和接收者
   import javax.jms.Connection;
   import javax.jms.ConnectionFactory;
   import javax.jms.MessageProducer;
   import javax.jms.Queue;
   import javax.jms.Session;
   import javax.jms.TextMessage;
   import javax.naming.Context;
   import javax.naming.InitialContext;
   import javax.naming.NamingException;
   public class Sender {
       public Sender() {}
       public static void main(String[] args) throws Exception {
    System.setProperty("jndi.factory","com.sun.jndi.cosnaming.CNCtxFactory");
    System.setProperty("jndi.provider.url","corbaloc::localhost:3700/NameService");
           Context context=new InitialContext();
           ConnectionFactory cf=(ConnectionFactory) context.lookup("jms/cfA");       
           /*
           //等价上面2行
           context context2=context.lookup("jms");
           ConnectionFactory cf2=context2.lookup("cfA");
           */
           Queue queueA=(Queue) context.lookup("jms/queueA");
           Connection con=cf.createConnection();
           //false不支持事务(自动通知接收者),手动通知
           Session session=con.createSession(false,Session.AUTO_ACKNOWLEDGE);
           MessageProducer producor=session.createProducer(queueA);
           TextMessage msg=session.createTextMessage();
           msg.setText("***********");
           producor.send(msg);
           System.out.println("send completed!!!");
     //关闭连接
           con.close();
       }
   }
    3.接收者
   public class Receiver {
       public Receiver() {}
       public static void main(String[] args) throws Exception {
    System.setProperty("jndi.factory","com.sun.jndi.cosnaming.CNCtxFactory");
    System.setProperty("jndi.provider.url","corbaloc::localhost:3700/NameService");
           Context context=new InitialContext();
           ConnectionFactory cf=(ConnectionFactory) context.lookup("jms/cfA");
           Queue queueA=(Queue) context.lookup("jms/queueA");
           Connection con=cf.createConnection();
           //false不支持事务(自动通知接收者),手动通知
           Session session=con.createSession(false,Session.AUTO_ACKNOWLEDGE);
           MessageConsumer consumer=session.createConsumer(queueA);
           //必需告诉消息服务器,准备好了
           con.start();
           //没有接收到消息则阻塞,每次只接收一条消息
           TextMessage msg=(TextMessage) consumer.receive();
           System.out.println(msg.getText());
            con.close();
       }   
   }
 ==============================================================================================
EJB day4 Friday 2007.4.2
1.Message Service(JMS)监听器(监听者、接收者)
 1).Message-Driven Bean(MDB):需要实现两个接口:
  javax.jms.MessageListener
  javax.ejb.MessageDrivenBean(可选)
  它一般是无状态bean.生命周期有:@PostConstruct、@PreDestroy 
  用NetBeans写MDB
   选择新建文件:[EJB 模块]->Enterprise->Message-Driven Bean(MDB)->[类名、包名、消息类别]
  //mappedName:表示服务器上的DNJI名。
  @MessageDriven(mappedName = "jms/queueA", activationConfig =  {
   //
      @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
      //消息的类型;Queue:队列、Topic:主题
      @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue",
      //(可选)消息选择器,JMSType='1':该监听器只接收类型为‘1’的消息,需要在发送者发送消息时著名类型:
      @ActivationConfigProperty(propertyName = "messageSelector", propertyValue = "JMSType='1'"
      )
  })
  public class Inserter implements MessageListener {
     
      @Resource(name = "jdbc/sample")
      private DataSource jdbcSample;
     
      /** Creates a new instance of Inserter */
      public Inserter() {
      }
     
      public void onMessage(Message message) {
          if(message instanceof TextMessage){
            //文本消息
              TextMessage msg=(TextMessage) message;
              //对象消息
//       ObjectMessage msg=(ObjectMessage)message4;
              request = msg.getText();            
              }
          }
      }     
  }
2. Return Results Back to Message Producers(发送者发送消息,并接收返回消息)

3.The Entity Class(实体)
  1).用NetBeans写MDB
   选择新建文件:[EnterpriseApplication-app-client]->Persistence(持久性)->Entity class->[类名、包名、创建持久性单元(选择数据库)]
  2).为实体类写一个stateless Session Bean
@Stateless
public class AccountSLBean implements AccountSLRemote {
  //注入持久性管理器
    @PersistenceContext
    private EntityManager em;
   
    /** Creates a new instance of AccountSLBean */
    public AccountSLBean() {
    }

    public void doSomething(){
        Account a1=new Account();
        a1.setBalance(1000);
        a1.setOwerName("yoogo");
        //持久化到数据库
        em.persist(a1);             
    }
   
    public Account findByPrimaryKey(Long id){
        return em.find(Account.class,id);
    }
   
    public List findAll(){
        String s="select a from Account a";
        return em.createQuery(s).getResultList();
    }
}  

==============================================================================================
EJB day5 Tuesday 2007.04.03
1.EntityManager(实体管理器)中的方法

 1). EntityManager.createQuery(String s);//等效于JDBC中的PreparedStatement()
     Query query=entityManager.createQuery("select a from Acount a where name= :name");
     query.setParamenter("name","hiloo");
 
 2). EntityManager.createNameQuery("select * from acount");//直接使用SQL语句
 3). EntityManager.createNamedQuery();//
     类前面声明namedQuery
     @NamedQuery(name="findAll",query="select a from Account a")
     class AccountBean{
     //....中间代码
     Query query=entityManager.createNamedQuery("findAll");
   
2.实体管理器注释
 @PersistenceContext(type=PersistenceContextType.EXTENDED)   //用于stateful session bean
 @PersistenceContext(type=PersistenceContextType.TRANSACTION)   //用于stateless session bean
 
 @Stateful
 public class AccountSFBean implements AccountSFRemote {
     unitName="EntityBean1-
     @PersistenceContext(type=PersistenceContextType.EXTENDED)
     private EntityManager em;  
     Account a;
     public AccountSFBean() {}
     public Account open(Long id,String name){
         a=em.find(Account.class,id);
         if(a==null){
             a=new Account();
             a.setOwerName(name);
             em.persist(a);
         }
         return a;
     }
     public void deposit(double amount){
         a.setBalance(a.getBalance()+amount);
     }  
     public void withdraw(double amount){
         a.setBalance(a.getBalance()-amount);
     }  
 }

3.Entity Life cycle(实体的声明周期)
 @PrePersist   //持久化前调用该方法
 @PostPersist   //持久化后调用该方法
 @PreUpdate   //更新前调用该方法
 @PostLoad   //加载后调用该方法
 举例:
     1).写一个EntityListener(实体监听器)
 public class AccountListener{
     @PrePersist
     public void prePersist(Account a){//代码块}
     @Postpersist
     //....  同PrePersist
 }
     2).在Entity中注册EntityListener
 @Entity
 @EntityListeners(AccountListener.class)
 public class Account implements Serializable{
     @Id
     @GeneratedValue(strategy=GenerationType.AUTO)
     private Long accountno;
     @Cloumn
     private String name;
     //...
 }

 


实体的状态
 
new新建,也就是新建的实体实例,其信息还没有持久到数据库中。
managed受管状态,也就是实体已经持久化到数据库中,并且已经和持久化上下文进行了关联。
detached分离状态,也就是与持久化上下文解除关联的实体的状态
removed删除,此时实体和持久化上下文进行了关联,但是要从数据库中删除这个实体。
 
 
  new      persist()    中止PersistenceContext >
  ——>新建————>受管========================分离
                     ||/   <  merge()
            remove()/|| persist()
                    删除
 
 
@PersistenceContext,持久化上下文是内存中的实例和数据库间的连接枢纽,就像是一快缓冲区,但这个缓冲区是由容器来进行管理的,在这个缓冲区中的实体是处在受管理状态。
 
@PersistenceContext(type=PersistenceContextType.EXTENDED,unitName="PetPU")
type属性使用来标识持久化上下文的类型的,持久化上下文有两种类型事务范围和扩展的。这两种类型的持久化上下文的生命周期不同。unitName属性是指定持久化单元的名字,其值是在持久化单元定义文件中persistence-unit标签中的name属性的值。
 
事务范围的持久化上下文应用到无状态SessionBean,一旦事务终结,就销毁,其中的实体也会变成分离状态。
扩展的持久化上下文应用在有状态的SessionBean,只有在有状态的SessionBean被容器销毁是才会销毁持久化上下文,也就使实体一直是被管理的。
 
持久化单元的定义文件,这个文件是描述数据库连接和事务管理的文件
 
<persistence version="1.0" 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">
    <!--"JTA"用于容器状态;"RESOURCE_LOCAL":非容器-->
  <persistence-unit name="PetPU" transaction-type="JTA">
    <!--transaction-type是事务管理的类型-->
    <provider>oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider</provider>
    <!--SPI,持久化API的实现类的提供者-->
    <jta-data-source>my.jdbc</jta-data-source>
     <!--数据源的配置-->
    <properties>
      <property name="toplink.ddl-generation" value="create-tables"/>
    </properties>
  </persistence-unit>
</persistence>
 
EntityManager实体管理器,它是用来管理实体的,如果使用容器管理实体,容器就会注入EntityManager,EntityManager可以提供实体类生命周期管理,实现数据的同步,和实体的数据的查询。
 
实体生命周期回调方法
 
实体的生命周期回调方法不是通用的。
在实体类中定义时,只在方法前加标注,并且方法的返回值为void,方法为public
也就是:
 
@PrePersist
public void save(){}
在另外的类中写生命周期回调方法时,就需要以这个实体类为参数了
class AcountListenter{
@PrePersist
public void save(Acount a){}
}
 
@Entity
@EntityListenters(AcountListenter.class)
class Acount...
 
PostPersist
PreRemove
PostRemove
PreUpdate
PostUpdate
PostLoad

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值