SAAS-HRM-day5(ElasticSearch)

  • 1. 课程上下线业务
    • 1.1 业务描述
    • 1.2 技术方案
      • 1.2.1 技术方案一:数据库状态做判断-->不可取
      • 1.2.2 技术方案二:全文检索服务器-->可取
  • 2. 课程上下线实现
    • 2.1 技术架构
    • 2.2 实现+分析
      • 2.2.1 搭建搜索服务
        • 2.2.1.1 步骤分析
        • 2.2.1.2 步骤实现
      • 2.2.2 课程上下线处理
        • 2.2.2.1 步骤分析
        • 2.2.2.2 步骤实现
  • 3. 易错点总结

1. 课程上下线业务

1.1 业务描述

  1. 上线

    在系统中,我们添加了一个课程,用户不能立即就搜索到,需要上线以后才行。

  2. 下线

    当某个课程不想卖的时候,就要下线.当课程下线后,用户不能搜索到,但是数据库是还有的。

1.2 技术方案

1.2.1 技术方案一:数据库状态做判断-->不可取

上线后,修改状态为”上线”,用户搜索时只能搜索到上线状态的.如果不想卖了,执行下线时,修改状态下线.

--->垃圾(每次都要操作数据库)

1.2.2 技术方案二:全文检索服务器-->可取

上线时把课程数据同步到es,用户查询直接从es查询.也就意味着没有上线的课程用户查询不到,因为没有放到es库.

下线时把es库课程数据删除掉.用户就查询不到了.

--->牛B(以基于索引搜索代替数据查询)

优点:

  • (1)降低数据库压力
  • (2)提高了查询速度,增强用户体验-基于索引搜索,效率远远数据库搜索

2. 课程上下线实现

2.1 技术架构

//TODO 结构图以后自己画上补充

简单描述:

用户查询直接从ES库中查

  1. 管理员:
    • (1)添加课程。管理员将课程添加到db
    • (2)课程上线。把需要上线的课程查出来,同步到ES库。
    • (3)删除或修改课程。同步操作ES库和DB库。
    • (4)查询课程。这是后台的查询,就直接从数据库查询。
  2. 用户:用户查询直接从ES库中查
    • 减少数据库压力
    • 提高查询效率,用户体验更佳

2.2 实现+分析

课程服务调用搜索服务-服务内部调用feign

步骤分析:

  1. 搭建搜索服务
  2. 课程的上下线处理

2.2.1 搭建搜索服务

2.2.1.1 步骤分析

  1. 创建项目
  2. 导包
  3. 配置
  4. 入口类
  5. doc准备
  6. repository准备-service
  7. query准备-interface
  8. IESCourseService接口-service
  9. ESCourseServiceImpl(实现上面那个接口)-service
  10. ESCourseController-service
  11. client-interface
  12. 生成文档映射-test-service
  13. 测试
  14. 日志集成
  15. 网关集成
  16. 本项目swagger集成
  17. 网关swagger集成
  18. 启动测试网关、日志、swagger

2.2.1.2 步骤实现

  1. 创建项目

    在二级子模块hrm_basic_parent下创建三级子模块hrm_basic_es_interface和三级子模块hrm_basic_es_service

  2. 导包

  • hrm_basic_es_interface
 
        
            cn.wangningbo.hrm
            hrm_basic_util
            1.0-SNAPSHOT
        
        
        
            org.springframework.boot
            spring-boot-starter-web
        
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
        
        
            org.springframework.cloud
            spring-cloud-starter-openfeign
        
        
        
            org.springframework.data
            spring-data-elasticsearch
            3.0.10.RELEASE
        
  • hrm_basic_es_service

            cn.wangningbo.hrm
            hrm_basic_es_interface
            1.0-SNAPSHOT
        
        
        
            org.springframework.boot
            spring-boot-starter-web
        
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
        
        
            org.springframework.cloud
            spring-cloud-starter-netflix-eureka-client
        
        
        
            io.springfox
            springfox-swagger2
            2.9.2
        
        
        
            io.springfox
            springfox-swagger-ui
            2.9.2
        
        
        
            org.springframework.cloud
            spring-cloud-starter-config
        
        
        
            org.springframework.boot
            spring-boot-starter-data-elasticsearch
        
  1. 配置(application.yml)-在service端
