网页静态化技术Freemarker在分布式项目中的应用

文章目录

      • Freemarker的概述
      • 工程搭建
      • 需求分析及实现
      • 测试

Freemarker的概述

网页静态化解决方案在实际开发中运用比较多,例如新闻网站,门户网站中的新闻频道或者是文章类的频道。
对于电商网站的商品详细页来说,至少几百万个商品,每个商品又有大量的信息,这样的情况同样也适用于使用网页静态化来解决。网页静态化技术和缓存技术的共同点都是为了减轻数据库的访问压力,但是具体的应用场景不同,缓存比较适合小规模的数据,而网页静态化比较适合大规模且相对变化不太频繁的数据。另外网页静态化还有利于SEO。
另外我们如果将网页以纯静态化的形式展现,就可以使用Nginx这样的高性能的web服务器来部署。Nginx可以承载5万的并发,而Tomcat只有几百。
什么是Freemarker?
FreeMarker 是一个用 Java 语言编写的模板引擎,它基于模板来生成文本输出。FreeMarker与 Web 容器无关,即在 Web 运行时,它并不知道 Servlet 或 HTTP。它不仅可以用作表现层的实现技术,而且还可以用于生成 XML,JSP 或 Java 等。

工程搭建

创建jar工程youlexuan_page_interface
创建war工程youlexuan_page_service,依赖dao(从数据库中查询商品数据填充到静态页面),添加Freemarker的依赖
pom依赖

<properties>
    <webVersion>3.0</webVersion>
</properties>

<dependencies>
    <!-- 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-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-orm</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context-support</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
    </dependency>
    <!-- dubbo -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>dubbo</artifactId>
    </dependency>
    <dependency>
        <groupId>org.apache.zookeeper</groupId>
        <artifactId>zookeeper</artifactId>
    </dependency>
    <dependency>
        <groupId>org.apache.curator</groupId>
        <artifactId>curator-recipes</artifactId>
    </dependency>
    <dependency>
        <groupId>org.freemarker</groupId>
        <artifactId>freemarker</artifactId>
    </dependency>

    <!--导入自己的项目-->
    <dependency>
        <groupId>com.youxin</groupId>
        <artifactId>youlexuan_common</artifactId>
        <version>1.0.0</version>
    </dependency>
    <dependency>
        <groupId>com.youxin</groupId>
        <artifactId>youlexuan_dao</artifactId>
        <version>1.0.0</version>
    </dependency>
    <dependency>
        <groupId>com.youxin</groupId>
        <artifactId>youlexuan_page_interface</artifactId>
        <version>1.0.0</version>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.tomcat.maven</groupId>
            <artifactId>tomcat7-maven-plugin</artifactId>
            <version>2.2</version>
            <configuration>
                <port>9008</port>
                <path>/</path>
                <uriEncoding>utf-8</uriEncoding>
            </configuration>
        </plugin>
    </plugins>
</build>

配置spring-page-dubbo.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:dubbo="http://code.alibabatech.com/schema/dubbo"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
    		http://www.springframework.org/schema/beans/spring-beans.xsd 
    		http://code.alibabatech.com/schema/dubbo 
    		http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
	
	<dubbo:protocol name="dubbo" port="20884"/>
	
	<!-- 提供方应用信息,用于计算依赖关系 -->
	<dubbo:application name="youlexuan_page_service" />

	<!-- 向zk注册服务 -->
	<dubbo:registry address="zookeeper://192.168.2.123:2181" />

	<!-- 扫描带service注解的类 -->
	<dubbo:annotation package="com.youxin.page.service.impl" />

</beans>

配置spring-page-service.xml,添加freemarkerConfig的bean

<?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:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop" 
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
    		http://www.springframework.org/schema/beans/spring-beans.xsd 
    		http://www.springframework.org/schema/context 
    		http://www.springframework.org/schema/context/spring-context.xsd
    		http://www.springframework.org/schema/aop
    		http://www.springframework.org/schema/aop/spring-aop.xsd
    		http://www.springframework.org/schema/tx
    		http://www.springframework.org/schema/tx/spring-tx.xsd">

	<context:component-scan base-package="com.offcn" />

	<bean id="transactionManager"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource" />
	</bean>

	<tx:advice id="crudAdvice" transaction-manager="transactionManager">
		<tx:attributes>
			<tx:method name="get*" read-only="true" />
			<tx:method name="select*" read-only="true" />
			<tx:method name="list*" read-only="true" />
			<tx:method name="query*" read-only="true" />
			<tx:method name="find*" read-only="true" />
			<tx:method name="*" propagation="REQUIRED" />
		</tx:attributes>
	</tx:advice>

	<aop:config>
		<aop:pointcut expression="execution(* com.youxin.page.service..*.*(..))"
			id="pointcut" />
		<aop:advisor advice-ref="crudAdvice" pointcut-ref="pointcut" />
	</aop:config>

	<bean id="freemarkerConfig"	class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
		<property name="templateLoaderPath" value="classpath:/template" />
		<property name="defaultEncoding" value="UTF-8" />
	</bean>
	
