Solr+ActiveMq使用

本文介绍如何将全文搜索引擎Solr与消息中间件ActiveMQ整合,实现数据实时同步更新,提升搜索系统的实时性和准确性。文章详细讲解了Solr的安装配置、中文分词器集成及ActiveMQ的消息传递机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.solr简介
        Solr 是Apache下的一个顶级开源项目,采用Java开发,它是基于Lucene的全文搜索服务器。
    Solr提供了比Lucene更为丰富的查询语言,同时实现了可配置、可扩展,并对索引、搜索性能进
    行了优化。
        Solr可以独立运行,运行在Jetty、Tomcat等这些Servlet容器中,Solr 索引的实现方法很
    简单,用 POST 方法向 Solr 服务器发送一个描述 Field 及其内容的 XML文档,Solr根据xml文
    档添加、删除、更新索引 。Solr 搜索只需要发送HTTP GET 请求,然后对 Solr 返回Xml、json
    等格式的查询结果进行解析,组织页面布局。Solr不提供构建UI的功能,Solr提供了一个管理界
    面,通过管理界面可以查询Solr的配置和运行情况。

    将搜索内容添加到solr,将数据库查不来的对象,封装成SolrInputDocument 对象添加到 httpsolrserver对象中然后集体提交到solr服务器。
    
    由spring创建httpSolrServer 包括配置的solr服务器地址。对象,
将数据库查不来的对象,封装成SolrInputDocument 对象添加到 httpsolrserver对象中然后集体提交到solr服务器。
搜索时将keyword等封装到solrQuery中;然后通过solrServer对象的query方法,返回一个queryresponse响应对象,
然后得到结果list,经行回显 因为这样的话查询只查询solr中的数据,如果后台数据变化时solr中就没有了 所以通过activemq发送改变的id 需要消息模板和消息目的地。另一方有这类消息的activemq的监听,监听到信息后去后台查找此id的信息然后添加到solr中

3.activemq    
    简易的使用HTTP来传递消息的API
    处理事务性的消息
        ActiveMQ的此种特性主要管理消息的事务,以及消息持久化,即使在出错时也不会漏掉一条消息。消息服务器需要进行信息持久化,一个服务器集群可以提高其可用性,ActiveMQ正式这样的一个高可用性的消息服务器,典型的情况就是当一个Server Node掉线的时候,它上面的所有消息都会被保存下来,以便在它重新上线时继续处理。
    高性能的数据分发
 
2.linux solr整合Tomcat
    1.将dist\solr-4.10.3.war拷贝到Tomcat的webapp目录下改名为solr.war
    2.启动tomcat后,solr.war自动解压,将原来的solr.war删除(先关闭tomcat)。
    3.拷贝example\lib\ext 目录下所有jar包到Tomcat的webapp\solr\WEB-INF\lib目录下    
    4.拷贝log4j.properties文件在Tomcat下webapps\solr\WEB-INF目录中创建文件 classes文件夹,
        复制Solr目录下example\resources\log4j.properties至Tomcat下webapps\solr\WEB-INF\classes目录
    5.创建solrhome,自己创建一个目录,作为solr的工作目录
    6.修改Tomcat目录 下webapp\solr\WEB-INF\web.xml文件,如下所示:设置Solr home
        <!--配置jndi告诉solr工程我们的solrhome的位置-->
        <env-entry>
            <env-entry-name>solr/home</env-entry-name>
            <env-entry-value>D:/temp/solr/solrhome</env-entry-value>
            <env-entry-type>java.lang.String</env-entry-type>
        </env-entry>
