首先,我们需要在taotao-item-web工程中添加对ActiveMQ的依赖,如下图所示。
然后,把taotao-search-service工程下的applicationContext-activemq.xml文件拷贝一份到taotao-item-web工程的src/main/resources/spring目录中,并且更名为springmvc-activemq.xml,除此之外,我们还得对springmvc-activemq.xml文件中的内容做一些修改,修改后的内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd">
<bean id="targetConnection" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://192.168.81.135:61616"></property>
</bean>
<!-- 通用的connectionfacotry 指定真正使用的连接工厂 -->
<bean id="connectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory">
<property name="targetConnectionFactory" ref="targetConnection"></property>
</bean>
<!-- 这个是主题目的地,一对多的 -->
<bean id="topicDestination" class="org.apache.activemq.command.ActiveMQTopic">
<constructor-arg name="name" value="item-change-topic"></constructor-arg>
</bean>
<!-- 配置消息监听器 -->
<bean id="itemChangeGenHtmMessageListener" class="com.taotao.listener.ItemChangeGenHtmMessageListener" />
<bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory" />
<property name="destination" ref="topicDestination" />
<property name="messageListener" ref="itemChangeGenHtmMessageListener" />
</bean>
</beans>
注意,咱们还得保证springmvc-activemq.xml文件能被Spring容器加载到,因此我们得修改一下web.xml文件,如下图所示,将classpath:spring/springmvc.xml
改为classpath:spring/springmvc*.xml
。
以上配置文件中配置了一个消息监听器,那么我们还需要创建这么一个消息监听器,当监听到有添加商品的消息时便去生成静态页面,该消息监听器类的代码如下所示。
package com.taotao.listener;
import java.io.File;
import java.io.FileWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
import com.taotao.item.pojo.Item;
import com.taotao.pojo.TbItem;
import com.taotao.pojo.TbItemDesc;
import com.taotao.service.ItemService;
import freemarker.template.Configuration;
import freemarker.template.Template;
/**
* 监听器
* 所做的事情:
* 1. 获取消息
* 2. 执行生成静态页面的业务逻辑
*
* @author liayun
*
*/
public class ItemChangeGenHtmMessageListener implements MessageListener {
@Autowired
private ItemService itemService;
@Autowired
private FreeMarkerConfigurer config;
@Override
public void onMessage(Message message) {
if (message instanceof TextMessage) {
// 1. 获取消息,也即商品id
TextMessage message2 = (TextMessage) message;
try {
String text = message2.getText();
if (StringUtils.isNotBlank(text)) {
Long itemId = Long.valueOf(text);
// 2. 从数据库中获取商品相关数据,可以调用taotao-manager中的服务,获取到了数据集
// 引入服务
// 注入服务
// 调用服务
TbItem tbItem = itemService.getItemById(itemId);
Item item = new Item(tbItem); // 转成在页面中显示数据时的pojo
TbItemDesc tbItemDesc = itemService.getItemDescById(itemId);
// 3. 生成静态页面,前提是准备好模板和数据集
//
genHtmlFreemarker(item, tbItemDesc);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 生成静态页面
* @param item
* @param tbItemDesc
*/
private void genHtmlFreemarker(Item item, TbItemDesc tbItemDesc) throws Exception {
// 1, 获取Configuration对象
Configuration configuration = config.getConfiguration();
// 2. 创建模板,并获取模板对象
Template template = configuration.getTemplate("item.htm");
// 3. 创建数据集
Map model = new HashMap();
model.put("item", item);
model.put("itemDesc", tbItemDesc);
// 4. 输出,D:/项目实战/淘淘商城/freemarker/item/1234.html
Writer writer = new FileWriter(new File("D:/项目实战/淘淘商城/freemarker/item" + "/" + item.getId() + ".html"));
template.process(model, writer);
// 5. 关闭流
writer.close();
}
}
其中,输出的文件路径我是写死在了代码中。
以上代码写完之后,接下来我们就要来测试一下了,测试之前,我们要先启动如下服务器,也就是启动那些虚拟机。
然后按照如下顺序依次启动这些maven工程,最好是先启动服务层的工程,再启动表现层的工程。
这些工程都启动成功后,我们在淘淘商城后台页面添加一个商品,如下图所示。
添加完商品后,我们到静态文件目录下查看生成的静态文件,发现啥都没有,如下图所示,不是说好了能生成静态页面吗?这尼玛是要闹哪一出啊😭!!!
除此之外,Eclipse控制台还打印出了一个java.lang.IllegalArgumentException异常,如下图所示。
然而当我们再次添加一个商品并成功之后,到静态文件目录下查看一下生成的静态文件,发现他妈的竟然就有了,如下图所示。
这就有点迷了,WDNMD,这到底怎么一回事啊😱?要想解决这个问题,不妨耐心看看我的这篇文章——《淘淘商城第86讲——实现商品详情页面静态化方案时,你没遇到过java.lang.IllegalArgumentException或者java.lang.NullPointerException这种异常》
接着我们重新启动taotao-item-web工程,再次添加一个商品,立马到静态文件目录下查看下生成的静态文件,发现是能看到刚刚生成的静态页面的,如下图所示。
使用浏览器查看生成的静态页面,可以看到生成的静态页面是没有样式的,这是因为我们没有把样式文件放到相应的目录下。
为了让页面的样式呈现出来,我们把taotao-item-web工程的webapp目录下的css、images以及js文件拷贝到"D:\项目实战\淘淘商城\freemarker"目录下,也就是要与"item"目录位于同一级别目录下。
要想看到页面的正常效果,我们可以先使用Windows版的Nginx作为Http服务器,大家可以到Nginx官网下载一个Windows版本的安装包,这儿我下载的是1.18.0这个版本。
然后解压该安装包到某个目录下,例如我解压到了"D:\javaee_develop\Nginx"这个目录中,这里有一点需要特别注意,千万不要将Nginx安装包解压到带有中文字符的目录中,否则会启动不起来。
打开解压之后的nginx-1.18.0目录,咱们看看里面都有些啥?
其中,conf目录下有一个很重要的配置文件,即nginx.conf文件。
接着我们便要修改nginx.conf文件了,即修改location下面的root目录为"D:/项目实战/淘淘商城/freemarker",如下图所示。
修改完后,紧接着我们就要启动Nginx服务器了,启动Nginx服务器有两种方式,第一种方式就是双击nginx.exe,这时你会看到什么东西一闪而过,很快Nginx服务器便会启动。第二种方式是在命令行窗口中使用cd命令切到nginx.exe所在的目录中,再使用start nginx.exe
命令来启动Nginx服务器,如下图所示。
怎么知道Nginx服务器启动起来了呢?查看任务管理器,如果能看到下面两个进程,那么就代表Nginx服务器已经启动了。
如果想要停掉Nginx服务器,那么使用nginx.exe -s stop
命令即可。
最后我们使用Nginx服务器来访问一下生成的静态网页,在浏览器地址栏中输入http://localhost/item/160518635071512.html
并回车,即可看到页面正常展示出了商品的详情。
注意,本文只是演示了如何生成静态页面,因为需要先生成静态页面才能访问,而生成静态页面又比较麻烦,所以后面的学习依旧使用动态页面来展示商品详情。