server:
  port: 9004
spring:
  application:
    name: hrm-es
  data:
    elasticsearch:
      cluster-name: elasticsearch
      cluster-nodes: 127.0.0.1:9300 #9200是图形界面端,9300代码端
eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka
  instance:
    prefer-ip-address: true
  1. 入口类-在service端
package cn.wangningbo.hrm;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

@SpringBootApplication
@EnableEurekaClient
public class ElasticSearch9004Application {
    public static void main(String[] args) {
        SpringApplication.run(ElasticSearch9004Application.class, args);
    }
}
  1. doc准备-interface

    根据业务和表设计这里的doc

package cn.wangningbo.hrm.doc;

import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;

import java.math.BigDecimal;
import java.util.Date;

@Document(indexName = "hrm", type = "course")
public class ESCourse {
    @Id
    private Long id;
    private String name;
    private String users;
    private Long courseTypeId;
    private String courseTypeName;
    private Long gradeId;
    private String gradeName;
    private Integer status;
    private Long tenantId;
    private String tenantName;
    private Long userId;
    private String userName;
    private Date startTime;
    private Date endTime;
    private String intro;
    private String resources; //图片
    private Date expires; //过期时间
    private BigDecimal priceOld; //原价
    private BigDecimal price; //原价
    private String qq; //原价

    @Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_max_word")
    private String all;

    public String getAll() {
        String tmp = name
                + " " + users
                + " " + courseTypeName
                + " " + gradeName
                + " " + tenantName
                + " " + userName
                + " " + intro;
        return tmp;
    }

    public void setAll(String all) {
        this.all = all;
    }
    //提供get、set和toString方法
}
  1. repository准备-service

    由于需要操作es,所需需要repository操作

package cn.wangningbo.hrm.repository;


import cn.wangningbo.hrm.doc.ESCourse;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;

public interface CourseRepository extends ElasticsearchRepository {
}
  1. query准备-interface
public class ESCourseQuery extends BaseQuery {
}
  1. IESCourseService接口-service
package cn.wangningbo.hrm.service;


import cn.wangningbo.hrm.doc.ESCourse;
import cn.wangningbo.hrm.query.ESCourseQuery;
import cn.wangningbo.hrm.util.PageList;

import java.util.List;

/**
 * @author wangningbo
 * @since 2019-09-06
 */
public interface IESCourseService {
    //添加
    void insert(ESCourse esCourse);

    //修改
    void updateById(ESCourse esCourse);

    //删除
    void deleteById(Long id);

    //查询一个
    ESCourse selectById(Long id);

    //查询所有
    List selectList(Object o);

    //dsl高级查询
    PageList selectListPage(ESCourseQuery query);

}
  1. ESCourseServiceImpl(实现上面那个接口)-service
@Service
public class ESCourseServiceImpl implements IESCourseService {

    @Autowired
    private CourseRepository courseRepository;

    @Override
    public void insert(ESCourse esCourse) {
        courseRepository.save(esCourse);
    }

    @Override
    public void updateById(ESCourse esCourse) {
        courseRepository.save(esCourse);
    }

    @Override
    public void deleteById(Long id) {
        courseRepository.deleteById(id);
    }

    @Override
    public ESCourse selectById(Long id) {
        return courseRepository.findById(id).get();
    }

    @Override
    public List selectList(Object o) {
        Page page = (Page) courseRepository.findAll();
        return page.getContent();
    }

    @Override
    public PageList selectListPage(ESCourseQuery query) {
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        BoolQueryBuilder bool = QueryBuilders.boolQuery();
        //模糊查询 @TODO
        bool.must(QueryBuilders.matchQuery("intro", "zhang"));
        //精确过滤 @TODO
        List filters = bool.filter();
        filters.add(QueryBuilders.rangeQuery("age").gte(0).lte(200));
        builder.withQuery(bool); //query bool must(filter)
        //排序 @TODO
        builder.withSort(SortBuilders.fieldSort("age").order(SortOrder.ASC));
        //分页 当前页从0开始
        builder.withPageable(PageRequest.of(query.getPage() - 1, query.getRows()));
        //构造查询条件
        NativeSearchQuery esQuery = builder.build();
        //查询
        Page page = courseRepository.search(esQuery);
        return new PageList<>(page.getTotalElements(), page.getContent());
    }
}
  1. ESCourseController-service
