需求产生原因

  • 要求在同一个接口中,根据不同的参数,返回不同的视图结果
  • 所有的视图中的数据基本一致
  • 要求页面能静态化,优化SEO

例如:A接口返回客户的信息

  1. 客户A在调用接口时,返回其个性化定制的页面A
  2. 客户B在调用这个接口时,返回其个性化主页B

实现方式 freemaker 的 TemplateLoader

freemaker的配置类freemarker.template.Configuration中提供了一个配置模版加载器的方法setTemplateLoader,需求是要求同时能加载本地和远程的模版,但是只提供了一个模版加载器的set方法,查询文档后官方给出了建议

//远程模版加载 RemoteTemplateLoader remoteTemplateLoader = new RemoteTemplateLoader(remotePath); //本地模版加载 ClassTemplateLoader classTemplateLoader = new ClassTemplateLoader(getClass(), "/WEB-INF/pages/"); MultiTemplateLoader templateLoader = new MultiTemplateLoader(new TemplateLoader[] {classTemplateLoader,remoteTemplateLoader});

  • SpringBoot配置
import freemarker.cache.ClassTemplateLoader;
import freemarker.cache.MultiTemplateLoader;
import freemarker.cache.TemplateLoader;
import freemarker.template.TemplateDirectiveModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer; import javax.annotation.PostConstruct;
import java.util.Map;
import java.util.Set; /**
* Freemarker配置
* @author wpy
* @create 2017/11/8 14:51
* @project_name jcstore
*/
@Configuration
public class FreemarkerConfig { @Autowired
private FreeMarkerConfigurer freeMarkerConfigurer; @Autowired
private WebApplicationContext applicationContext; // @Value("")
private String remotePath = "http://localhost:8080/static"; @PostConstruct
public void freeMarkerConfigurer() {
freemarker.template.Configuration configuration = freeMarkerConfigurer.getConfiguration(); //注册所有自定义标签
Map<String, TemplateDirectiveModel> tagsMap = applicationContext.getBeansOfType(TemplateDirectiveModel.class);
Set<Map.Entry<String, TemplateDirectiveModel>> entries = tagsMap.entrySet();
entries.forEach(entry ->
configuration.setSharedVariable(entry.getKey(), entry.getValue())
); //远程模版加载
RemoteTemplateLoader remoteTemplateLoader = new RemoteTemplateLoader(remotePath);
//本地模版加载
ClassTemplateLoader classTemplateLoader = new ClassTemplateLoader(getClass(), "/WEB-INF/pages/");
MultiTemplateLoader templateLoader = new MultiTemplateLoader(new TemplateLoader[] {classTemplateLoader,remoteTemplateLoader}); configuration.setTemplateLoader(templateLoader);
} }
  • RemoteTemplateLoader 实现
import freemarker.cache.URLTemplateLoader;

import java.net.URL;
import java.net.URLConnection; /**
* 自定义远程模板加载器,用来加载文件服务
*
* @author Administrator
*/
public class RemoteTemplateLoader extends URLTemplateLoader {
// 远程模板文件的存储路径(目录)
private String remotePath; public RemoteTemplateLoader(String remotePath) {
if (remotePath == null) {
throw new IllegalArgumentException("remotePath is null");
}
this.remotePath = canonicalizePrefix(remotePath);
if (this.remotePath.indexOf('/') == 0) {
this.remotePath = this.remotePath.substring(this.remotePath
.indexOf('/') + 1);
}
} @Override
protected URL getURL(String name) {
String fullPath = this.remotePath + name;
if ((this.remotePath.equals("/")) && (!isSchemeless(fullPath))) {
return null;
}
if (name.contains("WEB-INF/template/")) {
fullPath = fullPath.replace("WEB-INF/template/", "");
}
URL url = null;
try {
url = new URL(fullPath);
URLConnection con = url.openConnection();
long lastModified = con.getLastModified();
if (lastModified == 0) {
url = null;
}
} catch (Exception e) {
e.printStackTrace();
url = null;
}
return url;
} private static boolean isSchemeless(String fullPath) {
int i = 0;
int ln = fullPath.length(); if ((i < ln) && (fullPath.charAt(i) == '/'))
i++; while (i < ln) {
char c = fullPath.charAt(i);
if (c == '/')
return true;
if (c == ':')
return false;
i++;
}
return true;
}
}
  • 自定义标签实现
