精华内容
下载资源
问答
  • spring提供了jms层的抽象正确吗
    千次阅读
    2016-02-16 14:30:02

    1.说说AOP和IOC的概念以及在spring中是如何应用的
    答:AOP:面向方面编程,ioc:依赖注入;声明式事务和编程式事务积极一些通用部分
    2.Spring DAO 中最常用的类是:
    A. JdbcTemplate ,SimpleJdbcTemplate
    B. SimpleJdbcInsert ,SimpleJdbcProcedure
    C. SimpleJdbcInsert ,SimpleJdbcStoredProc
    D.SimpleJdbcQuery ,SimpleJdbcExec
    答:A
    3.你更推荐那种类型的事务管理?
    答:许多Spring框架的用户选择声明式事务管理,因为这种方式和应用程序的关联较少,因此更加符合轻量级容器的概念。声明式事务管理要优于编程式事务管理,尽管在灵活性方面它弱于编程式事务管理(这种方式允许你通过代码控制业务)。
    4.Spring AOP 中, 织入(Weaving) 可以在下面什么时间完成?
    A. 全部选项
    B. Run time
    C. Load time
    D. Compile time
    答:A
    5.Spring的配置文件
    答:Spring的配置文件是一个XML文件,文件包含了类信息并描述了这些类是如何配置和互相调用的。
    6.下面关于Spring MVC 描述正确的是?
    A. DispatcherServlet在 Spring MVC 中是核心servlet , 它负责接收请求并将请求分发给适合的控制器
    B. 在Spring MVC 中,可以配置多个DispatcherServlet
    C. 全部选项
    D. 要使Spring MVC可用,DispatcherServlet需要在web.xml中配置
    答:C
    7.下面哪项是Spring自动装载模式?
    A. autodetect
    B. 全部选项
    C. constructor
    D. byname, byType
    答:B
    8.Spring 中,下面哪一项不是使用事务的方法?
    A. proxies
    B. declaratively
    C. programmaticly
    答:A
    9.Action是不是线程安全的?如果不是 有什么方式可以保证Action的线程安全?如果是,说明原因
    答:不是 声明局部变量,或者扩展RequestProcessor,让每次都创建一个Action,或者在spring中用scope=”prototype”来管理
    10.Spring提供了JMS层的抽象,正确吗?
    答:正确
    11.Spring应用程序看起来像什么?
    答:一个定义功能的接口 实现包括属性,setter和getter方法,功能等 Spring AOP Spring的XML配置文件 使用该功能的客户端编程 依赖注入
    12.关于”@Order” 注解,最正确的描述是?
    A. 实现org.springframework.core.Ordered接口
    B. 指定一个bean的范围
    C. 通常用于注入域对象的属性
    D. 全不正确
    答:A
    13.如何在Spring应用中使用SLF4J?
    A. 作为日志框架
    B. 全不正确
    C. 作为一个bean
    D. 作为JDBC框架
    答:A
    14.解释基于XML Schema方式的切面实现
    答:在这种情况下,切面由使用XML文件配置的类实现。
    15.解释web模块
    答:Spring的web模块建立在应用上下文(application context)模块之上,提供了一个适合基于web应用程序的上下文环境。该模块还支持了几个面向web的任务,如透明的处理多文件上传请求及将请求参数同业务对象绑定起来。

    更多相关内容
  • Spring系列的第四部分(也是最后一部分)中,我将向您介绍Spring JMS(Java消息服务)框架的功能。 JMS定义了Java应用程序通过面向消息的中间件(MOM)创建和交换消息的标准方法。 与本系列的前几篇文章一样,我...

    Spring系列的第四部分(也是最后一部分)中,我将向您介绍Spring JMS(Java消息服务)框架的功能。 JMS定义了Java应用程序通过面向消息的中间件(MOM)创建和交换消息的标准方法。

    与本系列的前几篇文章一样,我使用一个简单的示例来演示Spring JMS的功能。 我将使用Spring JMS框架通过JMS接口与IBM的WebSphere MQ集成,以开发基于点对点(P2P)消息的系统。 完成练习后,您将能够通过系统发送和接收简单的文本消息。

    开始之前,请下载文章源 。 请参阅相关主题访问Spring框架和IBM WebSphere MQ 5.3。 您还将需要Apache Ant来运行示例应用程序。

    SpringJMS

    Spring的JMS抽象框架简化了JMS API的使用,并与JMS提供程序(例如IBM的WebSphere MQ 5.3)顺利集成。 包org.springframework.jms.core提供了在Spring中使用JMS的核心功能。 它的模板类通过处理资源的创建和释放来简化JMS的使用。

    像大多数其他Spring模板类一样,JMS模板类提供了执行常用操作的辅助方法。 如果需要更复杂的用法,则这些类将处理任务的本质委托给用户实现的回调接口。 JMS类提供了方便的方法来发送消息,同步使用消息以及向用户公开JMS会话和消息生成器。

    以下JMS软件包与org.springframework.jms.core一起 ,包含Spring JMS功能:

    org.springframework.jms.support
    提供翻译JMSException的功能。 转换代码将已检查的JMSException层次结构转换为未检查的异常的镜像层次结构。
    org.springframework.jms.support.converter
    提供MessageConverter抽象以在Java对象和JMS消息之间进行转换。
    org.springframework.jms.support.destination
    提供用于管理JMS目的地的各种策略,例如用于JNDI中存储的目的地的服务定位器。
    org.springframework.jms.connection
    提供适用于独立应用程序的ConnectionFactory的实现。 该连接包还包含Spring的JMS PlatformTransactionManager实现。 这允许将JMS作为事务资源集成到Spring的事务管理机制中。

    IBM WebSphere MQ

    如前所述,示例应用程序将使用Spring JMS框架通过JMS接口与IBM的WebSphere MQ集成。 WebSphere MQ通过在应用程序和Web服务之间传递消息来提供可靠,有弹性的应用程序集成。 它使用排队和事务处理功能来帮助维护整个网络中消息的完整性。 WebSphere MQ降低了信息丢失的风险以及调和通信IT系统的需求。

    WebSphere MQ在其所有受支持的平台上提供了一致的应用程序编程接口(MQI),这有助于使集成程序具有可移植性。 除了标准接口之外,WebSphere MQ还完全实现了JMS接口,包括对发布和订阅消息传递的支持。 WebSphere MQ Explorer工具使整个MQ网络都可以进行远程管理和配置。 该管理和配置工具基于开源Eclipse框架,并且是可扩展的。

    Spring JMS模板

    Spring框架提供了JmsTemplate两种实现。 JmsTemplate类使用JMS 1.1 API,而子类JmsTemplate102使用JMS 1.0.2 API。 我的示例应用程序使用JmsTemplate102

    JMS模板用于发送和接收JMS消息。 Spring使用回调机制来协调JMS消息传递。 MessageCreator回调接口根据JmsTemplate的调用代码提供的Session创建消息。 为了允许更复杂地使用JMS API,回调SessionCallback向用户提供了JMS会话,而callback ProducerCallback公开了SessionMessageProducer对。

    清单1显示了用于示例应用程序的JMS模板的配置。 清单是spring-mqseries-jms.xml文件的摘录 (请参阅下载 )。

    清单1. JMS模板配置
    <!-- JMS Queue Template -->
      <bean id="jmsQueueTemplate" 
              class="org.springframework.jms.core.JmsTemplate102">
        <property name="connectionFactory">
          <ref bean="jmsQueueConnectionFactory"/>
        </property>
        <property name="destinationResolver">
          <ref bean="jmsDestinationResolver"/>
        </property>
        <property name="pubSubDomain">
          <value>false</value>
        </property>
        <property name="receiveTimeout">
          <value>20000</value>
        </property>
      </bean>

    jmsQueueTemplate bean与JMS连接工厂和JMS目标解析器连接在一起,用于解析JMS客户端通过JNDI提供的目标队列名称。 connectionFactory属性指定如何获取与JMS提供程序的连接。 在该示例的情况下,清单2显示了如何从JNDI检索连接工厂。

    清单2.通过JNDI配置JMS连接工厂
    <!-- JMS Queue Connection Factory -->
      <bean id="internalJmsQueueConnectionFactory"
              class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiTemplate">
          <ref bean="jndiTemplate"/>
        </property>
        <property name="jndiName">
          <value>MQ_JMS_MANAGER</value>
        </property>
      </bean>

    如您所见, JndiObjectFactoryBean连接到一个internalJmsQueueConnectionFactoryJndiObjectFactoryBean使用JndiTemplate属性进行JNDI查找。 Spring将使用JndiTemplate中指定的环境属性和初始上下文在JNDI中查找连接工厂。 清单3显示了JndiTemplate配置bean的配置。

    清单3.用于JNDI查找的JNDI模板配置
    <bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
        <property name="environment">
          <props>
            <prop key="java.naming.factory.initial">
                com.sun.jndi.fscontext.RefFSContextFactory
            </prop>
            <prop key="java.naming.provider.url">
                file:/C:/JNDI-Directory
            </prop>
          </props>
        </property>
      </bean>

    上面的配置将初始上下文工厂指定为com.sun.jndi.fscontext.RefFSContextFactory ,并将提供程序URL指定为基于文件的文件:/ C:/ JNDI-Directory以进行JNDI查找。 示例应用程序的目的,JNDI访问将使用基于文件FSContext版本(请参阅相关信息 ),配置为MQ队列绑定到JNDI。

    定义了JMS模板后,下一步是将其连接到示例应用程序中,然后可以使用它发送和接收消息。

    Spring JMS实施

    可以将JMS模板连接到应用程序中,以发送和接收JMS消息。 在清单4中,您可以看到如何将清单1中的JMS模板连接到示例应用程序中。

    清单4.将JmsTemplate连接到应用程序
    <bean id="jmsSender" 
              class="springexample.client.JMSSender">
        <property name="jmsTemplate102">
          <ref bean="jmsQueueTemplate"/>
        </property>
    
        </bean>
    
        <bean id="jmsReceiver" 
              class="springexample.client.JMSReceiver">
        <property name="jmsTemplate102">
            <ref bean="jmsQueueTemplate"/>
          </property>
    
        </bean>

    正如你所看到的,我有线jmsQueueTemplate到两个JmsSender应用bean和JmsReceiver用于发送和接收消息豆。 清单5显示了JMSSender类的相关代码。

    清单5.使用JmsTemplate发送JMS消息的JMSSender
    public class JMSSender {
    
       private JmsTemplate102 jmsTemplate102;
    
       public JmsTemplate102 getJmsTemplate102() {
         return jmsTemplate102;
       }
    
       public void setJmsTemplate102(JmsTemplate102 jmsTemplate102) {
         this.jmsTemplate102 = jmsTemplate102;
       }
    
       public void sendMesage(){
         jmsTemplate102.send("JMS_RequestResponseQueue", 
                      new MessageCreator() {
            public Message createMessage(Session session) 
                      throws JMSException {
              return session.createTextMessage("This is a sample message");
            }
          });
    
    
       }

    JMSSender类使用jmsTemplate102.send()方法发送JMS消息。 send()方法的第一个参数是JNDI队列名称,它指定应该将消息发送到的位置。 (稍后,您将看到WebSphere MQ的队列名称如何绑定到JNDI。) send()方法的第二个参数是MessageCreator类。 给定JmsTemplate的调用代码提供的Session ,此类提供了一个回调接口来创建JMS消息。

    下一步是使用JMS Session类创建一条简单的文本消息。 该消息将在执行代码时传递到WebSphere MQ服务器的队列中。 清单6显示了使用JmsTemplate接收JMS消息的JMSReceiver应用程序bean代码。

    清单6.使用JmsTemplate接收JMS消息的JMSReceiver
    public class JMSReceiver {
    
        private JmsTemplate102 jmsTemplate102;
    
        public JmsTemplate102 getJmsTemplate102() {
          return jmsTemplate102;
        }
    
        public void setJmsTemplate102(JmsTemplate102 jmsTemplate102) {
         this.jmsTemplate102 = jmsTemplate102;
        }
    
        public void processMessage(){
          Message msg = jmsTemplate102.receive("JMS_RequestResponseQueue");
          try{
            TextMessage textMessage = (TextMessage) msg;
            if( msg!=null){
            System.out.println(" Message Received -->" + 
                        textMessage.getText());
            }
    
    
          }catch(Exception e){
                e.printStackTrace();
          }
    
    
        }
    }

    所述JMSReceiver类使用jmsTemplate102.receive()方法来接收JMS消息synchronously.The receive()方法指定JNDI队列名称从中检索消息。 接收JMS客户端将调用JMSTemplate类的processMessage()方法。 JSMTemplate Bean属性receiveTimeout (在JMSTemplate配置中列出)指定接收客户端将等待从队列同步接收消息的时间。

    并完成了应用程序代码! 我的下一步是配置WebSphere MQ队列并将其绑定到JNDI对象。

    队列管理器设置

    在运行该应用程序之前,需要设置WebSphere MQ队列管理器和队列并将它们绑定到JNDI。 如果愿意,您可以遵循该示例的这一部分:只需下载批处理文件以设置WebSphere MQ队列以及该应用程序的源代码和部署描述符。 将压缩文件解压缩到C:驱动器。

    设置队列
    运行在C提供的mqsetup.bat文件:\ SpringSeriesPart4JMS \ batch文件夹。 此批处理文件要求您在环境路径变量中设置MQ安装的bin文件夹(例如C:\ mqseries \ bin )。 运行批处理文件之后,您应该看到消息“ All valid MQSC commands were processed 。 要打开MQ Explorer并检查是否创建了队列管理器,请选择Start-> Programs-> IBM MQSeries-> MQSeriesExplorer 。 图1显示示例应用程序QueueManager MQJMS.QManager已创建并正在运行。

    图1. WebSphere MQ的QueueManager配置
    WebSphere MQ的QueueManager配置

    单击应用程序屏幕左窗格上MQJMS.QManagerQueues文件夹。 您应该看到还创建了一个队列RequestResponseQueue ,如图2所示。

    图2. WebSphere MQ的请求/响应队列配置
    WebSphere MQ的请求/响应队列配置

    这样就完成了队列的设置。

    设置JMS和JNDI管理

    在示例应用程序中,JNDI访问使用了JNDI主页上提供的基于文件的FSContext版本(请参阅参考资料 )。 FSContext.jar文件也包含在WebSphere MQ的JMS支持中。 将文件夹\ MQSeriesInstallable \ MQSeries \ Java \ lib和\ MQSeriesInstallable \ MQSeries \ Java \ bin添加到系统的PATH环境变量中。 另外,将\ MQSeriesInstallable \ MQSeries \ Java \ lib文件夹中的所有jar文件添加到系统的CLASSPATH环境变量中。 您还可以运行C:\ SpringSeriesPart4JMS \ batch文件夹中提供的classpath.cmd批处理文件,该文件设置必要的路径和CLASSPATH变量。 为此,只需修改classpath.cmd文件中的MQ_JAVA_INSTALL_PATH变量以指向您的WebSphere MQ JMS安装目录。

    接下来,修改MQSeries JMS管理使用的\ MQSeriesInstallableDirectory \ Java \ bin中的JMSAdmin.config配置文件,以指示应用程序将使用的上下文工厂和JNDI实现的地址。 取消注释以下行:

    INITIAL_CONTEXT_FACTORY=com.sun.jndi.fscontext.RefFSContextFactory

    并注释掉其余两个INITIAL_CONTEXT_FACTORY变量。 还要取消注释以下行:

    PROVIDER_URL=file:/C:/JNDI-Directory

    并注释掉其余两个PROVIDER_URL变量。

    您可以在C:\ SpringSeriesPart4JMS \ batch文件夹中找到一个示例配置文件,以供参考。

    要存储JNDI对象,请在C:驱动器上创建一个名为JNDI-Directory的目录 。 切换到\ MQSeriesInstallableDirectory \ Java \ bin目录并运行JMSAdmin批处理文件,您应该看到InitCtx变量。

    依次键入以下内容:

    def qcf(MQ_JMS_MANAGER) qmgr(MQJMS.QManager)
    press Enter
    def q(JMS_RequestResponseQueue) qmgr(MQJMS.QManager) queue(RequestResponseQueue)
    press Enter

    现在,您已将WebSphere MQ队列绑定到JNDI对象,可以通过JNDI将其作为应用程序客户机进行查找。 剩下要做的就是查看运行中的代码!

    运行示例

    要运行该示例,请从spring sourceforge下载 Spring框架及其所有依赖项文件,并将其解压缩到例如c:\。 将创建文件夹C:\ spring-framework-1.2-rc2 (或最新版本)。

    要运行Spring应用程序,请将文章源代码提取到任何文件夹,例如c:\ 。 将创建文件夹SpringSeriesPart4JMS 。 如前所述,您还需要安装Apache Ant及其Spring依赖项jar文件。 将Spring库(即C:\ spring-framework-1.2-rc2 \ dist中的 spring.jar和commons-logging.jar-从C:\ spring-framework-1.2-rc2 \ lib \ jakarta-commons复制到SpringSeriesPart4JMS \ lib文件夹。 还将所有jar库从\ MQSeriesInstallableDirectory \ Java \ lib目录复制到SpringSeriesPart4JMS \ lib文件夹。 它包含与MQseries和JMS相关的库。 现在,您已经设置了构建依赖项。

    接下来,打开命令提示符,并将目录更改为SpringProject4,然后在命令提示符处键入以下内容:

    > ant -f build-jmssender.xml.

    这将构建并运行SendMQSpringJMS类,该类调用JMSSender类以将文本消息发送到WebSphere MQ RequestResponse队列。 SendMQSpringJMS还通过其ClassPathXmlApplicationContext加载spring配置文件。 装入Bean之后,可以通过Spring ApplicationContext getBean()方法访问JMSSender(请参见清单7)。

    清单7.加载示例应用程序的Spring配置
    ClassPathXmlApplicationContext appContext = 
                       new ClassPathXmlApplicationContext(new String[] {
         "spring-mqseries-jms.xml"
        });
    
    JMSSender jmsSender = (JMSSender)
            appContext.getBean("jmsSender");

    将消息传递到队列中后,请运行JMS接收器客户端以检索它。 打开命令提示符,将目录更改为SpringProject4 ,然后键入:

    > ant -f build-jmsreceiver.xml

    这将构建并运行ReceiveMQSpringJMS类,该类将调用JMSReceiver类以从WebSphere MQ RequestResponse队列接收文本消息。 在控制台上将显示以下消息:

    Message Received --> This is a sample message.

    结论

    在Spring系列的最后一篇文章中,您了解了Spring JMS框架的基础。 我首先介绍了示例应用程序的基本组件(Spring JMS框架和IBM的WebSphere MQ 5.3),然后向您展示了如何使用Spring JMS模板从WebSphere MQ队列发送和接收消息。 尽管该示例非常简单,但是您可以将概述的步骤应用于复杂性更高的应用程序。

    我希望本系列介绍Spring框架的基本模块对您有所帮助。 请参阅相关主题 ,以了解更多关于Spring框架和Spring JMS。


    翻译自: https://www.ibm.com/developerworks/web/library/wa-spring4/index.html

    展开全文
  • Spring集成】-Spring使用JMS发送消息

    千次阅读 2018-07-06 16:29:25
    1.JMS简介: Java 消息服务( Java Message Service , JMS )是一个 Java ...但是借助 JMS ,所有遵从规范的实现都使用通用的接口,这就类似于 JDBC 为数据库操作提供了通用的接口一样。Spring 通过基于模板的抽...

    1.JMS简介:

        Java 消息服务( Java Message Service  , JMS )是一个 Java 标准,定义了使用消息代理的通用API 。在 JMS 出现之前,每个消息代理都有私有的 API ,这就使得不同代理之间的消息代码很难通用。但是借助 JMS ,所有遵从规范的实现都使用通用的接口,这就类似于 JDBC 为数据库操作提供了通用的接口一样。Spring 通过基于模板的抽象为 JMS 功能提供了支持,这个模板也就是 JmsTemplate 。使用 JmsTemplate ,能够非常容易地在消息生产方发送队列和主题消息,在消费消息的那一方,也能够非常容易地接收这些消息。 Spring 还提供了消息驱动 POJO 的理念:这是一个简单的 Java 对象,它能够以异步的方式响应队列或主题上到达的消息。

    二.安装消息代理activemq

        ActiveMQ 是一个伟大的开源消息代理产品,也是使用 JMS 进行异步消息传递的最佳选择。在开始使用 ActiveMQ 之前,我们需要从 http://activemq.apache.org 下载二进制发行包。下载完 ActiveMQ 后,我们将其解压缩到本地硬盘中。在解压目录中,我们会找到文件 activemq-core-5.9.1.jar 。为了能够使用 ActiveMQ 的 API ,我们需要将此 JAR 文件添加到应用程序的类路径中。安装完成解压缩会有下面目录结构:


    运行bin目录下的activemq.bat出现下面结果表明安装成功:


    三:spring配置JMS


                    项目目录结构    

    第一步:创建实体类

    package chapter17.domain;
    
    import java.io.Serializable;
    
    
    public class JinNang implements Serializable{
    	private static final long serialVersionUID = 1L; 	
    	private String jice;//计策
    	private String people;//计策实施者
    	
    	public JinNang(){}
    	
    	public JinNang(String jice,String people){
    		this.jice=jice;
    		this.people=people;
    	}
    
    	public String getJice() {
    		return jice;
    	}
    
    	public void setJice(String jice) {
    		this.jice = jice;
    	}
    
    	public String getPeople() {
    		return people;
    	}
    
    	public void setPeople(String people) {
    		this.people = people;
    	}
    }

    第二步:创建service接口和实现类

    package chapter17.service.interfaces;
    
    public interface JinNangService {
    	public abstract void sendJinNang();
    
    }

    service实现类:

    package chapter17.service;
    
    import org.springframework.jms.core.JmsOperations;
    import chapter17.domain.JinNang;
    import chapter17.service.interfaces.JinNangService;
    
    public class JinNangServiceImpl implements JinNangService{
    
    	JmsOperations jmsOperations;
    	
    	public JinNangServiceImpl(JmsOperations jmsOperations){
    		this.jmsOperations=jmsOperations;
    	}
    	
    	@Override
    	public void sendJinNang() {
    		JinNang jinnang=new JinNang("空城计","诸葛亮");
    		jmsOperations.convertAndSend(jinnang);
    	}
    }

    JinNangServiceImpl有一个JmsOperations属性,并通过构造函数实例化,JmsTemplate 可以创建连接、获得会话以及发送和接收消息。这使得我们可以专注于构建要发送的消息或者处理接收到的消息。另外, JmsTemplate 可以处理所有抛出的笨拙的 JMSException 异常。如果在使用 JmsTemplate 时抛出 JMSException 异常, JmsTemplate 将捕获该异常,然后抛出一个非检查型异常,该异常是 Spring 自带的 JmsException 异常的子类。

    第三步:创建消息生产者

    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import chapter17.service.interfaces.JinNangService;
    
    
    public class JinNangProduce {
    	
    	public static void main(String[] args) {
    		 ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("chapter17/messaging.xml");
    		    JinNangService alertService = context.getBean(JinNangService.class);     
    		    alertService.sendJinNang();
    	}
    }

    生产者通过调用JinNangService来发送消息给消息代理activemq.

    message.xml代码如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns:p="http://www.springframework.org/schema/p"
    	xmlns:jms="http://www.springframework.org/schema/jms"
    	xmlns:amq="http://activemq.apache.org/schema/core"
    	xmlns:c="http://www.springframework.org/schema/c"
    	xsi:schemaLocation="http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms-3.2.xsd
    		http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd
    		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--定义消息队列  点对点模型-->
    <amq:queue id="jinnangQueue" physicalName="chapter17.queue" />
    <!-- 定义消息主题  对应订阅发布模型 -->
    <amq:topic id="jinnangTopic" physicalName="chapter17.topic" />
    <!-- 连接工厂 连接到activemq消息代理 -->
    <amq:connectionFactory id="connectionFactory" 
          brokerURL="tcp://localhost:61616" />
    <!--定义jmsTemplate spring封装的jms模板,类似于jdbcTemplate  -->
    <bean id="jmsTemplate" 
          class="org.springframework.jms.core.JmsTemplate"
          c:_-ref="connectionFactory" 
          p:defaultDestinationName="chapter17.queue" />
    <!-- 定义service实现类 -->
    <bean id="jinNangService" class="chapter17.service.JinNangServiceImpl"
          c:_-ref="jmsTemplate" />
    <!--jms监听器容器,添加监听器,当消息代理返回消息,触发监听器执行相应的代码  -->
    <jms:listener-container>
      <jms:listener destination="chapter17.queue" 
                    ref="jinnangConsumer" 
                    method="getJinnang" />
    </jms:listener-container>
    <!-- 定义消息消费者 -->
    <bean id="jinnangConsumer" class="chapter17.test.JinNangConsumer" />
    </beans>

    最后一步:定义消息消费者:

    package chapter17.test;
    
    import chapter17.domain.JinNang;
    
    public class JinNangConsumer {
    	
    	public void getJinnang(JinNang jinnang){
    		System.out.println(jinnang.getPeople()+"实施"+jinnang.getJice());
    	}
    }

    通过运行消息生产者JinNangProduce生产一条消息-发送一个JinNang对象给消息代理,jms:listener-container定义了一个监听器容器,该容器不停的去询问消息代理,有消息给我了没,如果有,该监听器容器查找该消息队列对应的监听器,然后监听器执行消费者代码jinnangConsumer.getJinNang();

    展开全文
  • Spring整合JMS异步消息

    千次阅读 2017-11-03 12:00:22
    Spring整合JMS异步消息 在应用程序之间通信的消息,可分为同步消息和异步消息两种。前者就是当请求的程序端发出请求后,一直处于等待状态(阻塞),直到接收请求方反馈正确的结果后,请求方才能继续往下执行。而...

    Spring整合JMS异步消息

      

        在应用程序之间通信的消息,可分为同步消息和异步消息两种。前者就是当请求的程序端发出请求后,一直处于等待状态(阻塞),直到接收请求方反馈正确的结果后,请求方才能继续往下执行。而异步消息,则请求的程序端发出请求后,则可以继续向下执行,不需要阻塞当前流程,很多时候大大提高了用户的即时体验。当然,选择同步还是异步形式的通信,全凭应用的场景而做出合理的选择,比如:针对用户的即时操作要求较高的功能,则建议采用异步通信;而例如工作流或对即时性要求不高的功能实现,则可采用同步方式通信。

     

     

    l  异步消息简介

    l  消息模型简介

    l  JMS异步消息

     

     

    一、异步消息简介

    让我们先看下同步消息的流程,如下所示:

    如上图,同步消息就是当客户端请求发出后,一直处于等待请求响应服务的反馈,否则会一直等待(阻塞)下去,待服务响应方返回内容后,客户端才能继续按程序流往下执行。接下来,再对比下异步消息,它的消息流程模型与同步很相似,如下所示:

    如上图,异步消息不同于同步消息的地方,主要就是当客户端发出请求到响应服务后,会继续按照程序流往下执行运作,此时,客户端不会被阻塞,也就是用户感觉不到被阻塞的体验。那么,当响应服务处理逻辑完成后,怎么才能找到是谁调取的它?一般我们会在调取的时候,传递一个绑定的回调标识进程,该进程会一直驻留等待,直到接收到服务响应的反馈才会被销毁,当然,也可以通过消息中间件,如:ActiveMQ或RabbitMQ等,先将请求消息放入中间件,待服务提供方完成处理后,从消息中间件中获取对应消息返还给客户端即可。

     

     

    二、消息模型简介

    上面介绍了同步及异步消息的流程及区别。接下来,我们一起看下现在通用的两种消息模型,分别是点对点模型(队列)和发布/订阅模型(主题)。

     

    1、点对点模型

    该模型中,每一个消息都有一个发送者和一个接收者,当消息代理得到消息时,它将其放入队列中,当接收者从队列中读取下一条消息时,消息会从队列中取出,并投递给接收者,此时对应的消息会从队列中删除,所以保证了消息只有一个接收者,如下所示:

     

     

    2、发布/订阅模型

    在发布-订阅消息模型中,消息会发送一个主题,而订阅了这个主题的所有接收者都会接收到此消息的副本。与队列类似,多个接收者可以监听同一个主题,不同的是消息不再只投递给一个接收者,所有订阅主题的接收者都可以收到消息副本,如下所示:

     

     

     

    三、JMS异步消息

    JMS,即为Java MessageService的简写,它是一个Java标准,定义了使用消息代理的通用API,类似于JDBC为数据库提供通用的接口一样。不过在Spring中提供了基于模版抽象实现JMS功能的支持,该模版就是JmsTemplate,使用它可以很方便地在消息生产方发送消息队列和主题消息,而接收方也能很方便地接收到消息。另外,Spring还提供了消息驱动POJO的概念,它是一个简单的java对象,其能够以异步的方式响应消息队列或主题上的消息。

     

    1、准备工作

     

    Maven配置:

         

     <dependency> 

           <groupId>org.springframework</groupId> 

           <artifactId>spring-jms</artifactId> 

           <version>4.3.2.RELEASE</version> 

           <scope>compile</scope> 

     </dependency> 

     <dependency> 

           <groupId>org.apache.activemq</groupId> 

           <artifactId>activemq-all</artifactId> 

           <version>5.9.0</version> 

           <scope>compile</scope> 

     </dependency>

     

     

    A、在Spring中搭建一消息代理角色。

    这里我们使用ActiveMQ作为消息代理角色,它是一个队列容器,可以很好地接收、存储、传递及管理消息,关于它的具体介绍,会在后续专题中介绍,这里主要介绍如何将其与Spring进行整合和使用。

    首先,我们到ActiveMQ官网下载最新的软件包,地址:

    http://activemq.apache.org/

     

    然后,解压下载的二进制软件包,并切换到其下的bin目录下,执行activemq  start 命令启动这个消息代理,供后续发送消息到该队列中做准备,如果未启动,则连接发送消息时,会报出未连接队列错误。

     

    B、建立一个连接工厂,通过它与消息代理进行直接交互。

    接下来,我们需要一个与消息代理队列交互的连接工厂,这里我选用ActiveMQ自身提供的连接工厂工具ActiveMQConnectionFactory ,它可以很好地与Spring结合,如下Java Config配置(与XML类似):

    @Bean

    public ActiveMQConnectionFactory connectionFactory() {    

           ActiveMQConnectionFactory mqConnectionFactory = new ActiveMQConnectionFactory();

           mqConnectionFactory.setBrokerURL("tcp://localhost:61616"); 

           mqConnectionFactory.setUserName("root"); 

           mqConnectionFactory.setPassword("123456");

           return mqConnectionFactory;

    }

    先建立一个ActiveMQConnectionFactory 实例,然后指定访问消息代理的地址:setBrokerURL ,而ActiveMQ默认的端口是61616。一般情况,消息代理组件都会有账号存在,所以需要设置访问的用户名和密码进行授权访问:setUserName 和setPassword 。

     

    C、声明消息目的地:队列和主题

    这里需声明一个ActiveMQ的点对点消息队列(ActiveMQQueue),和一个发布/订阅队列(ActiveMQTopic),因为它们指定了消息发送的队列类型和地址,具体配置如下:

    ActiveMQQueue 配置:

     

    @Bean

    public ActiveMQQueue queue() {

        ActiveMQQueue mqQueue = new ActiveMQQueue();

        mqQueue.setPhysicalName("channel.test.queue");  

        return mqQueue;

    }

     

    ActiveMQTopic 配置:

    @Bean

    public ActiveMQTopic topic() {

        ActiveMQTopic mqTopic = new ActiveMQTopic();

        mqTopic.setPhysicalName("channel.test.topic");  

        return mqTopic;

    }

     

    如上所示,不论哪种类型的队列,我们都需要为其配置对应的Physical Name地址,因为它们是目的队列的引用地址。

     

     

    D、自定义消息驱动,可以异步的接收消息

    为了可以在接收端异步的接收消息,我们需要实现基于EJB的消息驱动模型,为了测试队列及主题两种方式的消息分发,这里建立了两个消息驱动,具体如下:

        @Bean

        public CMessageHandler messageHandler() {      

           return new CMessageHandler();

        }

       

        @Bean

        public CMessageHandler2 messageHandler2() { 

           return new CMessageHandler2();

        }

     

    CMessageHandler.java:

    public class CMessageHandler {

        public void handleMessage(CMessage message) {

           System.out.println(message.getType() + ":" + message.getData());

        }

    }

     

    CMessageHandler2.java:

    public class CMessageHandler2 {

        public void handleMessage(CMessage message) {

           System.out.println(message.getType() + ":" + message.getData());

        }

    }

     

    需要注意的是这两个消息驱动POJO,在后面需要注入到消息监听适配器中,以实现异步接收消息的目的。

     

    E、声明消息监听适配器,以实现异步接收消息

    如上一步,我们已经自定义了两个消息驱动POJO模型,那么对应的也需要通过MessageListenerAdapter 监听方式,声明两个消息监听适配器,分别监听上面两个消息驱动,具体如下:

    @Bean

    public MessageListenerAdapter messageListenerAdapter(){

           MessageListenerAdapter  mlAdapter = new MessageListenerAdapter();

           mlAdapter.setDelegate(messageHandler());

           mlAdapter.setDefaultListenerMethod("handleMessage");

           return mlAdapter;

        }

       

    @Bean

    public MessageListenerAdapter messageListenerAdapter2() {

           MessageListenerAdapter  mlAdapter = new MessageListenerAdapter();

           mlAdapter.setDelegate(messageHandler2());

           mlAdapter.setDefaultListenerMethod("handleMessage");

           return mlAdapter;

        }

     

    如上所示,通过setDelegate 指定了对应的两个消息驱动POJO模型,然后使用setDefaultListenerMethod 指定了监听的启动方法。

     

    F、声明消息监听适配器容器,注入和管理监听适配器

    接下来,我们需要针对队列(Queue)和主题(Topic),分别声明对应的两个监听适配器容器,具体如下:

    @Bean

        public DefaultMessageListenerContainer queueMessageListenerAdapterContainer() {

           DefaultMessageListenerContainer container = new DefaultMessageListenerContainer();

           container.setConnectionFactory(connectionFactory());

           container.setDestination(queue());

           container.setMessageListener(messageListenerAdapter());

           return container;

        }

       

        @Bean

        public DefaultMessageListenerContainer queueMessageListenerAdapterContainer2() {  

           DefaultMessageListenerContainer container = new DefaultMessageListenerContainer();

           container.setConnectionFactory(connectionFactory());

           container.setDestination(queue());

           container.setMessageListener(messageListenerAdapter2());

           return container;

        }

       

        @Bean

        public DefaultMessageListenerContainer topicMessageListenerAdapterContainer() {

           DefaultMessageListenerContainer container = new DefaultMessageListenerContainer();

           container.setConnectionFactory(connectionFactory());

           container.setDestination(topic());

           container.setMessageListener(messageListenerAdapter());

           return container;

        }

       

        @Bean

        public DefaultMessageListenerContainer topicMessageListenerAdapterContainer2() {

           DefaultMessageListenerContainer container = new DefaultMessageListenerContainer();

           container.setConnectionFactory(connectionFactory());

           container.setDestination(topic());

           container.setMessageListener(messageListenerAdapter2());

           return container;

        }

    如上所示,我们声明了两种类型的监听容器,分别为Queue和Topic,而每种容器分别声明两个监听容器,对应上面的两个监听适配器。

    这里通过DefaultMessageListenerContainer 作为默认监听容器,使用setConnectionFactory 指定连接工厂,使用setDestination 绑定消息发送的目的地队列,并使用setMessageListener 设置对应的监听适配器。

     

    G、使用Spring提供的JmsTemplate模版

    在Spring中,已经提供了方便操作消息代理的工具JmsTemplate,通过它可以设置消息转发的模式(点对点或是发布/订阅),指定默认发送的消息目的地队列,及连接工厂。当然,为了保证传递的消息能够被正确的转换,我们可以指定消息转换器,如json格式转换,可以使用MappingJackson2MessageConverter ,可以这样配置:

    @Bean

        public MappingJackson2MessageConverter messageConverter() {  

           return new MappingJackson2MessageConverter();

        }

     

    那么,下面罗列下两个JmsTemplate的配置,具体细节可以查看代码中的注释说明,具体如下:

    @Bean

    public JmsTemplate jmsQueueTemplate() {      // 声明点对点队列JmsTemplate

           JmsTemplate jmsTemplate = new JmsTemplate();

           jmsTemplate.setConnectionFactory(connectionFactory());  // 指定连接消息代理工厂

           jmsTemplate.setMessageConverter(messageConverter());    // 指定默认的消息转换器

           jmsTemplate.setDefaultDestinationName("channel.test.queue");       // 指定默认消息地址,针对目的地址不变情况

           jmsTemplate.setPubSubDomain(false);      // 关闭发布/订阅模式

           return jmsTemplate;

        }

       

    @Bean

    public JmsTemplate jmsTopicTemplate() {      // 声明发布订阅队列JmsTemplate

           JmsTemplate jmsTemplate = new JmsTemplate();

           jmsTemplate.setConnectionFactory(connectionFactory());  // 指定连接消息代理工厂

            jmsTemplate.setMessageConverter(messageConverter());    // 指定默认的消息转换器

           jmsTemplate.setDefaultDestinationName("channel.test.topic");       // 指定默认消息地址,针对目的地址不变情况

           jmsTemplate.setPubSubDomain(true);    // 开启发布/订阅模式

           return jmsTemplate;

        }

     

     

    2、发送消息

    A、建立一个消息业务服务

    CMessageService.java:

    public interface CMessageService {

        public void sendMessage(CMessage message);

    }

     

    CMessageServiceImpl.java:

    @Service("CMessageService")

    public class CMessageServiceImpl implements CMessageService {

        @Autowired

        JmsTemplate jmsQueueTemplate;

       

        @Autowired

        JmsTemplate jmsTopicTemplate;

       

        public void sendMessage(final CMessage message) {

           JmsTemplate jmsTemplate = null;

           if(message.getType().equals("queue")) {

               jmsTemplate = jmsQueueTemplate;

           }else if(message.getType().equals("topic")) {

               jmsTemplate = jmsTopicTemplate;

           }

          

           jmsTemplate.send(new MessageCreator() {      // 缺省目的地地址

               public Message createMessage(Session session) throws JMSException {

                  return session.createObjectMessage(message);    // 创建消息

               }

           });

        }

    }

     

     

    B、建立一个发送消息控制器

    MessageAction.java:

    @RestController

    @RequestMapping("/message")

    public class MessageAction {

       @Autowired

       CMessageService messageService;

      

       @RequestMapping("/show")

       public ModelAndView sendPage() {

          return new ModelAndView("test/jms_api");

       }

      

       @RequestMapping(value="/sendMessage")

       public void sendMessage(HttpServletRequest request) throws Exception {

          String type = request.getParameter("type");

          String data = request.getParameter("data");

         

          CMessage message = new CMessage();  // 消息内容

          message.setType(type);

          message.setData(data);

          messageService.sendMessage(message);      // 发送消息

       }

    }

     

    C、建立一个发送的jsp页面

    jms_api.jsp(js部分):

    <script type="text/javascript">

               // 发送queue消息

               function sendQueueMessage(){

                   var data = $.trim($("#taQueue").val());

                  $.ajax({

                          url:'/xxx/message/sendMessage',

                          data:{type:'queue',data:data},

                          type:"get",

                          dataType:'json',

                          contentType:'application/json',

                          success:function(result){

                          }

                  });

               }

              

               // 发送topic消息

               function sendTopicMessage(){

                  var data = $.trim($("#taTopic").val());

                  $.ajax({

                          url:'/xxx/message/sendMessage',

                          data:{type:'topic',data:data},

                          type:"get",

                          dataType:'json',

                          contentType:'application/json',

                          success:function(result){

                          }

                  });

               }

           </script>

     

    具体的效果如下:

     

     

    3、接收消息

    接收消息,则是通过上面声明的消息驱动POJO来处理的,其通过注入到消息监听器中,当有消息到队列的时候,监听器会即时从队列中获取消息,并将其传递给对应的消息驱动POJO来处理,并且是以异步的方式处理的消息。

     

    A、点击发送Queue消息:

     

     

    B、点击发送Topic消息:

     

     

    如上所示,同样声明了两个监听者角色,Queue点对点模式时,接收者只收到一条消息,而Topic发布/订阅模式时,则注册订阅了这个主题的,都可以接收该主题消息,所以有两个接收者都收到消息。

     

     

     

     

    由于作者水平有限,请在评论或(QQ: 245389109)不吝发言讨论,谢谢。

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

    展开全文
  • Spring整合JMS(消息中间件)

    万次阅读 多人点赞 2016-06-20 10:18:26
    本篇主要介绍了异步消息机制及SpringJMS封装,本篇文章讲解较为详细,如果想直接看如何配置,可以参考: Spring整合JMS(消息中间件)实例,但还是建议大家先看完本篇文章。一、消息异步处理类似于RMI、Hessian、...
  • Java常见的spring笔试选择题

    千次阅读 2020-01-31 14:06:48
    1、Spring DAO 中最常用的类是() A,JdbcTemplate ,SimpleJdbcTemplate B,SimpleJdbcInsert,SimpleJdbcProcedure C,SimpleJdbcInsert ,SimpleJdbcStoredProc D,SimpleJdbcQuery ,SimpleJdbcExec 正确...
  • spring jms 消息 介绍 .NET和Java之间存在多种实现互操作性的方法。 最受欢迎的方法之一是使用Web服务,并设计可在两种环境中均可使用的WSDL和XML Schema。 如您所料,Web服务最适合基于Internet的应用程序。 如果...
  • 第29章 Spring框架对JMS的集成(二)

    千次阅读 2022-07-23 15:06:11
    在这个场景中,服务器端提供通用的用户验证服务,在客户端以JMS消息的形式发送验证请求之后,服务器端将接收这些验证请求并进行处理,一旦处理完毕,则将验证结果同样以JMS消息的形式发送给请求的客户端,客户端只有...
  • spring提供了一个jms集成框架,这个框架如spring 集成jdbc api一样,简化了jms api的使用。 jms可以简单的分成两个功能区,消息的生产和消息的消费。JmsTemplate类用来生成消息和同步接受消息。和其它java ee的消息...
  • spring框架三架构 这是Spring Framework Architecture的概述。 了解Spring Framework的各个组成部分如何组织以及如何相互联系。 如果您想了解什么是Spring框架及其功能,请阅读Spring框架简介。 总览 Spring是一个...
  • SpringJMS发送消息

    2019-08-27 23:47:05
    一、SpringJMS发送消息 Java消息服务(Java Message Service ,JMS)是一个Java标准,定义了使用消息代理的通用API。在JMS出现之前,每个消息代理都有私有的API,这就...Spring通过基于模板的抽象JMS功能提供...
  • Spring JMS

    2010-07-20 09:33:37
    SpringJMS 很好的结合介绍 并有实例模板
  • Spring框架对消息系统的整合提供了广泛的支持:从简单使用 Jms Template 的 JMS API,到可接收异步消息的完整基础结构。Spring AMQP 为“高级消息队列协议”提供了类似的功能集。 同时,Spring Boot 也为 ...
  • springCloud

    2018-08-09 16:54:33
    服务治理 由于Spring Cloud为服务治理做了一层抽象接口,所以在Spring Cloud应用中可以支持多种不同的服务治理框架,比如:Netflix Eureka、Consul、Zookeeper。在Spring Cloud服务治理抽象层的作用下,我们可以无缝...
  • -- Spring提供JMS工具类,它可以进行消息发送、接收等 -->   < bean   id = "jmsTemplate"   class = "org.springframework.jms.core.JmsTemplate" >     <!-- 这个connectionFactory对应的是我们定义的...
  • spring_in_action-sixth-edition.pdf
  • SpringJMS的支持

    2014-03-06 10:01:51
    Spring提供了一个用于简化JMS API使用的抽象框架,用户利用Spring使用JMS可以不用关心connection factory,session等资源的管理.类似于对JDBC的抽象,Spring提供了一个JmsTemplate类,抽象了操作JMS都必须做的公共步骤,...
  • 12.4.1. SessionFactory 抽象层 12.4.2. TopLinkTemplate 和 TopLinkDaoSupport 12.4.3. 基于原生的TopLink API的DAO实现 12.4.4. 事务管理 12.5. iBATIS SQL Maps 12.5.1. iBATIS 1.x和2.x的概览与区别 12.5.2. ...
  • SpringJMS的支持

    千次阅读 2017-04-21 20:52:16
    关于JMS的基础知识请参阅一篇写的简洁漂亮的文章,这篇文章将JMS的基本概念,以及JMS中主要类都介绍了。...关于JMS和AMQP的区别请参照这篇文章AMQP相对于JMS是一种跨语言的通用的协议下面开始介绍SpringJMS的支持
  • 文章目录前言点睛之笔:接口的抽象方法和抽象类的抽象方法的应用差别?举个例子UML 关系图关门,放代码抽象父类 Top子类 Bottom测试方法 和 结果最佳实践 前言 体能状态先于精神状态,习惯先于决心,聚焦先于喜好。...
  • 主要介绍了浅谈spring 线程异步执行,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • Spring Framework 5.3.6

    2021-05-06 12:56:16
    • JDBC抽象层提供了有针对性的异常等级(不再从SQL异常中提取原始代码),简化了错误处理, 大大减少了程序员的编码量. 再次利用JDBC时,你无需再写出另一个'终止'(finally) 模块. 并且面向JDBC的异常与Spring通用数据...
  • spring-kafka

    2021-05-01 23:16:16
    您将看到与Spring框架中的JMS支持和Spring AMQP中的RabbitMQ支持相似。 见关于该项目的更多datails。 卡夫卡制片人 为了连接到Kafka代理,您需要为spring.kafka.producer.bootstrap-servers指定host:port属性
  • java8 集合源码分析 Spring 编程思想示例项目 第一章 Spring Framework 总览 核心特性 核心特性(Core) IoC 容器(IoC ...Spring ...Spring 表达式(Spring ...事务抽象(Transactions) ...Spring ...Spring ...消息服务(JMS)

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 12,986
精华内容 5,194
关键字:

spring提供了jms层的抽象正确吗

spring 订阅