springboot中Thymeleaf模板插入Freemarker模板页面

概述

最近在修改springboot架构的项目,项目之前配置的是Thymeleaf模板,
但是在我新加的功能中,我非常想用Freemarker模板来新加一些页面功能。
看到网上很多其他地方描述,要么用不同的文件后缀来区分(如html文件为Thymeleaf,ftl为Freemarker),要么放到不同的文件夹。
我不想这么做,因为会限制我后面的功能修改。
本人单独用一个类来转换Freemarker模板的html文件。

软件环境

eclipse:Version: 2021-06 (4.20.0)
jdk:1.8

项目已有的Thymeleaf

这里和大家习惯使用的一样,项目原来使用的简单描述一下,非常熟悉的就跳过Thymeleaf描述吧,
在application.properties中配置

spring.thymeleaf.enabled=true
spring.thymeleaf.cache=false

在pom.xml中加入依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

登录页面,后台java

@GetMapping("/LogIn")public String LogIn(Model model, HttpServletRequest request, HttpServletResponse response) {KeyPairGenerator keyPairGen = null;KeyPair keyPair = null;String tmp = null;RSAPrivateKey prk = null;RSAPublicKey pubK = null;// System.out.println("AABBCCDDGGFFTTR112 = " +// PciVerify.PciMathCountHexChars("AABBCCDDGGFFTTR112"));request.getSession().setMaxInactiveInterval(GlobalConfig.mSessionSecondTimeout);if (GlobalConfig.mIsDebugMode) {model.addAttribute("DefaultUserName", "pci_test");model.addAttribute("DefaultPassword", "123456");model.addAttribute("DefaultVerifyCode", "123456");} else {model.addAttribute("DefaultUserName", "");model.addAttribute("DefaultPassword", "");model.addAttribute("DefaultVerifyCode", "");}model.addAttribute("UseDebugMode", GlobalConfig.mIsDebugMode);model.addAttribute("UseVerifyCode", GlobalConfig.mIsLoginUseVerifyCode);pubK = null;prk = null;tmp = null;tmp = (String) request.getSession().getAttribute("SessionKeyRsaPri");// System.out.println("SessionKeyRsaPri = " + tmp);if (tmp != null) {prk = Crypto.RsaPrikeyGetFromPkcs8Base64String(tmp);}if (prk != null) {pubK = Crypto.rsaGetPubKeyFromPriKey(prk);}// System.out.println("pubK = " + pubK);if (pubK == null) {try {keyPairGen = KeyPairGenerator.getInstance("RSA");keyPairGen.initialize(new RSAKeyGenParameterSpec(2048, BigInteger.valueOf(65537)));keyPair = keyPairGen.generateKeyPair();pubK = (RSAPublicKey) keyPair.getPublic();} catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException e) {// TODO Auto-generated catch blocke.printStackTrace();}tmp = Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded());tmp = tmp.replace("\r", "");tmp = tmp.replace("\n", "");// System.out.println("setAttribute SessionKeyRsaPri = " + tmp);request.getSession().setAttribute("SessionKeyRsaPri", tmp);}tmp = Base64.getEncoder().encodeToString(pubK.getEncoded());tmp = tmp.replace("\r", "");tmp = tmp.replace("\n", "");model.addAttribute("RsaPub", tmp);response.setHeader("Etag", "\"11223344556677889900/login\"");return "main_login";}

前端xml

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>User Login</title><link rel="stylesheet" type="text/css" href="/static/css/Login.css"/><script type="text/javascript" src="/static/js/main_login.js"></script><script type="text/javascript" src="/static/js/rsacrypto.js" ></script>
</head>
<body onload="onLoadLogIn()"><script type="text/javascript">onSetTranserRsaPub('{{session_rsa_pub}}');</script><span id="idTmpRsaPub" style="display:none;" th:text="${RsaPub}"></span><div id="login" style="top: 35%;"><center><img  id="idImgLogo" style="align:center;max-width:160px;max-height:160px;" onclick="onGetUserNameLogo()"></center><h1 class="title">用户登陆</h1><form action="/login" method="post"><nobr><input id="id_username" type="text" required="required" placeholder="用户" name="username" onkeypress="return runScriptEnter(event)" th:value="${DefaultUserName}" onkeyup="onUserNameInputChange()" onchange="onUserNameInputChange()"></input></nobr><nobr><input id="id_password" type="password" required="required" placeholder="密码" name="password" onkeypress="return runScriptEnter(event)"  th:value="${DefaultPassword}"></input></nobr><nobr style="vertical-align:top;" th:if="${UseVerifyCode}"><input style="width:120px;height:24px" id="idInputVerifyCode" type="text" required="required" placeholder="验证码" name="verifycode" onkeypress="return runScriptEnter(event)"  th:value="${DefaultVerifyCode}"></input><img  id="idImgVerifyCode" onclick="this.src='/main_login/code?'+ Math.random()"></nobr></form><span th:if="${UseVerifyCode}"><button id="idLogin" class="but" onclick="onClickLogIn('', 1)">登陆</button></span><span th:if="${not UseVerifyCode}"><button id="idLogin" class="but" onclick="onClickLogIn('', 0)">登陆</button></span><div id="show_status"><h5></h5></div></div><div class="bottom"><span class="style4">  </span><span an class="style4">  </span><span class="style4"></span> <br/></div>
</body></html>

这里就不详细描述运行效果等,因为牵涉到其他变量,且功能不是本文说的重点。

Freemarker配置依赖

在pom.xml中加入依赖

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

Freemarker处理的java类

这里是最重要最关键的
新建一个类FreemarkerConvert,html文件放在resource/templates目录下

package com.shenweihong.main;import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;
import java.util.Map;import org.springframework.util.ResourceUtils;import com.shenweihong.global.GlobalSysParam;import freemarker.core.ParseException;
import freemarker.template.Configuration;
import freemarker.template.MalformedTemplateNameException;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateExceptionHandler;
import freemarker.template.TemplateNotFoundException;public class FreemarkerConvert {private static Configuration mConfig = null;public static void initConfig(Class cl) {if (mConfig != null) {return;}mConfig = new Configuration(Configuration.getVersion());try {		if (GlobalSysParam.mIsJarRun) {mConfig.setClassForTemplateLoading(cl, "/templates");} else {mConfig.setDirectoryForTemplateLoading(ResourceUtils.getFile("classpath:templates"));}mConfig.setDefaultEncoding("UTF-8");mConfig.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);} catch (IOException e) {e.printStackTrace();}}public static void WriteToStream(String fileName, Map<String, Object> dataMap, OutputStream outStream) {Template template = null;FreemarkerWriter writer = null;try {writer = new FreemarkerWriter(outStream);template = mConfig.getTemplate(fileName);template.process(dataMap, writer);} catch (TemplateNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (MalformedTemplateNameException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (ParseException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (TemplateException e) {// TODO Auto-generated catch blocke.printStackTrace();}}
}class FreemarkerWriter extends Writer {private OutputStream mOutStream = null;FreemarkerWriter(OutputStream outStream) {mOutStream = outStream;}@Overridepublic void write(char[] cbuf, int off, int len) throws IOException {// TODO Auto-generated method stub//System.out.println("write");//System.out.println(new String(cbuf, off, len));String str = new String(cbuf, off, len);mOutStream.write(str.getBytes("UTF8"));}@Overridepublic void flush() throws IOException {// TODO Auto-generated method stub//System.out.println("Writer flush");mOutStream.flush();}@Overridepublic void close() throws IOException {// TODO Auto-generated method stub//System.out.println("Writer close");//mOutStream.close();}}

initConfig在启动的时候调用一次
依赖的一个外部boolean变量:GlobalSysParam.mIsJarRun
这是表示是否为jar包运行,还是java代码IDE调试运行,在main里面赋值的

if (MainStartApplication.class.getResource("").getProtocol().equals("jar") == false) {GlobalSysParam.mIsJarRun = false;
} else {GlobalSysParam.mIsJarRun = true;
}

main函数调用

@EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class, FreeMarkerAutoConfiguration.class })
@SpringBootApplication
@ServletComponentScan
@ComponentScan("com.shenweihong.controller")
public class MainStartApplication {public static void main(String[] args) {if (MainStartApplication.class.getResource("").getProtocol().equals("jar") == false) {GlobalSysParam.mIsJarRun = false;} else {GlobalSysParam.mIsJarRun = true;}FreemarkerConvert.initConfig(MainStartApplication.class);SpringApplication.run(MainStartApplication.class, args);}
}

注意注解FreeMarkerAutoConfiguration.class ,如果不确定就全部拷贝类MainStartApplication 前面的注解,@ComponentScan(“com.shenweihong.controller”)除外。

Contoller里面调用

	@RequestMapping(value = "/Function/UserManageMent/AddUserShow", method = RequestMethod.GET)public void AddUserShow(HttpServletRequest request, HttpServletResponse response) {Map<String, Object> dataMap = new HashMap<String, Object>();int i = 0;String[] listPriviliges = null;listPriviliges = new String[GlobalConfig.mMapPriviliges.length / 2];for (i = 0; i < listPriviliges.length; i++) {listPriviliges[i] = GlobalConfig.mMapPriviliges[i * 2 + 1];}dataMap.put("list_privilleges", listPriviliges);	dataMap.put("show_privilleges", true); 	response.setContentType("text/html; charset=utf-8");try {FreemarkerConvert.WriteToStream("fun_user_mgt_add.html", dataMap, response.getOutputStream());} catch (IOException e) { // TODO Auto-generated catch blocke.printStackTrace();}}

用到的一个外部变量GlobalConfig.mMapPriviliges:

public static final String[] mMapPriviliges = {"1", "超级管理员","100", "密钥超级管理A","101", "密钥超级管理B","1000", "密钥管理A","1001", "密钥管理B","1002", "银联认证测试验证","1003", "银联认证测试验证管理","1100", "悦泰管理员","1101", "悦泰经销商","1102", "悦泰工厂拆单员","1103", "悦泰安装师傅","1104", "悦泰售后师傅","1105", "悦泰生产工人","1106", "悦泰用户","1200", "远程文件系统管理","1201", "远程文件系统"};

html显示

这是整个页面某一个局部(其他如导航栏,用户信息栏),所以没有标签html、head、body

<h2>添加用户</h2>
<h5>用户名:</h5>
<input id="idInputUserName"></input>
<hr>
<h5>密码:</h5>
<input id="idInputPassword"></input>
<button id="idAddUserGenPassword" onclick="UserManagementAddUserGenPassword()">随机生成</button>
<hr>
<#if show_privilleges>
<p><span class="span_account_label">权限:</span></p>
<p id="idAllUserPrivileges">
<#assign list_cnt=0>  
<table class="clTableManageUserPrivillages" id="idTableManageUserPrivillages">  
<#list list_privilleges as privilleges><#if (list_cnt % 5)==0><tr></#if><td style="vertical-align:middle; text-align:left;cursor:default;"><input type="checkbox" value="${privilleges}" unchecked>${privilleges}</input><span></span></td><#assign list_cnt=list_cnt+1><#if (list_cnt % 5)==0></tr></#if>
</#list>
<#if (list_cnt % 5)!=0>
</tr>
</#if>
</table>
</p>
<hr>
</#if>
<#if show_privilleges>
<button id="idAddUser" onclick="UserManagementAddUser(1)">添加</button>
<#else>
<button id="idAddUser" onclick="UserManagementAddUser(0)">添加</button>
</#if>
<p id="idStShow" style="font-size:16px;color:blue;display:none"></p>

测试界面效果

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/7545.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C# 交错数组学习

C# 交错数组是元素为数组的数组。 一个示例&#xff1b; using System;class Program {static void Main(string[] args) {string[][] weeks new string[3][];weeks[0] new string[] { "星期日", "星期一", "星期二", "星期三", &…

举例说明什么是循环神经网络

循环神经网络&#xff08;Recurrent Neural Network, RNN&#xff09;是一种处理时间序列数据和自然语言等具有顺序信息的数据的神经网络模型。与普通的前馈神经网络&#xff08;Feedforward Neural Network&#xff09;不同&#xff0c;RNN具有循环连接&#xff0c;使得网络能…

区块链技术如何改变Web3认证的现状?

随着加密货币和区块链技术的迅猛发展&#xff0c;Web3钱包成为了数字经济时代中的重要组成部分。Web3钱包是一种工具&#xff0c;用于存储、管理和交互加密货币及其他数字资产&#xff0c;以及与去中心化应用程序&#xff08;DApp&#xff09;进行交互。它们是实现Web3.0理念的…

谈高考志愿填报

目录 不如先说说我自己。 一、选专业还是选学校&#xff1a; 二、你想推荐/避雷的专业&#xff1a; 三、填报志愿的策略&#xff1a; 四、影响专业选择的因素&#xff1a; 各省高考成绩已出&#xff0c;又到一年高考季。张雪峰提到&#xff1a;“普通家庭不要光谈理想&…

LINUX系统(ubuntu)安装以及应用调试(不定时更新)

一&#xff1a;linux的介绍 Linux是一种基于UNIX操作系统的开源&#xff08;Open Source&#xff09;操作系统。它由芬兰计算机科学家 Linus Torvalds 在1991年首次发布&#xff0c;目前已经发展成为最流行和广泛使用的操作系统之一。 Linux以其稳定性、安全性和灵活性而闻名…

探究Vue源码:mustache模板引擎(4) 了解mustache转换概念,简述tokens转换

上文 探究Vue源码:mustache模板引擎(3) 通过编写简单正则了解mustache转换思路我们用正则表达式构建了一个简易版的render模板编译函数 但是 我们有特意强调过 mustache的render函数并非用简单正则实现的 因为这样无法实现循环和一些比较复杂的逻辑处理 它的实现基理可以参考这…

基础的git命令使用

Git区域概念 Git命令行操作 Git单人使用 注意项&#xff08;务必认真阅读&#xff09; Git Bash Here”终端 初始化仓库 提交工作区的内容到版本库 查看版本的记录 查看工作区的状态 版本回退 版本前进 Git远程仓库 克隆项目 推送到远程 拉取远程的更新 Git区域概…

mysql的集群和主从的区别

现在的项目使用mysql数据库&#xff0c;要自己设计数据存储架构。所以研究了一下mysql的集群(cluster)和主从&#xff08;master/slave&#xff09;这两个概念。两者非常容易混淆&#xff0c;所以需要分辨出这2者之间的区别。 一、Mysql cluster: share-nothing,分布式节点架构…

个性化邮件营销怎么做?试试这几种方法

电子邮件营销是最古老的数字营销形式之一&#xff0c;但也是最有效的营销策略之一。企业不仅可以通过电子邮件来推广产品或服务&#xff0c;也可以用来维护与潜在客户或已有顾客的关系&#xff0c;因此电子邮件营销被广泛应用于网络营销领域。在海量的邮件营销推广中&#xff0…

MySQL数据引擎、建库及账号管理

目录 一、引言 二、MySQL数据库引擎 1、InnoDB(MySQL默认引擎) 2、事务 ACID事务 四种隔离级别 何为脏读&#xff0c;幻读&#xff0c;不可重复读&#xff1f; 脏读 不可重复读 幻读 三、数据库授权 1、查看用户 2、创建用户、用户设置密码 3、设置用户授权 4、…

namecheap 域名服务器 设置为Cloudflare

Namecheap 设置 自定义 域名服务器 登录Namecheap 帐户。进入后&#xff0c;将鼠标悬停在页面右上角的“帐户”选项上&#xff0c;然后选择“域列表”或选择左侧边栏中的“域列表” 参考 如何在 Cloudflare 帐户中域设置 DNS 记录

leetcode 206.反转链表

⭐️ 往期相关文章 ✨链接&#xff1a;数据结构-手撕单链表代码详解。 ⭐️ 题目描述 &#x1f31f; leetcode链接&#xff1a;反转链表 1️⃣ 代码&#xff1a; /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* }…