refactor(商城): es操作优化

master
wayn 4 years ago
parent 4d418fa1a1
commit d1f5a2208d

@ -1,103 +0,0 @@
package com.wayn.admin.api.controller.shop;
import com.alibaba.fastjson.JSONObject;
import com.wayn.common.core.domain.shop.Goods;
import com.wayn.common.core.service.shop.IGoodsService;
import com.wayn.common.util.R;
import com.wayn.common.util.file.FileUtils;
import com.wayn.data.elastic.manager.ElasticDocument;
import com.wayn.data.elastic.manager.ElasticEntity;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchPhraseQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@RestController
@RequestMapping("elastic")
public class ElasticTestController {
@Autowired
private ElasticDocument elasticDocument;
@Autowired
private IGoodsService iGoodsService;
@GetMapping("index")
public R index() throws IOException {
InputStream is = this.getClass().getResourceAsStream("/es/index/goods.json");
System.out.println(FileUtils.getContent(is));
// baseElasticService.createIndex("goods", indexSql);
return R.success();
}
@GetMapping("insert")
public R insert() {
List<Goods> list = iGoodsService.list();
List<ElasticEntity> entities = new ArrayList<>();
for (Goods goods : list) {
ElasticEntity elasticEntity = new ElasticEntity();
Map<String, Object> map = new HashMap<>();
elasticEntity.setId(goods.getId().toString());
map.put("id", goods.getId());
map.put("name", goods.getName());
map.put("countPrice", goods.getCounterPrice());
map.put("retailPrice", goods.getRetailPrice());
map.put("keyword", goods.getKeywords());
map.put("isOnSale", goods.getIsOnSale());
elasticEntity.setData(map);
entities.add(elasticEntity);
}
elasticDocument.insertBatch("goods", entities);
return R.success();
}
@GetMapping("search")
public R search(String keyword, int page, int pageSize) {
// MultiSearchRequest request = new MultiSearchRequest();
// SearchRequest firstSearchRequest = new SearchRequest("goods");
// SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
// searchSourceBuilder.query(QueryBuilders.matchQuery("name", "羊毛"));
// firstSearchRequest.source(searchSourceBuilder);
// request.add(firstSearchRequest);
// SearchRequest secondSearchRequest = new SearchRequest("goods");
// searchSourceBuilder = new SearchSourceBuilder();
//
// searchSourceBuilder.query(QueryBuilders.matchQuery("name", "手机"));
// secondSearchRequest.source(searchSourceBuilder);
// request.add(firstSearchRequest);
// request.add(secondSearchRequest);
// List<Object> list = baseElasticService.search(request, Object.class);
// 查询
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
MatchQueryBuilder matchQuery1 = QueryBuilders.matchQuery("name", keyword);
// MatchQueryBuilder matchQuery2 = QueryBuilders.matchQuery("isOnSale", true);
MatchPhraseQueryBuilder matchPhraseQueryBuilder = QueryBuilders.matchPhraseQuery("keyword", keyword);
boolQueryBuilder.should(matchQuery1).should(matchPhraseQueryBuilder);
searchSourceBuilder.query(boolQueryBuilder);
searchSourceBuilder.from(page);
searchSourceBuilder.size(pageSize);
searchSourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
List<JSONObject> list = elasticDocument.search("goods", searchSourceBuilder, JSONObject.class);
list = list.stream().filter(jsonObject -> (boolean) jsonObject.get("isOnSale")).collect(Collectors.toList());
return R.success().add("data", list);
}
}

