SSM分布式项目之淘淘商城-第九天(IDEA)

文章大纲
一 、第九天课程计划
二、商品详情页面展示
三、网页静态化

淘淘商城课程大纲

课程大纲
一共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. 商品详情页面展示

SSM分布式项目之淘淘商城-第九天(IDEA)_第1张图片

从架构中可以看出商品详情页面是一个表现层工程。
创建一个商品详情页面展示的工程。

2.1. 工程搭建

taotao-item-web。打包方式war。可以参考taotao-portal-web
SSM分布式项目之淘淘商城-第九天(IDEA)_第2张图片

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>/*
  
  
  
    taotao-item-web
    org.springframework.web.servlet.DispatcherServlet
    
    
      contextConfigLocation
      classpath:spring/springmvc*.xml
    
    1
  
  
    taotao-item-web
    
    *.html
  

2.2. 功能分析

在搜索结果页面点击商品图片或者商品标题,展示商品详情页面。
如图在商品搜索系统中的搜索结果页面中search.jsp,修改如下:
SSM分布式项目之淘淘商城-第九天(IDEA)_第3张图片

请求的url:/item/{itemId}
参数:商品id
返回值:String 逻辑视图
业务逻辑:

1、从url中取参数,商品id
2、根据商品id查询商品信息(tb_item)得到一个TbItem对象,缺少images属性,可以创建一个pojo继承 ,添加一个getImages方法,放在taotao-item-web工程中。
3、还需要商品的描述信息  通过商品描述的Mapper查询出来,再通过调用service将数据传递页面。
4、返回页面

SSM分布式项目之淘淘商城-第九天(IDEA)_第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

接口定义

SSM分布式项目之淘淘商城-第九天(IDEA)_第5张图片

2.4.3. 接口实现
SSM分布式项目之淘淘商城-第九天(IDEA)_第6张图片

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.实现效果

SSM分布式项目之淘淘商城-第九天(IDEA)_第7张图片

以上是通过数据库查询得到商品的数据,展示,但是一般商品的详情页面的访问的并发量是比较高的,所以为了减轻数据库的压力,需要做优化。

优化方案就是:添加缓存。

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中添加如下:
SSM分布式项目之淘淘商城-第九天(IDEA)_第8张图片

要添加缓存需要可以使用之前开发过的jedisclient
SSM分布式项目之淘淘商城-第九天(IDEA)_第9张图片

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工程中添加如下缓存

实现类的需要的属性:
SSM分布式项目之淘淘商城-第九天(IDEA)_第10张图片

实现类的方法如下:

@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中加载属性文件:使用:

如图:
在这里插入图片描述
用客户端查看
SSM分布式项目之淘淘商城-第九天(IDEA)_第11张图片

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的使用方法

学习它,自己创建一个工程进行学习
SSM分布式项目之淘淘商城-第九天(IDEA)_第12张图片

可以导入:
SSM分布式项目之淘淘商城-第九天(IDEA)_第13张图片

创建maven工程
把freemarker的jar包添加到工程中。
Maven工程添加依赖

<dependency>
  <groupId>org.freemarker</groupId>
  <artifactId>freemarker</artifactId>
  <version>2.3.23</version>
</dependency>

原理:
SSM分布式项目之淘淘商城-第九天(IDEA)_第14张图片

模板+数据=静态页面

简单的使用
需要创建模板文件和编写测试类:

使用步骤:
第一步:创建一个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的插件

SSM分布式项目之淘淘商城-第九天(IDEA)_第15张图片

如图:拷贝如图所示的plugins文件到eclipse所在目录的文件,覆盖掉,之后重启eclipse, 再打开就会出现高亮及颜色相关的提示。

3.4. 模板的语法

访问map中的key
${key} 参考入门的简单示例。

访问pojo中的属性

创建Person
SSM分布式项目之淘淘商城-第九天(IDEA)_第16张图片

编辑输出的代码:
在这里插入图片描述

编辑模板:
SSM分布式项目之淘淘商城-第九天(IDEA)_第17张图片

效果:
SSM分布式项目之淘淘商城-第九天(IDEA)_第18张图片

如果模型数据中设置的值是1000以上,会出现千分位,
SSM分布式项目之淘淘商城-第九天(IDEA)_第19张图片

可以使用?c 去除。如图:
SSM分布式项目之淘淘商城-第九天(IDEA)_第20张图片

效果:
SSM分布式项目之淘淘商城-第九天(IDEA)_第21张图片

取集合中的数据
编辑模型数据逻辑:
SSM分布式项目之淘淘商城-第九天(IDEA)_第22张图片

修改模板:
SSM分布式项目之淘淘商城-第九天(IDEA)_第23张图片

其中:list as item中的
list 为模型设置中的key
item:为集合中的元素的名称 (可以任意)

效果:
SSM分布式项目之淘淘商城-第九天(IDEA)_第24张图片

取循环中的下标
模板文件:
SSM分布式项目之淘淘商城-第九天(IDEA)_第25张图片

效果:下标从0开始,当然也可以支持运算,比如 ${item_index+1} 则输出为1,2,3
SSM分布式项目之淘淘商城-第九天(IDEA)_第26张图片

3.4.5. 取Map集合中的数据
代码:
SSM分布式项目之淘淘商城-第九天(IDEA)_第27张图片

模板:
SSM分布式项目之淘淘商城-第九天(IDEA)_第28张图片

效果:

SSM分布式项目之淘淘商城-第九天(IDEA)_第29张图片

第二种:
SSM分布式项目之淘淘商城-第九天(IDEA)_第30张图片

效果:
SSM分布式项目之淘淘商城-第九天(IDEA)_第31张图片

判断
模板:

<#if >
	dosomething 
<#else>
	dosomething
</#if>

SSM分布式项目之淘淘商城-第九天(IDEA)_第32张图片

效果:
SSM分布式项目之淘淘商城-第九天(IDEA)_第33张图片

3.4.7. 日期类型格式化

SSM分布式项目之淘淘商城-第九天(IDEA)_第34张图片

3.4.8. Null值的处理
代码逻辑:
在这里插入图片描述

模板:
在这里插入图片描述

这是没有问题的,如果代码中注释掉呢?

就会报错,所以需要针对空值做处理:左边模板文件,右边效果图。

SSM分布式项目之淘淘商城-第九天(IDEA)_第35张图片
SSM分布式项目之淘淘商城-第九天(IDEA)_第36张图片

3.4.9. Include标签
<#include “模板名称”>
先创建一个模板文件:hello.htm
在这里插入图片描述

在template.htm中使用<#include “hello.htm” />

效果:
在这里插入图片描述

3.5. Freemarker整合spring

为了测试方便,
在taotao-item-web工程中的进行测试,
首先pom.xml引入Freemarker的依赖

SSM分布式项目之淘淘商城-第九天(IDEA)_第37张图片

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(商品添加)

SSM分布式项目之淘淘商城-第九天(IDEA)_第38张图片

多台服务器订阅一个主题(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>

SSM分布式项目之淘淘商城-第九天(IDEA)_第39张图片

修改web.xml
加载activmq的配置文件
SSM分布式项目之淘淘商城-第九天(IDEA)_第40张图片

测试:在后台管理系统中,添加商品,测试已经能够生成静态页面。

我的生成目录,首先需要创建E:\freemarker\item,运行然后就会出现.html文件
SSM分布式项目之淘淘商城-第九天(IDEA)_第41张图片
新增商品,之后访问…
SSM分布式项目之淘淘商城-第九天(IDEA)_第42张图片

3.8. 商品详情的页面的访问改造

模板的创建
原来使用的是JSP展示页面,我们可以参考原来的JSP页面样式展示,将JSP中的JSTL标签,@page等语法,换成freemarker的标签及语法规则。并命名文件名为.ftl,如下图:
SSM分布式项目之淘淘商城-第九天(IDEA)_第43张图片

注意:在footer.ftl中:需要处理空值的问题:

SSM分布式项目之淘淘商城-第九天(IDEA)_第44张图片

nginx服务器的安装及配置
使用nginx作为Http服务器,暂使用windows版本的

解压到磁盘E:(注意:不要将nginx解压到带有中文目录的目录中,否则启动不起来)

/conf目录下的nginx.conf配置如下:
SSM分布式项目之淘淘商城-第九天(IDEA)_第45张图片

添加JS及样式资源
SSM分布式项目之淘淘商城-第九天(IDEA)_第46张图片

启动nginx
第一种:双击nginx.exe ;
第二种:使用命令:

cd到nginx所在的目录:

启动命令:start nginx.exe 

关闭命令: nginx.exe -s stop

刷新配置文件:nginx. exe -s reload

访问:http://localhost/item/160065770400702.html

测试成功
SSM分布式项目之淘淘商城-第九天(IDEA)_第47张图片

注意:为了后续的学习,这里只是演示如何生成静态页面,因为需要先生成静态页面才能访问,生成比较麻烦,所以后面的学习依旧使用动态页面展示商品详情。

你可能感兴趣的:(淘淘商城项目,spring,freemarker,分布式,java)