商城项目笔记 · 5-7天

第五天

今天开始做前台。需要新建一个前台页面的表现层工程xing-portal-web,和一个管理前台页面内容的服务层工程xing-content。

整个工程依赖关系如下:

第六天

  • redis的安装

Redis是c语言开发的。安装redis需要c语言的编译环境。如果没有gcc需要在线安装。yum install gcc-c++

安装步骤:

第一步:redis的源码包上传到linux系统。

第二步:解压缩redis。tar zxvf redis-3.0.0.tar

第三步:编译。进入redis源码目录。make (这不是安装)

第四步:安装。make install PREFIX=/usr/local/redis(指定目录)。PREFIX参数指定redis的安装目录。一般软件安装到/usr目录下

前端启动:

在redis的安装目录下(/usr/local/redis/bin)直接启动redis-server

[root@localhost bin]# ./redis-server

后台启动:

把解压目录/root/redis-3.0.0/redis.conf复制到/usr/local/redis/bin目录下[root@localhost redis-3.0.0]# cp redis.conf /usr/local/redis/bin/

修改配置文件redis.conf,no改为yes。

带上配置文件启动redis:[root@localhost bin]# ./redis-server redis.conf

查看redis进程:[root@localhost bin]# ps aux|grep redis

root      5190  0.1  0.3  33936  1712 ?        Ssl  18:23   0:00 ./redis-server *:6379   
root      5196  0.0  0.1   4356   728 pts/0    S+   18:24   0:00 grep redis

关闭redis:

[root@localhost bin]kill+进程号:kill 5190
或者使用客户端关闭:./redis-cli shutdown(推荐)

使用客户端连接服务端:[root@localhost bin]# ./redis-cli

默认连接localhost(127.0.0.1)运行在6379端口的redis服务。

指定连接的ip和端口:[root@localhost bin]# ./redis-cli -h 192.168.25.153 -p 6379

-h:连接的服务器的地址       -p:服务的端口号

常用命令:健康检查:ping

redis的windows客户端管理软件:RedisDesktopManager

  • 五种数据类型

redis五种数据类型string,hash,list,set,sortedset,常用的有两个:string、hash。Redis中所有的数据都是字符串。命令不区分大小写,key是区分大小写的。Redis是单线程的。Redis中不适合保存内容大的数据。

String:key-value

创建:set key1 value1   查看key1的值:get key1      查看所有的key:keys  *

加一:incr key2(key2的值加1,key2的值需要是整数,如果key2不存在会自动创建)       减一:decr key2              

删除:del key2

Hash:key-fields-values(一般用于给key分类)

创建:hset hash1(这是key) field1(这是key) 1(这是value)       查看:hget hash1 field1     

查看所有的key:keys  *        查看hash1的所有key:hkeys hash1        查看hash1的所有值:hvals hash1

查看hash1所有的key和value:hgetall hash1

删除hash1里的某个key:hdel   hash1  field1

List:有序可重复

从左边添加:lpush list1 1 2 3 4 5 6     对应的顺序是:6 5 4 3 2 1

从右边添加:rpush list1 a b c    对应的顺序是:6 5 4 3 2 1 a b c 

查看list1中所有的元素:lrange  list1  0  -1

从左边取出一个元素:lpop list1(取出之后list1里就没有这个元素了)      从右边取出一个元素:rpop list1(取出之后list1里就没有这个元素了)    

Set:无序不能重复

创建:sadd set1 a b c d a b(set不允许重复,所以会去掉重复元素,只会存abcd)      删除一个元素:srem set1 a

查看set1的所有元素:smembers  set1      

set1减去set2的元素(补集):sdiff  set1  set2    (set1{1,2,3}、set2{3,4,5},减去之后就是{1,2})

set1和set2交集:sinter  set1  set2        并集:sunion set1  set2

SortedSet(zset):有序不能重复

创建:zadd zset1 1 a 3 b 2 c 4 d(四条数据,按指定顺序排列)    

查看zset1的所有元素:zrange  zset1 0 -1   )(顺序是a,c,b,d)(withscores,如果加上这个,会把分数也显示出来)

删除某个元素:zrem zset1 a                

查询之后按降序排列:zrevrange zset1  0 -1  (withscores,如果加上这个,会把分数也显示出来)