/**
* 自定义标签示例
*
* <table style="width: 633px; height: 217px;" border="0">
<tbody>
<tr>
<td style="text-align: center;"><span style="font-size: 13px;"><strong>类型</strong></span></td>
<td style="text-align: center;"><span style="font-size: 13px;"><strong>FreeMarker接口</strong></span></td>
<td style="text-align: center;"><span style="font-size: 13px;"><strong>FreeMarker实现</strong></span></td>
</tr>
<tr>
<td style="text-align: center;"><span style="font-size: 13px;">字符串</span></td>
<td style="text-align: left;"><span style="font-size: 13px;">TemplateScalarModel</span></td>
<td style="text-align: left;"><span style="font-size: 13px;">SimpleScalar</span></td>
</tr>
<tr>
<td style="text-align: center;"><span style="font-size: 13px;">数值</span></td>
<td style="text-align: left;"><span style="font-size: 13px;">TemplateNumberModel</span></td>
<td style="text-align: left;"><span style="font-size: 13px;">SimpleNumber</span></td>
</tr>
<tr>
<td style="text-align: center;"><span style="font-size: 13px;">日期</span></td>
<td style="text-align: left;"><span style="font-size: 13px;">TemplateDateModel</span></td>
<td style="text-align: left;"><span style="font-size: 13px;">SimpleDate</span></td>
</tr>
<tr>
<td style="text-align: center;"><span style="font-size: 13px;">布尔</span></td>
<td style="text-align: left;"><span style="font-size: 13px;">TemplateBooleanModel</span></td>
<td style="text-align: left;"><span style="font-size: 13px;">TemplateBooleanModel.TRUE</span></td>
</tr>
<tr>
<td style="text-align: center;"><span style="font-size: 13px;">哈希</span></td>
<td style="text-align: left;"><span style="font-size: 13px;">TemplateHashModel</span></td>
<td style="text-align: left;"><span style="font-size: 13px;">SimpleHash</span></td>
</tr>
<tr>
<td style="text-align: center;"><span style="font-size: 13px;">序列</span></td>
<td style="text-align: left;"><span style="font-size: 13px;">TemplateSequenceModel</span></td>
<td style="text-align: left;"><span style="font-size: 13px;">SimpleSequence</span></td>
</tr>
<tr>
<td style="text-align: center;"><span style="font-size: 13px;">集合</span></td>
<td style="text-align: left;"><span style="font-size: 13px;">TemplateCollectionModel</span></td>
<td style="text-align: left;"><span style="font-size: 13px;">SimpleCollection</span></td>
</tr>
<tr>
<td style="text-align: center;"><span style="font-size: 13px;">节点</span></td>
<td><span style="font-size: 13px;">TemplateNodeModel</span></td>
<td><span style="font-size: 13px;">NodeModel</span></td>
</tr>
</tbody>
</table>
* @author wpy
* @create 2017/11/8 14:34
* @project_name jcstore
*/
@Component
public class ExampleTag implements TemplateDirectiveModel { /**
* 标签中的参数 name
*/
private static final String NAME = "name";
/**
*
*/
private static final String AGE = "age";
/**
*
*/
private static final String SEX = "sex"; private DefaultObjectWrapper objectWrapper;
{
Version version = new Version("2.3.21");
DefaultObjectWrapperBuilder defaultObjectWrapperBuilder = new DefaultObjectWrapperBuilder(version);
objectWrapper = defaultObjectWrapperBuilder.build();
} @Override
public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body) throws TemplateException, IOException { TemplateScalarModel name = (TemplateScalarModel) params.get("name");
TemplateNumberModel age = (TemplateNumberModel) params.get("age");
TemplateScalarModel sex = (TemplateScalarModel) params.get("sex");
JSONObject jsonObject = new JSONObject();
jsonObject.put("name",name.getAsString() + 1);
jsonObject.put("age",age.getAsNumber().intValue() + 1);
jsonObject.put("sex",sex.getAsString().equals("男") ? "女":"男"); TemplateModel wrap = objectWrapper.wrap(jsonObject);
if(loopVars.length > 0){
loopVars[0] = wrap;
}
body.render(env.getOut());
}
}
  • 模版 exampleTag.ftl
<html>
<head></head>
<body>
<h1> 自定义标签测试(我是远程模版)</h1>
<p>
<@exampleTag name = "张三" age = 18 sex = "男"; loopv>
<h1>${loopv.name}</h1>
<h1>${loopv.age}</h1>
<h1>${loopv.sex}</h1>
</@exampleTag>
</p>
</body> </html>
  • CustomTagController
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping; /**
* @author wpy
* @create 2017/11/8 15:02
* @project_name jcstore
*/
@Controller
public class CustomTagController { @RequestMapping("/testTags")
public String testTags(){
return "/common/exampleTag";
} @RequestMapping("/testTagsRemote")
public String testTagsRemote(){
return "/exampleTag";
}
}

我的个人主页

