Java提取${}占位符并组装对应值

实现了一个${}装配工~

零、起因

最近写个JavaWeb项目,数据库相关的配置想放到properties文件中,用的H2,想直接内嵌,但是数据库文件位置想随程序移动,因为这个项目准备是放到U盘里随插随用的程序。然后配置URL时一开始用的是./data,它是在Tomcat bin目录下生成的,后面了解到有个私有的工作目录:${catalina.base},想我的数据库初始化程序也支持这个,直接加到H2的URL中jdbc:h2:${catalina.base}/data;报错,H2不支持。现在了解到可以通过System.getProperty("catalina.base")的方式获取到这个路径,那如何把URL中的${catalina.base}替换成System.getProperty("catalina.base")的值呢?

壹、想法

百度没得啥资料,我感觉可以通过正则匹配${},然后一个一个替换掉。

贰、实现

首先写了个正则表达式

\$\{[^}]+}

在菜鸟在线工具上测试通过

输入:

jdbc:h2:${catalina.base}/${catalina.base}work/data;MODE=MySQL;DATABASE_TO_LOWER=TRUE;CIPHER=AES;

输出:

共找到 2 处匹配:
${catalina.base}
${catalina.base}

然后在Java中实现了这个正则表达式的匹配

String str = "jdbc:h2:${catalina.base}/${catalina.base}work/data;MODE=MySQL;DATABASE_TO_LOWER=TRUE;CIPHER=AES;";
String pattern = "\\$\\{[^}]+}"; Pattern r = Pattern.compile(pattern);
Matcher m = r.matcher(str);
if(m.find()) {
System.out.println(m.group());
str = m.replaceFirst("第一个位置");
System.out.println(str);
}

输出

${catalina.base}
jdbc:h2:第一个位置/${catalina.base}work/data;MODE=MySQL;DATABASE_TO_LOWER=TRUE;CIPHER=AES;

很好,加了个循环,依次替换掉后面的值

String str = "jdbc:h2:${catalina.base}/${catalina.base}work/data;MODE=MySQL;DATABASE_TO_LOWER=TRUE;CIPHER=AES;";
String pattern = "\\$\\{[^}]+}"; Pattern r = Pattern.compile(pattern);
int index = 0;
while (true) {
Matcher m = r.matcher(str);
if(m.find()){
index++;
System.out.println(m.group());
str = m.replaceFirst("第" + index + "个位置");
System.out.println(str);
}else {
break;
}
}

输出

${catalina.base}
jdbc:h2:第1个位置/${catalina.base}work/data;MODE=MySQL;DATABASE_TO_LOWER=TRUE;CIPHER=AES;
${catalina.base}
jdbc:h2:第1个位置/第2个位置work/data;MODE=MySQL;DATABASE_TO_LOWER=TRUE;CIPHER=AES;

好,真不戳,然后封装一下,替换的值由接口来决定,到时候重写这个接口就好了

package minuhy.ymz.WorkManage.Util;

import java.util.regex.Matcher;
import java.util.regex.Pattern; /**
* @Auther: Minuhy
* @Date: 2022/10/2 13:02
* @Decsription: 装配 ${} 表达式的值
*/
public class StringAssembler {
public interface Assemble {
/**
* 装配过程中需要通过${}里面的表达式找到对应的值
* @param key ${}里面的表达式
* @return ${}里面的表达式对应的值
*/
String getStringByKey(String key);
} /**
* 装配 ${} 格式的字符串
* @param str 原始字符串
* @param assemble 装配过程中获取值的接口
* @return 装配好之后的字符串
*/
public static String assemble(String str, Assemble assemble) {
String pattern = "\\$\\{[^}]+}"; Pattern r = Pattern.compile(pattern); while (true) {
Matcher m = r.matcher(str);
if (m.find()) {
String key = getKey(m.group());
str = m.replaceFirst(assemble.getStringByKey(key));
} else {
break;
}
} return str;
} /**
* 获取 ${} 里面的值
* @param g ${} 表达式
* @return ${} 里面的值
*/
public static String getKey(String g) {
return g.substring(2, g.length() - 1);
}
}

测试:

	@Test
public void Test$Exp() {
String str = "jdbc:h2:${key1}/${key2}work/data;";
str = StringAssembler.assemble(str, key ->{
System.out.println(key);
if (key.equals("key1")) {
return "第一个键";
} else if (key.equals("key2")) {
return "第二个键";
}
return "";
});
System.out.println(str);
}

输出:

"C:\Program Files\Java\jdk1.8.0_301\bin\java.exe" -ea -......
key1
key2
jdbc:h2:第一个键/第二个键work/data; Process finished with exit code 0

成功!

叁、总结

这个方式实现比较简单,但是复杂度应该是挺高的,后面可以尝试优化一下。

肆、参考文档

菜鸟正则表达式工具

问题:Java正则表达式匹配不到结果的解决

