商品管理 - 上架、下架 + 列表页实现 - 跳转到列表页
一、搭建搜索服务 - 公共模块
1、导入依赖:
<dependency><groupId>com.zhengqing</groupId><artifactId>basic_util</artifactId><version>1.0-SNAPSHOT</version>
</dependency>
<!--springboot 对 spring data es 的支持-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
2、配置:
spring:data:elasticsearch:cluster-name: elasticsearchcluster-nodes: 127.0.0.1:9300 # 注:9200->图形界面端、9300->代码端
注: 这里暂时先将8010中的bootstrap.yml备份一份bootstrap_bak.yml 然后将github上的配置application-common-dev.yml 里面的内容拷贝到项目中bootstrap.yml本地里 !! -->原因:暂时只能拿到项目本地配置!
3、编写服务 - 接口层
① ProductDoc
@Document(indexName = "aigou",type = "product")
public class ProductDoc {
@Idprivate Long id;private Long productTypeId;//类型idprivate Long brandId;//品牌idprivate Integer minPrice;//最小价格private Integer maxPrice;//最大价格private Integer saleCount;//销量private Integer onSaleTime;//上架时间private Integer commentCount;//评论总数private Integer viewCount;//浏览数@Field(type = FieldType.Keyword)List<String> images = new ArrayList<>();//图片@Field(type = FieldType.Text,analyzer = "ik_max_word",searchAnalyzer = "ik_max_word")private String all;//模糊查询所有字段 name、subName、brandName、productTypeName@Field(type = FieldType.Keyword)private String viewProperties;//显示属性@Field(type = FieldType.Keyword)private String skuProperties;//sku属性//getter/setter方法...
}
② feign/fallbackFactory
@FeignClient(value = "AIGOU-COMMON", fallbackFactory = ProductDocClientFallbackFactory.class)
@RequestMapping("/productDoc")
public interface ProductDocClient {
//crud@RequestMapping(value = "/save",method = RequestMethod.POST)AjaxResult save(ProductDoc productDoc); //添加、修改@RequestMapping(value = "/{id}",method = RequestMethod.DELETE)AjaxResult del(@PathVariable("id") Long id); //删除@RequestMapping(value = "/{id}",method = RequestMethod.GET)ProductDoc get(@PathVariable("id") Long id); //获取一个//批量操作@RequestMapping(value = "/batchSave",method = RequestMethod.POST)AjaxResult batchSave(@RequestBody List<ProductDoc> productDocs); //批量添加@RequestMapping(value = "/batchDel",method = RequestMethod.DELETE)AjaxResult batchDel(@RequestBody List<Long> ids); //批量上传//分页搜索@RequestMapping(value = "/search",method = RequestMethod.GET)PageList<ProductDoc> search(Map<String,Object> params); //搜索
}
@Component
public class ProductDocClientFallbackFactory implements FallbackFactory<ProductDocClient>{
@Overridepublic ProductDocClient create(Throwable throwable) {
return new ProductDocClient() {
@Overridepublic AjaxResult save(ProductDoc productDoc) {
return null;}@Overridepublic AjaxResult del(Long id) {
return null;}@Overridepublic ProductDoc get(Long id) {
return null;}@Overridepublic AjaxResult batchSave(List<ProductDoc> productDocs) {
return null;}@Overridepublic AjaxResult batchDel(List<Long> ids) {
return null;}@Overridepublic PageList<ProductDoc> search(Map<String, Object> params) {
return null;}};}
}
4、编写服务层:
① repository
@Repository
public interface ProductDocRepository extends ElasticsearchRepository<ProductDoc,Long> {
}
② service
public interface IProductDocService {
void add(ProductDoc productDoc);//添加文档void del(Long id);//删除文档ProductDoc get(Long id);//获取文档void batchAdd(List<ProductDoc> productDocs);//批量添加文档void batchDel(List<Long> ids);//批量删除PageList<ProductDoc> search(Map<String, Object> params);//查询
}
@Service
public class ProductDocServiceImpl implements IProductDocService{
@Autowiredprivate ProductDocRepository repository;@Overridepublic void add(ProductDoc productDoc) {
repository.save(productDoc);}@Overridepublic void del(Long id) {
repository.deleteById(id);}@Overridepublic ProductDoc get(Long id) {
return repository.findById(id).get();}@Overridepublic void batchAdd(List<ProductDoc> productDocs) {
repository.saveAll(productDocs);}@Overridepublic void batchDel(List<Long> ids) {
for (Long id : ids) {
repository.deleteById(id);}}@Overridepublic PageList<ProductDoc> search(Map<String, Object> params) {
return null;}
}
③ controller实现feign
@RestController
@RequestMapping("/productDoc")
public class ProductDocController implements ProductDocClient{
@Autowiredprivate IProductDocService productDocService;//crud@RequestMapping(value = "/save",method = RequestMethod.POST)public AjaxResult save(ProductDoc productDoc){
try {
productDocService.add(productDoc);return AjaxResult.me();} catch (Exception e) {
e.printStackTrace();return AjaxResult.me().setSuccess(false).setMessage("保存失败!"+e.getMessage());}}@RequestMapping(value = "/{id}",method = RequestMethod.DELETE)public AjaxResult del(@PathVariable("id") Long id){
try {
productDocService.del(id);return AjaxResult.me();} catch (Exception e) {
e.printStackTrace();return AjaxResult.me().setSuccess(false).setMessage("删除失败!"+e.getMessage());}}@RequestMapping(value = "/{id}",method = RequestMethod.GET)public ProductDoc get(@PathVariable("id") Long id){
return productDocService.get(id);}//批量操作@RequestMapping(value = "/batchSave",method = RequestMethod.POST)public AjaxResult batchSave(@RequestBody List<ProductDoc> productDocs){
try {
productDocService.batchAdd(productDocs);return AjaxResult.me();} catch (Exception e) {
e.printStackTrace();return AjaxResult.me().setSuccess(false).setMessage("保存失败!"+e.getMessage());}}@RequestMapping(value = "/batchDel",method = RequestMethod.DELETE)public AjaxResult batchDel(@RequestBody List<Long> ids){
try {
productDocService.batchDel(ids);return AjaxResult.me();} catch (Exception e) {
e.printStackTrace();return AjaxResult.me().setSuccess(false).setMessage("删除失败!"+e.getMessage());}}//分页搜索@RequestMapping(value = "/search",method = RequestMethod.GET)public PageList<ProductDoc> search(Map<String,Object> params){
return productDocService.search(params);}
}
④ 创建索引,并且建立类型映射
@RunWith(SpringRunner.class)
@SpringBootTest(classes = CommonApplication_8010.class)
public class ProductDocInitTest {
@Autowiredprivate ElasticsearchTemplate template;@Test //创建索引,并且建立类型映射public void testInit() throws Exception {
template.createIndex(ProductDoc.class); //创建索引template.putMapping(ProductDoc.class); //类型映射-自定义映射}
}
二、上下架处理
Product.java中修改:
public Long getOnSaleTime() {
return onSaleTime;
}public void setOnSaleTime(Long onSaleTime) {
this.onSaleTime = onSaleTime;
}
mapper:
void onSale(Map<String, Object> params);//上架
void offSale(Map<String, Object> params);//下架
mapper.xml: (注意collection里面是ids)
<update id="onSale" parameterType="map">UPDATE t_product set state = 1, onSaleTime = #{timeStamp} where id in<foreach collection="ids" item="item" open="(" close=")" separator=",">#{item}</foreach>
</update>
<update id="offSale" parameterType="map">UPDATE t_product set state = 0, offSaleTime = #{timeStamp} where id in<foreach collection="ids" item="item" open="(" close=")" separator=",">#{item}</foreach>
</update>
service:
void onSale(String ids, Integer onSale);//上下架处理
@Autowired
private BrandMapper brandMapper;
@Autowired
private ProductTypeMapper productTypeMapper;
@Autowired
private ProductDocClient productDocClient;@Override
public boolean updateById(Product entity) {
//添加本表信息以外,还要存放关联表entity.setUpdateTime(new Date().getTime());productMapper.updateById(entity);//通过productId查询productExtWrapper<ProductExt> wrapper = new EntityWrapper<ProductExt>().eq("productId", entity.getId());ProductExt productExt = productExtMapper.selectList(wrapper).get(0);//把前台传递进来值设置给数据库查询出来值,并且把它修改进去ProductExt tmp = entity.getProductExt();if ( tmp!= null) {
productExt.setDescription(tmp.getDescription());productExt.setRichContent(tmp.getRichContent());productExtMapper.updateById(productExt);}// 如果是上架状态,要同步修改es库if (entity.getState()==1){
ProductDoc productDoc = product2productDoc(entity);productDocClient.save(productDoc);}return true;
}@Override
public boolean deleteById(Serializable id) {
super.deleteById(id);//如果是上架状态,要同步删除es库Product product = productMapper.selectById(id);if (product.getState()==1){
productDocClient.del(Long.valueOf(id.toString()));}return true;
}@Override
public void onSale(String ids, Integer onSale) {
List<Long> idsLong = StrUtils.splitStr2LongArr(ids);if (1==onSale.intValue()){
//上架//数据库状态和上架时间要修改 id 时间Map<String,Object> params = new HashMap<>();params.put("ids", idsLong);params.put("timeStamp", new Date().getTime());productMapper.onSale(params);//添加esku// productDocClient.batchDel(Arrays.asList(idsLong));List<ProductDoc> productDocs = product2productDocs(idsLong);productDocClient.batchSave(productDocs);}else{
//下架//数据库状态和下架时间要修改Map<String,Object> params = new HashMap<>();params.put("ids", idsLong);params.put("timeStamp", new Date().getTime());productMapper.offSale(params);//删除eskuproductDocClient.batchDel(idsLong);}
}//转换多个
private List<ProductDoc> product2productDocs(List<Long> ids) {
List<ProductDoc> productDocs = new ArrayList<>();for (Long id : ids) {
Product product = productMapper.selectById(id);ProductDoc productDoc = product2productDoc(product);productDocs.add(productDoc);}return productDocs;
}// 转换一个
private ProductDoc product2productDoc(Product product) {
//选中productDoc -》 alt+enter -》 快速生成set方法赋值ProductDoc productDoc = new ProductDoc();productDoc.setId(product.getId());productDoc.setProductTypeId(product.getProductTypeId());productDoc.setBrandId(product.getBrandId());//从某个商品sku中获取最大或最小List<Sku> skus = skuMapper.selectList(new EntityWrapper<Sku>().eq("productId", product.getId()));Integer minPrice = skus.get(0).getPrice();Integer maxPrice = skus.get(0).getPrice();for (Sku sku : skus) {
if (sku.getPrice()<minPrice) minPrice=sku.getPrice();if (sku.getPrice()>maxPrice) maxPrice = sku.getPrice();}productDoc.setMinPrice(minPrice);productDoc.setMaxPrice(maxPrice);productDoc.setSaleCount(product.getSaleCount());productDoc.setOnSaleTime(product.getOnSaleTime().intValue());productDoc.setCommentCount(product.getCommentCount());productDoc.setViewCount(product.getViewCount());String medias = product.getMedias();if (StringUtils.isNotBlank(medias)) {
productDoc.setImages(Arrays.asList(medias.split(",")));}Brand brand = brandMapper.selectById(product.getBrandId());ProductType productType = productTypeMapper.selectById(product.getProductTypeId());//投机-有空格就会分词String all = product.getName()+" "+product.getSubName()+" "+brand.getName()+" "+productType.getName();productDoc.setAll(all);productDoc.setViewProperties(product.getViewProperties());productDoc.setSkuProperties(product.getSkuTemplate());//设置值return productDoc;
}
controller:
@RequestMapping(value="/onSale",method= RequestMethod.POST)
public AjaxResult onSale(@RequestBody Map<String,Object> params){
try {
String ids = (String) params.get("ids");//1,2,3System.out.println(ids);Integer onSale = Integer.valueOf(params.get("onSale").toString());System.out.println(onSale);productService.onSale(ids,onSale);return AjaxResult.me();} catch (Exception e) {
e.printStackTrace();return AjaxResult.me().setSuccess(false).setMessage("上下架失败!"+e.getMessage());}
}
三、列表页实现 - 跳转到列表页:
1、主页携带参数跳转到列表页.
location.href = list.html?keyword ==xx
location.href = list.html?productType==154
2、列表页,加载完毕后,获取传递过来keyword ,或者productType
keyword
? ①回显搜索框
? ②以keyword为搜索条件到es中查询分页数据,展示在界面
productType
? ①发送获取面包屑请求,展示在界面
? ②发送品牌请求获取品牌,展示在界面
? ③以productType为搜索条件到es中查询分页数据,展示在界面
修改模板路径: (notepad++ 替换打开所有文件 - 具体见代码…)
前端代码部分略:见源码即可…
最后启动测试:
源码和文档: https://pan.baidu.com/s/1FkLU_KPsd79Qci611BK0BQ