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());
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章