知识大全 Spring Integration学习笔记(一)

Posted 消息

篇首语:知之者不如好之者,好之者不如乐之者。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 Spring Integration学习笔记(一)相关的知识,希望对你有一定的参考价值。

Spring Integration学习笔记(一)  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!

  The Cafe Sample(小卖部订餐例子)

  小卖部有一个订饮料服务 客户可以通过订单来订购所需要饮料 小卖部提供两种咖啡饮料LATTE(拿铁咖啡)和MOCHA(摩卡咖啡) 每种又都分冷饮和热饮整个流程如下

   有一个下订单模块 用户可以按要求下一个或多个订单

   有一个订单处理模块 处理订单中那些是关于订购饮料的

   有一个饮料订购处理模块 处理拆分订购的具体是那些种类的饮料 把具体需要生产的饮料要求发给生产模块 有一个生产模块

  

  这个例子利用Spring Integration实现了灵活的 可配置化的模式集成了上述这些服务模块

  先来看一下配置文件

   <beans:beans xmlns=     xmlns:xsi= instance     xmlns:beans=     xmlns:context=     xsi:schemaLocation=          beans xsd                 integration xsd                 context xsd >    <!  启动Message bus 消息服务总线 支持四个属性             auto startup[boolean是否自动启动 default=true]如果设置false 则需要手动调用applicationContext start()方法            auto create channels[boolean是否自动注册MessageChannel default=false] 如果使用的MessagChannle不存在            error channel 设置错误时信息发送的MessageChannle 如果不设置 则使用DefaultErrorChannel            dispatcher pool size 使用的启动线程数 默认为 >    <message bus/>    <!  启动支持元数据标记  >    <annotation driven/>    <!  设置 @Component标识的元数据扫描包(package)  >    <context:ponent scan base package= springframework integration samples cafe />        <!  下面启动了四个 MessageChannel服务 处理接收发送端发过来的消息和把消息流转到消息的消费端  >        <!  属性说明  capacity 消息最大容量默认为  publish subscribe是否是发布订阅模式 默认为否                                        id bean的id名称 datatype ?  >    <channel id= orders /> <!  订单Channel  >    <channel id= drinks /> <!  饮料订单Channel 处理饮料的类别  >    <channel id= coldDrinks /> <!  热饮生产Channel  >    <channel id= hotDrinks /> <!  冷饮生产Channel  >        <!  消息处理终端 接收 channel coldDrinks的消息后 执行barista prepareColdDrink方法 生产冷饮  >        <!  属性说明  input channel 接收消息的Channel必须 default output channel设置默认回复消息Channel                                        handler ref 引用bean的id名称 handler method Handler处理方法名(参数类型必须与发送消息的payLoad使用的一致)                                        error handler设置错误时信息发送的MessageChannle   reply handler 消息回复的Channel  >    <endpoint input channel= coldDrinks  handler ref= barista                                          handler method= prepareColdDrink />        <!  消息处理终端 接收 channel hotDrinks的消息后 执行barista prepareHotDrink方法 生产热饮  >    <endpoint input channel= hotDrinks  handler ref= barista                                         handler method= prepareHotDrink />        <!  定义一个启动下定单操作的bean 它通过 channel orders下定单  >    <beans:bean id= cafe  class= springframework integration samples cafe Cafe >        <beans:property name= orderChannel  ref= orders />    </beans:bean></beans:beans>

  下面我们来看一下源代码目录

  

  我们来看一下整体服务是怎么启动的

  首先我们来看一下CafeDemo这个类 它触发下定单操作

      public class CafeDemo               public static void main(String[] args)                //加载Spring 配置文件               AbstractApplicationContext context = null;               if(args length >  )                    context = new FileSystemXmlApplicationContext(args);                              else                   context = new ClassPathXmlApplicationContext( cafeDemo xml  CafeDemo class);                            //启动 Spring容器(启动所有实现 ntext Lifecycle接口的实现类的start方法)              context start();              //从Spring容器 取得cafe实例              Cafe cafe = (Cafe) context getBean( cafe );              DrinkOrder order = new DrinkOrder();              //一杯热饮               参数说明 饮料类型  数量  是否是冷饮(true表示冷饮)              Drink hotDoubleLatte = new Drink(DrinkType LATTE    false);              Drink icedTripleMocha = new Drink(DrinkType MOCHA    true);              order addDrink(hotDoubleLatte);              order addDrink(icedTripleMocha);              //下 个订单              for (int i =  ; i <  ; i++)                   //调用cafe的placeOrder下订单                  cafe placeOrder(order);                              

  下面是Cafe的源代码

      public class Cafe               private MessageChannel orderChannel;                       public void setOrderChannel(MessageChannel orderChannel)                this orderChannel = orderChannel;                               //其实下订单操作 调用的是orderChannel(orders channel)的send方法 把消息发出去          public void placeOrder(DrinkOrder order)               this orderChannel send(new GenericMessage<DrinkOrder>(order));                  //GenericMessage有三个构建方法 参考如下                  //new GenericMessage<T>(Object id  T payload);                  //new GenericMessage<T>(T payload);                  //new GenericMessage<T>(T payload  MessageHeader headerToCopy)                

  下面我们来看一下哪个类标记有@MessageEndpoint(input= orders ) 表示它会消费orders Channel的消息我们发现OrderSplitter类标记这个元数据 下面是源代码 我们来分析

      //标记 MessageEndpoint 元数据  input表示 设置后所有 orders Channel消息都会被OrderSplitter收到           @MessageEndpoint(input= orders )           public class OrderSplitter                          //@Splitter表示 接收消息后 调用这个类的该方法  其的参数类型必须与message的 payload属性一致                //即在new GenericMessage<T>的泛型中指定               //元数据设置的 channel属性表示 方法执行完成后 会把方法返回的结果保存到message的payload属性后 发送到指定的channel中去               //这里指定发送到 drinks channel               @Splitter(channel= drinks )              public List<Drink> split(DrinkOrder order)                   return order getDrinks(); //方法中 是把订单中的饮料订单取出来                        

  接下来 与找OrderSplitter方法相同 我们要找哪个类标记有@MessageEndpoint(input= drinks ) 表示它会消费drinks Channel的消息找到DrinkRouter这个类

      @MessageEndpoint(input= drinks )           public class DrinkRouter                          //@Router表示 接收消息后 调用这个类的该方法  其的参数类型必须与message的 payload属性一致                //方法执行完毕后 其返回值为 在容器中定义的channel名称 channel名称必须存在               @Router               public String resolveDrinkChannel(Drink drink)                    return (drink isIced()) ?  coldDrinks  :  hotDrinks ; //方法中 是根据处理饮料是否是冷饮 送不同的channel处理                         