package cn.wangningbo.hrm.web.controller;

import cn.wangningbo.hrm.doc.ESCourse;
import cn.wangningbo.hrm.query.ESCourseQuery;
import cn.wangningbo.hrm.service.IESCourseService;
import cn.wangningbo.hrm.util.AjaxResult;
import cn.wangningbo.hrm.util.PageList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/esCourse")
public class ESCourseController {
    @Autowired
    public IESCourseService esCourseService;

    /**
     * 保存和修改公用的
     *
     * @param esCourse 传递的实体
     * @return Ajaxresult转换结果
     */
    @RequestMapping(value = "/save", method = RequestMethod.POST)
    public AjaxResult save(@RequestBody ESCourse esCourse) {
        try {
            if (esCourse.getId() != null) {
                esCourseService.updateById(esCourse);
            } else {
                esCourseService.insert(esCourse);
            }
            return AjaxResult.me();
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.me().setMessage("保存对象失败!" + e.getMessage());
        }
    }

    /**
     * 删除
     *
     * @param id
     * @return
     */
    @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
    public AjaxResult delete(@PathVariable("id") Long id) {
        try {
            esCourseService.deleteById(id);
            return AjaxResult.me();
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.me().setMessage("删除对象失败!" + e.getMessage());
        }
    }

    //获取用户
    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    public ESCourse get(@PathVariable("id") Long id) {
        return esCourseService.selectById(id);
    }


    /**
     * 查看所有信息
     *
     * @return
     */
    @RequestMapping(value = "/list", method = RequestMethod.GET)
    public List list() {

        return esCourseService.selectList(null);
    }


    /**
     * 分页查询数据
     *
     * @param query 查询对象
     * @return PageList 分页对象
     */
    @RequestMapping(value = "/json", method = RequestMethod.POST)
    public PageList json(@RequestBody ESCourseQuery query) {
        return esCourseService.selectListPage(query);
    }
}
  1. client-interface

    注意点:@FeignClient的value = "HRM-ES",自己服务端的名字,@RequestMapping("/esCourse")要与自己服务端controller的一样

package cn.wangningbo.hrm.client;


import cn.wangningbo.hrm.doc.ESCourse;
import cn.wangningbo.hrm.query.ESCourseQuery;
import cn.wangningbo.hrm.util.AjaxResult;
import cn.wangningbo.hrm.util.PageList;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.cloud.openfeign.FeignClientsConfiguration;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@FeignClient(value = "HRM-ES", configuration = FeignClientsConfiguration.class,
        fallbackFactory = EsCourseClientHystrixFallbackFactory.class)
@RequestMapping("/esCourse")
public interface ESCourseClient {
    /**
     * 保存和修改公用的
     *
     * @param esCourse 传递的实体
     * @return Ajaxresult转换结果
     */
    @RequestMapping(value = "/save", method = RequestMethod.POST)
    AjaxResult save(ESCourse esCourse);

    /**
     * 删除
     *
     * @param id
     * @return
     */
    @RequestMapping(value = "/delete/{id}", method = RequestMethod.DELETE)
    AjaxResult delete(@PathVariable("id") Integer id);

    //获取用户
    @RequestMapping("/{id}")
    ESCourse get(@RequestParam(value = "id", required = true) Long id);


    /**
     * 查看所有信息
     *
     * @return
     */
    @RequestMapping("/list")
    public List list();

    /**
     * 分页查询数据
     *
     * @param query 查询对象
     * @return PageList 分页对象
     */
    @RequestMapping(value = "/json", method = RequestMethod.POST)
    PageList json(@RequestBody ESCourseQuery query);
}
package cn.wangningbo.hrm.client;