3.安装中文分词器
    1.第一步:配置IKAnalyzer的jar包
        拷贝IKAnalyzer的文件到Tomcat下Solr目录中
        将IKAnalyzer2012FF_u1.jar拷贝到 Tomcat的webapps/solr/WEB-INF/lib 下。
    2.第二步:IKAnalyzer的配置文件
        在Tomcat的webapps/solr/WEB-INF/下创建classes目录
        将IKAnalyzer.cfg.xml   ext_stopword.dic  mydict.dic  拷贝到 Tomcat的
        webapps/solr/WEB-INF/classes下
        注意:ext_stopword.dic 和mydict.dic必须保存成无BOM的utf-8类型。
    3.第三步:修改schema.xml文件
        注意:把/opt/solr-4.10.3/example/solr/下的collection1文件夹拷贝到solr的工作目录下
        修改schema.xml文件(/opt/solr/collection1/conf)
        修改Solr的schema.xml文件,添加FieldType:
        <fieldType name="text_ik" class="solr.TextField">
          <analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/>
        </fieldType>
    4.第四步:设置业务系统Field
        设置业务系统Field,配置在schema.xml,solr中默认有id,对应了商品的id
        <field name="item_title" type="text_ik" indexed="true" stored="true"/>
        <field name="item_sell_point" type="text_ik" indexed="true" stored="true"/>
        <field name="item_price"  type="long" indexed="true" stored="true"/>
        <field name="item_image" type="string" indexed="false" stored="true" />
        <field name="item_category_name" type="string" indexed="true" stored="true" />
        <field name="item_desc" type="text_ik" indexed="true" stored="false" />
        
        <field name="item_keywords" type="text_ik" indexed="true" stored="false" multiValued="true"/>
        <copyField source="item_title" dest="item_keywords"/>
        <copyField source="item_sell_point" dest="item_keywords"/>
        <copyField source="item_category_name" dest="item_keywords"/>
        <copyField source="item_desc" dest="item_keywords"/>

4.添加jar
    <!-- solr客户端 -->
            <dependency>
                <groupId>org.apache.solr</groupId>
                <artifactId>solr-solrj</artifactId>
                <version>4.10.3</version>
            </dependency>

5.配置文件
<!-- 发消息方,activemq和spring整合 applicationcontext的配置-->
        <!-- 创建管理ActiveMQ的Connection的ConnectionFactory -->
        <bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
            <property name="brokerURL" value="tcp://10.0.129.26:61616"></property>
        </bean>
        
        <!-- 创建Spring的管理ActiveMQ的ConnectionFactory的 ConnectionFactory-->
        <bean id="connectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory">
            <property name="targetConnectionFactory" ref="targetConnectionFactory"></property>
        </bean>
        
        <!-- 创建spring提供的发消息的模板 -->
        <bean class="org.springframework.jms.core.JmsTemplate">
             <property name="connectionFactory" ref="connectionFactory"></property>
        </bean>
        
        <!-- 点对点发送的目的地 -->
        <bean class="org.apache.activemq.command.ActiveMQQueue">
            <constructor-arg value="itemAddQueue"></constructor-arg>
        </bean>
        
        <!-- 群发的目的地 -->
        <bean id="topicDes" class="org.apache.activemq.command.ActiveMQTopic">
             <constructor-arg>
                  <value>itemAddTopic</value>
             </constructor-arg>
        </bean>
        <bean id="topicDelItem" class="org.apache.activemq.command.ActiveMQTopic">
            <constructor-arg>
                <value>itemDelTopic</value>
            </constructor-arg>
        </bean>
        
<!-- 创建HttpSolrServer对象 -->    //接收方solr的 applicationcontext的配置
            <bean class="org.apache.solr.client.solrj.impl.HttpSolrServer">
                <constructor-arg index="0" value="http://10.0.129.80:8080/solr/collection1"></constructor-arg>
            </bean>

<!-- 消息的接收方,和spring整合 -->//监听方的activemq的 applicationcontext的配置
        <bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
            <property name="brokerURL" value="tcp://10.0.129.26:61616"></property>
        </bean>
        
        <bean id="connectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory">
            <property name="targetConnectionFactory" ref="targetConnectionFactory"></property>
        </bean>
        
        <bean id="topicDestination" class="org.apache.activemq.command.ActiveMQTopic">
            <constructor-arg value="itemAddTopic"></constructor-arg>
        </bean>
        <!-- 创建Item添加的监听 -->
        <bean id="itemAddListener" class="com.lp.listener.ItemAddMessageListener">
        </bean>
        <bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">
            <property name="connectionFactory" ref="connectionFactory"></property>
            <property name="destination" ref="topicDestination"></property>
            <property name="messageListener" ref="itemAddListener"></property>
        </bean>
        
        <!-- 创建item删除的监听 -->
        <bean id="topicDelItemDestination" class="org.apache.activemq.command.ActiveMQTopic">
            <constructor-arg value="itemDelTopic"></constructor-arg>
        </bean>
        <bean id="itemDelListener" class="com.lp.listener.ItemDelMessageListener"></bean>
        <bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">
            <property name="connectionFactory" ref="connectionFactory"></property>
            <property name="messageListener" ref="itemDelListener"></property>
            <property name="destination" ref="topicDelItemDestination"></property>
        </bean>    
            
