2020-10-31 15:16:17 登录注册 RSS

当前位置: 公理网 >> 曝光信息 >> ActiveMQ在分布式项目中的实际应用(配合solr和freemarker)

ActiveMQ在分布式项目中的实际应用(配合solr和freemarker)
发布时间:2019-06-15| 来源:公理网 | 点击发表评论
具体需求:
后台添加商品后,需要执行两个操作:

????????1.同步索引库(商品搜索使用了Solr实现)

??????2.生成静态页面(使用freemarker)
实现构思:
??使用消息队列。MQ作为消息中间件,传递的消息内容为新增商品的ID。


20180622210750919?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM5MDU2ODA1/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70"alt=""/>

准备工作:
????????在需要的地方添加相应的依赖(基础依赖就不再说了)

????????商品服务需要发送商品添加消息,所以需要添加三个依赖,分别是整合Spring需要的两个Jar和ActiveMQ的Jar:

dependencygroupIdorg.springframework/groupIdartifactIdspring-jms/artifactId/dependencydependencygroupIdorg.springframework/groupIdartifactIdspring-context-support/artifactId/dependencydependencygroupIdorg.apache.activemq/groupIdartifactIdactivemq-all/artifactId/dependency
??????索引服务需要接收消息,然后同步索引库,所以需要添加四个依赖,分别是整合Spring需要的两个Jar和ActiveMQ的Jar和Solr客户端的Jar:

dependencygroupIdorg.springframework/groupIdartifactIdspring-jms/artifactId/dependencydependencygroupIdorg.springframework/groupIdartifactIdspring-context-support/artifactId/dependencydependencygroupIdorg.apache.activemq/groupIdartifactIdactivemq-all/artifactId/dependencydependencygroupIdorg.apache.solr/groupIdartifactIdsolr-solrj/artifactId/dependency
??????商品详情工程需要就收消息,然后生成静态页面,所以需要添加四个依赖,分别是整合Spring需要的两个Jar和ActiveMQ的Jar和Solr客户端的Jar:

dependencygroupIdorg.springframework/groupIdartifactIdspring-jms/artifactId/dependencydependencygroupIdorg.springframework/groupIdartifactIdspring-context-support/artifactId/dependencydependencygroupIdorg.apache.activemq/groupIdartifactIdactivemq-all/artifactId/dependencydependency????????groupIdorg.freemarker/groupId????????artifactIdfreemarker/artifactId/dependency具体实现:1.商品服务添加商品信息后,发布商品添加消息
spring-activemq.xml

!--真正可以产生Connection的ConnectionFactory,由对应的JMS服务厂商提供--beanid="targetConnectionFactory"propertyname="brokerURL"value="tcp://192.168.25.131:61616"/!--activemq地址--/bean!--Spring用于管理真正的ConnectionFactory的ConnectionFactory--beanid="connectionFactory"!--目标ConnectionFactory对应真实的可以产生JMSConnection的ConnectionFactory--propertyname="targetConnectionFactory"ref="targetConnectionFactory"//bean!--配置生产者--!--Spring提供的JMS工具类,它可以进行消息发送、接收等--beanid="jmsTemplate"!--这个connectionFactory对应的是我们定义的Spring提供的那个ConnectionFactory对象--propertyname="connectionFactory"ref="connectionFactory"//bean!--配置主题目的地,一对多的,以为我们有多个接收方,所以这里使用topic而不是queue--beanid="topicDestination"constructor-argvalue="itemAddTopic"//bean
ItemServiceImpl.java

@AutowiredprivateJmsTemplatejmsTemplate;@Resource//默认通过id注入,找不到再通过类型注入privateDestinationtopicDestination;@OverridepublicE3ResultaddItem(TbItemitem,Stringdesc,StringitemParams){//生成商品IDfinallongitemId=IDUtils.genItemId();/***将商品信息插入数据库中*///发送一个商品添加消息jmsTemplate.send(topicDestination,newMessageCreator(){@OverridepublicMessagecreateMessage(Sessionsession)throwsJMSException{TextMessagetextMessage=session.createTextMessage(itemId+"");returntextMessage;}});//返回成功returnE3Result.ok();}2.索引服务配置监听器,接收到商品添加消息后,同步索引库
ItemAddMessageListener.java

