Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
Y
yudao-cloud
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
hblj
yudao-cloud
Commits
b98e21e1
提交
b98e21e1
authored
4月 24, 2019
作者:
YunaiV
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
前端 + 后端:商品搜索
上级
68dadab8
隐藏空白字符变更
内嵌
并排
正在显示
29 个修改的文件
包含
769 行增加
和
125 行删除
+769
-125
StringUtil.java
...ain/java/cn/iocoder/common/framework/util/StringUtil.java
+5
-2
SortingField.java
...ain/java/cn/iocoder/common/framework/vo/SortingField.java
+41
-0
search.js
mobile-web/src/api/search.js
+16
-0
productcard.vue
mobile-web/src/components/common/productcard.vue
+6
-3
searchtop.vue
mobile-web/src/components/search/searchtop.vue
+10
-5
request.js
mobile-web/src/config/request.js
+8
-0
router.js
mobile-web/src/config/router.js
+6
-6
search.vue
mobile-web/src/page/product/search.vue
+127
-68
CalcSkuPriceBO.java
...ain/java/cn/iocoder/mall/order/api/bo/CalcSkuPriceBO.java
+3
-1
ProductSpuMapper.xml
...rvice-impl/src/main/resources/mapper/ProductSpuMapper.xml
+2
-2
pom.xml
search/search-application/pom.xml
+74
-0
SearchApplication.java
...cn/iocoder/mall/search/application/SearchApplication.java
+13
-0
MVCConfiguration.java
...oder/mall/search/application/config/MVCConfiguration.java
+59
-0
SwaggerConfiguration.java
.../mall/search/application/config/SwaggerConfiguration.java
+36
-0
UsersProductSearchController.java
...cation/controller/users/UsersProductSearchController.java
+43
-0
application.yaml
...ch/search-application/src/main/resources/application.yaml
+9
-0
ProductSearchService.java
...java/cn/iocoder/mall/search/api/ProductSearchService.java
+2
-1
ESProductBO.java
.../main/java/cn/iocoder/mall/search/api/bo/ESProductBO.java
+86
-0
ESProductPageBO.java
...n/java/cn/iocoder/mall/search/api/bo/ESProductPageBO.java
+22
-0
ProductSearchPageDTO.java
.../cn/iocoder/mall/search/api/dto/ProductSearchPageDTO.java
+6
-1
SortFieldDTO.java
...ain/java/cn/iocoder/mall/search/api/dto/SortFieldDTO.java
+0
-17
pom.xml
search/search-service-impl/pom.xml
+12
-0
JPAConfiguration.java
...a/cn/iocoder/mall/search/biz/config/JPAConfiguration.java
+9
-0
ProductSearchConvert.java
...iocoder/mall/search/biz/convert/ProductSearchConvert.java
+39
-0
ProductRepository.java
...ava/cn/iocoder/mall/search/biz/dao/ProductRepository.java
+54
-0
ProductSearchServiceImpl.java
...der/mall/search/biz/service/ProductSearchServiceImpl.java
+33
-17
application.yaml
...h-service-impl/src/main/resources/config/application.yaml
+3
-2
ProductRepositoryTest.java
...cn/iocoder/mall/search/biz/dao/ProductRepositoryTest.java
+18
-0
ProductSearchServiceImplTest.java
...mall/search/biz/service/ProductSearchServiceImplTest.java
+27
-0
没有找到文件。
common/common-framework/src/main/java/cn/iocoder/common/framework/util/StringUtil.java
浏览文件 @
b98e21e1
...
...
@@ -9,6 +9,10 @@ import java.util.List;
public
class
StringUtil
{
public
static
boolean
hasText
(
String
str
)
{
return
StringUtils
.
hasText
(
str
);
}
public
static
String
join
(
Collection
<?>
coll
,
String
delim
)
{
return
StringUtils
.
collectionToDelimitedString
(
coll
,
delim
);
}
...
...
@@ -31,4 +35,4 @@ public class StringUtil {
return
org
.
apache
.
commons
.
lang3
.
StringUtils
.
substring
(
str
,
start
);
}
}
\ No newline at end of file
}
common/common-framework/src/main/java/cn/iocoder/common/framework/vo/SortingField.java
0 → 100644
浏览文件 @
b98e21e1
package
cn
.
iocoder
.
common
.
framework
.
vo
;
/**
* 排序字段 DTO
*
* 类名加了 ing 的原因是,避免和 ES SortField 重名。
*/
public
class
SortingField
{
/**
* 字段
*/
private
String
field
;
/**
* 排序
*/
private
String
order
;
public
SortingField
(
String
field
,
String
order
)
{
this
.
field
=
field
;
this
.
order
=
order
;
}
public
String
getField
()
{
return
field
;
}
public
SortingField
setField
(
String
field
)
{
this
.
field
=
field
;
return
this
;
}
public
String
getOrder
()
{
return
order
;
}
public
SortingField
setOrder
(
String
order
)
{
this
.
order
=
order
;
return
this
;
}
}
mobile-web/src/api/search.js
0 → 100644
浏览文件 @
b98e21e1
import
request
from
"../config/request"
;
export
function
getProductPage
({
cid
,
keyword
,
pageNo
,
pageSize
,
sortField
,
sortOrder
})
{
return
request
({
url
:
'/search-api/users/product/page'
,
method
:
'get'
,
params
:
{
cid
,
keyword
,
pageNo
:
pageNo
||
1
,
pageSize
:
pageSize
||
10
,
sortField
:
sortField
,
sortOrder
:
sortOrder
,
}
});
}
mobile-web/src/components/common/productcard.vue
浏览文件 @
b98e21e1
...
...
@@ -8,17 +8,20 @@
style=
"background:#fff"
>
<template
slot=
"thumb"
>
<img
:src=
"product.picUrls
[0]
"
/>
<img
:src=
"product.picUrls
&& product.picUrls ? product.picUrls[0] : ''
"
/>
<!-- TODO 芋艿 暂时去掉 -->
<!--
<p
v-if=
"product.imageTag!=null&&product.imageTag!=''"
class=
"image_tag"
>
{{
product
.
imageTag
}}
</p>
-->
</
template
>
<
template
slot=
"tags"
>
<p
class=
"price"
v-if=
"product.
price!=null && product.price !== ''
"
>
¥
<span>
{{
product
.
price
/
100.00
}}
</span>
<p
class=
"price"
v-if=
"product.
buyPrice || product.price
"
>
¥
<span>
{{
product
.
buyPrice
?
product
.
buyPrice
/
100.00
:
product
.
price
/
100.00
}}
</span>
<!-- TODO 芋艿 暂时去掉 -->
<!--
<van-tag
v-if=
"product.tags!=null"
v-for=
"tag in product.tags"
:key=
"tag"
plain
type=
"danger"
>
-->
<!--
{{
tag
}}
-->
<!--
</van-tag>
-->
<van-tag
v-if=
"product.promotionActivityTitle"
plain
type=
"danger"
>
{{
product
.
promotionActivityTitle
}}
</van-tag>
</p>
<!-- TODO 芋艿 暂时去掉 -->
...
...
mobile-web/src/components/search/searchtop.vue
浏览文件 @
b98e21e1
...
...
@@ -8,13 +8,13 @@
placeholder=
"请输入搜索关键词"
background=
"#fff"
show-action
@
search=
"onSearch"
@
search=
"onSearch
Click
"
slot=
"title"
>
<div
slot=
"action"
@
click=
"onSearch"
>
搜索
</div>
<div
slot=
"action"
@
click=
"onSearch
Click
"
>
搜索
</div>
</van-search>
</van-nav-bar>
</div>
</
template
>
...
...
@@ -27,14 +27,19 @@ export default {
components
:{
[
Search
.
name
]:
Search
,
},
props
:
{
// keyword: String,
// onSearch: Function,
},
data
(){
return
{
value
:
''
,
}
},
methods
:{
onSearch
()
{
console
.
log
(
this
.
value
);
onSearchClick
()
{
// this.props.onSearch(this.keyword);
this
.
$emit
(
'onSearch'
,
this
.
value
);
},
onBack
()
{
history
.
back
();
...
...
mobile-web/src/config/request.js
浏览文件 @
b98e21e1
...
...
@@ -28,6 +28,10 @@ const serviceRouter = function(requestUrl) {
prefix
:
'/pay-api'
,
target
:
'http://127.0.0.1:18084/pay-api'
,
},
'/search-api'
:
{
prefix
:
'/search-api'
,
target
:
'http://127.0.0.1:18086/search-api'
,
},
};
const
configProd
=
{
...
...
@@ -51,6 +55,10 @@ const serviceRouter = function(requestUrl) {
prefix
:
'/pay-api'
,
target
:
'http://api.shop.iocoder.cn:18099/pay-api'
,
},
'/search-api'
:
{
prefix
:
'/search-api'
,
target
:
'http://api.shop.iocoder.cn:18099/search-api'
,
},
};
if
(
process
.
env
.
NODE_ENV
==
'development'
)
{
...
...
mobile-web/src/config/router.js
浏览文件 @
b98e21e1
...
...
@@ -154,17 +154,17 @@ const routes = [
}
},
{
path
:
'/product/
:id
'
,
component
:
()
=>
import
(
'../page/product/
detail
'
),
path
:
'/product/
search
'
,
component
:
()
=>
import
(
'../page/product/
search
'
),
meta
:
{
title
:
'商品
详情
'
title
:
'商品
搜索
'
}
},
{
path
:
'/product/
search
'
,
component
:
()
=>
import
(
'../page/product/
search
'
),
path
:
'/product/
:id
'
,
component
:
()
=>
import
(
'../page/product/
detail
'
),
meta
:
{
title
:
'商品
搜索
'
title
:
'商品
详情
'
}
},
{
...
...
mobile-web/src/page/product/search.vue
浏览文件 @
b98e21e1
<
template
>
<div
class=
"product-list"
>
<searchtop/>
<searchtop
@
onSearch=
"onSearch"
/>
<div
class=
"filterbar"
>
<ul
:class=
"filter
s
ort?'show':''"
>
<li
:class=
"filter
index==0?'selected':''"
v-on:click=
"onFilterBar(0)"
><span>
{{
filterindex
==
11
?
'价格最低'
:(
filteri
ndex
==
12
?
'价格最高'
:
'综合'
)
}}
</span><van-icon
name=
"arrow"
class=
"down"
/></li>
<li
:class=
"filter
index
==1?'selected':''"
v-on:click=
"onFilterBar(1)"
><span>
销量
</span></li>
<li
:class=
"filter
index
==2?'selected':''"
v-on:click=
"onFilterBar(2)"
><span>
上新
</span></li>
<li
:class=
"filter
index
==3?'selected':''"
v-on:click=
"onFilterBar(3)"
><span>
筛选
</span></li>
<ul
:class=
"filter
S
ort?'show':''"
>
<li
:class=
"filter
Index===0?'selected':''"
v-on:click=
"onFilterBar(0)"
><span>
{{
filterIndex
==
11
?
'价格最低'
:(
filterI
ndex
==
12
?
'价格最高'
:
'综合'
)
}}
</span><van-icon
name=
"arrow"
class=
"down"
/></li>
<li
:class=
"filter
Index=
==1?'selected':''"
v-on:click=
"onFilterBar(1)"
><span>
销量
</span></li>
<li
:class=
"filter
Index=
==2?'selected':''"
v-on:click=
"onFilterBar(2)"
><span>
上新
</span></li>
<li
:class=
"filter
Index=
==3?'selected':''"
v-on:click=
"onFilterBar(3)"
><span>
筛选
</span></li>
</ul>
<div
:class=
"'item_options '+(filter
s
ort?'show':'')"
>
<div
:class=
"'item_options '+(filter
S
ort?'show':'')"
>
<ul>
<li
:class=
"filter
i
ndex==10?'selected':''"
v-on:click=
"onFilterBar(10)"
>
综合
</li>
<li
:class=
"filter
index==11?'selected':''"
v-on:click=
"onFilterBar(11)"
>
价格最低
</li>
<li
:class=
"filter
i
ndex==12?'selected':''"
v-on:click=
"onFilterBar(12)"
>
价格最高
</li>
<li
:class=
"filter
I
ndex==10?'selected':''"
v-on:click=
"onFilterBar(10)"
>
综合
</li>
<li
:class=
"filter
Index==11?'selected':''"
v-on:click=
"onFilterBar(11)"
>
价格降序
</li>
<li
:class=
"filter
I
ndex==12?'selected':''"
v-on:click=
"onFilterBar(12)"
>
价格最高
</li>
</ul>
</div>
<van-popup
v-model=
"filter
s
how"
position=
"right"
class=
"filterlayer"
>
<van-popup
v-model=
"filter
S
how"
position=
"right"
class=
"filterlayer"
>
<div
class=
"filterInner"
style=
"overflow-y: scroll;max-height: 100%;"
>
<ul>
<li>
...
...
@@ -163,14 +163,23 @@
</van-popup>
</div>
<div
v-for=
"(product,i) in products"
:key=
"i"
>
<product-card
:product=
'product'
@
click=
"showProduct(product)"
/>
</div>
<van-list
v-model=
"loading"
:finished=
"finished"
finished-text=
"没有更多了"
@
load=
"onLoad"
>
<div
v-for=
"(product,i) in products"
:key=
"i"
>
<product-card
:product=
'product'
@
click=
"showProduct(product)"
/>
</div>
</van-list>
</div>
</
template
>
<
script
>
import
searchtop
from
"../../components/search/searchtop"
;
import
{
getProductPage
}
from
"../../api/search"
;
export
default
{
components
:
{
...
...
@@ -178,70 +187,120 @@ export default {
},
data
()
{
return
{
value
:
""
,
filterindex
:
0
,
filtersort
:
false
,
filtershow
:
false
,
products
:[
{
id
:
1
,
imageURL
:
'https://pop.nosdn.127.net/19e33c9b-6c22-4a4b-96da-1cb7afb32712'
,
title
:
'BEYOND博洋家纺 床上套件 秋冬保暖纯棉床单被套 双人被罩 磨毛全棉印花床品四件套'
,
price
:
'13.00'
,
},
{
id
:
1
,
imageURL
:
'https://pop.nosdn.127.net/19e33c9b-6c22-4a4b-96da-1cb7afb32712'
,
title
:
'BEYOND博洋家纺 床上套件 秋冬保暖纯棉床单被套 双人被罩 磨毛全棉印花床品四件套'
,
price
:
'499.00'
,
tags
:[
'满199减100'
,
'2件起购'
],
},
{
id
:
1
,
imageURL
:
'https://pop.nosdn.127.net/19e33c9b-6c22-4a4b-96da-1cb7afb32712'
,
title
:
'BEYOND博洋家纺 床上套件 秋冬保暖纯棉床单被套 双人被罩 磨毛全棉印花床品四件套'
,
price
:
'499.00'
,
tags
:[
'新品'
],
imageTag
:
'仅剩1件'
,
},
{
id
:
1
,
imageURL
:
'https://pop.nosdn.127.net/19e33c9b-6c22-4a4b-96da-1cb7afb32712'
,
title
:
'BEYOND博洋家纺 床上套件 秋冬保暖纯棉床单被套 双人被罩 磨毛全棉印花床品四件套'
,
price
:
'499.00'
,
tags
:[
'赠'
],
imageTag
:
'预约'
,
},
{
id
:
1
,
imageURL
:
'https://pop.nosdn.127.net/19e33c9b-6c22-4a4b-96da-1cb7afb32712'
,
title
:
'BEYOND博洋家纺 床上套件 秋冬保暖纯棉床单被套 双人被罩 磨毛全棉印花床品四件套'
,
price
:
'15.00'
,
},
{
id
:
1
,
imageURL
:
'https://pop.nosdn.127.net/19e33c9b-6c22-4a4b-96da-1cb7afb32712'
,
title
:
'BEYOND博洋家纺 床上套件 秋冬保暖纯棉床单被套 双人被罩 磨毛全棉印花床品四件套'
,
price
:
'125.50'
,
},
]
page
:
0
,
pageSize
:
10
,
loading
:
false
,
finished
:
false
,
keyword
:
""
,
filterIndex
:
0
,
filterSort
:
false
,
// 是否展示几个【排序】
filterShow
:
false
,
// 是否展示【筛选】
sortField
:
undefined
,
sortOrder
:
undefined
,
products
:[]
};
},
methods
:
{
onFilterBar
(
value
)
{
if
(
value
==
0
)
{
this
.
filter
sort
=
!
this
.
filters
ort
;
}
else
if
(
value
==
3
)
{
this
.
filter
show
=
!
this
.
filters
how
;
if
(
value
==
=
0
)
{
this
.
filter
Sort
=
!
this
.
filterS
ort
;
}
else
if
(
value
==
=
3
)
{
this
.
filter
Show
=
!
this
.
filterS
how
;
}
else
{
this
.
filtersort
=
false
;
this
.
filterindex
=
value
;
// 如果非合法 10、11、12
if
(
value
!==
10
&&
value
!==
11
&&
value
!==
12
)
{
alert
(
'暂不支持'
);
return
;
}
// 设置 filterSort 和 filterIndex 属性
this
.
filterSort
=
false
;
this
.
filterIndex
=
value
;
// 标记加载中
this
.
loading
=
true
;
// 根据 value 的值,设置 sortField、sortOrder
switch
(
value
)
{
case
10
:
this
.
sortField
=
undefined
;
this
.
sortOrder
=
undefined
;
break
;
case
11
:
this
.
sortField
=
'buyPrice'
;
this
.
sortOrder
=
'desc'
;
break
;
case
12
:
this
.
sortField
=
'buyPrice'
;
this
.
sortOrder
=
'asc'
;
break
;
}
// 根据排序,重新搜索
let
page
=
1
;
getProductPage
({
pageNo
:
page
,
pageSize
:
this
.
pageSize
,
keyword
:
this
.
keyword
,
sortField
:
this
.
sortField
,
sortOrder
:
this
.
sortOrder
,
}).
then
(
data
=>
{
this
.
products
=
[];
this
.
handleData
(
page
,
data
);
});
}
},
showProduct
(
product
){
this
.
$router
.
push
(
'/product/'
+
product
.
id
);
},
onSearch
(
keyword
)
{
this
.
loading
=
true
;
// 设置 keyword
this
.
keyword
=
keyword
;
// 重置其它字段
this
.
filterIndex
=
0
;
this
.
filterSort
=
false
;
this
.
filterShow
=
false
;
this
.
sortField
=
undefined
;
this
.
sortOrder
=
undefined
;
// 查询
let
page
=
1
;
getProductPage
({
pageNo
:
page
,
pageSize
:
this
.
pageSize
,
keyword
:
keyword
,
}).
then
(
data
=>
{
this
.
products
=
[];
this
.
handleData
(
page
,
data
);
});
},
onLoad
()
{
// 进入下一页
let
page
=
this
.
page
+
1
;
getProductPage
({
pageNo
:
page
,
pageSize
:
this
.
pageSize
,
}).
then
(
data
=>
{
this
.
handleData
(
page
,
data
);
});
},
handleData
(
page
,
data
)
{
this
.
loading
=
true
;
// 设置下页面
this
.
page
=
page
;
// 数据保存到 list 中
this
.
products
.
push
(...
data
.
list
);
// 判断页数
if
(
this
.
products
.
length
>=
data
.
total
)
{
this
.
finished
=
true
;
}
// 标记不在加载中
this
.
loading
=
false
;
}
},
mounted
()
{
}
};
</
script
>
...
...
order/order-service-api/src/main/java/cn/iocoder/mall/order/api/bo/CalcSkuPriceBO.java
浏览文件 @
b98e21e1
...
...
@@ -4,12 +4,14 @@ import cn.iocoder.mall.promotion.api.bo.PromotionActivityBO;
import
lombok.Data
;
import
lombok.experimental.Accessors
;
import
java.io.Serializable
;
/**
* 计算商品 SKU 价格结果 BO
*/
@Data
@Accessors
(
chain
=
true
)
public
class
CalcSkuPriceBO
{
public
class
CalcSkuPriceBO
implements
Serializable
{
/**
* 满减送促销活动
...
...
product/product-service-impl/src/main/resources/mapper/ProductSpuMapper.xml
浏览文件 @
b98e21e1
...
...
@@ -33,10 +33,10 @@
FROM product_spu
<where>
<if
test=
"id != null"
>
id >
=
#{id}
id > #{id}
</if>
AND deleted = 0
</where>
AND deleted = 0
ORDER BY id ASC
LIMIT #{limit}
</select>
...
...
search/search-application/pom.xml
浏览文件 @
b98e21e1
...
...
@@ -11,5 +11,79 @@
<artifactId>
search-application
</artifactId>
<dependencies>
<dependency>
<groupId>
cn.iocoder.mall
</groupId>
<artifactId>
common-framework
</artifactId>
<version>
1.0-SNAPSHOT
</version>
</dependency>
<dependency>
<groupId>
cn.iocoder.mall
</groupId>
<artifactId>
user-sdk
</artifactId>
<version>
1.0-SNAPSHOT
</version>
</dependency>
<dependency>
<groupId>
cn.iocoder.mall
</groupId>
<artifactId>
search-service-api
</artifactId>
<version>
1.0-SNAPSHOT
</version>
</dependency>
<dependency>
<groupId>
cn.iocoder.mall
</groupId>
<artifactId>
search-service-impl
</artifactId>
<version>
1.0-SNAPSHOT
</version>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-web
</artifactId>
</dependency>
<dependency>
<groupId>
com.alibaba
</groupId>
<artifactId>
dubbo
</artifactId>
</dependency>
<dependency>
<groupId>
com.alibaba.boot
</groupId>
<artifactId>
dubbo-spring-boot-starter
</artifactId>
</dependency>
<dependency>
<groupId>
org.apache.curator
</groupId>
<artifactId>
curator-framework
</artifactId>
</dependency>
<dependency>
<groupId>
io.springfox
</groupId>
<artifactId>
springfox-swagger2
</artifactId>
</dependency>
<dependency>
<groupId>
io.springfox
</groupId>
<artifactId>
springfox-swagger-ui
</artifactId>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-test
</artifactId>
<scope>
test
</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 提供给 mapstruct 使用 -->
<plugin>
<groupId>
org.apache.maven.plugins
</groupId>
<artifactId>
maven-compiler-plugin
</artifactId>
</plugin>
<!-- 打包 -->
<plugin>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-maven-plugin
</artifactId>
</plugin>
</plugins>
</build>
</project>
search/search-application/src/main/java/cn/iocoder/mall/search/application/SearchApplication.java
0 → 100644
浏览文件 @
b98e21e1
package
cn
.
iocoder
.
mall
.
search
.
application
;
import
org.springframework.boot.SpringApplication
;
import
org.springframework.boot.autoconfigure.SpringBootApplication
;
@SpringBootApplication
(
scanBasePackages
=
{
"cn.iocoder.mall.search"
})
public
class
SearchApplication
{
public
static
void
main
(
String
[]
args
)
{
SpringApplication
.
run
(
SearchApplication
.
class
,
args
);
}
}
search/search-application/src/main/java/cn/iocoder/mall/search/application/config/MVCConfiguration.java
0 → 100644
浏览文件 @
b98e21e1
package
cn
.
iocoder
.
mall
.
search
.
application
.
config
;
import
cn.iocoder.common.framework.config.GlobalExceptionHandler
;
import
cn.iocoder.common.framework.servlet.CorsFilter
;
import
org.springframework.boot.web.servlet.FilterRegistrationBean
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.context.annotation.Import
;
import
org.springframework.web.servlet.config.annotation.EnableWebMvc
;
import
org.springframework.web.servlet.config.annotation.InterceptorRegistry
;
import
org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry
;
import
org.springframework.web.servlet.config.annotation.WebMvcConfigurer
;
@EnableWebMvc
@Configuration
@Import
(
value
=
{
GlobalExceptionHandler
.
class
,
// 统一全局返回
// AdminSecurityInterceptor.class, UserAccessLogInterceptor.class,
// UserSecurityInterceptor.class, AdminAccessLogInterceptor.class,
})
public
class
MVCConfiguration
implements
WebMvcConfigurer
{
// @Autowired
// private UserSecurityInterceptor securityInterceptor;
// @Autowired
// private UserSecurityInterceptor userSecurityInterceptor;
// @Autowired
// private UserAccessLogInterceptor userAccessLogInterceptor;
// @Autowired
// private AdminSecurityInterceptor adminSecurityInterceptor;
// @Autowired
// private AdminAccessLogInterceptor adminAccessLogInterceptor;
//
@Override
public
void
addInterceptors
(
InterceptorRegistry
registry
)
{
// // 用户
// registry.addInterceptor(userAccessLogInterceptor).addPathPatterns("/users/**");
// registry.addInterceptor(userSecurityInterceptor).addPathPatterns("/users/**"); // 只拦截我们定义的接口
// // 管理员
// registry.addInterceptor(adminAccessLogInterceptor).addPathPatterns("/admins/**");
// registry.addInterceptor(adminSecurityInterceptor).addPathPatterns("/admins/**");
}
@Override
public
void
addResourceHandlers
(
ResourceHandlerRegistry
registry
)
{
// 解决 swagger-ui.html 的访问,参考自 https://stackoverflow.com/questions/43545540/swagger-ui-no-mapping-found-for-http-request 解决
registry
.
addResourceHandler
(
"swagger-ui.html**"
).
addResourceLocations
(
"classpath:/META-INF/resources/swagger-ui.html"
);
registry
.
addResourceHandler
(
"webjars/**"
).
addResourceLocations
(
"classpath:/META-INF/resources/webjars/"
);
}
@Bean
public
FilterRegistrationBean
<
CorsFilter
>
corsFilter
()
{
FilterRegistrationBean
<
CorsFilter
>
registrationBean
=
new
FilterRegistrationBean
<>();
registrationBean
.
setFilter
(
new
CorsFilter
());
registrationBean
.
addUrlPatterns
(
"/*"
);
return
registrationBean
;
}
}
search/search-application/src/main/java/cn/iocoder/mall/search/application/config/SwaggerConfiguration.java
0 → 100644
浏览文件 @
b98e21e1
package
cn
.
iocoder
.
mall
.
search
.
application
.
config
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
springfox.documentation.builders.ApiInfoBuilder
;
import
springfox.documentation.builders.PathSelectors
;
import
springfox.documentation.builders.RequestHandlerSelectors
;
import
springfox.documentation.service.ApiInfo
;
import
springfox.documentation.spi.DocumentationType
;
import
springfox.documentation.spring.web.plugins.Docket
;
import
springfox.documentation.swagger2.annotations.EnableSwagger2
;
@Configuration
@EnableSwagger2
// TODO 生产环境时,禁用掉。
public
class
SwaggerConfiguration
{
@Bean
public
Docket
createRestApi
()
{
return
new
Docket
(
DocumentationType
.
SWAGGER_2
)
.
apiInfo
(
apiInfo
())
.
select
()
.
apis
(
RequestHandlerSelectors
.
basePackage
(
"cn.iocoder.mall.search.application.controller"
))
.
paths
(
PathSelectors
.
any
())
.
build
();
}
private
ApiInfo
apiInfo
()
{
return
new
ApiInfoBuilder
()
.
title
(
"搜索子系统"
)
.
description
(
"搜索子系统"
)
.
termsOfServiceUrl
(
"http://www.iocoder.cn"
)
.
version
(
"1.0.0"
)
.
build
();
}
}
search/search-application/src/main/java/cn/iocoder/mall/search/application/controller/users/UsersProductSearchController.java
0 → 100644
浏览文件 @
b98e21e1
package
cn
.
iocoder
.
mall
.
search
.
application
.
controller
.
users
;
import
cn.iocoder.common.framework.util.StringUtil
;
import
cn.iocoder.common.framework.vo.CommonResult
;
import
cn.iocoder.common.framework.vo.SortingField
;
import
cn.iocoder.mall.search.api.ProductSearchService
;
import
cn.iocoder.mall.search.api.bo.ESProductPageBO
;
import
cn.iocoder.mall.search.api.dto.ProductSearchPageDTO
;
import
com.alibaba.dubbo.config.annotation.Reference
;
import
io.swagger.annotations.Api
;
import
org.springframework.web.bind.annotation.GetMapping
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RequestParam
;
import
org.springframework.web.bind.annotation.RestController
;
import
java.util.Collections
;
@RestController
@RequestMapping
(
"users/product"
)
@Api
(
"商品搜索"
)
public
class
UsersProductSearchController
{
@Reference
(
validation
=
"true"
)
private
ProductSearchService
productSearchService
;
@GetMapping
(
"/page"
)
// TODO 芋艿,后面把 BO 改成 VO
public
CommonResult
<
ESProductPageBO
>
page
(
@RequestParam
(
value
=
"cid"
,
required
=
false
)
Integer
cid
,
@RequestParam
(
value
=
"keyword"
,
required
=
false
)
String
keyword
,
@RequestParam
(
value
=
"pageNo"
,
required
=
false
)
Integer
pageNo
,
@RequestParam
(
value
=
"pageSize"
,
required
=
false
)
Integer
pageSize
,
@RequestParam
(
value
=
"sortField"
,
required
=
false
)
String
sortField
,
@RequestParam
(
value
=
"sortOrder"
,
required
=
false
)
String
sortOrder
)
{
// 创建 ProductSearchPageDTO 对象
ProductSearchPageDTO
productSearchPageDTO
=
new
ProductSearchPageDTO
().
setCid
(
cid
).
setKeyword
(
keyword
)
.
setPageNo
(
pageNo
).
setPageSize
(
pageSize
);
if
(
StringUtil
.
hasText
(
sortField
)
&&
StringUtil
.
hasText
(
sortOrder
))
{
productSearchPageDTO
.
setSorts
(
Collections
.
singletonList
(
new
SortingField
(
sortField
,
sortOrder
)));
}
// 执行搜索
return
productSearchService
.
searchPage
(
productSearchPageDTO
);
}
}
search/search-application/src/main/resources/application.yaml
0 → 100644
浏览文件 @
b98e21e1
spring
:
application
:
name
:
search-application
# server
server
:
port
:
18086
servlet
:
context-path
:
/search-api/
search/search-service-api/src/main/java/cn/iocoder/mall/search/api/ProductSearchService.java
浏览文件 @
b98e21e1
package
cn
.
iocoder
.
mall
.
search
.
api
;
import
cn.iocoder.common.framework.vo.CommonResult
;
import
cn.iocoder.mall.search.api.bo.ESProductPageBO
;
import
cn.iocoder.mall.search.api.dto.ProductSearchPageDTO
;
public
interface
ProductSearchService
{
CommonResult
<
Integer
>
rebuild
();
CommonResult
searchPage
(
ProductSearchPageDTO
searchPageDTO
);
CommonResult
<
ESProductPageBO
>
searchPage
(
ProductSearchPageDTO
searchPageDTO
);
}
search/search-service-api/src/main/java/cn/iocoder/mall/search/api/bo/ESProductBO.java
0 → 100644
浏览文件 @
b98e21e1
package
cn
.
iocoder
.
mall
.
search
.
api
.
bo
;
import
lombok.Data
;
import
lombok.experimental.Accessors
;
import
java.io.Serializable
;
import
java.util.List
;
/**
* 商品 ES BO
*/
@Data
@Accessors
(
chain
=
true
)
public
class
ESProductBO
implements
Serializable
{
private
Integer
id
;
// ========== 基本信息 =========
/**
* SPU 名字
*/
private
String
name
;
/**
* 卖点
*/
private
String
sellPoint
;
/**
* 描述
*/
private
String
description
;
/**
* 分类编号
*/
private
Integer
cid
;
/**
* 分类名
*/
private
String
categoryName
;
/**
* 商品主图地数组
*/
private
List
<
String
>
picUrls
;
// ========== 其他信息 =========
/**
* 是否上架商品(是否可见)。
*
* true 为已上架
* false 为已下架
*/
private
Boolean
visible
;
/**
* 排序字段
*/
private
Integer
sort
;
// ========== Sku 相关字段 =========
/**
* 原价格,单位:分
*/
private
Integer
originalPrice
;
/**
* 购买价格,单位:分。
*/
private
Integer
buyPrice
;
/**
* 库存数量
*/
private
Integer
quantity
;
// ========== 促销活动相关字段 =========
// 目前只促销单体商品促销,目前仅限制折扣。
/**
* 促销活动编号
*/
private
Integer
promotionActivityId
;
/**
* 促销活动标题
*/
private
String
promotionActivityTitle
;
/**
* 促销活动类型
*/
private
Integer
promotionActivityType
;
}
search/search-service-api/src/main/java/cn/iocoder/mall/search/api/bo/ESProductPageBO.java
0 → 100644
浏览文件 @
b98e21e1
package
cn
.
iocoder
.
mall
.
search
.
api
.
bo
;
import
lombok.Data
;
import
lombok.experimental.Accessors
;
import
java.io.Serializable
;
import
java.util.List
;
@Data
@Accessors
(
chain
=
true
)
public
class
ESProductPageBO
implements
Serializable
{
/**
* 管理员数组
*/
private
List
<
ESProductBO
>
list
;
/**
* 总量
*/
private
Integer
total
;
}
search/search-service-api/src/main/java/cn/iocoder/mall/search/api/dto/ProductSearchPageDTO.java
浏览文件 @
b98e21e1
package
cn
.
iocoder
.
mall
.
search
.
api
.
dto
;
import
cn.iocoder.common.framework.util.CollectionUtil
;
import
cn.iocoder.common.framework.vo.SortingField
;
import
lombok.Data
;
import
lombok.experimental.Accessors
;
import
java.util.List
;
import
java.util.Set
;
/**
* 商品检索分页 DTO
...
...
@@ -12,6 +15,8 @@ import java.util.List;
@Accessors
(
chain
=
true
)
public
class
ProductSearchPageDTO
{
public
static
final
Set
<
String
>
SORT_FIELDS
=
CollectionUtil
.
asSet
(
"buyPrice"
);
/**
* 分类编号
*/
...
...
@@ -33,6 +38,6 @@ public class ProductSearchPageDTO {
/**
* 排序字段数组
*/
private
List
<
Sort
FieldDTO
>
sorts
;
private
List
<
Sort
ingField
>
sorts
;
}
search/search-service-api/src/main/java/cn/iocoder/mall/search/api/dto/SortFieldDTO.java
deleted
100644 → 0
浏览文件 @
68dadab8
package
cn
.
iocoder
.
mall
.
search
.
api
.
dto
;
/**
* 排序字段 DTO
*/
public
class
SortFieldDTO
{
/**
* 字段
*/
private
String
field
;
/**
* 排序
*/
private
String
order
;
}
search/search-service-impl/pom.xml
浏览文件 @
b98e21e1
...
...
@@ -49,6 +49,18 @@
<artifactId>
spring-boot-starter-test
</artifactId>
<scope>
test
</scope>
</dependency>
<dependency>
<groupId>
com.alibaba.boot
</groupId>
<!-- 引入该包,为了写单元测试用 -->
<artifactId>
dubbo-spring-boot-starter
</artifactId>
</dependency>
<dependency>
<groupId>
org.apache.curator
</groupId>
<!-- 引入该包,为了写单元测试用 -->
<artifactId>
curator-framework
</artifactId>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<!-- 引入该包,为了写单元测试用 -->
<artifactId>
spring-boot-starter-web
</artifactId>
</dependency>
</dependencies>
<build>
...
...
search/search-service-impl/src/main/java/cn/iocoder/mall/search/biz/config/JPAConfiguration.java
0 → 100644
浏览文件 @
b98e21e1
package
cn
.
iocoder
.
mall
.
search
.
biz
.
config
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories
;
@Configuration
@EnableElasticsearchRepositories
(
basePackages
=
"cn.iocoder.mall.search.biz.dao"
)
public
class
JPAConfiguration
{
}
search/search-service-impl/src/main/java/cn/iocoder/mall/search/biz/convert/ProductSearchConvert.java
0 → 100644
浏览文件 @
b98e21e1
package
cn
.
iocoder
.
mall
.
search
.
biz
.
convert
;
import
cn.iocoder.mall.order.api.bo.CalcSkuPriceBO
;
import
cn.iocoder.mall.product.api.bo.ProductSpuDetailBO
;
import
cn.iocoder.mall.promotion.api.bo.PromotionActivityBO
;
import
cn.iocoder.mall.search.api.bo.ESProductBO
;
import
cn.iocoder.mall.search.biz.dataobject.ESProductDO
;
import
org.mapstruct.Mapper
;
import
org.mapstruct.Mappings
;
import
org.mapstruct.factory.Mappers
;
import
java.util.List
;
@Mapper
public
interface
ProductSearchConvert
{
ProductSearchConvert
INSTANCE
=
Mappers
.
getMapper
(
ProductSearchConvert
.
class
);
@Mappings
({})
ESProductDO
convert
(
ProductSpuDetailBO
spu
);
@Mappings
({})
default
ESProductDO
convert
(
ProductSpuDetailBO
spu
,
CalcSkuPriceBO
calcSkuPrice
)
{
// Spu 的基础数据
ESProductDO
product
=
this
.
convert
(
spu
);
product
.
setOriginalPrice
(
calcSkuPrice
.
getOriginalPrice
()).
setBuyPrice
(
calcSkuPrice
.
getBuyPrice
());
// 设置促销活动相关字段
if
(
calcSkuPrice
.
getTimeLimitedDiscount
()
!=
null
)
{
PromotionActivityBO
activity
=
calcSkuPrice
.
getTimeLimitedDiscount
();
product
.
setPromotionActivityId
(
activity
.
getId
()).
setPromotionActivityTitle
(
activity
.
getTitle
())
.
setPromotionActivityType
(
activity
.
getActivityType
());
}
// 返回
return
product
;
}
List
<
ESProductBO
>
convert
(
List
<
ESProductDO
>
list
);
}
search/search-service-impl/src/main/java/cn/iocoder/mall/search/biz/dao/ProductRepository.java
浏览文件 @
b98e21e1
package
cn
.
iocoder
.
mall
.
search
.
biz
.
dao
;
import
cn.iocoder.common.framework.util.CollectionUtil
;
import
cn.iocoder.common.framework.util.StringUtil
;
import
cn.iocoder.common.framework.vo.SortingField
;
import
cn.iocoder.mall.search.biz.dataobject.ESProductDO
;
import
org.elasticsearch.common.lucene.search.function.FunctionScoreQuery
;
import
org.elasticsearch.index.query.QueryBuilders
;
import
org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder
;
import
org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders
;
import
org.elasticsearch.search.sort.SortBuilders
;
import
org.elasticsearch.search.sort.SortOrder
;
import
org.springframework.data.domain.Page
;
import
org.springframework.data.domain.PageRequest
;
import
org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder
;
import
org.springframework.data.elasticsearch.repository.ElasticsearchRepository
;
import
org.springframework.stereotype.Repository
;
import
java.util.List
;
import
static
org
.
elasticsearch
.
index
.
query
.
QueryBuilders
.
matchQuery
;
@Repository
public
interface
ProductRepository
extends
ElasticsearchRepository
<
ESProductDO
,
Integer
>
{
@Deprecated
ESProductDO
findByName
(
String
name
);
default
Page
<
ESProductDO
>
search
(
Integer
cid
,
String
keyword
,
Integer
pageNo
,
Integer
pageSize
,
List
<
SortingField
>
sortFields
)
{
NativeSearchQueryBuilder
nativeSearchQueryBuilder
=
new
NativeSearchQueryBuilder
()
.
withPageable
(
PageRequest
.
of
(
pageNo
-
1
,
pageSize
));
// 筛选条件 cid
if
(
cid
!=
null
)
{
nativeSearchQueryBuilder
.
withFilter
(
QueryBuilders
.
termQuery
(
"cid"
,
cid
));
}
// 筛选
if
(
StringUtil
.
hasText
(
keyword
))
{
FunctionScoreQueryBuilder
.
FilterFunctionBuilder
[]
functions
=
{
// TODO 芋艿,分值随便打的
new
FunctionScoreQueryBuilder
.
FilterFunctionBuilder
(
matchQuery
(
"name"
,
keyword
),
ScoreFunctionBuilders
.
weightFactorFunction
(
10
)),
new
FunctionScoreQueryBuilder
.
FilterFunctionBuilder
(
matchQuery
(
"sellPoint"
,
keyword
),
ScoreFunctionBuilders
.
weightFactorFunction
(
2
)),
new
FunctionScoreQueryBuilder
.
FilterFunctionBuilder
(
matchQuery
(
"categoryName"
,
keyword
),
ScoreFunctionBuilders
.
weightFactorFunction
(
3
)),
// new FunctionScoreQueryBuilder.FilterFunctionBuilder(matchQuery("description", keyword),
// ScoreFunctionBuilders.weightFactorFunction(2)), // TODO 芋艿,目前这么做,如果商品描述很长,在按照价格降序,会命中超级多的关键字。
};
FunctionScoreQueryBuilder
functionScoreQueryBuilder
=
QueryBuilders
.
functionScoreQuery
(
functions
)
.
scoreMode
(
FunctionScoreQuery
.
ScoreMode
.
SUM
)
.
setMinScore
(
2
F
);
// TODO 芋艿,需要考虑下 score
nativeSearchQueryBuilder
.
withQuery
(
functionScoreQueryBuilder
);
}
else
{
nativeSearchQueryBuilder
.
withQuery
(
QueryBuilders
.
matchAllQuery
());
}
// 排序
if
(
CollectionUtil
.
isEmpty
(
sortFields
))
{
nativeSearchQueryBuilder
.
withSort
(
SortBuilders
.
scoreSort
().
order
(
SortOrder
.
DESC
));
}
else
{
sortFields
.
forEach
(
sortField
->
nativeSearchQueryBuilder
.
withSort
(
SortBuilders
.
fieldSort
(
sortField
.
getField
())
.
order
(
SortOrder
.
fromString
(
sortField
.
getOrder
()))));
}
// 执行查询
return
search
(
nativeSearchQueryBuilder
.
build
());
}
}
search/search-service-impl/src/main/java/cn/iocoder/mall/search/biz/service/ProductSearchServiceImpl.java
浏览文件 @
b98e21e1
package
cn
.
iocoder
.
mall
.
search
.
biz
.
service
;
import
cn.iocoder.common.framework.util.CollectionUtil
;
import
cn.iocoder.common.framework.vo.CommonResult
;
import
cn.iocoder.common.framework.vo.SortingField
;
import
cn.iocoder.mall.order.api.CartService
;
import
cn.iocoder.mall.order.api.bo.CalcSkuPriceBO
;
import
cn.iocoder.mall.product.api.ProductSpuService
;
import
cn.iocoder.mall.product.api.bo.ProductSpuDetailBO
;
import
cn.iocoder.mall.search.api.ProductSearchService
;
import
cn.iocoder.mall.search.api.bo.ESProductPageBO
;
import
cn.iocoder.mall.search.api.dto.ProductSearchPageDTO
;
import
cn.iocoder.mall.search.biz.convert.ProductSearchConvert
;
import
cn.iocoder.mall.search.biz.dao.ProductRepository
;
import
cn.iocoder.mall.search.biz.dataobject.ESProductDO
;
import
com.alibaba.dubbo.config.annotation.Reference
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.data.domain.Page
;
import
org.springframework.stereotype.Service
;
import
org.springframework.util.Assert
;
import
java.util.Comparator
;
import
java.util.List
;
import
java.util.function.Function
;
import
java.util.stream.Collectors
;
@Service
@com
.
alibaba
.
dubbo
.
config
.
annotation
.
Service
(
validation
=
"true"
)
public
class
ProductSearchServiceImpl
implements
ProductSearchService
{
private
static
final
Integer
REBUILD_FETCH_PER_SIZE
=
2
;
private
static
final
Integer
REBUILD_FETCH_PER_SIZE
=
100
;
@Autowired
private
ProductRepository
productRepository
;
@
Autowired
@
Reference
(
validation
=
"true"
)
private
ProductSpuService
productSpuService
;
@
Autowired
@
Reference
(
validation
=
"true"
)
private
CartService
cartService
;
@Override
...
...
@@ -39,17 +44,12 @@ public class ProductSearchServiceImpl implements ProductSearchService {
int
rebuildCounts
=
0
;
while
(
true
)
{
CommonResult
<
List
<
ProductSpuDetailBO
>>
result
=
productSpuService
.
getProductSpuDetailListForSync
(
lastId
,
REBUILD_FETCH_PER_SIZE
);
Assert
.
isTrue
(
result
.
is
Error
(),
"获得商品列表必然成功"
);
Assert
.
isTrue
(
result
.
is
Success
(),
"获得商品列表必然成功"
);
List
<
ProductSpuDetailBO
>
spus
=
result
.
getData
();
rebuildCounts
+=
spus
.
size
();
// 存储到 ES 中
List
<
ESProductDO
>
products
=
spus
.
stream
().
map
(
new
Function
<
ProductSpuDetailBO
,
ESProductDO
>()
{
@Override
public
ESProductDO
apply
(
ProductSpuDetailBO
spu
)
{
return
convert
(
spu
);
}
}).
collect
(
Collectors
.
toList
());
List
<
ESProductDO
>
products
=
spus
.
stream
().
map
(
this
::
convert
).
collect
(
Collectors
.
toList
());
productRepository
.
saveAll
(
products
);
// 设置新的 lastId ,或者结束
if
(
spus
.
size
()
<
REBUILD_FETCH_PER_SIZE
)
{
break
;
...
...
@@ -66,14 +66,30 @@ public class ProductSearchServiceImpl implements ProductSearchService {
ProductSpuDetailBO
.
Sku
sku
=
spu
.
getSkus
().
stream
().
min
(
Comparator
.
comparing
(
ProductSpuDetailBO
.
Sku
::
getPrice
)).
get
();
// 价格计算
CommonResult
<
CalcSkuPriceBO
>
calSkuPriceResult
=
cartService
.
calcSkuPrice
(
sku
.
getId
());
Assert
.
isTrue
(
calSkuPriceResult
.
is
Error
(),
String
.
format
(
"SKU(%d) 价格计算不会出错"
,
sku
.
getId
()));
return
new
ESProductDO
(
);
Assert
.
isTrue
(
calSkuPriceResult
.
is
Success
(),
String
.
format
(
"SKU(%d) 价格计算不会出错"
,
sku
.
getId
()));
// 拼装结果
return
ProductSearchConvert
.
INSTANCE
.
convert
(
spu
,
calSkuPriceResult
.
getData
()
);
}
@Override
public
CommonResult
searchPage
(
ProductSearchPageDTO
searchPageDTO
)
{
return
null
;
public
CommonResult
<
ESProductPageBO
>
searchPage
(
ProductSearchPageDTO
searchPageDTO
)
{
checkSortFieldInvalid
(
searchPageDTO
.
getSorts
());
// 执行查询
Page
<
ESProductDO
>
searchPage
=
productRepository
.
search
(
searchPageDTO
.
getCid
(),
searchPageDTO
.
getKeyword
(),
searchPageDTO
.
getPageNo
(),
searchPageDTO
.
getPageSize
(),
searchPageDTO
.
getSorts
());
// 转换结果
ESProductPageBO
resultPage
=
new
ESProductPageBO
()
.
setList
(
ProductSearchConvert
.
INSTANCE
.
convert
(
searchPage
.
getContent
()))
.
setTotal
((
int
)
searchPage
.
getTotalElements
());
return
CommonResult
.
success
(
resultPage
);
}
private
void
checkSortFieldInvalid
(
List
<
SortingField
>
sorts
)
{
if
(
CollectionUtil
.
isEmpty
(
sorts
))
{
return
;
}
sorts
.
forEach
(
sortingField
->
Assert
.
isTrue
(
ProductSearchPageDTO
.
SORT_FIELDS
.
contains
(
sortingField
.
getField
()),
String
.
format
(
"排序字段(%s) 不在允许范围内"
,
sortingField
.
getField
())));
}
}
search/search-service-impl/src/main/resources/application.yaml
→
search/search-service-impl/src/main/resources/
config/
application.yaml
浏览文件 @
b98e21e1
#
#
es
spring
:
data
:
elasticsearch
:
...
...
@@ -6,6 +6,7 @@ spring:
cluster-nodes
:
192.168.88.10:9300
repositories
:
enable
:
true
# dubbo
dubbo
:
application
:
...
...
@@ -16,4 +17,4 @@ dubbo:
port
:
-1
name
:
dubbo
scan
:
base-packages
:
cn.iocoder.mall.search.
service.biz
base-packages
:
cn.iocoder.mall.search.
biz.service
search/search-service-impl/src/test/java/cn/iocoder/mall/search/biz/dao/ProductRepositoryTest.java
浏览文件 @
b98e21e1
package
cn
.
iocoder
.
mall
.
search
.
biz
.
dao
;
import
cn.iocoder.mall.search.biz.dataobject.ESProductDO
;
import
org.junit.Ignore
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.boot.test.context.SpringBootTest
;
import
org.springframework.test.context.junit4.SpringJUnit4ClassRunner
;
import
java.util.List
;
@RunWith
(
SpringJUnit4ClassRunner
.
class
)
@SpringBootTest
(
webEnvironment
=
SpringBootTest
.
WebEnvironment
.
NONE
)
public
class
ProductRepositoryTest
{
...
...
@@ -15,6 +18,7 @@ public class ProductRepositoryTest {
private
ProductRepository
productRepository
;
@Test
@Ignore
public
void
testSave
()
{
// productRepository.deleteById(1);
ESProductDO
product
=
new
ESProductDO
()
...
...
@@ -24,9 +28,23 @@ public class ProductRepositoryTest {
}
@Test
@Ignore
public
void
testFindByName
()
{
ESProductDO
product
=
productRepository
.
findByName
(
"锤子"
);
System
.
out
.
println
(
product
);
}
@Test
public
void
testSearch
()
{
// Page<ESProductDO> page = productRepository.search(639, null, 1, 10);
// console(page.getContent());
// Page<ESProductDO> page = productRepository.search(null, "数据库Oracle", 1, 10);
// console(page.getContent());
}
private
void
console
(
List
<
ESProductDO
>
list
)
{
list
.
forEach
(
System
.
out
::
println
);
}
}
search/search-service-impl/src/test/java/cn/iocoder/mall/search/biz/service/ProductSearchServiceImplTest.java
0 → 100644
浏览文件 @
b98e21e1
package
cn
.
iocoder
.
mall
.
search
.
biz
.
service
;
import
cn.iocoder.mall.search.biz.dao.ProductRepository
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.boot.test.context.SpringBootTest
;
import
org.springframework.test.context.junit4.SpringJUnit4ClassRunner
;
@RunWith
(
SpringJUnit4ClassRunner
.
class
)
@SpringBootTest
(
webEnvironment
=
SpringBootTest
.
WebEnvironment
.
NONE
)
public
class
ProductSearchServiceImplTest
{
@Autowired
private
ProductSearchServiceImpl
productSearchService
;
@Autowired
private
ProductRepository
productRepository
;
@Test
public
void
testRebuild
()
{
int
counts
=
productSearchService
.
rebuild
().
getData
();
System
.
out
.
println
(
"重建数量:"
+
counts
);
System
.
out
.
println
(
productRepository
.
count
());
}
}
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论