Key命令:

设置key的过期时间:expire key1 100 (100s后key1过期)

查看key的有效期:ttl key1 (如果是-1,表示是永久保存持久化的,如果是-2.表示不存在,如果是正数,表示有效期时间)

清除key的过期时间:persist key1 (此时key1就持久化了)

  •  
redis的持久化方案

Redis的所有数据都是保存到内存中的。

rdb:快照形式,定期把内存中当前时刻的数据保存到磁盘。Redis默认支持的持久化方案。(/usr/local/redis/bin目录下redis.conf中可以配置,dump.rdb)

aof形式:append only file。把所有对redis数据库操作的命令,增删改操作的命令。保存到文件中。数据库恢复时把所有的命令执行一遍即可。

配置:把no改为yes即可(如果使用这种方式,bin下会生成一个.aof文件):

如果两种持久化方案同时开启,会使用aof文件来恢复数据库。

  • redis集群

架构细节:

(1)所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽.

(2)节点的fail­通过集群中超过半数的节点检测失效时才生效.

(3)客户端与redis节点直连,不需要中间proxy.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可

(4)redis-cluster把所有的物理节点映射到[0-16383]slot,cluster 负责维护node<->slot<->value

Redis 集群中内置了 16384 个哈希槽,当需要在 Redis 集群中放置一个 key-value 时,redis 先对 key 使用 crc16 算法算出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,redis 会根据节点数量大致均等的将哈希槽映射到不同的节点

搭建redis集群:比较麻烦,不记录了

  • Jedis连接redis单机版

需要把jedis依赖的jar包添加到工程中,推荐添加到服务层。xing-content-Service工程中。

  1. 连接单机版

第一步:创建一个Jedis对象。需要指定服务端的ip及端口。

第二步:使用Jedis对象操作数据库,每个redis命令对应一个方法。

第三步:打印结果。

第四步:关闭Jedis

@Test

     public void testJedis() throws Exception {

          // 第一步:创建一个Jedis对象。需要指定服务端的ip及端口。

          Jedis jedis = new Jedis("192.168.25.153", 6379);

          // 第二步:使用Jedis对象操作数据库,每个redis命令对应一个方法。

          String result = jedis.get("hello");

          // 第三步:打印结果。

          System.out.println(result);

          // 第四步:关闭Jedis

          jedis.close();

     }

2.连接单机版使用连接池

第一步:创建一个JedisPool对象。需要指定服务端的ip及端口。

第二步:从JedisPool中获得Jedis对象。

第三步:使用Jedis操作redis服务器。

第四步:操作完毕后关闭jedis对象,连接池回收资源。

第五步:关闭JedisPool对象。

@Test

     public void testJedisPool() throws Exception {

          // 第一步:创建一个JedisPool对象。需要指定服务端的ip及端口。

          JedisPool jedisPool = new JedisPool("192.168.25.153", 6379);

          // 第二步:从JedisPool中获得Jedis对象。

          Jedis jedis = jedisPool.getResource();

          // 第三步:使用Jedis操作redis服务器。

          jedis.set("jedis", "test");

          String result = jedis.get("jedis");

          System.out.println(result);

          // 第四步:操作完毕后关闭jedis对象,连接池回收资源。

          jedis.close();

          // 第五步:关闭JedisPool对象。

          jedisPool.close();

     }

 

  • 向业务逻辑中添加缓存

因为在开发中连接的是redis单机版,而项目上线运行使用的是集群版,而向集群版和单机版存取数据的代码是不一样的,所以需要灵活切换。使用接口+两个实现类完成。工具类代码如下:

package com.xing.utils;

import java.util.List;

public interface JedisClient {

	String set(String key, String value);
	String get(String key);
	Boolean exists(String key);
	Long expire(String key, int seconds);
	Long ttl(String key);
	Long incr(String key);
	Long hset(String key, String field, String value);
	String hget(String key, String field);
	Long hdel(String key, String... field);
	Boolean hexists(String key, String field);
	List<String> hvals(String key);
	Long del(String key);
}

 

package com.xing.utils;

import java.util.List;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

public class JedisClientPool implements JedisClient {
	
	private JedisPool jedisPool;

	public JedisPool getJedisPool() {
		return jedisPool;
	}