import cn.wangningbo.hrm.doc.ESCourse;
import cn.wangningbo.hrm.query.ESCourseQuery;
import cn.wangningbo.hrm.util.AjaxResult;
import cn.wangningbo.hrm.util.PageList;
import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * @author wangningbo
 * @date 2019/09/06
 */
@Component
public class EsCourseClientHystrixFallbackFactory implements FallbackFactory {

    @Override
    public ESCourseClient create(Throwable throwable) {
        return new ESCourseClient() {
            @Override
            public AjaxResult save(ESCourse esCourse) {
                return null;
            }

            @Override
            public AjaxResult delete(Integer id) {
                return null;
            }

            @Override
            public ESCourse get(Long id) {
                return null;
            }

            @Override
            public List list() {
                return null;
            }

            @Override
            public PageList json(ESCourseQuery query) {
                return null;
            }
        };
    }
}
  1. 生成文档映射-test-service
@RunWith(SpringRunner.class)
@SpringBootTest(classes = ElasticSearch9004Application.class)
public class IESCourseServiceTest {
    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;

    @Test
    public void testInit() throws Exception {
        elasticsearchTemplate.createIndex(ESCourse.class);
        elasticsearchTemplate.putMapping(ESCourse.class);
    }
}
  1. 测试

    http://localhost:9004/esCourse/list

  2. 日志集成

    resources下存放一个名字为logback-spring.xml的配置文件




    
    
    
    
    
    
        
        
            %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
        
    

      
    
        
        ${LOG_HOME}/${appName}/${appName}.log
        
        
            
            ${LOG_HOME}/${appName}/${appName}-%d{yyyy-MM-dd}-%i.log
            
            365
            
            
                100MB
            
        
             
        
            %d{yyyy-MM-dd HH:mm:ss.SSS} [ %thread ] - [ %-5level ] [ %logger{50} : %line ] - %msg%n
        
    

    
    
    
    
    



    
    
        
        
    
 
  1. 网关集成

    在网关的配置文件中zuul.routes中再新加两行,配置es

    es.serviceId: hrm-es # 服务名
    es.path: /es/** # 把es打头的所有请求都转发给hrm-es
  1. 本项目swagger集成
package cn.wangningbo.hrm.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.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
public class Swagger2 {

    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                //对外暴露服务的包,以controller的方式暴露,所以就是controller的包.
                .apis(RequestHandlerSelectors.basePackage("cn.wangningbo.hrm.web.controller"))
                .paths(PathSelectors.any())
                .build();
    }


    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("分布式全文检索api")
                .description("分布式全文检索接口文档说明")
                .contact(new Contact("wangningbo", "", "[email protected]"))
                .version("1.0")
                .build();
    }
}
  1. 网关swagger集成

    在网关的DocumentationConfig配置类里面新加个

resources.add(swaggerResource("分布式全文检索", "/services/es/v2/api-docs", "2.0"));
  1. 启动测试网关、日志、swagger

2.2.2 课程上下线处理

架构分析图(后续补上)

2.2.2.1 步骤分析

  1. 改造商品的删除和修改(索引库也要进行对应的操作)
  2. 课程的上下线逻辑
  3. client

2.2.2.2 步骤实现

  1. 改造商品的删除和修改(索引库也要进行对应的操作)

    由于要使用es,这里操作删除和修改的时候也要操作es库,所以要覆写删除和修改方法!

    @Override
    public boolean deleteById(Serializable id) {
        //删除数据库的同时也要判断状态是否要删除es库
        courseMapper.deleteById(id);
        Course course = courseMapper.selectById(id);
        if (course.getStatus() == 1)
            esCourseClient.delete(Integer.valueOf(id.toString()));
        return true;
    }

    // @TODO 不同服务,反3Fn设计冗余字段
    // @TODO 相同服务,关联查询
    //根据自己的需求和库中的表设计
    private ESCourse course2EsCourse(Course course) {
        ESCourse result = new ESCourse();
        result.setId(course.getId());
        result.setName(course.getName());
        result.setUsers(course.getUsers());
        result.setCourseTypeId(course.getCourseTypeId());
        //type-同库
        if (course.getCourseType() != null)
            result.setCourseTypeName(course.getCourseType().getName());
        //跨服务操作
        result.setGradeId(course.getGrade());
        result.setGradeName(null);
        result.setStatus(course.getStatus());
        result.setTenantId(course.getTenantId());
        result.setTenantName(course.getTenantName());
        result.setUserId(course.getUserId());
        result.setUserName(course.getUserName());
        result.setStartTime(course.getStartTime());
        result.setEndTime(course.getEndTime());
        //Detail
        result.setIntro(null);
        //resource
        result.setResources(null);
        //market
        result.setExpires(null);
        result.setPrice(null);
        result.setPriceOld(null);
        result.setQq(null);
        return result;
    }

    @Override
    public boolean updateById(Course entity) {
        //修改数据库的时候也要根据状态判断是否操作修改es库
        courseMapper.updateById(entity);
        Course course = courseMapper.selectById(entity.getId());
        if (course.getStatus() == 1)
            esCourseClient.save(course2EsCourse(entity));
        return true;
    }
  1. 课程的上下线逻辑

    简单逻辑:前端会发起上线或下线请求!到我这里的controller接口。我这里进行一层一层的实现逻辑!既要操作db库,也要操作es库!

    controller层新增两个方法,上线和下线。我这里先实现上线,再写下线(下线比较简单)!

==(上线---------------------->)==

controller

//由于前端可能是批量操作,所以我这里使用数组接收参数
    @PostMapping("/onLine")
    public AjaxResult onLine(@RequestBody Long[] ids) {
        try {
            courseService.onLine(ids);
            return AjaxResult.me();
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("online failed!"+e);
            return AjaxResult.me().setSuccess(false)
                    .setMessage("上线失败!"+e.getMessage());
        }
    }

IService

    void onLine(Long[] ids);

ServiceImpl

    /**
     * 商品课程上线
     * @param ids
     */
    @Override
    public void onLine(Long[] ids) {
        //批量操作数据库状态字段 //类似于这种update t_course set status = 1,start_time=xxx where id in (1,2,3)
        ArrayList> listMap = new ArrayList<>();
        if (ids != null || ids.length > 0) {
            for (Long id : ids) {
                HashMap map = new HashMap<>();
                map.put("id", id);
                map.put("start_time", new Date());
                listMap.add(map);
            }
        }
        //批量修改db状态字段
        courseMapper.batchOnline(listMap);
        //批量操作索引库
        //从数据库中查出来需要上线的商品课程
        List courseList = courseMapper.selectBatchIds(Arrays.asList(ids));
        //把从数据库中查出来的商品课程转化为es的doc
        List esCourseList = courseList2EsCourse(courseList);
        //批量操作把doc添加到es库 //批量添加到es库中的方法没有,自己实现一个
        esCourseClient.batchSave(esCourseList);
    }
    
        /**
     * db库的domain转化为es的doc
     *
     * @param courseList
     * @return
     */
    private List courseList2EsCourse(List courseList) {
        ArrayList list = new ArrayList<>();
        courseList.forEach(course -> list.add(course2EsCourse(course)));
        return list;
    }

