Springcloud微服務項目——人力資源管理(HRM)Day09 頁面靜態化完善&課程列表頁(前端)

前面我們只講了將靜態頁面上傳到Fastdfs 今天我們將頁面作爲消息發送Message到mq中 然後前臺取到頁面

步驟

首先我們可以在公共的模塊中建一個子模塊hrm-basic-rabbitmq
在這裏插入圖片描述

導入spirngboot集成rabbitmq的依賴

<!--spirngboot集成rabbitmq-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

創建一個存放rabbitmq常量的工具類

//存放rabbitmq的常量,就是消費者和生產者公共東西
public class RabbitMqConstants {
    public static final String EXCHANGE_TOPICS_PAGE = "exchange_topics_page";
    public static final String FILE_SYS_TYPE = "fileSysType";
    public static final String PAGE_URL = "pageUrl";
    public static final String PHYSICAL_PATH = "physicalPath";
}

然後在page模塊中引入rabbitmq的模塊引入mq的jar包

<dependency>
    <groupId>org.leryoo</groupId>
    <artifactId>hrm-basic-rabbitmq</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

Service層

String routingKey = siteMapper.selectById(pager.getSiteId()).getSn();
//消息的內容
Map<String,Object> params = new HashMap<>();
params.put(RabbitMqConstants.FILE_SYS_TYPE,pageConfig.getDfsType()); //文件系統,從哪兒系統系統
params.put(RabbitMqConstants.PAGE_URL,pageConfig.getPageUrl());//從那個路徑下載
params.put(RabbitMqConstants.PHYSICAL_PATH,pageConfig.getPhysicalPath());//下載完了放到哪兒
rabbitTemplate.convertAndSend(
        RabbitMqConstants.EXCHANGE_TOPICS_PAGE,routingKey
        ,JSONObject.toJSONString(params));

創建一個hrm-page-agent-parent模塊

1 這個模塊用來從文件系統下載靜態化頁面的
2 上線時要作爲一個jar和nginx部署在一個服務器上面
3 他沒有common模塊(沒有domain),沒有client(也不給別人調用),只有servie模塊
4 servie模塊開發步驟
  1) jar springboot,rabbitmq
  2) 配置-rabbitmq(configserver需要)
  3 ) 入口類(Eureka)
  ====
  4)zuul訪問映射
  5)swagger
  4,5不需要,不暴露服務
  6)聲明交換機,聲明隊列,把隊列綁定到交換機
  7)消費者的handler綁定到隊列
  8)實現handler的功能給你

子模塊hrm-page-agent-service-2040
導入相關依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

<!-- Eureka 客戶端依賴 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

<!--配置中心支持-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-config</artifactId>
</dependency>

<!-- 通過公共rabbitmq的模塊引入mq的jar包-->
<dependency>
    <groupId>org.leryoo</groupId>
    <artifactId>hrm-basic-rabbitmq</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>
<!--        fastdfsclient支持-->
<dependency>
    <groupId>org.leryoo</groupId>
    <artifactId>hrm-common-client</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.4</version>
</dependency>
<!-- 給調用的模塊來轉換json-->
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson  調用者需要轉換-->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.58</version>
</dependency>

然後是配置文件bootstrap.yml

spring:
  profiles:
    active: dev
  cloud:
    config:
      name: application-page-agent #github上面名稱
      profile: ${spring.profiles.active} #環境 java -jar -D xxx jar
      label: master #分支
      discovery:
        enabled: true #從eureka上面找配置服務
        service-id: hrm-config-server #指定服務名
      #uri: http://127.0.0.1:1299 #配置服務器 單機配置
eureka: #eureka不能放到遠程配置中
  client:
    service-url:
      defaultZone: http://localhost:1010/eureka  #告訴服務提供者要把服務註冊到哪兒 #單機環境
  instance:
    prefer-ip-address: true #顯示客戶端真實ip