	public void setJedisPool(JedisPool jedisPool) {
		this.jedisPool = jedisPool;
	}

	@Override
	public String set(String key, String value) {
		Jedis jedis = jedisPool.getResource();
		String result = jedis.set(key, value);
		jedis.close();
		return result;
	}

	@Override
	public String get(String key) {
		Jedis jedis = jedisPool.getResource();
		String result = jedis.get(key);
		jedis.close();
		return result;
	}

	@Override
	public Boolean exists(String key) {
		Jedis jedis = jedisPool.getResource();
		Boolean result = jedis.exists(key);
		jedis.close();
		return result;
	}

	@Override
	public Long expire(String key, int seconds) {
		Jedis jedis = jedisPool.getResource();
		Long result = jedis.expire(key, seconds);
		jedis.close();
		return result;
	}

	@Override
	public Long ttl(String key) {
		Jedis jedis = jedisPool.getResource();
		Long result = jedis.ttl(key);
		jedis.close();
		return result;
	}

	@Override
	public Long incr(String key) {
		Jedis jedis = jedisPool.getResource();
		Long result = jedis.incr(key);
		jedis.close();
		return result;
	}

	@Override
	public Long hset(String key, String field, String value) {
		Jedis jedis = jedisPool.getResource();
		Long result = jedis.hset(key, field, value);
		jedis.close();
		return result;
	}

	@Override
	public String hget(String key, String field) {
		Jedis jedis = jedisPool.getResource();
		String result = jedis.hget(key, field);
		jedis.close();
		return result;
	}

	@Override
	public Long hdel(String key, String... field) {
		Jedis jedis = jedisPool.getResource();
		Long result = jedis.hdel(key, field);
		jedis.close();
		return result;
	}

	@Override
	public Boolean hexists(String key, String field) {
		Jedis jedis = jedisPool.getResource();
		Boolean result = jedis.hexists(key, field);
		jedis.close();
		return result;
	}

	@Override
	public List<String> hvals(String key) {
		Jedis jedis = jedisPool.getResource();
		List<String> result = jedis.hvals(key);
		jedis.close();
		return result;
	}

	@Override
	public Long del(String key) {
		Jedis jedis = jedisPool.getResource();
		Long result = jedis.del(key);
		jedis.close();
		return result;
	}

}

 

在xing-common中新建一个接口,两个实现类(一个单机版,一个集群版),这样可以便捷地切换单机版和集群版

在xing-content-service中,配置applicationContext-redis.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
	http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
	http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd">

	<!-- 配置redis单机版的连接 -->
	<bean id="jedisPool" class="redis.clients.jedis.JedisPool">
		<constructor-arg name="host" value="192.168.159.130"></constructor-arg>
		<constructor-arg name="port" value="6379"></constructor-arg>
	</bean>
	<!-- 这个是操作单机版redis的工具类,实例化的是实现类,不是接口 -->
	<bean id="jedisClientPool" class="cn.xing.jedis.JedisClientPool">
		<property name="jedisPool" ref="jedisPool"></property>
	</bean>
	
	
	
</beans>

测试:

@Test
	public void testJedisClient() throws Exception {
		//初始化Spring容器
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring/applicationContext-redis.xml");
		//从容器中获得JedisClient对象
		JedisClient jedisClient = applicationContext.getBean(JedisClient.class);//这里使用接口,切换集群版时不需要改代码,只需改配置文件
		jedisClient.set("first", "100");
		String result = jedisClient.get("first");
		System.out.println(result);
		
				
	}

向业务(xing-content-service)中添加缓存:

分析:查询内容列表时添加缓存。

  1. 查询数据库之前先查询缓存。
  2. 查询到结果,直接响应结果。
  3. 查询不到,缓存中没有,需要查询数据库。
  4. 把查询结果添加到缓存中。
  5. 返回结果。

向redis中添加缓存,即键值对:

key:cid

value:内容列表。需要把java对象转换成json。

使用hash对key进行归类。key-fields-value

content_key:

            |--cid:内容所属的分类id

            |--value:list

注意:添加缓存不能影响正常业务逻辑。

代码:

