前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >freemarker

freemarker

作者头像
周杰伦本人
发布2023-10-12 14:16:57
2240
发布2023-10-12 14:16:57
举报
文章被收录于专栏:同步文章同步文章

freemarker

为什么用freemarker

商品详情信息频繁访问 jsp页面被频繁解析 加载起来太慢, 因此我们要把网页静态化。

什么是freemarker

FreeMarker是一个用Java语言编写的模板引擎,它基于模板来生成文本输出。FreeMarker与Web容器无关,即在Web运行时,它并不知道Servlet或HTTP。它不仅可以用作表现层的实现技术,而且还可以用于生成XML,JSP或Java 等。

目前企业中:主要用Freemarker做静态页面或是页面展示

Freemarker的语法和使用方法

把freemarker的jar包添加到工程中。

Maven工程添加依赖

代码语言:javascript
复制
<dependency>
  <groupId>org.freemarker</groupId>
  <artifactId>freemarker</artifactId>
  <version>2.3.23</version>
</dependency>

原理就是用java文件和模板通过freemarker来生成html静态文件。

ftl文件和jsp文件差不多 就是有点语法稍微不同 ftl文件在jsp文件中改造。

student.ftl

代码语言:javascript
复制
<html>
<head>
	<title>student</title>
</head>
<body>
	学生信息:<br>
	学号:${student.id}&nbsp;&nbsp;&nbsp;&nbsp;
	姓名:${student.name}&nbsp;&nbsp;&nbsp;&nbsp;
	年龄:${student.age}&nbsp;&nbsp;&nbsp;&nbsp;
	家庭住址:${student.address}<br>
	学生列表:
	<table border="1">
		<tr>
			<th>学号</th>
			<th>姓名</th>
			<th>年龄</th>
			<th>家庭住址</th>
		</tr>
		<#list students as stu>
		<#if stu_index % 2 ==0>
		<tr bgcolor="red">
		<#else>
		<tr bgcolor="green">
		</#if>
			<td>${stu_index}</td>
			<td>${stu.id}</td>
			<td>${stu.name}</td>
			<td>${stu.age}</td>
			<td>${stu.address}</td>
		</tr>
		</#list>
	</table>
	<!-- 可以使用?date ?time ?datetime ?string(partten)-->
	当前日期:${date?string("yyyy/MM/dd HH:mm:ss")}<br>
	null值的处理: ${val!"val的值为null"}<br>
	判断val的值是否为null:<br>
	<#if val??>
	val中有内容
	<#else>
	val的值为null
	</#if>
	引用模板测试:<br>
	<#include "hello.ftl">
</body>
</html>

hello.ftl

代码语言:javascript
复制
${hello}

java文件

student实体类

代码语言:javascript
复制
package cn.e3mall.freemarker;

public class Student {

	private int id;
	private String name;
	private int age;
	private String address;
	
	
	public Student() {}
	
	public Student(int id, String name, int age, String address) {
		super();
		this.id = id;
		this.name = name;
		this.age = age;
		this.address = address;
	}

	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}
	
	
}

测试类:

代码语言:javascript
复制
package cn.e3mall.freemarker;
import java.io.File;
import java.io.FileWriter;
import java.io.FilterWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.junit.Test;

import freemarker.template.Configuration;
import freemarker.template.Template;

public class FreeMarkerTest {
	
	@Test
	public void testFreeMarker() throws Exception {
		
		//创建Configuration对象
		Configuration configuration = new Configuration(Configuration.getVersion());
		//设置模板文件
		configuration.setDirectoryForTemplateLoading(new File("D:/workspace/e3-item-web/src/main/webapp/WEB-INF/ftl"));
		//模板文件编码格式
		configuration.setDefaultEncoding("utf-8");
		//加载模板文件 创建模板对象
//		Template template = configuration.getTemplate("hello.ftl");
		Template template = configuration.getTemplate("student.ftl");
		//创建数据集
		Map data = new HashMap<>();
		data.put("hello", "hello freemarker!");
		//创建pojo对象
		Student student = new Student(1,"小明",18,"北京");
		data.put("student", student);
		List<Student> students = new ArrayList<>();
		students.add(new Student(1,"小明1",18,"北京"));
		students.add(new Student(2,"小明2",18,"北京"));
		students.add(new Student(3,"小明3",18,"北京"));
		students.add(new Student(4,"小明4",18,"北京"));
		students.add(new Student(5,"小明5",18,"北京"));
		students.add(new Student(6,"小明6",18,"北京"));
		students.add(new Student(7,"小明7",18,"北京"));
		data.put("students", students);
		//添加日期类型
		data.put("date", new Date());
		//null值的处理
		data.put("val", "123");
		//创建Writer对象 指定输出文件的路径和文件名
//		Writer out = new FileWriter(new File("D:/freemarkertest/hello.txt"));
		Writer out = new FileWriter(new File("D:/freemarkertest/student.html"));
		//生成静态页面
		template.process(data, out);
		//关闭流
		out.close();
		
	}
}

生成的html文件:

这里写图片描述
这里写图片描述
freemarker与spring整合:

springmvc.xml文件

代码语言:javascript
复制
<?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:mvc="http://www.springframework.org/schema/mvc"
	xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
	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:conf/resource.properties" />
	<context:component-scan base-package="cn.e3mall.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="e3-item-web"/>
	<dubbo:registry protocol="zookeeper" address="192.168.25.128:2181"/>	
	<dubbo:reference interface="cn.e3mall.service.ItemService" id="itemService" />
	