@ -12,11 +12,12 @@ import com.wayn.common.util.file.FileUtils;
import com.wayn.data.elastic.manager.ElasticDocument;
import com.wayn.data.elastic.manager.ElasticEntity;
import com.wayn.data.redis.manager.RedisCache;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
@ -35,13 +36,11 @@ import java.util.concurrent.TimeUnit;
@Slf4j
@RestController
@RequestMapping("/shop/goods")
@AllArgsConstructor
public class GoodsController extends BaseController {
@Autowired
private IGoodsService iGoodsService;
@Autowired
private ElasticDocument elasticDocument;
@Autowired
private RedisCache redisCache;
@GetMapping("/list")
@ -51,12 +50,12 @@ public class GoodsController extends BaseController {
}
@PostMapping
public R addGoods(@Validated @RequestBody GoodsSaveRelatedVO goodsSaveRelatedVO) {
public R addGoods(@Validated @RequestBody GoodsSaveRelatedVO goodsSaveRelatedVO) throws IOException {
return iGoodsService.saveGoodsRelated(goodsSaveRelatedVO);
}
@PutMapping
public R updateGoods(@Validated @RequestBody GoodsSaveRelatedVO goodsSaveRelatedVO) {
public R updateGoods(@Validated @RequestBody GoodsSaveRelatedVO goodsSaveRelatedVO) throws IOException {
return iGoodsService.updateGoodsRelated(goodsSaveRelatedVO);
}
@ -66,7 +65,7 @@ public class GoodsController extends BaseController {
}
@DeleteMapping("{goodsId}")
public R deleteGoods(@PathVariable Long goodsId) {
public R deleteGoods(@PathVariable Long goodsId) throws IOException {
return R.result(iGoodsService.deleteGoodsRelatedByGoodsId(goodsId));
}

@ -8,6 +8,7 @@ import com.wayn.common.core.domain.vo.GoodsSaveRelatedVO;
import com.wayn.common.core.domain.vo.SearchVO;
import com.wayn.common.util.R;
import java.io.IOException;
import java.util.List;
import java.util.Map;
@ -57,7 +58,7 @@ public interface IGoodsService extends IService<Goods> {
* @param goodsSaveRelatedVO VO
* @return R
*/
R saveGoodsRelated(GoodsSaveRelatedVO goodsSaveRelatedVO);
R saveGoodsRelated(GoodsSaveRelatedVO goodsSaveRelatedVO) throws IOException;
/**
*
@ -73,7 +74,7 @@ public interface IGoodsService extends IService<Goods> {
* @param goodsId ID
* @return boolean
*/
boolean deleteGoodsRelatedByGoodsId(Long goodsId);
boolean deleteGoodsRelatedByGoodsId(Long goodsId) throws IOException;
/**
*
@ -81,7 +82,7 @@ public interface IGoodsService extends IService<Goods> {
* @param goodsSaveRelatedVO VO
* @return R
*/
R updateGoodsRelated(GoodsSaveRelatedVO goodsSaveRelatedVO);
R updateGoodsRelated(GoodsSaveRelatedVO goodsSaveRelatedVO) throws IOException;
/**
* Id

@ -14,10 +14,11 @@ import com.wayn.common.exception.BusinessException;
import com.wayn.common.util.R;
import com.wayn.data.elastic.manager.ElasticDocument;
import com.wayn.data.elastic.manager.ElasticEntity;
import org.springframework.beans.factory.annotation.Autowired;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;
@ -30,24 +31,14 @@ import java.util.*;
* @since 2020-07-06
*/
@Service
@AllArgsConstructor
public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements IGoodsService {
@Autowired
private GoodsMapper goodsMapper;
@Autowired
private IGoodsProductService iGoodsProductService;
@Autowired
private IGoodsAttributeService iGoodsAttributeService;
@Autowired
private IGoodsSpecificationService iGoodsSpecificationService;
@Autowired
private ICategoryService iCategoryService;
@Autowired
private ElasticDocument elasticDocument;
@Override
@ -55,7 +46,6 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements
return goodsMapper.selectGoodsListPage(page, goods);
}
@Override
public List<Goods> selectHomeIndexGoods(Goods goods) {
return goodsMapper.selectHomeIndex(goods);
@ -97,7 +87,7 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements
@Transactional(rollbackFor = Exception.class)
@Override
public R saveGoodsRelated(GoodsSaveRelatedVO goodsSaveRelatedVO) {
public R saveGoodsRelated(GoodsSaveRelatedVO goodsSaveRelatedVO) throws IOException {
Goods goods = goodsSaveRelatedVO.getGoods();
GoodsAttribute[] attributes = goodsSaveRelatedVO.getAttributes();
GoodsSpecification[] specifications = goodsSaveRelatedVO.getSpecifications();
@ -148,8 +138,7 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements
// 保存商品货品
iGoodsProductService.saveBatch(Arrays.asList(products));
// baseElasticService.syncGoods2Es(goods);
return R.success();
return R.result(syncGoods2Es(goods));
}
@Override
@ -164,7 +153,7 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements
@Transactional(rollbackFor = Exception.class)
@Override
public boolean deleteGoodsRelatedByGoodsId(Long goodsId) {
public boolean deleteGoodsRelatedByGoodsId(Long goodsId) throws IOException {
removeById(goodsId);
iGoodsSpecificationService.remove(new QueryWrapper<GoodsSpecification>().eq("goods_id", goodsId));
iGoodsAttributeService.remove(new QueryWrapper<GoodsAttribute>().eq("goods_id", goodsId));
@ -177,8 +166,9 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements
return true;
}
@Transactional(rollbackFor = Exception.class)
@Override
public R updateGoodsRelated(GoodsSaveRelatedVO goodsSaveRelatedVO) {
public R updateGoodsRelated(GoodsSaveRelatedVO goodsSaveRelatedVO) throws IOException {
Goods goods = goodsSaveRelatedVO.getGoods();
GoodsAttribute[] attributes = goodsSaveRelatedVO.getAttributes();
List<GoodsAttribute> updateAttributes = new ArrayList<>();
@ -231,8 +221,7 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements
// 更新商品货品
iGoodsProductService.updateBatchById(Arrays.asList(products));
syncGoods2Es(goods);
return R.success();
return R.result(syncGoods2Es(goods));
}
@Override
@ -250,7 +239,7 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements
*
* @param goods
*/
public void syncGoods2Es(Goods goods) {
public boolean syncGoods2Es(Goods goods) throws IOException {
// 同步es
ElasticEntity elasticEntity = new ElasticEntity();
elasticEntity.setId(goods.getId().toString());
@ -263,9 +252,9 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements
map.put("isOnSale", goods.getIsOnSale());
map.put("createTime", goods.getCreateTime());
elasticEntity.setData(map);
boolean one = elasticDocument.insertOrUpdateOne(SysConstants.ES_GOODS_INDEX, elasticEntity);
if (!one) {
if (!elasticDocument.insertOrUpdateOne(SysConstants.ES_GOODS_INDEX, elasticEntity)) {
throw new BusinessException("商品同步es失败");
}
return true;
}
}

@ -24,7 +24,6 @@ public class ElasticConfig {
@Value("${es.replicas}")
public int replicas;
@Bean
public RestClientBuilder restClientBuilder() {
return RestClient.builder(makeHttpHost());

@ -2,10 +2,10 @@ package com.wayn.data.elastic.manager;
import com.alibaba.fastjson.JSON;
import com.wayn.data.elastic.config.ElasticConfig;
import com.wayn.data.elastic.exception.ElasticException;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.DocWriteResponse;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.bulk.BulkItemResponse;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
@ -26,26 +26,28 @@ import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.reindex.BulkByScrollResponse;
import org.elasticsearch.index.reindex.DeleteByQueryRequest;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
@Slf4j
@Component
public class ElasticDocument {
@AllArgsConstructor
public class ElasticDocument implements DisposableBean {
@Autowired
private ElasticConfig elasticConfig;
@Autowired
private RestHighLevelClient restHighLevelClient;
/**
@ -56,7 +58,8 @@ public class ElasticDocument {
*/
public boolean createIndex(String idxName, String idxSQL) throws IOException {
if (indexExist(idxName)) {
throw new ElasticException(String.format("idxName=%s 已经存在,idxSql=%s", idxName, idxSQL));
log.info("idxName={} 已经存在,idxSql={}", idxName, idxSQL);
return false;
}
CreateIndexRequest request = new CreateIndexRequest(idxName);
buildSetting(request);
@ -96,25 +99,19 @@ public class ElasticDocument {
* @param idxName index
* @param entity
*/
public boolean insertOrUpdateOne(String idxName, ElasticEntity entity) {
public boolean insertOrUpdateOne(String idxName, ElasticEntity entity) throws IOException {
IndexRequest request = new IndexRequest(idxName);
log.info("Data : id={},entity={}", entity.getId(), JSON.toJSONString(entity.getData()));
request.id(entity.getId());
request.source(entity.getData(), XContentType.JSON);
try {
IndexResponse indexResponse = restHighLevelClient.index(request, RequestOptions.DEFAULT);
ReplicationResponse.ShardInfo shardInfo = indexResponse.getShardInfo();
if (shardInfo.getFailed() > 0) {
for (ReplicationResponse.ShardInfo.Failure failure :
shardInfo.getFailures()) {
log.error(failure.reason());
}
return false;
IndexResponse indexResponse = restHighLevelClient.index(request, RequestOptions.DEFAULT);
ReplicationResponse.ShardInfo shardInfo = indexResponse.getShardInfo();
if (shardInfo.getFailed() > 0) {
for (ReplicationResponse.ShardInfo.Failure failure : shardInfo.getFailures()) {
log.error(failure.reason(), failure.getCause());
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return true;
return indexResponse.status().equals(RestStatus.OK);
}
@ -124,19 +121,30 @@ public class ElasticDocument {
* @param idxName index
* @param list
*/
public boolean insertBatch(String idxName, List<ElasticEntity> list) {
public boolean insertBatch(String idxName, List<ElasticEntity> list) throws IOException {
BulkRequest request = new BulkRequest();
list.forEach(item -> request.add(new IndexRequest(idxName).id(item.getId())
.source(item.getData(), XContentType.JSON)));
try {
BulkResponse bulkResponse = restHighLevelClient.bulk(request, RequestOptions.DEFAULT);
if (bulkResponse.hasFailures()) {
return false;
BulkResponse bulkResponse = restHighLevelClient.bulk(request, RequestOptions.DEFAULT);
return bulkResponseHandler(bulkResponse);
}
/**
* bulkResponse
*
* @param bulkResponse
* @return boolean
*/
private boolean bulkResponseHandler(BulkResponse bulkResponse) {
boolean flag = true;
for (BulkItemResponse response : bulkResponse) {
if (response.isFailed()) {
flag = false;
BulkItemResponse.Failure failure = response.getFailure();
log.error(failure.getMessage(), failure.getCause());
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return true;
return flag;
}
/**
@ -145,14 +153,11 @@ public class ElasticDocument {
* @param idxName index
* @param idList
*/
public <T> void deleteBatch(String idxName, Collection<T> idList) {
public <T> boolean deleteBatch(String idxName, Collection<T> idList) throws IOException {
BulkRequest request = new BulkRequest();
idList.forEach(item -> request.add(new DeleteRequest(idxName, item.toString())));
try {
restHighLevelClient.bulk(request, RequestOptions.DEFAULT);
} catch (Exception e) {
throw new RuntimeException(e);
}
BulkResponse bulk = restHighLevelClient.bulk(request, RequestOptions.DEFAULT);
return bulkResponseHandler(bulk);
}
/**
@ -162,87 +167,71 @@ public class ElasticDocument {
* @param id ID
* @return boolean
*/
public boolean delete(String idxName, String id) {
DeleteRequest request = new DeleteRequest(
idxName, id);
try {
DeleteResponse deleteResponse = restHighLevelClient.delete(
request, RequestOptions.DEFAULT);
ReplicationResponse.ShardInfo shardInfo = deleteResponse.getShardInfo();
if (shardInfo.getFailed() > 0) {
for (ReplicationResponse.ShardInfo.Failure failure :
shardInfo.getFailures()) {
log.error(failure.reason());
}
return false;
public boolean delete(String idxName, String id) throws IOException {
DeleteRequest request = new DeleteRequest(idxName, id);
DeleteResponse deleteResponse = restHighLevelClient.delete(request, RequestOptions.DEFAULT);
ReplicationResponse.ShardInfo shardInfo = deleteResponse.getShardInfo();
if (shardInfo.getFailed() > 0) {
for (ReplicationResponse.ShardInfo.Failure failure : shardInfo.getFailures()) {
log.error(failure.reason());
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return true;
return deleteResponse.status().equals(RestStatus.OK);
}
/**
*
*
* @param idxName index
* @param builder
* @param c
* @return java.util.List<T>
*/
public <T> List<T> search(String idxName, SearchSourceBuilder builder, Class<T> c) {
public <T> List<T> search(String idxName, SearchSourceBuilder builder, Class<T> c) throws IOException {
SearchRequest request = new SearchRequest(idxName);
request.source(builder);
try {
SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
SearchHit[] hits = response.getHits().getHits();
List<T> res = new ArrayList<>(hits.length);
for (SearchHit hit : hits) {
res.add(JSON.parseObject(hit.getSourceAsString(), c));
}
return res;
} catch (Exception e) {
throw new RuntimeException(e);
}
SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
SearchHit[] hits = response.getHits().getHits();
return Arrays.stream(hits).map(hit -> JSON.parseObject(hit.getSourceAsString(), c)).collect(Collectors.toList());
}
public <T> List<T> search(MultiSearchRequest request, Class<T> c) {
try {
MultiSearchResponse response = restHighLevelClient.msearch(request, RequestOptions.DEFAULT);
MultiSearchResponse.Item[] responseResponses = response.getResponses();
List<T> all = new ArrayList<>();
for (MultiSearchResponse.Item item : responseResponses) {
SearchHits hits = item.getResponse().getHits();
List<T> res = new ArrayList<>();
for (SearchHit hit : hits) {
res.add(JSON.parseObject(hit.getSourceAsString(), c));
}
all.addAll(res);
/**
* http
*
* @param request
* @param c
* @return java.util.List<T>
*/
public <T> List<T> msearch(MultiSearchRequest request, Class<T> c) throws IOException {
MultiSearchResponse response = restHighLevelClient.msearch(request, RequestOptions.DEFAULT);
MultiSearchResponse.Item[] responseResponses = response.getResponses();
List<T> all = new ArrayList<>();
for (MultiSearchResponse.Item item : responseResponses) {
SearchHits hits = item.getResponse().getHits();
List<T> res = new ArrayList<>(hits.getHits().length);
for (SearchHit hit : hits) {
res.add(JSON.parseObject(hit.getSourceAsString(), c));
}
return all;
} catch (Exception e) {
throw new RuntimeException(e);
all.addAll(res);
}
return all;
}
/**
* index
*
* @param idxName
* @return boolean
*/
public boolean deleteIndex(String idxName) {
try {
if (!this.indexExist(idxName)) {
log.error(" idxName={} 不存在", idxName);
return false;
}
AcknowledgedResponse acknowledgedResponse = restHighLevelClient.indices().delete(new DeleteIndexRequest(idxName), RequestOptions.DEFAULT);
if (!acknowledgedResponse.isAcknowledged()) {
return false;
}
} catch (Exception e) {
throw new RuntimeException(e);
public boolean deleteIndex(String idxName) throws IOException {
if (!this.indexExist(idxName)) {
log.error(" idxName={} 不存在", idxName);
return false;
}
return true;
AcknowledgedResponse acknowledgedResponse = restHighLevelClient.indices()
.delete(new DeleteIndexRequest(idxName), RequestOptions.DEFAULT);
return acknowledgedResponse.isAcknowledged();
}
@ -251,19 +240,36 @@ public class ElasticDocument {
*
* @param idxName
* @param builder
* @return boolean
*/
public void deleteByQuery(String idxName, QueryBuilder builder) {
public boolean deleteByQuery(String idxName, QueryBuilder builder) throws IOException {
DeleteByQueryRequest request = new DeleteByQueryRequest(idxName);
request.setQuery(builder);
//设置批量操作数量,最大为10000
request.setBatchSize(10000);
// 设置批量操作数量,最大为10000
request.setBatchSize(100);
// 版本冲突时继续执行
request.setConflicts("proceed");
try {
restHighLevelClient.deleteByQuery(request, RequestOptions.DEFAULT);
} catch (Exception e) {
throw new RuntimeException(e);
BulkByScrollResponse bulkByScrollResponse = restHighLevelClient.deleteByQuery(request, RequestOptions.DEFAULT);
List<BulkItemResponse.Failure> bulkFailures = bulkByScrollResponse.getBulkFailures();
boolean flag = true;
for (BulkItemResponse.Failure bulkFailure : bulkFailures) {
log.error(bulkFailure.getMessage(), bulkFailure.getCause());
flag = false;
}
return flag;
}
/**
* bean
*/
@Override
public void destroy() {
try {
if (restHighLevelClient != null) {
restHighLevelClient.close();
}
} catch (Exception exception) {
log.error(exception.getMessage(), exception);
}
}
}

@ -32,6 +32,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.constraints.NotEmpty;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
@ -63,7 +64,7 @@ public class SearchController extends BaseController {
private ElasticDocument elasticDocument;
@GetMapping("result")
public R list(SearchVO searchVO) {
public R list(SearchVO searchVO) throws IOException {
Long memberId = MobileSecurityUtils.getUserId();
String keyword = searchVO.getKeyword();
Boolean filterNew = searchVO.getFilterNew();

Loading…
Cancel
Save