feign:
  hystrix:
    enabled: true #開啓熔斷支持
  client:
    config:
      remote-service:           #服務名,填寫default爲所有服務
        connectTimeout: 3000
        readTimeout: 3000
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 3000

配置倉庫中的配置

server:
  port: 2040
spring:
  application:
    name: hrm-page-agent
rabbitmq:
  host: 127.0.0.1
  port: 5672
  username: guest
  password: guest
  virtualHost: /
  routingKey: hrmCourseSit

注意因爲生產者和消費者都需要連接rabbitmq 所以在application-page-dev.yml中也需要配置

rabbitmq:
  host: 127.0.0.1
  port: 5672
  username: guest
  password: guest
  virtualHost: /

然後是RabbitMqConfig.java
用來聲明交換機和隊列 並將交換機和隊列綁定到在一起

import org.leryoo.util.RabbitMqConstants;
import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RabbitMqConfig {
    //隊列
    public static final String QUEUE_PAGE_STATIC = "queue_page_static";
    //交換機名字
    public static final String EXCHANGE_TOPICS_PAGE = RabbitMqConstants.EXCHANGE_TOPICS_PAGE;

    @Value("${rabbitmq.routingKey}")
    private String routingKey;

    /**
     * 交換機配置
     * ExchangeBuilder提供了fanout、direct、topic、header交換機類型的配置
     *
     * @return the exchange
     */
    @Bean(EXCHANGE_TOPICS_PAGE) //spring中bean
    public Exchange EXCHANGE_TOPICS_INFORM() {
        //durable(true)持久化,消息隊列重啓後交換機仍然存在
        return ExchangeBuilder.topicExchange(EXCHANGE_TOPICS_PAGE).durable(true).build();
    }


    //聲明隊列
    @Bean(QUEUE_PAGE_STATIC)
    public Queue QUEUE_INFORM_SMS() {
        Queue queue = new Queue(QUEUE_PAGE_STATIC);
        return queue;
    }

    /**
     *
     * @param queue    the queue
     * @param exchange the exchange
     * @return the binding
     */
    @Bean
    public Binding BINDING_QUEUE_INFORM_SMS(@Qualifier(QUEUE_PAGE_STATIC) Queue queue, //通過名字從spring獲取bean
                                            @Qualifier(EXCHANGE_TOPICS_PAGE) Exchange exchange) {
        //每個站點的routing可以是不一樣的
        System.out.println(routingKey);
        return BindingBuilder.bind(queue).to(exchange).with(routingKey).noargs();
    }

}

StaticPageHandler.java
用來接受消息 並下載到指定的目錄

import com.alibaba.fastjson.JSONObject;
import com.rabbitmq.client.Channel;
import feign.Response;
import org.apache.commons.io.IOUtils;
import org.leryoo.client.FastDfsClient;
import org.leryoo.config.RabbitMqConfig;
import org.leryoo.util.RabbitMqConstants;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;

@Component
public class StaticPageHandler {
    @RabbitListener(queues = RabbitMqConfig.QUEUE_PAGE_STATIC)
    public void handle(String msg, Message message, Channel channel){
        System.out.println("接收消息:"+msg);
        Map map = JSONObject.parseObject(msg, Map.class);
        Integer fileSysType = (Integer) map.get(RabbitMqConstants.FILE_SYS_TYPE);
        String pageUrl = (String) map.get(RabbitMqConstants.PAGE_URL);
        String physicalPath = (String) map.get(RabbitMqConstants.PHYSICAL_PATH);
        //判斷是那個文件系統,分別做處理

        switch(fileSysType){
            case 0 : //fastdfs
                downloadAndCopyOfFastDfs(pageUrl,physicalPath);
                break;
            case 1 : //hdfs
                downloadAndCopyOfHdfs(pageUrl,physicalPath);
                break;
        }
    }
    @Autowired
    private FastDfsClient fastDfsClient;