6.在后台添加所有商品信息到solr索引
    @Autowired
    private SolrServer solrServer;
    public TaotaoResult importItemDatas() {
        List<SearchItem> items=mapper.findItems();//数据库查询到所有数据
        for(SearchItem item:items){
            SolrInputDocument doc=new SolrInputDocument();
            doc.setFile("id",item.getId());
            doc.setField("item_title", item.getTitle());
            doc.setField("item_sell_point", item.getSell_point());
            doc.setField("item_price", item.getPrice());
            doc.setField("item_image", item.getImage());
            doc.setField("item_category_name", item.getCategory_name());
            solrServer.add(doc);
        }
        solrServer.commit();
    }

7.service层配置文件封装搜索信息
    @Autowired
    private SearchDao searchDao;
    public SearchResult searchItemPage(String keyword, Integer page, Integer rows) {
        //构建搜索条件,并把条件封装到SolrQuery中
        SolrQuery solrQuery=new SolrQuery();
        //设置搜索内容
        solrQuery.setQuery(keyword);
        solrQuery.setStart((page-1)*rows);
        solrQuery.setRows(rows);
        //设置从哪个索引上搜索
        solrQuery.set("df","item_keywords");
        //设置高亮
        solrQuery.setHighlight(true);
        //设置谁得数据被高亮
        solrQuery.addHighlightField("item_title");
        solrQuery.setHighlightSimplePre("<em style=\"color:red\">");
        solrQuery.setHighlightSimplePost("</em>");    
        //去dao层获取搜索结果 之后封装结果接
        SearchResult result=searchDao.findItems(solrQuery);
        return result;
    }
    
8.dao搜索
    @Autowired
    private SolrServer solrServer;
    //solr的查询条件需要封装到SolrQuery对象中进行搜索
    //查询当前页的数据
    QueryResponse response=solrServer.query(solrQuery);
    //文档集合 得到当前页所有查询出的文档 List
    SolrDocumentList docs=response.getResults();
    //得到所有商品的个数
    long totalCount=docs.getNumFound();
    SearchResult searchResult = new SearchResult();
    searchResult.setTotalCount(totalCount);
    //得到高亮数据item_title
    Map<String,Map<String,List<String>>> highlighting=response.getHighlighting();
    //封装数据到items
    List<SearchItem> items=new ArrayList<>();
    for (SolrDocument doc : docs) {
        SearchItem item=new SearchItem();
            item.setId((String)doc.get("id"));
            item.setSell_point((String)doc.get("item_sell_point"));
            item.setImage((String)doc.get("item_image"));
            item.setPrice((long)doc.get("item_price"));
            item.setCategory_name((String)doc.get("item_category_name"));
            List<String > list=highlighting.get(doc.get("id")).get("item_title");
            if (list!=null&&list.size()>0) {
                item.setTitle(list.get(0));
            }else {
                item.setTitle((String)doc.get("item_title"));
            }
            items.add(item);
    }
    searchResult.setItems(items);
    
9.solr 添加商品时,发送消息通知,
    @Autowired //发消息模板
    JmsTemplate jmsTemplate;
    @Autowired //发消息目的地
    Destination topicdes;
    //把新添加的商品添加到solr的索引库使用发消息的机制,
    //发送商品的id,搜索系统接收到消息,从数据库查询商品,再添加到索引库
    jmsTemplate.send(topicdes,new MessageCreator(){
        public Message createMessage(Session session){
            TextMessage message=session.createMessage(id+"");
            return message;
        }
    });    
10.监听消息,将收到的id商品添加到solr索引
    @Autowired
    private SolrServer solrServer;
    //实现MessageListener接口
    public class ItemAddMessageListener implements MessageListener {
        public void onMessage(Message mess) {
            TextMessage message=(TextMessage)mess;
            long id=Long.parseLong(message.getText());
            Thread.sleep(100);
            SearchItem item=mapper.findItemById(id);
            SolrInputDocument document = new SolrInputDocument();
            ...
            ...
            solrServer.add(document);
            solrServer.commit();
        }
        
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值