前面我们只讲了将静态页面上传到Fastdfs 今天我们将页面作为消息发送Message到mq中 然后前台取到页面
步骤
首先我们可以在公共的模块中建一个子模块
hrm-basic-rabbitmq
导入spirngboot集成rabbitmq的依赖
1
2
3
4
5
6
7 1<!--spirngboot集成rabbitmq-->
2<dependency>
3 <groupId>org.springframework.boot</groupId>
4 <artifactId>spring-boot-starter-amqp</artifactId>
5</dependency>
6
7
创建一个存放rabbitmq常量的工具类
1
2
3
4
5
6
7
8
9 1//存放rabbitmq的常量,就是消费者和生产者公共东西
2public class RabbitMqConstants {
3 public static final String EXCHANGE_TOPICS_PAGE = "exchange_topics_page";
4 public static final String FILE_SYS_TYPE = "fileSysType";
5 public static final String PAGE_URL = "pageUrl";
6 public static final String PHYSICAL_PATH = "physicalPath";
7}
8
9
然后在page模块中引入rabbitmq的模块引入mq的jar包
1
2
3
4
5
6
7 1<dependency>
2 <groupId>org.leryoo</groupId>
3 <artifactId>hrm-basic-rabbitmq</artifactId>
4 <version>1.0-SNAPSHOT</version>
5</dependency>
6
7
Service层
1
2
3
4
5
6
7
8
9
10
11 1String routingKey = siteMapper.selectById(pager.getSiteId()).getSn();
2//消息的内容
3Map<String,Object> params = new HashMap<>();
4params.put(RabbitMqConstants.FILE_SYS_TYPE,pageConfig.getDfsType()); //文件系统,从哪儿系统系统
5params.put(RabbitMqConstants.PAGE_URL,pageConfig.getPageUrl());//从那个路径下载
6params.put(RabbitMqConstants.PHYSICAL_PATH,pageConfig.getPhysicalPath());//下载完了放到哪儿
7rabbitTemplate.convertAndSend(
8 RabbitMqConstants.EXCHANGE_TOPICS_PAGE,routingKey
9 ,JSONObject.toJSONString(params));
10
11
创建一个
hrm-page-agent-parent模块
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 11 这个模块用来从文件系统下载静态化页面的
22 上线时要作为一个jar和nginx部署在一个服务器上面
33 他没有common模块(没有domain),没有client(也不给别人调用),只有servie模块
44 servie模块开发步骤
5 1) jar springboot,rabbitmq
6 2) 配置-rabbitmq(configserver需要)
7 3 ) 入口类(Eureka)
8 ====
9 4)zuul访问映射
10 5)swagger
11 4,5不需要,不暴露服务
12 6)声明交换机,声明队列,把队列绑定到交换机
13 7)消费者的handler绑定到队列
14 8)实现handler的功能给你
15
16
子模块
hrm-page-agent-service-2040
导入相关依赖
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 1<dependency>
2 <groupId>org.springframework.boot</groupId>
3 <artifactId>spring-boot-starter-web</artifactId>
4</dependency>
5
6<dependency>
7 <groupId>org.springframework.boot</groupId>
8 <artifactId>spring-boot-starter-test</artifactId>
9 <scope>test</scope>
10</dependency>
11
12<!-- Eureka 客户端依赖 -->
13<dependency>
14 <groupId>org.springframework.cloud</groupId>
15 <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
16</dependency>
17
18<!--配置中心支持-->
19<dependency>
20 <groupId>org.springframework.cloud</groupId>
21 <artifactId>spring-cloud-starter-config</artifactId>
22</dependency>
23
24<!-- 通过公共rabbitmq的模块引入mq的jar包-->
25<dependency>
26 <groupId>org.leryoo</groupId>
27 <artifactId>hrm-basic-rabbitmq</artifactId>
28 <version>1.0-SNAPSHOT</version>
29</dependency>
30<!-- fastdfsclient支持-->
31<dependency>
32 <groupId>org.leryoo</groupId>
33 <artifactId>hrm-common-client</artifactId>
34 <version>1.0-SNAPSHOT</version>
35</dependency>
36
37<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
38<dependency>
39 <groupId>commons-io</groupId>
40 <artifactId>commons-io</artifactId>
41 <version>2.4</version>
42</dependency>
43<!-- 给调用的模块来转换json-->
44<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson 调用者需要转换-->
45<dependency>
46 <groupId>com.alibaba</groupId>
47 <artifactId>fastjson</artifactId>
48 <version>1.2.58</version>
49</dependency>
50
51
然后是配置文件bootstrap.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 1spring:
2 profiles:
3 active: dev
4 cloud:
5 config:
6 name: application-page-agent #github上面名称
7 profile: ${spring.profiles.active} #环境 java -jar -D xxx jar
8 label: master #分支
9 discovery:
10 enabled: true #从eureka上面找配置服务
11 service-id: hrm-config-server #指定服务名
12 #uri: http://127.0.0.1:1299 #配置服务器 单机配置
13eureka: #eureka不能放到远程配置中
14 client:
15 service-url:
16 defaultZone: http://localhost:1010/eureka #告诉服务提供者要把服务注册到哪儿 #单机环境
17 instance:
18 prefer-ip-address: true #显示客户端真实ip
19feign:
20 hystrix:
21 enabled: true #开启熔断支持
22 client:
23 config:
24 remote-service: #服务名,填写default为所有服务
25 connectTimeout: 3000
26 readTimeout: 3000
27hystrix:
28 command:
29 default:
30 execution:
31 isolation:
32 thread:
33 timeoutInMilliseconds: 3000
34
35
配置仓库中的配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14 1server:
2 port: 2040
3spring:
4 application:
5 name: hrm-page-agent
6rabbitmq:
7 host: 127.0.0.1
8 port: 5672
9 username: guest
10 password: guest
11 virtualHost: /
12 routingKey: hrmCourseSit
13
14
注意因为生产者和消费者都需要连接rabbitmq 所以在
application-page-dev.yml中也需要配置
1
2
3
4
5
6
7
8 1rabbitmq:
2 host: 127.0.0.1
3 port: 5672
4 username: guest
5 password: guest
6 virtualHost: /
7
8
然后是
RabbitMqConfig.java
用来声明交换机和队列 并将交换机和队列绑定到在一起
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54 1import org.leryoo.util.RabbitMqConstants;
2import org.springframework.amqp.core.*;
3import org.springframework.beans.factory.annotation.Qualifier;
4import org.springframework.beans.factory.annotation.Value;
5import org.springframework.context.annotation.Bean;
6import org.springframework.context.annotation.Configuration;
7
8@Configuration
9public class RabbitMqConfig {
10 //队列
11 public static final String QUEUE_PAGE_STATIC = "queue_page_static";
12 //交换机名字
13 public static final String EXCHANGE_TOPICS_PAGE = RabbitMqConstants.EXCHANGE_TOPICS_PAGE;
14
15 @Value("${rabbitmq.routingKey}")
16 private String routingKey;
17
18 /**
19 * 交换机配置
20 * ExchangeBuilder提供了fanout、direct、topic、header交换机类型的配置
21 *
22 * @return the exchange
23 */
24 @Bean(EXCHANGE_TOPICS_PAGE) //spring中bean
25 public Exchange EXCHANGE_TOPICS_INFORM() {
26 //durable(true)持久化,消息队列重启后交换机仍然存在
27 return ExchangeBuilder.topicExchange(EXCHANGE_TOPICS_PAGE).durable(true).build();
28 }
29
30
31 //声明队列
32 @Bean(QUEUE_PAGE_STATIC)
33 public Queue QUEUE_INFORM_SMS() {
34 Queue queue = new Queue(QUEUE_PAGE_STATIC);
35 return queue;
36 }
37
38 /**
39 *
40 * @param queue the queue
41 * @param exchange the exchange
42 * @return the binding
43 */
44 @Bean
45 public Binding BINDING_QUEUE_INFORM_SMS(@Qualifier(QUEUE_PAGE_STATIC) Queue queue, //通过名字从spring获取bean
46 @Qualifier(EXCHANGE_TOPICS_PAGE) Exchange exchange) {
47 //每个站点的routing可以是不一样的
48 System.out.println(routingKey);
49 return BindingBuilder.bind(queue).to(exchange).with(routingKey).noargs();
50 }
51
52}
53
54
StaticPageHandler.java
用来接受消息 并下载到指定的目录
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81 1import com.alibaba.fastjson.JSONObject;
2import com.rabbitmq.client.Channel;
3import feign.Response;
4import org.apache.commons.io.IOUtils;
5import org.leryoo.client.FastDfsClient;
6import org.leryoo.config.RabbitMqConfig;
7import org.leryoo.util.RabbitMqConstants;
8import org.springframework.amqp.core.Message;
9import org.springframework.amqp.rabbit.annotation.RabbitListener;
10import org.springframework.beans.factory.annotation.Autowired;
11import org.springframework.stereotype.Component;
12
13import java.io.FileOutputStream;
14import java.io.IOException;
15import java.io.InputStream;
16import java.util.Map;
17
18@Component
19public class StaticPageHandler {
20 @RabbitListener(queues = RabbitMqConfig.QUEUE_PAGE_STATIC)
21 public void handle(String msg, Message message, Channel channel){
22 System.out.println("接收消息:"+msg);
23 Map map = JSONObject.parseObject(msg, Map.class);
24 Integer fileSysType = (Integer) map.get(RabbitMqConstants.FILE_SYS_TYPE);
25 String pageUrl = (String) map.get(RabbitMqConstants.PAGE_URL);
26 String physicalPath = (String) map.get(RabbitMqConstants.PHYSICAL_PATH);
27 //判断是那个文件系统,分别做处理
28
29 switch(fileSysType){
30 case 0 : //fastdfs
31 downloadAndCopyOfFastDfs(pageUrl,physicalPath);
32 break;
33 case 1 : //hdfs
34 downloadAndCopyOfHdfs(pageUrl,physicalPath);
35 break;
36 }
37 }
38 @Autowired
39 private FastDfsClient fastDfsClient;
40
41 //fastdfs支持
42 private void downloadAndCopyOfFastDfs(String pageUrl, String physicalPath) {
43 InputStream is = null;
44 FileOutputStream os = null;
45 try{
46 //以pageUrl到fastdfs下载文件
47 Response response = fastDfsClient.download(pageUrl);
48 is = response.body().asInputStream();
49 //放入特定文件
50 System.out.println(physicalPath);
51 os = new FileOutputStream(physicalPath);
52 IOUtils.copy(is,os) ;
53 }catch (Exception e){
54 e.printStackTrace();
55 }
56 finally {
57
58 if (os != null) {
59 try {
60 os.close();
61 } catch (IOException e) {
62 e.printStackTrace();
63 }
64 }
65 if (is != null) {
66
67 try {
68 is.close();
69 } catch (IOException e) {
70 e.printStackTrace();
71 }
72 }
73 }
74 }
75
76 //@TODO hdfs以后支持
77 private void downloadAndCopyOfHdfs(String pageUrl, String physicalPath) {
78 }
79}
80
81
最后别忘了写一个启动类
然后启动服务 就ok啦
需要注意的是 因为我们这里是生成的静态页面 所以我们如果修改了数据后 我们都需要重新生成静态页面
课程列表页
因为是新的页面 所以注意跨域问题
1)主页里面关键字搜索
2)主页里面通过类型导航过去.
这里因为没找到课程商城的模板 就随便找了一个 实现起来都差不多
实现
主页跳转列表页
分析:
①主页携带参数跳转到列表页.
location.href = list.html?keyword =xx 关键字
转发到列表页后进行回显 回显到输入框
然后是一个小功能 面包屑导航
如果是通过这个地方点进来的 会去搜索文件 也会有一个面包屑的导航
后台的实现:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 1@Override
2public List<Map<String, Object>> queryCrumbs(Long courseTypeId) {
3 List<Map<String,Object>> result = new ArrayList<>();
4 //1 通过courseTypeId获取CourseType,从而得到path,就能得到层次结构 .1.2.3. List
5 String path = courseTypeMapper.selectById(courseTypeId).getPath(); //.1.2.3.
6 path = path.substring(1,path.length()-1); // 1.2.3
7 System.out.println(path);
8 String[] paths = path.split("\\."); //[1,2,3]
9 //2 对每个节点进行处理 Map
10 for (String idStr : paths) {
11 Map<String,Object> node = new HashMap<>();
12 //2.1 自己
13 CourseType owerCourseType = courseTypeMapper.selectById(Long.valueOf(idStr));
14 node.put("ownerCourseType",owerCourseType);
15 //2.2 兄弟
16 //2.1.1 获取父亲的所有儿子
17 Long pid = owerCourseType.getPid();
18 List<CourseType> allChirdren = courseTypeMapper
19 .selectList(new EntityWrapper<CourseType>().eq("pid", pid));
20 //2.1.2 删除自己
21 Iterator<CourseType> iterator = allChirdren.iterator();
22 while (iterator.hasNext()){
23 CourseType type = iterator.next();
24 //自己id为遍历出来的id
25 if (owerCourseType.getId().intValue()==type.getId().intValue()){
26 iterator.remove();
27 break;
28 }
29 }
30 node.put("otherCourseTypes",allChirdren);
31 result.add(node);
32 }
33
34 return result;
35}
36
37
然后是搜索功能
后台实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 1@Override
2public PageList<EsCourse> queryCourses(CourseQuery query) {
3
4 NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
5 //1条件
6 BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
7 builder.withQuery(boolQuery);
8 //2 排序
9 FieldSortBuilder order = SortBuilders.fieldSort(query.getSortField()).order(SortOrder.DESC);
10 builder.withSort(order);
11 //3 分页
12 builder.withPageable(PageRequest.of(query.getPage()-1,query.getRows()));
13 //4 截取字段 先不多
14 //5 查询封装
15 NativeSearchQuery esQuery = builder.build();
16 org.springframework.data.domain.Page<EsCourse> page =
17 repository.search(esQuery);
18 return new PageList<>(page.getTotalElements(),page.getContent());
19}
20
21