SpringBoot下配置FreeMarker配置远程模版的更多相关文章

  1. springboot下https证书配置

    没有证书的小伙伴首先申请一个阿里云免费证书,按照我的步骤来操作 1.购买页面是这样的 按照顺序选择 神奇的一幕出现了 然后就去购买成功,我们会看到证书没有签发,我们需要去申请 填写需要绑定的域名 一般 ...

  2. SpringBoot下Schdule的配置与使用

    我们在平常项目开发中,经常会用到周期性定时任务,这个时候使用定时任务就能很方便的实现.在SpringBoot中用得最多的就是Schedule. 一.SpringBoot集成Schedule 1.依赖配 ...

  3. spring-boot下mybatis的配置

    问题描述:spring boot项目想添加mybatis的配置,在src/main/resources目录下新建了mybatis-config.xml文件,在application.propertie ...

  4. SpringBoot下,@WebFilter配置获取日志

    CREATE TABLE [dbo].[SWEBSERVICELOG]( [WLG_ID] [varchar](100) NOT NULL, [WLG_SESSIONID] [varchar](100 ...

  5. SpringBoot下如何配置实现跨域请求?

    一.什么是跨域请求? 跨域请求,就是说浏览器在执行脚本文件的ajax请求时,脚本文件所在的服务地址和请求的服务地址不一样.说白了就是ip.网络协议.端口都一样的时候,就是同一个域,否则就是跨域.这是由 ...

  6. SpringBoot(十三)-- 不同环境下读取不同配置

    一.场景: 在开发过程中 会使用 开发的一套数据库,测试的时候 又会使用测试的数据库,生产环境中 又会切换到生产环境中.常用的方式是 注释掉一些配置,然后释放一下配置.SpringBoot提供了在不同 ...

  7. Yii2项目高级模版 三个模块在同一个目录下的重定向配置

    最近做项目用到的,非常好用. 修改 advanced/backend/config/main.PHP 文件如下: return [ 'homeUrl' => '/admin', 'compone ...

  8. springboot集成freemarker 配置application.properties详解

    #配置freemarker详解 #spring.freemarker.allow-request-override=false # Set whether HttpServletRequest att ...

  9. spring boot 配置 freemarker

    1.springboot 中自带的页面渲染工具为thymeleaf 还有freemarker 这两种模板引擎 简单比较下两者不同, 1.1freemaker 优点 freemarker 不足:thym ...

随机推荐

  1. IDEA——IDEA使用Tomcat服务器出现乱码问题

    最近刚使用IDEA,在开发一个功能的时候,开始使用Jetty作为容器进行web项目开发,测试通过.然后想了一下线上服务器使用的容器是Tomcat,还是用Tomcat跑一下项目在测试一下,本地和服务器使 ...

  2. 通过express搭建自己的服务器

    前言 为了模拟项目上线,我们就需要一个服务器去提供API给我们调用数据.这次我采用express框架去写API接口.所有请求都是通过ajax请求去请求服务器来返回数据.第一次用node写后端,基本就是 ...

  3. 不要62 hdu2089

    不要62 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  4. easyUI表单基础知识

    easyUI创建异步提交表单 我们创建一个带有 name.email 和 phone 字段的表单.通过使用 easyui 表单(form)插件来改变表单(form)为 ajax 表单(form).表单 ...

  5. php使用PHPMailer邮件类发送邮件

    PHPMailer是一个用于发送电子邮件的PHP函数包.它提供的功能包括:*.在发送邮时指定多个收件人,抄送地址,暗送地址和回复地址*.支持多种邮件编码包括:8bit,base64,binary和qu ...

  6. ZOJ1171

    错误代码先放这 #include<cstdio> #include<cstdlib> #include<iostream> #include<cstring& ...

  7. canvas图表详解系列(1):柱状图

    本章建议学习时间4小时 学习方式:详细阅读,并手动实现相关代码(如果没有canvas基础,需要先学习前面的canvas基础笔记) 学习目标:此教程将教会大家如何使用canvas绘制各种图表,详细分解步 ...

  8. JSONP、图片Ping、XMLHttpRequest2.0等跨域资源请求(CORS)

    跨域:当协议.主域名.子域名.端口号中任意一个不相同时都不算同一个域,而在不同域之间请求数据即为跨域请求.解决方法有以下几种(如有错误欢迎指出)以请求图片url为例: 1.通过XMLHttpReque ...

  9. java之基础数据类型学习————(一)

    JAVA数据类型: 总结来说,java的基本数据类型分为 四类八种 • 第一类:整数类型:byte.short.int.long • 第二类:浮点型:float.double • 第三类:字符类型:c ...

  10. Hadoop2.7.3集群搭建

    hadoop2.0已经发布了稳定版本了,增加了很多特性,比如HDFS HA.YARN等.最新的hadoop-2.4.1又增加了YARN HA   注意:apache提供的hadoop-2.4.1的安装 ...