备注 @Router可以把消息路由到多个channel 实现方式如下            @Router            public MessageChannel route(Message message)                        @Router            public List<MessageChannel> route(Message message)                        @Router            public String route(Foo payload)                        @Router            public List<String> route(Foo payload) 

  接下来 我们就要找 MessageEndpoint 标记为处理 coldDrinks 和 hotDrinks 的类 我们发现这个两个类并不是通过元数据@MessageEndpoint来实现的 而是通过容器配置(下面会演示如何用元数据配置 但元数据配置有局限性 这两种配置方式看大家喜好 系统中都是可以使用)

  下面是容器配置信息

   <!  消息处理终端 接收 channel coldDrinks的消息后 执行barista prepareColdDrink方法 生产冷饮  >    <endpoint input channel= coldDrinks  handler ref= barista                                          handler method= prepareColdDrink />        <!  消息处理终端 接收 channel hotDrinks的消息后 执行barista prepareHotDrink方法 生产热饮  >    <endpoint input channel= hotDrinks  handler ref= barista                                         handler method= prepareHotDrink />

  我们来看一下源代码

      @Component //这个必须要有 表示是一个消息处理组件           public class Barista                          private long hotDrinkDelay =  ;                         private long coldDrinkDelay =  ;                         private AtomicInteger hotDrinkCounter = new AtomicInteger();                            private AtomicInteger coldDrinkCounter = new AtomicInteger();                                public void setHotDrinkDelay(long hotDrinkDelay)                   this hotDrinkDelay = hotDrinkDelay;                                     public void setColdDrinkDelay(long coldDrinkDelay)                   ldDrinkDelay = coldDrinkDelay;                                     public void prepareHotDrink(Drink drink)                   try                       Thread sleep(this hotDrinkDelay);                   catch (InterruptedException e)                       Thread currentThread() interrupt();                                    System out println( prepared hot drink #  + hotDrinkCounter incrementAndGet() +  :   + drink);                                     public void prepareColdDrink(Drink drink)                   try                       Thread sleep(ldDrinkDelay);                   catch (InterruptedException e)                       Thread currentThread() interrupt();                                    System out println( prepared cold drink #  + coldDrinkCounter incrementAndGet() +  :   + drink);                                 

  如果要用元数据标识实现上述方法 要用元数据配置 它不像容器配置 可以在一个类中 支持多个不同的Handler方法 以处理prepareColdDrink方法为例

      @MessageEndpoint(input= coldDrinks ) //加了该元数据 它会自动扫描 并作为@Componet标记处理           public class Barista                          private long hotDrinkDelay =  ;                         private long coldDrinkDelay =  ;                         private AtomicInteger hotDrinkCounter = new AtomicInteger();                            private AtomicInteger coldDrinkCounter = new AtomicInteger();                                public void setHotDrinkDelay(long hotDrinkDelay)                   this hotDrinkDelay = hotDrinkDelay;                                     public void setColdDrinkDelay(long coldDrinkDelay)                   ldDrinkDelay = coldDrinkDelay;                                     public void prepareHotDrink(Drink drink)                   try                       Thread sleep(this hotDrinkDelay);                   catch (InterruptedException e)                       Thread currentThread() interrupt();                                    System out println( prepared hot drink #  + hotDrinkCounter incrementAndGet() +  :   + drink);                                         @Handler//回调处理的方法              public void prepareColdDrink(Drink drink)                   try                       Thread sleep(ldDrinkDelay);                   catch (InterruptedException e)                       Thread currentThread() interrupt();                                    System out println( prepared cold drink #  + coldDrinkCounter incrementAndGet() +  :   + drink);                        

  这样整个流程就执行完了 最终我们的饮料产品就按照订单生产出来了 累了吧 喝咖啡提神着呢!!!

  初充 下面是针对 Spring Integration adapter扩展的学习笔记

  JMS Adapters

  jms adapters 目前有两种实现

  JmsPollingSourceAdapter 和 JmsMessageDrivenSourceAdapter 前者是使用Srping的JmsTemplate模板类通过轮循的方式接收消息

  后者是使用则通过代理Spring的DefaultMessageListenerContainer实例 实现消息驱动的方式

  xml配置如下

  

  <bean class= springframework integration adapter jms JmsPollingSourceAdapter >    <constructor arg ref= jmsTemplate />    <property name= channel ref= exampleChannel />    <property name= period value= /> <! 轮循时间间隔 >    <property name= messageMapper ref= /> <! message转换 ></bean><! 备注 消息的转换方式如下 收到JMS Message消息后 SourceAdapter会调用Spring的MessageConverter实现类 把javax jms Message对象转换成普通Java对象 再调用Spring Integration的MessageMapper把该对象转成 springframessage Message对象 >

  JmsMessageDrivenSourceAdapter

   <bean class= springframework integration adapter jms JmsMessageDrivenSourceAdapter >    <property name= connectionFactory ref= connectionFactory />    <property name= destinationName value= exampleQueue />    <property name= channel ref= exampleChannel />    <property name= messageConverter ref= /> <! jms消息对象转换 >    <property name= messageMapper ref= /> <! 普通java对象转换成 Spring Integration Message >    <property name= sessionAcknowledgeMode value= />     <! sesssion回复模式 AUTO_ACKNOWLEDGE= CLIENT_ACKNOWLEDGE=   DUPS_OK_ACKNOWLEDGE= SESSION_TRASACTED= ></bean>

  另外还有一个比较有用的类JmsTargetAdapter 它实现了MessageHandler接口 它提把Spring Integration Message对象转换成JMS消息并发送到指定的消息队列 与JMS服务连接的实现可以通过设定 jmsTemplate属性引用或是connectionFactory和destination或destinationName属性

cha138/Article/program/Java/ky/201311/28092

相关参考

知识大全 Spring2 提供的remote包学习笔记

Spring2提供的remote包学习笔记  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  Sp

知识大全 Spring2 提供的remote包学习笔记[3]

Spring2提供的remote包学习笔记[3]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 

知识大全 Spring2 提供的remote包学习笔记[2]

Spring2提供的remote包学习笔记[2]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 

知识大全 Spring2 提供的remote包学习笔记[1]

Spring2提供的remote包学习笔记[1]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 

知识大全 Spring笔记和小结(一)

Spring笔记和小结(一)  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  

知识大全 Spring笔记和小结(二)

Spring笔记和小结(二)  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  

知识大全 Spring笔记和小结(三)

Spring笔记和小结(三)  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  

知识大全 Spring笔记和小结(四)

Spring笔记和小结(四)  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  

知识大全 Spring Security学习总结一

SpringSecurity学习总结一  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  在认识Sp

知识大全 C#学习笔记(一)

C#学习笔记(一)  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  finalize方法:终结器