【Java】Java提取${}占位符并组装对应值的更多相关文章

  1. Java中Void占位符的測试及个人理解

    Java对Void类的说明是:Void 类是一个不可实例化的占位符类,它保持一个对代表 Java keyword void 的 Class 对象的引用. 代表的是: 代表主要的 Java 类型 voi ...

  2. java中的占位符\t\n\r\f

    \t 相当于tab,缩进\n NewLine 换行 System.out.println("aaa\tbbb"); //aaa bbbSystem.out.println(&quo ...

  3. java:Hibernate框架3(使用Myeclipse逆向工程生成实体和配置信息,hql语句各种查询(使用hibernate执行原生SQL语句,占位符和命名参数,封装Vo查询多个属性,聚合函数,链接查询,命名查询),Criteria)

    1.使用Myeclipse逆向工程生成实体和配置信息: 步骤1:配置MyEclipse Database Explorer: 步骤2:为项目添加hibernate的依赖: 此处打开后,点击next进入 ...

  4. java之mybatis之占位符

    1.mybatis中有两种占位符 #{}和 ${}. 2. #{} 占位符是为了获取值,获取的值用在 where 语句后,insert 语句后,update 语句. #{} 获取值,是根据值的名称取值 ...

  5. Android Gradle manifestPlaceholders 占位符详解

    Android Gradle manifestPlaceholders 占位符详解 在实际项目中,AndroidManifest里十几个地方的值是需要动态的改变(生成apk文件的时候).如果每次去改也 ...

  6. Spring中手动增加配置文件中占位符引用的变量

    在项目中遇到一个这样的需求,项目的配置文件由外部传入,这时spring配置文件那些占位符变量该如何取值呢? 解决这个问题的做法有几种,我想到的大概有以下三种: 1.通过系统属性来实现,把外部传入的配置 ...

  7. SpringBoot环境属性占位符解析和类型转换

    前提 前面写过一篇关于Environment属性加载的源码分析和扩展,里面提到属性的占位符解析和类型转换是相对复杂的,这篇文章就是要分析和解读这两个复杂的问题.关于这两个问题,选用一个比较复杂的参数处 ...

  8. placeholder 占位符

    placeholder 简介  |  TensorFlow https://tensorflow.google.cn/programmers_guide/low_level_intro 供给 目前来讲 ...

  9. Tensorflow学习笔记——占位符和feed_dict(二)

    创建了各种形式的常量和变量后,但TensorFlow 同样还支持占位符.占位符并没有初始值,它只会分配必要的内存.在会话中,占位符可以使用 feed_dict 馈送数据. feed_dict是一个字典 ...

  10. spring源码分析之配置文件名占位符的解析(一)

    一.直接写个测试例子 package com.test; import org.junit.Test; import org.springframework.context.ApplicationCo ...

随机推荐

  1. Solution Set -「LOCAL」冲刺省选 Round XXXI

    \(\mathscr{Summary}\)   前期节奏太懒散,后面发现 C 题是水题都没时间写,提起精神来啊!   A 题卡得比较久,对线性基的理解不够深刻,思来想去半天才把转移系数调对.B 题也卡 ...

  2. 彻底讲透Spring三级缓存,原理源码深度剖析!

    一.前言循环依赖:就是N个类循环(嵌套)引用.通俗的讲就是N个Bean互相引用对方,最终形成闭环.在日常的开发中,我们都会碰到类似如下的代码 @Servicepublic class AService ...

  3. biancheng-Pygame(python)

    http://c.biancheng.net/pygame/ Python Pygame 是一款专门为开发和设计 2D 电子游戏而生的软件包,它支 Windows.Linux.Mac OS 等操作系统 ...

  4. threejs 实现镜面反射,只反射指定物体,背景透明

    一.背景 最近在做数字孪生项目,使用threejs渲染模型,UI要求地面反射建筑物,也就是模型要有倒影. 二.调研 在官网找到一个镜面反射的例子(https://threejs.org/example ...

  5. Hat靶机

    Hat靶机的ip是192.168.200.8 先用nmap扫描一下靶机所有的端口 nmap -p- 192.168.200.8 发现22端口不知道是否开放 还有一个65535 的unkown端口 详细 ...

  6. 牛客周赛 Round 77

    题目链接:牛客周赛 Round 77 A. 时间表 tag:签到 B. 数独数组 tag:签到 Description:给定n个数,每个数的范围为1-9,问能否经过排列,使其每个长度为9的连续子数组都 ...

  7. 首个“全4K”运动会,上云!

    采用"全4K"超高清制作标准的世-界级赛事--成都世界大学生运动会,可以用手机看.用电视看,甚至用VR沉浸式观看,并且既高清又流畅--在"2023数字科技生态大会&quo ...

  8. idea插件仓库连接不到网络

    IDEA的插件中心连不上网 打开:设置-插件 选择:设置按钮-HTTP代理设置 勾选自动设置 输入 https://plugins.jetbrains.com/或者 http://127.0.0.1: ...

  9. Luogu P11543 Code+#5 我有矩阵,你有吗? 题解 [ 绿 ] [ 扩展域并查集 ]

    我有矩阵,你有吗?:并查集小清新题. 思路 看到这题,我第一个想到的竟然是高斯消元. 首先一行和一列肯定不会操作两次以上,不然一定可以等效为操作 \(0\) 次和操作 \(1\) 次的情况. 于是我们 ...

  10. Atcoder [AGC006D] Median Pyramid Hard 题解 [ 紫 ] [ 二分 ] [ adhoc ]

    Median Pyramid Hard:二分 trick 加上性质观察题. trick 我们可以二分值域,然后把大于等于它的数标记成 \(1\),其他标记为 \(0\)(有些题需要标记成 \(-1\) ...