</beans>

在freemarkerConfig的bean中配置模板路径
在这里插入图片描述
配置page.properties

pagedir=d:\\item\\

注意
properties文件一定要进行扫描,不然是无法注入的
我们这里是依赖了common工程,而common对properties文件的读取进行了配置(这样就可以把所有有关联项目的properties文件进行读取)

<context:property-placeholder location="classpath*:*.properties" />

如果你的项目没有这样的效果,一定要在上述xml中配置读取properties文件

需求分析及实现

通过Freemarker实现商品详细页的静态化。通过地址栏输入某地址,如下形式
http://localhost:9007/goods/genHtml.do?goodsId=149187842867974
能在本地电脑某目录生成商品详细页,页面的名称为商品id.html

在后端根据goodid连接数据库查询出页面所需要的所有数据,然后把数据包装成map交给freemarkerConfig的bean进行网页静态化

@Service
public class ItemPageServiceImpl implements ItemPageService {

    @Value("${pagedir}")
    private String pagedir;
    @Autowired
    private TbGoodsMapper goodsMapper;
    @Autowired
    private TbGoodsDescMapper goodsDescMapper;
    @Autowired
    private TbItemCatMapper itemCatMapper;
    @Autowired
    private TbItemMapper itemMapper;
    @Autowired
    private FreeMarkerConfig freemarkerConfig;
    @Override
    public boolean genItemHtml(Long goodsId){
        // 创建Writer对象
        FileWriter out =null;
        try {
            // 1. 根据商品id, 查询模板需要的数据
            // tb_goods
            TbGoods goods = goodsMapper.selectByPrimaryKey(goodsId);
            // tb_goods_desc
            TbGoodsDesc goodsDesc = goodsDescMapper.selectByPrimaryKey(goodsId);
            // 三级分类名
            String cat1Name = itemCatMapper.selectByPrimaryKey(goods.getCategory1Id()).getName();
            String cat2Name = itemCatMapper.selectByPrimaryKey(goods.getCategory2Id()).getName();
            String cat3Name = itemCatMapper.selectByPrimaryKey(goods.getCategory3Id()).getName();
            // tb_items
            TbItemExample example = new TbItemExample();
            TbItemExample.Criteria criteria = example.createCriteria();
            criteria.andGoodsIdEqualTo(goodsId);

            // 1表示正常
            criteria.andStatusEqualTo("1");
            // 按照is_default列  进行降序排列
            example.setOrderByClause("is_default desc");
            List<TbItem> itemsList = itemMapper.selectByExample(example);
            // 2. 将数据都组装到map, 以便和freemarker模板结合
            Map<String,Object> map = new HashMap<>();
            map.put("goods", goods);
            map.put("goodsDesc", goodsDesc);
            map.put("cat1Name", cat1Name);
            map.put("cat2Name", cat2Name);
            map.put("cat3Name", cat3Name);
            map.put("itemList", itemsList);
            System.out.println("遍历map");
            for (String s : map.keySet()) {
                System.out.println(s+"\t"+map.get(s));
            }

            // 3. 使用freemarkder的api, 生成页面
            Configuration conf = freemarkerConfig.getConfiguration();
            // 加载模板
            Template template = conf.getTemplate("item.ftl");
            out = new FileWriter(new File(pagedir+goodsId+".html"));
            System.out.println(pagedir+goodsId+".html");
            // 输出
            template.process(map,out);
            System.out.println("输出!");
            return true;
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }finally {
            if (out!=null){//关闭输出流
                try {
                    out.close();
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }

    }
}

测试

我们在manager_web中添加测试url,传递参数goosId

@Reference(timeout = 4000)
	private ItemPageService itemPageService;
/*
测试
 */
@RequestMapping("/test")
public void testHtml(Long goodsId) throws Exception {
	itemPageService.genItemHtml(goodsId);
}

在地址栏输入测试链接http://localhost:9002/goods/test.do?goodsId=149187842867963
网页静态化技术Freemarker在分布式项目中的应用_第1张图片
网页静态化技术Freemarker在分布式项目中的应用_第2张图片

你可能感兴趣的:(分布式电商项目,Freemarker)