上面这个serviceImpl主要是做2步操作,第一步是批量修改db库的状态字段为上线,第二步是操作es库,批量把上线的商品课程添加es库中。

①先说操作db库的字段修改为上线的逻辑步骤

Mapper.java

void batchOnline(ArrayList> listMap);

Mapper.xml

    
    
        UPDATE t_course set status =1,start_time=now() where id IN
        
            #{item.id}
        
    

②再说操作es库,把上线的商品课程添加到es库

es-->client

    //批量上线
    @PostMapping("/online")
    AjaxResult batchSave(List esCourseList);

es-->ClientHystrixFallbackFactory

            @Override
            public AjaxResult batchSave(List esCourseList) {
                return null;
            }

es-->controller

    /**
     * 批量保存到es库,批量上线
     * @param esCourseList
     * @return
     */
    @PostMapping("/online")
    AjaxResult batchSave(@RequestBody List esCourseList){
        try {
            esCourseService.batchSave(esCourseList);
            return AjaxResult.me();
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.me().setSuccess(false).setMessage("批量添加失败!"+e.getMessage());
        }
    }

es-->IService

    //批量保存
    void batchSave(List ids);

es-->ServiceImpl

    //批量保存
    @Override
    public void batchSave(List esCourseList) {
        courseRepository.saveAll(esCourseList);
    }