@Override
	public List<TbContent> getContentList(long cid) {
		//查询缓存
		try {
			String json = jedisClient.hget(CONTENT_KEY, cid + "");
			//判断json是否为空
			if (StringUtils.isNotBlank(json)) {
				//把json转换成list
				List<TbContent> list = JsonUtils.jsonToList(json, TbContent.class);
				return list;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		//根据cid查询内容列表
		TbContentExample example = new TbContentExample();
		//设置查询条件
		Criteria criteria = example.createCriteria();
		criteria.andCategoryIdEqualTo(cid);
		//执行查询
		List<TbContent> list = contentMapper.selectByExample(example);
		//向缓存中添加数据
		try {
			jedisClient.hset(CONTENT_KEY, cid + "", JsonUtils.objectToJson(list));
		} catch (Exception e) {
			e.printStackTrace();
		}
		return list;
	}

缓存同步:如果修改了数据库的数据,而redis缓存没有清除,查询的依然是缓存中的数据,所以需要做同步

对内容信息做增删改操作后只需要把对应缓存删除即可。

例如添加一条新的内容,需要把对应的缓存删除,可以根据cid删除缓存。

@Override
	public E3Result addContent(TbContent content) {
		//补全属性
		content.setCreated(new Date());
		content.setUpdated(new Date());
		//插入数据
		contentMapper.insert(content);
		//缓存同步
		jedisClient.hdel(CONTENT_KEY, content.getCategoryId().toString());
		
		return E3Result.ok();
	}

 

第七天

  • solr服务搭建

Solr是一个独立的企业级搜索应用服务器,是java开发。需要安装jdk。安装环境Linux。需要安装Tomcat。

1.搭建步骤

第一步:把solr 的压缩包上传到Linux系统

第二步:解压solr:tar zxf solor….tgz

第三步:安装Tomcat,解压缩即可。

第四步:把解压后的solr文件夹里的/dist/solor-4.10.3.war复制到Tomcat的webapps下。

cp solr-4.10.3.war /usr/local/tomcat7/webapps/solr.war

第五步:解压缩war包:启动Tomcat即可解压,得到solr文件夹

第六步:把/root/solr-4.10.3/example/lib/ext目录下的所有的jar包,添加到solr工程中。

 [root@localhost ext]# cp * /usr/local/tomcat7/webapps/solr/WEB-INF/lib/

第七步:创建一个solrhome。/example/solr目录就是一个solrhome。复制此目录到/usr/local/,改名为solrhome,和tomcat同级目录。

 [root@localhost example]# cp -r solr /usr/local/solrhome

第八步:关联solr及solrhome。需要修改solr工程的web.xml文件。(图里面是错的,按照上面的命令,应该是/usr/local/solrhome)

第九步:启动Tomcat

http://安装solr的机器ip:8080/solr/

和windows下的配置完全一样。

  • 2.配置业务域

搜索商品,结果需要包含:

  1. 商品Id(solr自带id,不用设置)
  2. 商品标题
  3. 商品卖点
  4. 商品价格
  5. 商品图片
  6. 分类名称

创建对应的业务域,因为标题、卖点等有中文,需要制定中文分析器。

创建步骤:

把IK Analyzer 2012FF_hf1文件夹上传到linux

第一步:把中文分析器添加到工程中。

  1. 把文件夹里的IKAnalyzer2012FF_u1.jar添加到solr工程的lib目录下:
    打开文件夹(\去掉空格干扰):cd IK\ Analyzer\ 2012FF_hf,有一个jar包IKAnalyzer2012FF_u1.jar,把jar包复制到solr的lib下:
    cp IKAnalyzer2012FF_u1.jar /usr/local/tomcat7/webapps/solr/WEB-INF/lib/
  2. 把扩展词典、配置文件放到solr工程的WEB-INF/classes目录下:

    在tomcat7/webapps/solr/WEB-INF/下新建classes文件夹:mkdir classes

    把三个文件复制到classes里:cp ext_stopword.dic IKAnalyzer.cfg.xml mydict.dic /usr/local/tomcat7/webapps/solr/WEB-INF/classes/

第二步:配置字段类型FieldType,指定使用IKAnalyzer:

修改Solr的schema.xml文件(在solrhome/collection1/conf下),在最后一行,schema标签里添加FieldType:

<fieldType name="text_ik" class="solr.TextField">
  <analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/>
</fieldType>

第三步:配置业务域,type指定使用自定义的FieldType。

设置业务系统的字段Field,中文字段的type需要设置成自定义的字段类型

<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_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"/>

如图:

第四步:重启tomcat

网页访问solr,测试中文分析器和业务域

 

  • solr索引库增删改查测试

1.添加文档测试:

把solr的jar包依赖添加到search-service的pom工程中,

@Test

     public void addDocument() throws Exception {

          // 第一步:把solrJ的jar包添加到工程中。

          // 第二步:创建一个SolrServer,使用HttpSolrServer创建对象。

          SolrServer solrServer = new HttpSolrServer("http://192.168.25.154:8080/solr");

          // 第三步:创建一个文档对象SolrInputDocument对象。

          SolrInputDocument document = new SolrInputDocument();

          // 第四步:向文档中添加域。必须有id域,域的名称必须在schema.xml中定义。

          document.addField("id", "test001");

          document.addField("item_title", "测试商品");//名称和schema.xml中一样

          document.addField("item_price", "199");

          // 第五步:把文档添加到索引库中。

          solrServer.add(document);

          // 第六步:提交。

          solrServer.commit();

     }

2.删除文档测试

根据id删除

@Test
	public void deleteDocumentById() throws Exception {
		// 第一步:创建一个SolrServer对象。
		SolrServer solrServer = new HttpSolrServer("http://192.168.25.154:8080/solr");
		// 第二步:调用SolrServer对象的根据id删除的方法。
		solrServer.deleteById("1");
		// 第三步:提交。
		solrServer.commit();
	}

根据查询删除

@Test
	public void deleteDocumentByQuery() throws Exception {
		SolrServer solrServer = new HttpSolrServer("http://192.168.25.154:8080/solr");
		solrServer.deleteByQuery("title:change.me");//域+关键字
		solrServer.commit();
	}

查询索引库:

简单查询:

@Test
	public void queryDocument() throws Exception {
		// 第一步:创建一个SolrServer对象
		SolrServer solrServer = new HttpSolrServer("http://192.168.25.154:8080/solr");
		// 第二步:创建一个SolrQuery对象。
		SolrQuery query = new SolrQuery();
		// 第三步:向SolrQuery中添加查询条件、过滤条件。。。
		query.setQuery("*:*");
		// 第四步:执行查询。得到一个Response对象。
		QueryResponse response = solrServer.query(query);
		// 第五步:取查询结果。
		SolrDocumentList solrDocumentList = response.getResults();
		System.out.println("查询结果的总记录数:" + solrDocumentList.getNumFound());
		// 第六步:遍历结果并打印。
		for (SolrDocument solrDocument : solrDocumentList) {
			System.out.println(solrDocument.get("id"));
			System.out.println(solrDocument.get("item_title"));
			System.out.println(solrDocument.get("item_price"));
		}
	}

带高亮显示的查询:

@Test
	public void queryDocumentWithHighLighting() throws Exception {
		// 第一步:创建一个SolrServer对象
		SolrServer solrServer = new HttpSolrServer("http://192.168.25.154:8080/solr");
		// 第二步:创建一个SolrQuery对象。
		SolrQuery query = new SolrQuery();
		// 第三步:向SolrQuery中添加查询条件、过滤条件。。。
		query.setQuery("测试");
		//指定默认搜索域
		query.set("df", "item_keywords");
		//开启高亮显示
		query.setHighlight(true);
		//高亮显示的域
		query.addHighlightField("item_title");
		query.setHighlightSimplePre("<em>");
		query.setHighlightSimplePost("</em>");
		// 第四步:执行查询。得到一个Response对象。
		QueryResponse response = solrServer.query(query);
		// 第五步:取查询结果。
		SolrDocumentList solrDocumentList = response.getResults();
		System.out.println("查询结果的总记录数:" + solrDocumentList.getNumFound());
		// 第六步:遍历结果并打印。
		for (SolrDocument solrDocument : solrDocumentList) {
			System.out.println(solrDocument.get("id"));
			//取高亮显示
			Map<String, Map<String, List<String>>> highlighting = response.getHighlighting();
			List<String> list = highlighting.get(solrDocument.get("id")).get("item_title");
			String itemTitle = null;
			if (list != null && list.size() > 0) {
				itemTitle = list.get(0);
			} else {
				itemTitle = (String) solrDocument.get("item_title");
			}
			System.out.println(itemTitle);
			System.out.println(solrDocument.get("item_price"));
		}
	}

 

  • 一键导入商品数据到solr索引库功能实现

从数据库查询所有的商品信息,把信息导入索引库

新建服务层工程:

    可以参考e3-manager创建。

    e3-search(聚合工程pom)

            |--e3-search-interface(jar)

            |--e3-search-Service(war)

表现层是manager-web的索引库管理

dao层:

查询需要的信息:商品Id、商品标题、商品卖点、商品价格、商品图片、分类名称

创建需要的pojo来封装数据,因为涉及到多表查询,需要手动创建接口和mapper映射文件。

SELECT

        a.id,

        a.title,

        a.sell_point,

        a.price,

        a.image,

        b.`name` category_name(把b的name字段改名为category_name)

FROM

        `tb_item` a

LEFT JOIN tb_item_cat b ON a.cid = b.id

WHERE a.`status`=1

service层:查询商品列表,循环把商品数据添加到索引库。使用solr实现,返回E3Result

@Service
public class SearchItemServiceImpl implements SearchItemService {

	@Autowired
	private ItemMapper itemMapper;//自己写的
	@Autowired
	private SolrServer solrServer;//需要在spring配置
	
	@Override
	public E3Result importItmes() {
		try {
			//查询商品列表
			List<SearchItem> itemList = itemMapper.getItemList();
			//导入索引库
			for (SearchItem searchItem : itemList) {
				//创建文档对象
				SolrInputDocument document = new SolrInputDocument();
				//向文档中添加域
				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();
			//返回成功
			return E3Result.ok();
			
		} catch (Exception e) {
			e.printStackTrace();
			return E3Result.build(500, "商品导入失败");
		}
	}

}

applicationContext-solr.xml配置solrServer:

<bean id="httpSolrServer" class="org.apache.solr.client.solrj.impl.HttpSolrServer">
		<constructor-arg index="0" value="http://192.168.25.154:8080/solr"/>
	</bean>

然后发布服务。

表现层:是manager-web的索引库管理

表现层引用服务,

@Controller
public class SearchItemController {

	@Autowired
	private SearchItemService searchItemService;
	
	@RequestMapping("/index/item/import")
	@ResponseBody
	public E3Result impotItemIndex() {
		E3Result result = searchItemService.importItmes();
		return result;
	}

}

 

  • 解决Mapper映射文件不存在异常

mybatis报错,一般是找不到映射文件。(这个项目中,在search-service中,有手写的mapperxml和接口)

在e3-search-service的pom文件中需要添加资源配置。

<!-- 如果不添加此节点mybatis的mapper.xml文件都会被漏掉。 -->

      <build>

            <resources>

            <resource>

                <directory>src/main/java</directory>

                <includes>

                    <include>**/*.properties</include>

                    <include>**/*.xml</include>

                </includes>

                <filtering>false</filtering>

            </resource>

            <resource>

                <directory>src/main/resources</directory>

                <includes>

                    <include>**/*.properties</include>

                    <include>**/*.xml</include>

                </includes>

                <filtering>false</filtering>

            </resource>

        </resources>

      </build>
  • 首页搜索功能实现

整体思路:在search-service里,新建一个dao,serviceImpl负责组装查询条件和高亮条件,dao负责拿到条件进行查询,返回结果给serviceImpl。

原理代码: 

//使用solrJ实现查询
	@Test
	public void queryDocument() throws Exception {
		//创建一个SolrServer对象
		SolrServer solrServer = new HttpSolrServer("http://192.168.25.154:8080/solr");
		//创建一个查询对象,可以参考solr的后台的查询功能设置条件
		SolrQuery query = new SolrQuery();
		//设置查询条件
//		query.setQuery("阿尔卡特");
		query.set("q","阿尔卡特");
		//设置分页条件
		query.setStart(1);
		query.setRows(2);
		//开启高亮
		query.setHighlight(true);
		query.addHighlightField("item_title");
		query.setHighlightSimplePre("<em>");
		query.setHighlightSimplePost("</em>");
		//设置默认搜索域
		query.set("df", "item_title");
		//执行查询,得到一个QueryResponse对象。
		QueryResponse queryResponse = solrServer.query(query);
		//取查询结果总记录数
		SolrDocumentList solrDocumentList = queryResponse.getResults();
		System.out.println("查询结果总记录数:" + solrDocumentList.getNumFound());
		//取查询结果
		Map<String, Map<String, List<String>>> highlighting = queryResponse.getHighlighting();
		for (SolrDocument solrDocument : solrDocumentList) {
			System.out.println(solrDocument.get("id"));
			//取高亮后的结果
			List<String> list = highlighting.get(solrDocument.get("id")).get("item_title");
			String title= "";
			if (list != null && list.size() > 0) {
				//取高亮后的结果
				title = list.get(0);
			} else {
				title = (String) solrDocument.get("item_title");
			}
			System.out.println(title);
			System.out.println(solrDocument.get("item_sell_point"));
			System.out.println(solrDocument.get("item_price"));
			System.out.println(solrDocument.get("item_image"));
			System.out.println(solrDocument.get("item_category_name"));
		}
		
	}

项目中的代码:

package cn.xing.search.service.impl;

import org.apache.solr.client.solrj.SolrQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import cn.xing.pojo.SearchResult;
import cn.xing.search.dao.SearchDao;
import cn.xing.search.service.SearchService;
/**
 * 商品搜索service
 * @author Xing
 *
 */

@Service
public class SearchServiceImpl implements SearchService {
	
	@Autowired
	private SearchDao searchDao;
	
	
	@Override
	public SearchResult search(String keyword, int page, int rows) throws Exception {
		//设置查询条件,调用dao查询
		SolrQuery query=new SolrQuery();
		query.setQuery(keyword);//设置查询条件
		if(page<=0) page=1;
		query.setStart((page-1)*rows);//设置分页索引
		query.setRows(rows);
		//设置默认搜索域
		query.set("df", "item_title");
		//设置高亮显示
		query.setHighlight(true);
		query.addHighlightField("item_title");
		query.setHighlightSimplePre("<em style=\"color:red\">");
		query.setHighlightSimplePost("</em>");
		//执行查询
		SearchResult rs = searchDao.querySolr(query);
		//设置总页数
		int totalpages=rs.getRecourdCount()/rows;
		if(rs.getRecourdCount()%rows>0) totalpages++;
		rs.setTotalPages((long) totalpages);
		return rs;
	}

}

 

package cn.xing.search.dao;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import cn.xing.pojo.SearchItem;
import cn.xing.pojo.SearchResult;

/**
 * 搜索商品dao
 * @author Xing
 *
 */
@Repository
public class SearchDao {

	@Autowired
	private SolrServer solrServer;
	
	//根据查询条件query查询索引库
	public SearchResult querySolr(SolrQuery query) throws SolrServerException{
		QueryResponse queryResponse = solrServer.query(query);//查询索引库
		//取出总记录数
		SolrDocumentList results = queryResponse.getResults();
		long num = results.getNumFound();
		SearchResult rs=new SearchResult();
		rs.setRecourdCount((int) num);
		//取出商品列表,高亮
		Map<String, Map<String, List<String>>> highlighting = queryResponse.getHighlighting();
		List<SearchItem> itemList=new ArrayList<>();
		for (SolrDocument solrDocument : results) {
			SearchItem item=new SearchItem();
			item.setId((String) solrDocument.get("id"));
			item.setCategory_name((String) solrDocument.get("item_category_name"));
			item.setImage((String) solrDocument.get("item_image"));
			item.setPrice((long) solrDocument.get("item_price"));
			item.setSell_point((String) solrDocument.get("item_sell_point"));
			//取高亮结果
			List<String> list = highlighting.get(solrDocument.get("id")).get("item_title");
			if(list!=null&&list.size()>0){
				item.setTitle(list.get(0));
			}else{
				item.setTitle((String) solrDocument.get("item_title"));
			}
			itemList.add(item);
		}
		rs.setItemList(itemList);
		return rs;
	}
	
	
}

 

高亮结果:Map<String, Map<String, List<String>>>

整个工程的结构图:

 

 

 

转载于:https://my.oschina.net/u/3943244/blog/2961905

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值