</beans>

web.xml文件

代码语言:javascript
复制
<?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"
	id="WebApp_ID" version="2.5">
	<display-name>e3-item-web</display-name>
	<welcome-file-list>
		<welcome-file>index.html</welcome-file>
	</welcome-file-list>
	
	<!-- 解决post乱码 -->
	<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>e3-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/*.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>e3-item-web</servlet-name>
		<url-pattern>*.html</url-pattern>
	</servlet-mapping>
</web-app>

测试类:

代码语言:javascript
复制
package cn.e3mall.item.controller;

import java.io.File;
import java.io.FileWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;

import freemarker.template.Configuration;
import freemarker.template.Template;

@Controller
public class HtmlGenController {
	
	@Autowired 
	private FreeMarkerConfigurer freeMarkerConfigurer;
	
	@RequestMapping("genhtml")
	@ResponseBody
	public String genHtml() throws Exception{
		Configuration configuration = freeMarkerConfigurer.getConfiguration();
		//加载模板对象
		Template template = configuration.getTemplate("hello.ftl");
		//创建数据集
		Map data = new HashMap<>();
		data.put("hello", 123456);
		Writer out = new FileWriter(new File("D:/freemarkertest/hello2.html"));
		template.process(data, out);
		out.close();
		return "OK";
	}
}

生产中:

在商品添加后发送消息 这边接收消息 因此我们需要配置ActiveMQ消息队列

我们需要改造商品详情页面的jsp页面,改成ftl文件 然后我们实现消息队列的MessageListener接口就可以生成指定目录下的静态文件 ,然后我们用Nginx访问html文件。

输出文件的名称:商品id+“.html”

输出文件的路径:工程外部的任意目录。

网页访问:使用nginx访问网页。在此方案下tomcat只有一个作用就是生成静态页面。

工程部署:可以把e3-item-web部署到多个服务器上。

生成静态页面的时机:商品添加后,生成静态页面。可以使用Activemq,订阅topic(商品添加)

applicationContext-activemq.xml

代码语言:javascript
复制
<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">
	
	<!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供 -->
	<bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
		<property name="brokerURL" value="tcp://192.168.25.130:61616" />
	</bean>
	<!-- Spring用于管理真正的ConnectionFactory的ConnectionFactory -->
	<bean id="connectionFactory"
		class="org.springframework.jms.connection.SingleConnectionFactory">
		<!-- 目标ConnectionFactory对应真实的可以产生JMS Connection的ConnectionFactory -->
		<property name="targetConnectionFactory" ref="targetConnectionFactory" />
	</bean>
	<!--这个是主题目的地,一对多的 -->
	<bean id="topicDestination" class="org.apache.activemq.command.ActiveMQTopic">
		<constructor-arg value="itemAddTopic" />
	</bean>
	<!-- 监听商品添加消息 同步索引库 -->
	<bean id="htmlGenListener" class="cn.e3mall.item.listener.HtmlGenListener"/>
	<bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">
		<property name="connectionFactory" ref="connectionFactory" />
		<property name="destination" ref="topicDestination" />
		<property name="messageListener" ref="htmlGenListener" />
	</bean>
</beans>

MessageListener接口实现类:

代码语言:javascript
复制
package cn.e3mall.item.listener;

import java.io.FileWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfig;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;

import cn.e3mall.item.pojo.Item;
import cn.e3mall.pojo.TbItem;
import cn.e3mall.pojo.TbItemDesc;
import cn.e3mall.service.ItemService;
import freemarker.template.Configuration;
import freemarker.template.Template;

public class HtmlGenListener implements MessageListener{

	@Autowired
	private ItemService itemService;
	@Autowired
	private FreeMarkerConfigurer freeMarkerConfigurer;
	@Value("${HTML_GEN_PATH}")
	private String HTML_GEN_PATH;
	
	@Override
	public void onMessage(Message message) {
		try {
			//创建模板
			//从消息中取商品id
			TextMessage textMessage = (TextMessage)message;
			String text = textMessage.getText();
			Long itemId = new Long(text);
			//等待事务提交
			Thread.sleep(1000);
			//根据商品id查询商品信息
			TbItem tbItem = itemService.geTbItemById(itemId);
			Item item = new Item(tbItem);
			//取商品描述信息
			TbItemDesc itemDesc = itemService.geTbItemDescById(itemId);
			Map data = new HashMap<>();
			data.put("item", item);
			data.put("itemDesc", itemDesc);
			//加载模板对象
			Configuration configuration = freeMarkerConfigurer.getConfiguration();
			Template template = configuration.getTemplate("item.ftl");
			//创建输出流 指定目录和文件名
			Writer out = new FileWriter(HTML_GEN_PATH+itemId+".html");
			//生成静态页面
			template.process(data, out);
			//关闭流
			out.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}

resource.properties

代码语言:javascript
复制
#静态页面输出目录
HTML_GEN_PATH=D:/freemarkertest/item/
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-10-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • freemarker
    • 为什么用freemarker
      • 什么是freemarker
        • Freemarker的语法和使用方法
          • freemarker与spring整合:
          相关产品与服务
          消息队列 CMQ
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档