一、后端Solr搜索业务逻辑
(1)新建Springboot项目prjsolrserach,在Dependencies中勾选Developer Tools里的Springboot DevTools、Web里的Spring Web、NoSQL里的 ->Finish
在pom.xml里更改版本号<version>1.5.9.RELEASE</version>
配置applicationcontext.properties
server.port=9003
spring.data.solr.host=http://localhost:8080/solr/hotel
(2)在po包引入与酒店相关的类,并对每个类implements Serializable序列化接口
新建vo包用来存放于Solr搜索相关的类ItripHotelVO implements Serializable
package com.zhaolong.biz;
import ...
public interface HotelSolrBiz {
public List<ItripHotelVO> queryPageAll(Integer page,Integer rows,ItripHotelVO hotelVO);
public int findMaxPage(Integer rows, ItripHotelVO hotelVO);
}
package com.zhaolong.biz.imp;
import ...
@Service
public class HotelSolrBizImg implements HotelSolrBiz {
@Autowired
private SolrClient solrClient;
public SolrClient getSolrClient() {
return solrClient;
}
public void setSolrClient(SolrClient solrClient) {
this.solrClient = solrClient;
}
@Override
public List<ItripHotelVO> queryPageAll(Integer page, Integer rows, ItripHotelVO hotelVO) {
System.out.println("hotelVO-->"+hotelVO);
//创建Solr的查询对象
SolrQuery solrQuery=new SolrQuery();
solrQuery.set("q", "*:*");
if(hotelVO!=null){
if(hotelVO.getHotelName()!=null){
//solrQuery.add("keyword",hotelVO.getHotelName());
solrQuery.set("q","keyword:"+hotelVO.getHotelName());
}
}
//设置分页显示
solrQuery.setStart((page-1)*rows);//从第几条记录开始
solrQuery.setRows(rows);//每页显示的记录数
//设置排序
solrQuery.setSort("id", SolrQuery.ORDER.asc);//按照id升序排列
try {
//QueryResponse表示查询响应的结果集合
QueryResponse response=solrClient.query(solrQuery);//执行查询
List<ItripHotelVO> hotelList=response.getBeans(ItripHotelVO.class);
return hotelList;
} catch (SolrServerException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@Override
public int findMaxPage(Integer rows, ItripHotelVO hotelVO) {
Long maxrow=0L;
int maxpage=1;
//创建Solr的查询对象
SolrQuery solrQuery=new SolrQuery();
solrQuery.set("q", "*:*");
if(hotelVO!=null){
if(hotelVO.getHotelName()!=null&&!hotelVO.getHotelName().equals("")){
System.out.println("hotelVO.getHotelName()--->"+hotelVO.getHotelName());
//solrQuery.add("keyword",hotelVO.getHotelName());
solrQuery.set("q","keyword:"+hotelVO.getHotelName());
}
}
try {
QueryResponse response=solrClient.query(solrQuery);
maxrow=response.getResults().getNumFound(); //通过solr文档对象获取找到的总记录数
System.out.println("maxrow-->"+maxrow);
List<ItripHotelVO> hotelList=response.getBeans(ItripHotelVO.class);
System.out.println("hotelList.size()-->"+hotelList.size());
//maxrow=(long)hotelList.size();//获取总记录数
if(maxrow>0){
maxpage=(int)(maxrow%rows==0?maxrow/rows:maxrow/rows+1);
return maxpage;
}
} catch (SolrServerException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return maxpage;
}
}
package com.zhaolong.action;
import ...
public interface HotelSolrAction {
public Map<String,Object> queryPageAll(HttpServletResponse response, HttpServletRequest request, Integer page, Integer rows, ItripHotelVO hotelVO);
}
package com.zhaolong.action.imp;
import ...
@CrossOrigin(allowCredentials = "true", maxAge = 3600) //跨域请求注解
@RestController
public class HotelActionImp implements HotelSolrAction {
@Autowired
private HotelSolrBiz hotelSolrBiz;
public HotelSolrBiz getHotelSolrBiz() {
return hotelSolrBiz;
}
public void setHotelSolrBiz(HotelSolrBiz hotelSolrBiz) {
this.hotelSolrBiz = hotelSolrBiz;
}
@Override
@RequestMapping(value = "queryPageAll_Hotel.do")
public Map<String,Object> queryPageAll(HttpServletResponse response, HttpServletRequest request, Integer page, Integer rows, ItripHotelVO hotelVO) {
Map<String,Object> map=new HashMap<String,Object>();
page=page==null?1:page;
rows=rows==null?5:rows;
//获取总页数
int maxpage=hotelSolrBiz.findMaxPage(rows,hotelVO);
List<ItripHotelVO> hotelVOList=hotelSolrBiz.queryPageAll(page,rows,hotelVO);
map.put("page",page);
map.put("rows",rows);
map.put("maxpage",maxpage);
map.put("hotelVOList",hotelVOList);
return map;
}
}
(3)在启动类PrjsolritrpsearcherApplication里添加扫描注释
注意在控制器类添加跨域请求注解@CrossOrigin(allowCredentials = "true", maxAge = 3600)
二、前端Solr搜索酒店业务
【搜索酒店】
(1)在prjview\src\main\webapp\tavern项目里打开trvern_list.js文件编写JavaScript事件,传递数据库里的对象并在trvern_list.js文件做对应修改
var tavernList = {
init: function (e) {
var sef = this;
sef.tavernMessage = '../hotelDetail.html';
var test = new Vcity.CitySelector({
input: 'tavernCitySelect1'
});
sef.bindEvent();
}, bindEvent: function (e) {
var sef = this;
$(".tavern-model-grid").on("click", function (e) {
if (!$(this).hasClass("tavern-gray")) {
window.location = sef.tavernMessage;
}
});
}, refresh: function (e) {
alert("刷新函数是否正常使用?")
}
};
$(function(){
showAll();
});
var page=1;
var maxpage=1;
var rows=5;
function showAll(){
/***************获取酒店数据*****************************************/
$.getJSON('http://localhost:9003/queryPageAll_Hotel.do?page='+page+'&rows='+rows,function(map){
page=map.page;
rows=map.rows;
maxpage=map.maxpage;
var hotelVOList=map.hotelVOList;
// alert(hotelVOList.length);
var mylist="";
for(var i=0;i<hotelVOList.length;i++){
var hotelVO=hotelVOList[i];
var hotelLevel=hotelVO.hotelLevel;
/***********获取星级************/
var lev='';
for(var n=0;n<hotelLevel;n++){
lev+="<i class='fa fa-diamond'></i>";
}
/*******************************/
/************酒店特征************/
var featureNames=hotelVO.featureNames;
var fnames=featureNames.split(","); //用逗号进行拆分
var featureName="";
//alert("fnames-->"+fnames.length);
for(var j=0;j<fnames.length;j++){
featureName+="<span class='item' >"+fnames[j]+"</span>";
}
/********************************/
/**************街景**************/
var extendPropertyNames=hotelVO.extendPropertyNames;
var epns=extendPropertyNames.split(',');
var extendPropertyName='';
for (var m=0;m<epns.length;m++){
extendPropertyName+=" <a>"+epns[m]+"</a>";
}
/********************************/
mylist+="<div class='tavern-model-grid'>"
+"<div class='modal-grid-left'>"
+"<div class='recommend'>"
+"<span class='text'>力推</span>"
+"</div>"
+"<img src='"+hotelVO.imgUrl+"' style='width: 285px'>"
+"</div>"
+"<div class='model-grid-right'>"
+"<div class='model-grid-title'>"+hotelVO.hotelName+"</div>"
+"<div class='model-grid-label'>"
+lev //星级
+featureName //特征
+"</div>"
+"<div class='model-grid-message'>"
+hotelVO.address //地址
+"<br>"
+extendPropertyName //街景
+"<i class='fa fa-wifi'></i>"
+"<i class=' icon-food'></i>"
+"<i class='fa fa-product-hunt'></i>"
+"</div>"
+"<div class='model-grid-grade'>"
+"<div class='cell-grade'>"
+"<div class='left'> <span>"+hotelVO.avgScore+"</span>/5分</div>"
+"<div class='right'>"+hotelVO.isOkCount+"用户推荐</div>"
+"<div>源自"+hotelVO.commentCount+"位住客点评</div>"
+"</div>"
+"<div class='cell-money'>"
+"¥<span>"+hotelVO.minPrice+"</span>起"
+"</div>"
+"<button class='btn btn-default' onclick='doDetail("+hotelVO.id+")'>查看详情</button>"
+"</div>"
+"</div>"
+"</div>";
}
$("#hotelist").html(mylist);
/*****************************获取酒店数据结束******************/
/************分页*******************/
var f1="<li><a href='#' id='up'>«</a></li>";
var fenyepage1=maxpage%5==0?maxpage/5:(Math.ceil(maxpage/5));
//alert("fenyepage1-->"+fenyepage1);
var f3="";
for(var i=1;i<=maxpage;i++){
f3+="<li><a href='#' onclick='dochangePage("+i+")'>"+i+"</a></li>"
}
var fenyeend=f1+f3+"<li><a href='#' id='next'>»</a></li>";
$("#pagelable").html(fenyeend);
/***********************************/
});
/*******************************************************************/
}
function dochangePage(pagenum){
// alert(pagenum);
page=pagenum;
showAll();
}
/***********查看详情**************/
function doDetail(id){
//alert(id); //将id传递给服务器进行处理,返回给hotelDetail.html
window.location='../hotelDetail.html页面'; //跳转到hotelDetail.html页面
}
【搜索区域】
(1)在prjsolrserach项目里新建mapper包,拷贝项目给定的mapper文件进去
(2)在resource目录下新建mapper包存放mapper映射文件
在mapper文件和mapper映射文件下添加findAll方法
package com.zhaolong.mapper;
@Mapper
public interface ItripAreaDicMapper {
...
public List<ItripAreaDic> findAll();
}
<mapper>
...
<select id="findAll" resultMap="BaseResultMap">
SELECT * FROM `itrip_area_dic` WHERE LEVEL=2 <!-- ‘2’代表“市” -->
</select>
</mapper>
(3)在biz包添加业务接口以及实现类
package com.zhaolong.biz;
import ...
public interface ItripAreaDicBiz {
public List<ItripAreaDic> findAll();
}
package com.zhaolong.biz.imp;
import ...
@Service
@Transactional
public class ItripAreaDicBizImp implements ItripAreaDicBiz {
@Autowired
private ItripAreaDicMapper itripAreaDicMapper;
public ItripAreaDicMapper getItripAreaDicMapper() {
return itripAreaDicMapper;
}
public void setItripAreaDicMapper(ItripAreaDicMapper itripAreaDicMapper) {
this.itripAreaDicMapper = itripAreaDicMapper;
}
@Override
public List<ItripAreaDic> findAll(){
return itripAreaDicMapper.findAll();
}
}
(4)在action包添加控制器接口以及实现类
package com.zhaolong.action;
import ...
public interface ItripAreaDicAction {
public List<ItripAreaDic> findAll(HttpServletRequest request, HttpServletResponse response);
}
package com.zhaolong.action.imp;
import...
//由于服务器端口不同,记得在控制器实现类上加跨域请求注解,否则访问不了
@CrossOrigin(allowCredentials = "true", maxAge = 3600) //跨域请求注解
@RestController
public class ItripAreaDicImpAction implements ItripAreaDicAction {
@Autowired
private ItripAreaDicBiz itripAreaDicBiz;
public ItripAreaDicBiz getItripAreaDicBiz() {
return itripAreaDicBiz;
}
public void setItripAreaDicBiz(ItripAreaDicBiz itripAreaDicBiz) {
this.itripAreaDicBiz = itripAreaDicBiz;
}
@Override
@RequestMapping(value = "findAll_ItripAreaDic.do")
public List<ItripAreaDic> findAll(HttpServletRequest request, HttpServletResponse response) {
return itripAreaDicBiz.findAll();
}
}
(5)在pom.xml文件中将需要的组件导入完整(Mybatis、数据库驱动、druid数据源、fastJson转换java对象为json字符串的包、redis依赖库、token依赖的组件包、jdis组件 )
配置applicationcontext.properties
server.port=9003
spring.data.solr.host=http://localhost:8080/solr/hotel
# \u6570\u636E\u6E90\u914D\u7F6E\u2014\u2014druid\u6570\u636E\u6E90
spring.datasource.url=jdbc:mysql://localhost:3306/itripdb
spring.datasource.username=root
spring.datasource.password=java
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.druid.initial-size=1
spring.datasource.druid.min-idle=1
spring.datasource.druid.max-active=20
spring.datasource.druid.test-on-borrow=true
spring.datasource.druid.stat-view.servlet.allow=true
# mybatis\u914D\u7F6E
mybatis.type-aliases-package=com.po
mybatis.mapper-locations=classpath:mapper/*.xml
##加入redis服务
#redis jedis配置
# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器地址
spring.redis.host=127.0.0.1
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
#spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.jedis.pool.max-idle=200
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.jedis.pool.max-wait=-1
# 连接池中的最小空闲连接
spring.redis.jedis.pool.min-idle=0
# 连接超时时间(毫秒)
spring.redis.timeout=0
#spring-session 使用
spring.session.store-type=none
(6)在启动类PrjsolritrpsearcherApplication里添加扫描注释
package com.zhaolong.main;
import ...
@SpringBootApplication
@ComponentScan(basePackages = {"com.zhaolong.biz","com.zhaolong.action"})
@MapperScan(basePackages = {"com.zhaolong.mapper"})
public class PrjsolritrpsearcherApplication {
public static void main(String[] args) {
SpringApplication.run(PrjsolritrpsearcherApplication.class, args);
}
}
由于trvern_list.html文件中关于区域搜索功能调用了cityselect.js
于是对cityselect.js进行逻辑代码的编写