    //fastdfs支持
    private void downloadAndCopyOfFastDfs(String pageUrl, String physicalPath) {
        InputStream is = null;
        FileOutputStream os = null;
        try{
            //以pageUrl到fastdfs下載文件
            Response response = fastDfsClient.download(pageUrl);
            is = response.body().asInputStream();
            //放入特定文件
            System.out.println(physicalPath);
            os = new FileOutputStream(physicalPath);
            IOUtils.copy(is,os) ;
        }catch (Exception e){
            e.printStackTrace();
        }
        finally {

            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (is != null) {

                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    //@TODO hdfs以後支持
    private void downloadAndCopyOfHdfs(String pageUrl, String physicalPath) {
    }
}

最後別忘了寫一個啓動類

然後啓動服務 就ok啦
在這裏插入圖片描述
在這裏插入圖片描述

需要注意的是 因爲我們這裏是生成的靜態頁面 所以我們如果修改了數據後 我們都需要重新生成靜態頁面

課程列表頁

因爲是新的頁面 所以注意跨域問題

在這裏插入圖片描述

1)主頁裏面關鍵字搜索
2)主頁裏面通過類型導航過去.

這裏因爲沒找到課程商城的模板 就隨便找了一個 實現起來都差不多

在這裏插入圖片描述
在這裏插入圖片描述

實現

主頁跳轉列表頁

分析:
①主頁攜帶參數跳轉到列表頁.
location.href = list.html?keyword =xx 關鍵字

在這裏插入圖片描述
轉發到列表頁後進行回顯 回顯到輸入框
在這裏插入圖片描述
在這裏插入圖片描述

然後是一個小功能 麪包屑導航
如果是通過這個地方點進來的 會去搜索文件 也會有一個麪包屑的導航
在這裏插入圖片描述

在這裏插入圖片描述
後臺的實現:

@Override
public List<Map<String, Object>> queryCrumbs(Long courseTypeId) {
    List<Map<String,Object>> result = new ArrayList<>();
    //1 通過courseTypeId獲取CourseType,從而得到path,就能得到層次結構 .1.2.3. List
    String path = courseTypeMapper.selectById(courseTypeId).getPath(); //.1.2.3.
    path = path.substring(1,path.length()-1); // 1.2.3
    System.out.println(path);
    String[] paths = path.split("\\."); //[1,2,3]
    //2 對每個節點進行處理 Map
    for (String idStr : paths) {
        Map<String,Object> node = new HashMap<>();
        //2.1 自己
        CourseType owerCourseType = courseTypeMapper.selectById(Long.valueOf(idStr));
        node.put("ownerCourseType",owerCourseType);
        //2.2 兄弟
        //2.1.1 獲取父親的所有兒子
        Long pid = owerCourseType.getPid();
        List<CourseType> allChirdren = courseTypeMapper
                .selectList(new EntityWrapper<CourseType>().eq("pid", pid));
        //2.1.2 刪除自己
        Iterator<CourseType> iterator = allChirdren.iterator();
        while (iterator.hasNext()){
            CourseType type = iterator.next();
            //自己id爲遍歷出來的id
            if (owerCourseType.getId().intValue()==type.getId().intValue()){
                iterator.remove();
                break;
            }
        }
        node.put("otherCourseTypes",allChirdren);
        result.add(node);
    }

    return result;
}

然後是搜索功能
在這裏插入圖片描述
在這裏插入圖片描述
後臺實現

@Override
public PageList<EsCourse> queryCourses(CourseQuery query) {

    NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
    //1條件
    BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
    builder.withQuery(boolQuery);
    //2 排序
    FieldSortBuilder order = SortBuilders.fieldSort(query.getSortField()).order(SortOrder.DESC);
    builder.withSort(order);
    //3 分頁
    builder.withPageable(PageRequest.of(query.getPage()-1,query.getRows()));
    //4 截取字段 先不多
    //5 查詢封裝
    NativeSearchQuery esQuery = builder.build();
    org.springframework.data.domain.Page<EsCourse> page =
            repository.search(esQuery);
    return new PageList<>(page.getTotalElements(),page.getContent());
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章