==注意:这时候调用es的那个模块的入口类就要打上注解@EnableFeignClients== 入口类获得feign支持

测试是否成功

==(下线---------------------->)==

下线的简单逻辑分析:管理员下线商品课程只需要做2步,第一步:修改db库中的商品课程字段为下线状态,第二步:删除es库中的商品课程

controller

    /**
     * 商品课程下线
     *
     * @param ids
     * @return
     */
    @PostMapping("/offLine")
    public AjaxResult offLine(@RequestBody Long[] ids) {
        try {
            courseService.offLine(ids);
            return AjaxResult.me();
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("offLine failed!"+e);
            return AjaxResult.me().setSuccess(false)
                    .setMessage("下线失败!"+e.getMessage());
        }
    }

IService

    void offLine(Long[] ids);

ServiceImpl

    @Override
    public void offLine(Long[] ids) {
        //批量修改db库中商品课程的状态为下线状态
        courseMapper.batchOffline(Arrays.asList(ids));
        //批量删除es库中的商品课程 //时间方面是使用mysql的语法生成的
        List courseList = courseMapper.selectBatchIds(Arrays.asList(ids));
        List esCourseList = courseList2EsCourse(courseList);
        esCourseClient.batchDel(esCourseList);
    }

上面这个serviceImpl主要是做2步操作,第一步是批量修改db库的状态字段为下线状态,第二步是操作es库,批量把下线的商品课程从es库中删除掉。

①批量修改db库的状态字段为下线状态

Mapper.java

    void batchOffline(List longs);

Mapper.xml

    
    
        UPDATE t_course set status =0,end_time=now() where id IN
        
            #{item}
        
    

es-->client

    //批量下线
    @PostMapping("/offline")
    void batchDel(List esCourseList);

es-->ClientHystrixFallbackFactory

            @Override
            public void batchDel(List esCourseList) {

            }

es-->controller

    @PostMapping("/offline")
    AjaxResult batchDel(@RequestBody List esCourseList){
        try {
            esCourseService.batchDel(esCourseList);
            return AjaxResult.me();
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.me().setSuccess(false).setMessage("批量删除失败!"+e.getMessage());
        }
    }

es-->Iservice

    //批量删除
    void batchDel(List esCourseList);

es-->ServiceImpl

    //批量删除
    @Override
    public void batchDel(List esCourseList) {
        courseRepository.deleteAll(esCourseList);
    }

测试是否成功

3. 易错点总结

  1. ESClient那里的注解@FeignClient的参数。value = "HRM-ES"的值指向自己注册到eureka的服务。以下面为例
@FeignClient(value = "HRM-ES",configuration = FeignClientsConfiguration.class,
        fallbackFactory = EsCourseClientHystrixFallbackFactory.class)
  1. ESClient那里的注@RequestMapping的参数值要与controller的一致。以下面的为例
//client
@FeignClient(value = "HRM-ES",configuration = FeignClientsConfiguration.class,
        fallbackFactory = EsCourseClientHystrixFallbackFactory.class)
@RequestMapping("/esCourse")
public interface EsCourseClient {}

//controller
@RestController
@RequestMapping("/esCourse")
public class EsCourseController {}
  1. 其他模块调用es的时候,作为es的客户端,在入口类上要加入feign的支持。也就是注解@EnableFeignClients。以下面为例
package cn.wangningbo.hrm;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableEurekaClient
@MapperScan("cn.wangningbo.hrm.mapper")
@EnableFeignClients
public class Course9002Application {
    public static void main(String[] args) {
        SpringApplication.run(Course9002Application.class, args);
    }
}

你可能感兴趣的:(SAAS-HRM-day5(ElasticSearch))