文章大纲
一 、第九天课程计划
二、商品详情页面展示
三、网页静态化
淘淘商城课程大纲
课程大纲
一共14天课程
(1)第一天:电商介绍–互联网术语-SOA-分布式-集群介绍-环境配置-框架搭建
(2)第二天:Dubbo介绍_dubbo框架整合_商品列表查询实现_分页_逆向工程
(3)第三天:Git&.Nginx,类目选择,新增商品
(4)第四天:门户网站介绍&商城首页搭建&内容系统创建&CMS实现
(5)第五天:首页轮播图显示实现,Redis环境搭建,Redis实现缓存
(6)第六天:solr索引库搭建&solr搜索功能实现&图片显示问题解决
(7)第七天:solr集群搭建_全局异常处理
(8)第八天:activeMQ介绍_搭建_解决同步索引库问题
(9)第九天:FreeMark入门_静态化页面标签介绍_静态化页面实现
(10)第十天:Nginx代理详解…单点登录系统工程搭建_接口文档讲解
(11)第十一天:SSO系统的搭建&单点登录系统实现_用户名回显_cookie跨域问题
(12)第十二天:购物车订单系统的实现。
(13)第十三天:订单提交的功能实现&项目的部署&服务器的域名规划。
(14)项目总结。
1. 课程计划
1、商品详情页面展示,动态展示 jsp + redis
2、使用freemarker实现网页静态化
3、ActiveMq同步生成静态网页
4、商品详情的网页静态化方案。
2. 商品详情页面展示
从架构中可以看出商品详情页面是一个表现层工程。
创建一个商品详情页面展示的工程。
2.1. 工程搭建
taotao-item-web。打包方式war。可以参考taotao-portal-web
Pom文件
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.taotao</groupId>
<artifactId>taotao-parent</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<groupId>com.taotao</groupId>
<artifactId>taotao-item-web</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<!-- 商品服务的接口 -->
<dependency>
<groupId>com.taotao</groupId>
<artifactId>taotao-manager-interface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<!-- JSP相关 -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<scope>provided</scope>
</dependency>
<!-- dubbo相关 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<!-- 排除依赖 -->
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
</exclusion>
<exclusion>
<groupId>org.jboss.netty</groupId>
<artifactId>netty</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
</dependency>
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 配置tomcat插件 -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<configuration>
<port>8086</port>
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>
</project>
springmvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd">
<context:property-placeholder location="classpath:resource/*.properties"/>
<context:component-scan base-package="com.taotao.item.controller" />
<mvc:annotation-driven />
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<bean id="freemarkerConfig"
class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPath" value="/WEB-INF/ftl/" />
<property name="defaultEncoding" value="UTF-8" />
</bean>
<!-- 引用dubbo服务 -->
<dubbo:application name="taotao-item-web"/>
<dubbo:registry protocol="zookeeper" address="192.168.25.128:2181"/>
<dubbo:reference interface="com.taotao.service.ItemService" id="itemService" timeout="300000"/>
</beans>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<display-name>taotao-item-web</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- springmvc的前端控制器 -->
<servlet>
<servlet-name>taotao-item-web</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- contextConfigLocation不是必须的, 如果不配置contextConfigLocation, springmvc的配置文件默认在:WEB-INF/servlet的name+"-servlet.xml" -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/springmvc*.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>taotao-item-web</servlet-name>
<!-- SEO :搜索引擎优化 伪静态化-->
<url-pattern>*.html</url-pattern>
</servlet-mapping>
</web-app>
2.2. 功能分析
在搜索结果页面点击商品图片或者商品标题,展示商品详情页面。
如图在商品搜索系统中的搜索结果页面中search.jsp,修改如下:
请求的url:/item/{itemId}
参数:商品id
返回值:String 逻辑视图
业务逻辑:
1、从url中取参数,商品id
2、根据商品id查询商品信息(tb_item)得到一个TbItem对象,缺少images属性,可以创建一个pojo继承 ,添加一个getImages方法,放在taotao-item-web工程中。
3、还需要商品的描述信息 通过商品描述的Mapper查询出来,再通过调用service将数据传递页面。
4、返回页面
package com.taotao.item.pojo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import com.taotao.pojo.TbItem;
public class Item extends TbItem {
public Item(TbItem item){
BeanUtils.copyProperties(item, this);//将原来数据有的属性的值拷贝到item有的属性中
}
public String[] getImages(){
if(StringUtils.isNotBlank(super.getImage())){
return super.getImage().split(",");
}
return null;
}
}
2.3. Dao层
查询tb_item, tb_item_desc两个表,都是单表查询。可以使用逆向工程。
2.4. Service层
分析
在taotao-manager-interface和taotao-manager-service工程中添加接口的方法和实现。
1、根据商品id查询商品信息
参数:商品id
返回值:TbItem
2、根据商品id查询商品描述
参数:商品id
返回值:TbItemDesc
接口定义
2.4.3. 接口实现
2.5. 表现层
分析
表现层调用服务层的方法,表现应当是商品详情 工程(taotao-item-web)
引用服务
在taotao-item-web工程中的springmvc.xml中引入服务:
Controller
请求的url:/item/{itemId}
参数:商品id
返回值:String 逻辑视图
package com.taotao.item.controller;
import com.taotao.item.pojo.Item;
import com.taotao.pojo.TbItem;
import com.taotao.pojo.TbItemDesc;
import com.taotao.service.ItemService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @Description : ItemController
* @ClassName : ItemController
* @Author : LH
* @Date: 2020-09-20 11:52
* @Version: 1.0
*/
@Controller
public class ItemController {
@Autowired
private ItemService service;
@RequestMapping("/item/{itemId}")
public String getItem(@PathVariable Long itemId, Model model){
//1.引入服务
//2.注入服务
//3.调用服务的方法
//商品的基本信息 tbitem 没有getImages
//商品的描述信息
TbItem tbItem = service.getItemById(itemId);
TbItemDesc tbItemDesc = service.getItemDescById(itemId);
//4.tbitem 转成item
Item item = new Item(tbItem);
//传递数据到页面中
model.addAttribute("item",item);
model.addAttribute("itemDesc",tbItemDesc);
return "item";
}
}
2.6.实现效果
以上是通过数据库查询得到商品的数据,展示,但是一般商品的详情页面的访问的并发量是比较高的,所以为了减轻数据库的压力,需要做优化。
优化方案就是:添加缓存。
2.7. 向业务逻辑中添加缓存
缓存添加分析
使用redis做缓存。
业务逻辑:
1、根据商品id到缓存中查询。
2、查到缓存,直接返回。
3、查不到,查询数据库。
4、把数据放到缓存中。
5、返回数据。
缓存中缓存热点数据,提高缓存的使用率。需要设置缓存的有效期expire。一般是一天的时间,可以根据实际情况调整。
需要使用String类型来保存商品数据。
可以加前缀方法对redis中的key进行归类。
例如:key:
ITEM_INFO:123456:BASE
ITEM_INFO:123456:DESC
作用:方便进行管理。
如果把二维表保存到redis中:
1、表名就是第一层
2、主键是第二层
3、字段名第三层
三层使用“:”分隔作为key,value就是字段中的内容。
2.6.2. 添加Redis客户端到工程
在taotao-manager-service工程中的pom.xml中添加如下:
要添加缓存需要可以使用之前开发过的jedisclient
applicationContext-redis.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 class="redis.clients.jedis.JedisPool">
<constructor-arg name="host" value="192.168.25.128"></constructor-arg>
<constructor-arg name="port" value="6379"></constructor-arg>
</bean>
<bean class="com.taotao.manager.jedis.JedisClientPool"></bean>
<!-- 配置集群版 -->
<!-- <bean class="redis.clients.jedis.JedisCluster">
<constructor-arg name="nodes">
<set>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.25.128"></constructor-arg>
<constructor-arg name="port" value="7001"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.25.128"></constructor-arg>
<constructor-arg name="port" value="7002"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.25.128"></constructor-arg>
<constructor-arg name="port" value="7003"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.25.128"></constructor-arg>
<constructor-arg name="port" value="7004"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.25.128"></constructor-arg>
<constructor-arg name="port" value="7005"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.25.128"></constructor-arg>
<constructor-arg name="port" value="7006"></constructor-arg>
</bean>
</set>
</constructor-arg>
</bean>
<bean class="com.taotao.manager.jedis.JedisClientCluster"></bean> -->
</beans>
添加缓存
在taotao-manager-service工程中添加如下缓存
实现类的需要的属性:
实现类的方法如下:
@Override
public TbItem getItemById(Long itemId) {
try {
//1.添加缓存
//2.从缓存中获取数据,如果有直接返回
String jsonStr = client.get(ITEM_INFO_KEY + ":" + itemId + ":BASE");
if (StringUtils.isNotBlank(jsonStr)){
//重新设置商品有效期
client.expire(ITEM_INFO_KEY+":"+itemId+":BASE",ITEM_INFO_KEY_EXPIRE);
return JsonUtils.jsonToPojo(jsonStr,TbItem.class);
}
} catch (Exception e) {
e.printStackTrace();
}
//如果没有数据
//注入Mapper
//调用方法
TbItem tbItem = mapper.selectByPrimaryKey(itemId);
try {
//3.添加缓存到redis数据库中
//注入jedisClient
client.set(ITEM_INFO_KEY+":"+itemId+":BASE", JsonUtils.objectToJson(tbItem));
//设置缓存的有效期
client.expire(ITEM_INFO_KEY+":"+itemId+":BASE",ITEM_INFO_KEY_EXPIRE);
} catch (Exception e) {
e.printStackTrace();
}
//返回tbitem
return tbItem;
}
@Override
public TbItemDesc getItemDescById(Long itemId) {
try {
//1.添加缓存
//2.从缓存中获取数据,如果有直接返回
String jsonStr = client.get(ITEM_INFO_KEY + ":" + itemId + ":DESC");
if (StringUtils.isNotBlank(jsonStr)){
//重新设置商品有效期
System.out.println("商品详情有缓存!!");
client.expire(ITEM_INFO_KEY+":"+itemId+":DESC",ITEM_INFO_KEY_EXPIRE);
return JsonUtils.jsonToPojo(jsonStr,TbItemDesc.class);
}
} catch (Exception e) {
e.printStackTrace();
}
//如果走到这,说明没有查到数据
TbItemDesc itemDesc = descmapper.selectByPrimaryKey(itemId);
try {
//3.添加缓存到redis数据库中
//注入jedisClient
client.set(ITEM_INFO_KEY+":"+itemId+":DESC", JsonUtils.objectToJson(itemDesc));
//设置缓存的有效期
System.out.println("商品详情还没有缓存!!");
client.expire(ITEM_INFO_KEY+":"+itemId+":DESC",ITEM_INFO_KEY_EXPIRE);
} catch (Exception e) {
e.printStackTrace();
}
return itemDesc;
}
添加属性文件 并加载
第一步:添加属性文件
第二步:在applicationContext-dao.xml中加载属性文件:使用:
<context:property-placeholder location=“classpath:properties/*.properties” />
如图:
用客户端查看
3. 网页静态化
什么是静态化?
通过一些技术手段(Freemarker/valocity)将动态的页面(jsp,asp.net,php) 转换成静态的页面,通过浏览器直接访问静态页面。
为什么要静态化?
通过浏览器直接访问静态的页面,不需要经过程序处理,它的访问速度高。
稳定性好。
更有效的防止安全漏洞问题,比如不易遭受黑客攻击。
静态的页面更容易被搜索引擎收录。
怎么样实现?
可以使用freemarker实现网页静态化。
3.1. 什么是freemarker
FreeMarker是一个用Java语言编写的模板引擎,它基于模板输出文本。FreeMarker与Web容器无关,即在Web运行时,它并不知道Servlet或HTTP。它不仅可以用作表现层的实现技术,而且还可以用于生成XML,JSP或Java 等。
目前企业中:主要用Freemarker做静态页面生成。
3.2. Freemarker的使用方法
学习它,自己创建一个工程进行学习
可以导入:
创建maven工程
把freemarker的jar包添加到工程中。
Maven工程添加依赖
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.23</version>
</dependency>
原理:
模板+数据=静态页面
简单的使用
需要创建模板文件和编写测试类:
使用步骤:
第一步:创建一个Configuration对象,直接new一个对象。构造方法的参数就是freemarker对于的版本号。
第二步:设置模板文件所在的路径。
第三步:设置模板文件使用的字符集。一般就是utf-8.
第四步:加载一个模板,创建一个模板对象。
第五步:创建一个模板使用的数据集,可以是pojo也可以是map。一般是Map。
第六步:创建一个Writer对象,一般创建一FileWriter对象,指定生成的文件名。
第七步:调用模板对象的process方法输出文件。
第八步:关闭流。
//使用模板技术实现静态网页的输出
@Test
public void GenHtml() throws Exception{
//1.创建个configuration对象
Configuration configuration = new Configuration(Configuration.getVersion());
//2.设置模板文件所在的路径的目录
configuration.setDirectoryForTemplateLoading(new File(diretorypath));
//3.设置模板文件的字符集
configuration.setDefaultEncoding("utf-8");
//4.首先创建模板文件,再加载模板文件 模板文件的后缀官方提供是.ftl 其实任何类型都行。
Template template = configuration.getTemplate("template.htm");//相对路径
//5.创建模板文件需要展示数据的数据集对象,可以使用POJO,也可以使用map 一般是使用map
Map model = new HashMap<>();
model.put("hello", "hello");
//6.创建一个FileWriter对象 指定生成的静态文件的文件路径及文件名
//拼接一个前缀和后缀
FileWriter writer = new FileWriter(new File(prehtmlfilepath+"/result.html"));
//7.调用模板对象的process方法,执行输出文件。
template.process(model, writer);
//8.关闭流
writer.close();
}
3.3. eclipse中可以使用freemarker的插件
如图:拷贝如图所示的plugins文件到eclipse所在目录的文件,覆盖掉,之后重启eclipse, 再打开就会出现高亮及颜色相关的提示。
3.4. 模板的语法
访问map中的key
${key} 参考入门的简单示例。
访问pojo中的属性
创建Person
编辑输出的代码:
编辑模板:
效果:
如果模型数据中设置的值是1000以上,会出现千分位,
可以使用?c 去除。如图:
效果:
取集合中的数据
编辑模型数据逻辑:
修改模板:
其中:list as item中的
list 为模型设置中的key
item:为集合中的元素的名称 (可以任意)
效果:
取循环中的下标
模板文件:
效果:下标从0开始,当然也可以支持运算,比如 ${item_index+1} 则输出为1,2,3
3.4.5. 取Map集合中的数据
代码:
模板:
效果:
第二种:
效果:
判断
模板:
<#if >
dosomething
<#else>
dosomething
</#if>
效果:
3.4.7. 日期类型格式化
3.4.8. Null值的处理
代码逻辑:
模板:
这是没有问题的,如果代码中注释掉呢?
就会报错,所以需要针对空值做处理:左边模板文件,右边效果图。
3.4.9. Include标签
<#include “模板名称”>
先创建一个模板文件:hello.htm
在template.htm中使用<#include “hello.htm” />
效果:
3.5. Freemarker整合spring
为了测试方便,
在taotao-item-web工程中的进行测试,
首先pom.xml引入Freemarker的依赖
3.5.1. 创建整合spring的配置文件
可以在springmvc.xml中配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="freemarkerConfig"
class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPath" value="/WEB-INF/ftl/" />
<property name="defaultEncoding" value="UTF-8" />
</bean>
</beans>
需要编写一Controller进行测试
Controller
请求的url:/genhtml
参数:无
返回值:ok (String, 需要使用@ResponseBody)
业务逻辑:
1、从spring容器中获得FreeMarkerConfigurer对象。
2、从FreeMarkerConfigurer对象中获得Configuration对象。
3、使用Configuration对象获得Template对象。
4、创建数据集
5、创建输出文件的Writer对象。
6、调用模板对象的process方法,生成文件。
7、关闭流。
@Controller
public class HtmlGenController {
@Autowired
private FreeMarkerConfigurer freeMarkerConfigurer;
@RequestMapping("/genhtml")
@ResponseBody
public String genHtml()throws Exception {
// 1、从spring容器中获得FreeMarkerConfigurer对象。
// 2、从FreeMarkerConfigurer对象中获得Configuration对象。
Configuration configuration = freeMarkerConfigurer.getConfiguration();
// 3、使用Configuration对象获得Template对象。
Template template = configuration.getTemplate("hello.ftl");
// 4、创建数据集
Map dataModel = new HashMap<>();
dataModel.put("hello", "1000");
// 5、创建输出文件的Writer对象。
Writer out = new FileWriter(new File("D:/temp/term197/out/spring-freemarker.html"));
// 6、调用模板对象的process方法,生成文件。
template.process(dataModel, out);
// 7、关闭流。
out.close();
return "OK";
}
}
3.6. 商品详情页面静态化(*)
3.6.1. 网页的静态化方案
输出文件的名称:商品id+“.html”
输出文件的路径:工程外部的任意目录。
网页访问:使用nginx访问网页。在此方案下tomcat只有一个作用就是生成静态页面。
工程部署:可以把taotao-item-web部署到多个服务器上。
生成静态页面的时机:商品添加后,生成静态页面。可以使用Activemq,订阅topic(商品添加)
多台服务器订阅一个主题(topic) 多台服务器生成的html都是一样。
3.7. 商品详情静态化方案实现
分析
使用activemq 需要导入acitvemq的依赖包:
在taotao-item-web工程的pom.xml文件中加入:
<!-- activemq -->
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
<version>${activemq.version}</version>
</dependency>
接收消息:
编写listener (实现messagelistener接口)
配置消息相关的配置文件(包括目的地,默认的消息监听容器)
获取消息中的商品ID 查询出数据集商品的基本信息和描述信息
生成静态页面需要(模板 和 数据 )
生成静态网页的逻辑:
做的事情:准备模板文件,准备数据集,数据集由消息获取商品ID查询数据库获取。
1、配置freemarker 的配置文件(模板的目录,默认字符集)
2、获取configuration
3、设置数据集
4、加载模板
5、设置输出目录文件(FileWriter)
6、生成文件,关闭流(输出文件的名称:商品id+“.html”)
7、部署http服务器(推荐使用nginx)
监听器的编写
package com.taotao.listener;
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;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
import java.io.File;
import java.io.FileWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;
/*
* 监听器
* 获取消息
* 执行生成静态页面的业务逻辑
*/
public class ItemChangeGenHtmMessageListener implements MessageListener {
@Autowired
private ItemService itemservcie;
@Autowired
private FreeMarkerConfigurer config;
@Override
public void onMessage(Message message) {
if(message instanceof TextMessage){
//1.获取消息 商品的id
TextMessage message2 = (TextMessage)message;
try {
Long itemId = Long.valueOf(message2.getText());
//2.从数据库中获取数据 可以调用manager中的服务 获取到了数据集
//引入服务
//注入服务
//调用
TbItem tbItem = itemservcie.getItemById(itemId);
Item item = new Item(tbItem);//转成在页面中显示数据时的POJO
TbItemDesc tbItemDesc = itemservcie.getItemDescById(itemId);
//3.生成静态页面 准备好模板 和 数据集
genHtmlFreemarker(item,tbItemDesc);
} catch (Exception e) {
e.printStackTrace();
}
}
}
//生成静态页面
private void genHtmlFreemarker(Item item, TbItemDesc tbItemDesc) throws Exception {
//1.获取configuration对象
Configuration configuration = config.getConfiguration();
//2.创建模板 获取模板文件对象
Template template = configuration.getTemplate("item.ftl");
//3.创建数据集
Map model = new HashMap<>();
model.put("item", item);
model.put("itemDesc", tbItemDesc);
//4.输出
//E:\freemarker\item\1234.html
Writer writer = new FileWriter(new File("E:\\freemarker\\item"+"\\"+item.getId()+".html"));
template.process(model, writer);
//5.关闭流
writer.close();
}
}
注意:目录在真实开发的时候应当是放在属性文件中配置,并且在linux系统中是没有G盘的概念,这里测试就不再编写了。
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.25.128: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>
<!-- messagelistener的初始化 -->
<bean id="itemChangeGenHtmMessageListener" class="com.taotao.listener.ItemChangeGenHtmMessageListener"></bean>
<!-- 设置默认的监听容器 -->
<bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory"></property>
<property name="destination" ref="topicDestination"></property>
<property name="messageListener" ref="itemChangeGenHtmMessageListener"></property>
</bean>
</beans>
在springmvc的配置文件中配置freemarker的配置项:
<bean id="freemarkerConfig"
class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<!-- 配置模板文件所在的目录 -->
<property name="templateLoaderPath" value="/WEB-INF/ftl/" />
<!-- 设置默认的编码 -->
<property name="defaultEncoding" value="UTF-8" />
</bean>
修改web.xml
加载activmq的配置文件
测试:在后台管理系统中,添加商品,测试已经能够生成静态页面。
我的生成目录,首先需要创建E:\freemarker\item,运行然后就会出现.html文件
新增商品,之后访问…
3.8. 商品详情的页面的访问改造
模板的创建
原来使用的是JSP展示页面,我们可以参考原来的JSP页面样式展示,将JSP中的JSTL标签,@page等语法,换成freemarker的标签及语法规则。并命名文件名为.ftl,如下图:
注意:在footer.ftl中:需要处理空值的问题:
nginx服务器的安装及配置
使用nginx作为Http服务器,暂使用windows版本的
解压到磁盘E:(注意:不要将nginx解压到带有中文目录的目录中,否则启动不起来)
/conf目录下的nginx.conf配置如下:
添加JS及样式资源
启动nginx
第一种:双击nginx.exe ;
第二种:使用命令:
cd到nginx所在的目录:
启动命令:start nginx.exe
关闭命令: nginx.exe -s stop
刷新配置文件:nginx. exe -s reload
访问:http://localhost/item/160065770400702.html
测试成功
注意:为了后续的学习,这里只是演示如何生成静态页面,因为需要先生成静态页面才能访问,生成比较麻烦,所以后面的学习依旧使用动态页面展示商品详情。