publicclassItemAddMessageListenerimplementsMessageListener{@AutowiredprivateItemMapperitemMapper;@AutowiredprivateSolrServersolrServer;@OverridepublicvoidonMessage(Messagemessage){try{//从消息中取商品IDTextMessagetextMessage=(TextMessage)message;Stringtext=textMessage.getText();LongitemId=newLong(text);//等待事务提交,不等待的话有可能下面会查不到商品信息Thread.sleep(1000);//根据商品ID查询商品信息SearchItemsearchItem=itemMapper.getItemById(itemId);//创建一个文档对象SolrInputDocumentdocument=newSolrInputDocument();//向文档对象中添加域document.addField("id",searchItem.getId());document.addField("item_title",searchItem.getTitle());document.addField("item_sell_point",searchItem.getSell_point());document.addField("item_price",searchItem.getPrice());document.addField("item_image",searchItem.getImage());document.addField("item_category_name",searchItem.getCategory_name());//把文档对象写入索引库solrServer.add(document);//提交solrServer.commit();}catch(Exceptione){e.printStackTrace();}}}
spring-activemq.xml

!--真正可以产生Connection的ConnectionFactory,由对应的JMS服务厂商提供--beanid="targetConnectionFactory"propertyname="brokerURL"value="tcp://192.168.25.131:61616"/!--activemq地址--/bean!--Spring用于管理真正的ConnectionFactory的ConnectionFactory--beanid="connectionFactory"!--目标ConnectionFactory对应真实的可以产生JMSConnection的ConnectionFactory--propertyname="targetConnectionFactory"ref="targetConnectionFactory"//bean!--配置主题目的地,一对多的--beanid="topicDestination"constructor-argvalue="itemAddTopic"//bean!--接收消息--!--配置消息监听器,监听商品添加消息,同步索引库--beanid="itemAddMessageListener"/!--消息监听容器--beanpropertyname="connectionFactory"ref="connectionFactory"/propertyname="destination"ref="topicDestination"/propertyname="messageListener"ref="itemAddMessageListener"//bean3.商品详情工程配置监听器,接收到商品添加消息后,生成商品详情静态页面
??????首先需要配置用于生成静态页面的模板,具体的配置方法请参看FreeMarker教程,在这里就不详细叙述了,我这里配置好的模板如下:

20180622214259114?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM5MDU2ODA1/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70"alt=""/>????item.ftl是商品详情页面,其他的几个ftl是include进去的,都需要配置。

FreeMarker的配置:


!--配置Freemaker--
beanid="freemarkerConfig"
propertyname="templateLoaderPath"value="/WEB-INF/ftl/"/!--指定模板所在目录--
propertyname="defaultEncoding"value="UTF-8"/!--指定默认编码方式--
/bean
监听器:

publicclassHtmlGenListenerimplementsMessageListener{
@Autowired
privateItemServiceitemService;
@Autowired
privateFreeMarkerConfigurerfreeMarkerConfigurer;
@Value("${HTML_GEN_PATH}")
privateStringHTML_GEN_PATH;//生成的静态页面保存的位置
@Override
publicvoidonMessage(Messagemessage){
try{
//从商品中取商品ID
TextMessagetextMessage=(TextMessage)message;
Stringtext=textMessage.getText();
LongitemId=newLong(text);
//等待事务提交(防止还未插入数据库就查询)
Thread.sleep(1000);
//根据商品id查询商品信息,商品基本信息和商品描述信息
TbItemtbItem=itemService.getItemById(itemId);
Itemitem=newItem(tbItem);
item.setPrice(item.getPrice()/100);//转换价格
//取商品描述
TbItemDescitemDesc=itemService.getItemDesc(itemId);
//创建一个数据集,将模板所需的数据全部放进去
MapString,Objectdata=newHashMap();
data.put("item",item);
data.put("itemDesc",itemDesc);
//加载模板对象
Configurationconfiguration=freeMarkerConfigurer.getConfiguration();
Templatetemplate=configuration.getTemplate("item.ftl");
//创建一个输出流,指定输出的目录以及文件名
Writerout=newFileWriter(HTML_GEN_PATH+itemId+".html");
//生成静态页面
template.process(data,out);
//关闭流
out.close();
}catch(Exceptione){
e.printStackTrace();
}
引用外部文件:

2018062221482076?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM5MDU2ODA1/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70"alt=""/>


监听器配置:

!--真正可以产生Connection的ConnectionFactory,由对应的JMS服务厂商提供--
beanid="targetConnectionFactory"
propertyname="brokerURL"value="tcp://192.168.25.131:61616"/
/bean
!--Spring用于管理真正的ConnectionFactory的ConnectionFactory--
beanid="connectionFactory"
!--目标ConnectionFactory对应真实的可以产生JMSConnection的ConnectionFactory--
propertyname="targetConnectionFactory"ref="targetConnectionFactory"/
/bean
!--配置主题目的地,一对多的--
beanid="topicDestination"
constructor-argvalue="itemAddTopic"/
/bean
!--接收消息--
!--监听商品添加消息,同步生成静态页面--
beanid="htmlGenListener"/
bean
propertyname="connectionFactory"ref="connectionFactory"/
propertyname="destination"ref="topicDestination"/
propertyname="messageListener"ref="htmlGenListener"/
/bean????????至此,功能就实现了。
功能测试
????????首先查看一下索引库,可以看到目前有943条商品数据

20180622215547627?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM5MDU2ODA1/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70"alt=""/>


??????添加商品:

20180622215811603?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM5MDU2ODA1/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70"alt=""/>


再次查看索引库,可以看到新增加了一条数据,现在有944条数据:

20180622215930325?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM5MDU2ODA1/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70"alt=""/>


搜索新添加的商品:,可以看到,已经能够查到了:

20180622220102615?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM5MDU2ODA1/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70"alt=""/>


查看商品详情,与本地生成的静态页面进行对比:

20180622220241170?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM5MDU2ODA1/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70"alt=""/>


本地生成静态文件:

2018062222032454?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM5MDU2ODA1/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70"alt=""/>


访问本地静态文件(这里使用了Nginx服务器访问静态文件)

20180622220500535?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM5MDU2ODA1/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70"alt=""/>


????????可以对比一下,两个绝对是一模一样的,这样以后用户访问商品详情的时候就可以返回给其一个静态页面,大大减小了服务器压力,访问速度加快,也提升了用户体验。





授予每个自然月内发布4篇或4篇以上原创或翻译IT博文的用户。不积跬步无以至千里,不积小流无以成江海,程序人生的精彩需要坚持不懈地积累!

39056805/article/details/79948304">SSM集成Redis做缓存(含完整...
42668355"target="_blank">qq_42668355:老哥项目运行报错CannotgetJedisconnection;nestedexceptionisredis.clients.jedis.exceptions.JedisConnectionException:Couldnotgetaresourcefromthepool
是不是你redis服务器关了???

最新新闻

手机浏览

公理网 版权所有

公理网 Total 0.116839(s) query 6, 报料QQ:点击这里

给我发消息