MultiHashKey
This commit is contained in:
@@ -11,8 +11,8 @@
|
|||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
|key|未定义|缓存的key,支持参数动态组合,比如"key_#{id}"|
|
|key|未定义|缓存的key,支持参数动态组合,比如"key_#{id}"|
|
||||||
|hash|```DEFAULT_HASH```|缓存的hash, 不能含有':'、'#'、'@'字符|
|
|hash|```DEFAULT_HASH```|缓存的hash, 不能含有':'、'#'、'@'字符|
|
||||||
|localExpire|-1|本地缓存过期时长, 0表示永不过期, -1表示不作本地缓存。 <br> 参数值支持方式:<br>  100: 设置数值 <br>  5*60: 乘法表达式,值为300 <br>  ${env.cache.expires}: 读取系统配置项 <br>  #delays: 读取宿主对象的delays字段值作为值,<br>       字段类型必须是int、long数值类型 |
|
|localExpire|-1|本地缓存过期时长, 0表示永不过期, -1表示不作本地缓存。 <br> 参数值支持方式:<br>  100: 设置数值 <br>  ${env.cache.expires}: 读取系统配置项 |
|
||||||
|remoteExpire|-1|远程缓存过期时长, 0表示永不过期, -1表示不作远程缓存。 <br> 参数值支持方式:<br>  100: 设置数值 <br>  5*60: 乘法表达式,值为300 <br>  ${env.cache.expires}: 读取系统配置项 <br>  #delays: 读取宿主对象的delays字段值作为值,<br>       字段类型必须是int、long数值类型 |
|
|remoteExpire|-1|远程缓存过期时长, 0表示永不过期, -1表示不作远程缓存。 <br> 参数值支持方式:<br>  100: 设置数值 <br>  ${env.cache.expires}: 读取系统配置项 |
|
||||||
|nullable|false|是否可以缓存null值|
|
|nullable|false|是否可以缓存null值|
|
||||||
|timeUnit|```TimeUnit.SECONDS```|时间单位TimeUnit|
|
|timeUnit|```TimeUnit.SECONDS```|时间单位TimeUnit|
|
||||||
|comment|未定义|备注描述|
|
|comment|未定义|备注描述|
|
||||||
|
|||||||
@@ -7,9 +7,9 @@
|
|||||||
|name|未定义|名称, 可用于第三方实现的定时任务组件的key, 比如xxl-job的任务标识|
|
|name|未定义|名称, 可用于第三方实现的定时任务组件的key, 比如xxl-job的任务标识|
|
||||||
|cron|未定义|cron表达式,也可以使用常量值: <br>  @yearly、@annually、@monthly、@weekly、<br>  @daily、@midnight、@hourly、@minutely <br>  @1m、@2m、@3m、@5m、@10m、@15m、@30m <br>  @1h、@2h、@3h、@6h <br>  ${env.scheduling.cron}: 读取系统配置项|
|
|cron|未定义|cron表达式,也可以使用常量值: <br>  @yearly、@annually、@monthly、@weekly、<br>  @daily、@midnight、@hourly、@minutely <br>  @1m、@2m、@3m、@5m、@10m、@15m、@30m <br>  @1h、@2h、@3h、@6h <br>  ${env.scheduling.cron}: 读取系统配置项|
|
||||||
|zone|未定义|时区,```cron```有值才有效, 例如: "Asia/Shanghai"|
|
|zone|未定义|时区,```cron```有值才有效, 例如: "Asia/Shanghai"|
|
||||||
|fixedDelay|-1|延迟时间,负数为无效值,支持参数配置、乘法表达式和对象字段值 <br> 参数值支持方式:<br>  100: 设置数值 <br>  5*60: 乘法表达式,值为300 <br>  ${env.scheduling.fixedDelay}: 读取系统配置项 <br>  #delays: 读取宿主对象的delays字段值作为值, <br>      字段类型必须是int、long数值类型 <br> 值大于0且fixedRate小于0则使用 ScheduledThreadPoolExecutor.scheduleWithFixedDelay |
|
|fixedDelay|-1|延迟时间,负数为无效值,支持参数配置、乘法表达式和对象字段值 <br> 参数值支持方式:<br>  100: 设置数值 <br>  ${env.scheduling.fixedDelay}: 读取系统配置项 <br> 值大于0且fixedRate小于0则使用 ScheduledThreadPoolExecutor.scheduleWithFixedDelay |
|
||||||
|fixedRate|-1|周期时间,负数为无效值,支持参数配置、乘法表达式和对象字段值 <br> 参数值支持方式:<br>  100: 设置数值 <br>  5*60: 乘法表达式,值为300 <br>  ${env.scheduling.fixedRate}: 读取系统配置项 <br>  #intervals: 读取宿主对象的intervals字段值作为值, <br>        字段类型必须是int、long数值类型 <br> 值大于0且fixedRate小于0则使用 ScheduledThreadPoolExecutor.scheduleAtFixedRate |
|
|fixedRate|-1|周期时间,负数为无效值,支持参数配置、乘法表达式和对象字段值 <br> 参数值支持方式:<br>  100: 设置数值 <br>  ${env.scheduling.fixedRate}: 读取系统配置项 <br> 值大于0且fixedRate小于0则使用 ScheduledThreadPoolExecutor.scheduleAtFixedRate |
|
||||||
|initialDelay|-1|起始延迟时间,负数为无效值,支持参数配置、乘法表达式和对象字段值 <br> 参数值支持方式:<br>  100: 设置数值 <br>  5*60: 乘法表达式,值为300 <br>  ${env.scheduling.initialDelay}: 读取系统配置项 <br>  #inits: 读取宿主对象的inits字段值作为值, <br>     字段类型必须是int、long数值类型 <br> 值大于0且fixedRate和fixedDelay小于0则使用 ScheduledThreadPoolExecutor.schedule |
|
|initialDelay|-1|起始延迟时间,负数为无效值,支持参数配置、乘法表达式和对象字段值 <br> 参数值支持方式:<br>  100: 设置数值 <br>  ${env.scheduling.initialDelay}: 读取系统配置项 <br> 值大于0且fixedRate和fixedDelay小于0则使用 ScheduledThreadPoolExecutor.schedule |
|
||||||
|timeUnit|```TimeUnit.SECONDS```|时间单位TimeUnit|
|
|timeUnit|```TimeUnit.SECONDS```|时间单位TimeUnit|
|
||||||
|comment|未定义|备注描述|
|
|comment|未定义|备注描述|
|
||||||
|mode|```LoadMode.LOCAL```|作用于Service模式,默认值为:LOCAL,<br> LOCAL: 表示远程模式的Service对象中的定时任务不起作用|
|
|mode|```LoadMode.LOCAL```|作用于Service模式,默认值为:LOCAL,<br> LOCAL: 表示远程模式的Service对象中的定时任务不起作用|
|
||||||
@@ -23,6 +23,14 @@
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
  <b>数值配置</b>, 系统启动后延迟10分钟后每60分钟执行一次,
|
||||||
|
```java
|
||||||
|
@Scheduled(fixedDelay = "10", fixedRate = "60", timeUnit = TimeUnit.MINUTES)
|
||||||
|
private void task3() {
|
||||||
|
System.out.println(Times.nowMillis() + "执行一次");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
  <b>环境配置</b>, 定时间隔时间由环境变量```env.schedule.fixedRate```配置,没配置采用默认值60秒)
|
  <b>环境配置</b>, 定时间隔时间由环境变量```env.schedule.fixedRate```配置,没配置采用默认值60秒)
|
||||||
```java
|
```java
|
||||||
@Scheduled(fixedRate = "${env.schedule.fixedRate:60}")
|
@Scheduled(fixedRate = "${env.schedule.fixedRate:60}")
|
||||||
@@ -32,13 +40,6 @@
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
  <b>支持乘法表达式</b>, 系统启动后延迟10分钟后每60分钟执行一次,
|
|
||||||
```java
|
|
||||||
@Scheduled(fixedDelay = "10", fixedRate = "2*30", timeUnit = TimeUnit.MINUTES)
|
|
||||||
private void task3() {
|
|
||||||
System.out.println(Times.nowMillis() + "执行一次");
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 基本配置
|
## 基本配置
|
||||||
```xml
|
```xml
|
||||||
|
|||||||
4
src/main/java/org/redkale/cache/Cached.java
vendored
4
src/main/java/org/redkale/cache/Cached.java
vendored
@@ -44,9 +44,7 @@ public @interface Cached {
|
|||||||
* 本地缓存过期时长, 0表示永不过期, -1表示不作本地缓存。<br>
|
* 本地缓存过期时长, 0表示永不过期, -1表示不作本地缓存。<br>
|
||||||
* 参数值支持方式:<br>
|
* 参数值支持方式:<br>
|
||||||
* 100: 设置数值
|
* 100: 设置数值
|
||||||
* 5*60: 乘法表达式,值为300
|
|
||||||
* ${env.cache.expires}: 读取系统配置项
|
* ${env.cache.expires}: 读取系统配置项
|
||||||
* #delays: 读取宿主对象的delays字段值作为值,字段类型必须是int、long数值类型
|
|
||||||
*
|
*
|
||||||
* @return 过期时长
|
* @return 过期时长
|
||||||
*/
|
*/
|
||||||
@@ -56,9 +54,7 @@ public @interface Cached {
|
|||||||
* 远程缓存过期时长, 0表示永不过期, -1表示不作远程缓存。<br>
|
* 远程缓存过期时长, 0表示永不过期, -1表示不作远程缓存。<br>
|
||||||
* 参数值支持方式:<br>
|
* 参数值支持方式:<br>
|
||||||
* 100: 设置数值
|
* 100: 设置数值
|
||||||
* 5*60: 乘法表达式,值为300
|
|
||||||
* ${env.cache.expires}: 读取系统配置项
|
* ${env.cache.expires}: 读取系统配置项
|
||||||
* #delays: 读取宿主对象的delays字段值作为值,字段类型必须是int、long数值类型
|
|
||||||
*
|
*
|
||||||
* @return 过期时长
|
* @return 过期时长
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import org.redkale.convert.json.JsonConvert;
|
|||||||
* <p>
|
* <p>
|
||||||
* 详情见: https://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
|
* @see org.redkale.mq.MessageConsumer
|
||||||
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*
|
*
|
||||||
* @since 2.8.0
|
* @since 2.8.0
|
||||||
|
|||||||
@@ -3,10 +3,10 @@
|
|||||||
*/
|
*/
|
||||||
package org.redkale.mq;
|
package org.redkale.mq;
|
||||||
|
|
||||||
|
import org.redkale.annotation.ClassDepends;
|
||||||
import org.redkale.annotation.Component;
|
import org.redkale.annotation.Component;
|
||||||
import org.redkale.service.Local;
|
import org.redkale.service.Local;
|
||||||
import org.redkale.util.AnyValue;
|
import org.redkale.util.AnyValue;
|
||||||
import org.redkale.annotation.ClassDepends;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MQ消费器, 实现类必须标记{@link org.redkale.mq.ResourceConsumer}
|
* MQ消费器, 实现类必须标记{@link org.redkale.mq.ResourceConsumer}
|
||||||
@@ -14,8 +14,11 @@ import org.redkale.annotation.ClassDepends;
|
|||||||
* <p>
|
* <p>
|
||||||
* 详情见: https://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
|
* @see org.redkale.mq.MessageConext
|
||||||
|
* @see org.redkale.mq.ResourceConsumer
|
||||||
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <T> 泛型
|
* @param <T> T
|
||||||
*
|
*
|
||||||
* @since 2.8.0
|
* @since 2.8.0
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ import org.redkale.convert.ConvertType;
|
|||||||
* <p>
|
* <p>
|
||||||
* 详情见: https://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
|
* @see org.redkale.mq.MessageProducer
|
||||||
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*
|
*
|
||||||
* @since 2.8.0
|
* @since 2.8.0
|
||||||
|
|||||||
@@ -52,9 +52,7 @@ public @interface Scheduled {
|
|||||||
* 延迟时间,支持参数配置、乘法表达式和对象字段值 <br>
|
* 延迟时间,支持参数配置、乘法表达式和对象字段值 <br>
|
||||||
* 参数值支持方式:<br>
|
* 参数值支持方式:<br>
|
||||||
* 100: 设置数值
|
* 100: 设置数值
|
||||||
* 5*60: 乘法表达式,值为300
|
|
||||||
* ${env.scheduling.fixedDelay}: 读取系统配置项
|
* ${env.scheduling.fixedDelay}: 读取系统配置项
|
||||||
* #delays: 读取宿主对象的delays字段值作为值,字段类型必须是int、long数值类型
|
|
||||||
*
|
*
|
||||||
* 值大于0且fixedRate小于0则使用 ScheduledThreadPoolExecutor.scheduleWithFixedDelay
|
* 值大于0且fixedRate小于0则使用 ScheduledThreadPoolExecutor.scheduleWithFixedDelay
|
||||||
*
|
*
|
||||||
@@ -66,9 +64,7 @@ public @interface Scheduled {
|
|||||||
* 周期时间,支持参数配置、乘法表达式和对象字段值 <br>
|
* 周期时间,支持参数配置、乘法表达式和对象字段值 <br>
|
||||||
* 参数值支持方式:<br>
|
* 参数值支持方式:<br>
|
||||||
* 100: 设置数值
|
* 100: 设置数值
|
||||||
* 5*60: 乘法表达式,值为300
|
|
||||||
* ${env.scheduling.fixedRate}: 读取系统配置项
|
* ${env.scheduling.fixedRate}: 读取系统配置项
|
||||||
* #intervals: 读取宿主对象的intervals字段值作为值,字段类型必须是int、long数值类型
|
|
||||||
*
|
*
|
||||||
* 值大于0则使用 ScheduledThreadPoolExecutor.scheduleAtFixedRate
|
* 值大于0则使用 ScheduledThreadPoolExecutor.scheduleAtFixedRate
|
||||||
*
|
*
|
||||||
@@ -80,9 +76,7 @@ public @interface Scheduled {
|
|||||||
* 起始延迟时间,支持参数配置、乘法表达式和对象字段值 <br>
|
* 起始延迟时间,支持参数配置、乘法表达式和对象字段值 <br>
|
||||||
* 参数值支持方式:<br>
|
* 参数值支持方式:<br>
|
||||||
* 100: 设置数值
|
* 100: 设置数值
|
||||||
* 5*60: 乘法表达式,值为300
|
|
||||||
* ${env.scheduling.initialDelay}: 读取系统配置项
|
* ${env.scheduling.initialDelay}: 读取系统配置项
|
||||||
* #inits: 读取宿主对象的inits字段值作为值,字段类型必须是int、long数值类型
|
|
||||||
*
|
*
|
||||||
* 值大于0且fixedRate和fixedDelay小于0则使用 ScheduledThreadPoolExecutor.schedule
|
* 值大于0且fixedRate和fixedDelay小于0则使用 ScheduledThreadPoolExecutor.schedule
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ package org.redkale.schedule.spi;
|
|||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
import java.lang.invoke.MethodHandles;
|
import java.lang.invoke.MethodHandles;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
@@ -221,9 +220,9 @@ public class ScheduleManagerService implements ScheduleManager, Service {
|
|||||||
CronExpression cronExpr = CronExpression.parse(cron);
|
CronExpression cronExpr = CronExpression.parse(cron);
|
||||||
return new CronTask(ref, name, method, cronExpr, zoneId);
|
return new CronTask(ref, name, method, cronExpr, zoneId);
|
||||||
} else {
|
} else {
|
||||||
long fixedDelayLong = getLongValue(ref.get(), fixedDelay);
|
long fixedDelayLong = Long.parseLong(fixedDelay);
|
||||||
long fixedRateLong = getLongValue(ref.get(), fixedRate);
|
long fixedRateLong = Long.parseLong(fixedRate);
|
||||||
long initialDelayLong = getLongValue(ref.get(), initialDelay);
|
long initialDelayLong = Long.parseLong(initialDelay);
|
||||||
return new FixedTask(ref, name, method, fixedDelayLong, fixedRateLong, initialDelayLong, timeUnit);
|
return new FixedTask(ref, name, method, fixedDelayLong, fixedRateLong, initialDelayLong, timeUnit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -270,46 +269,6 @@ public class ScheduleManagerService implements ScheduleManager, Service {
|
|||||||
return propertyFunc.apply(value);
|
return propertyFunc.apply(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
//支持5*60乘法表达式
|
|
||||||
protected long getLongValue(Object service, String value) {
|
|
||||||
if (value.indexOf('*') > -1) {
|
|
||||||
long rs = 1;
|
|
||||||
boolean flag = false;
|
|
||||||
for (String v : value.split("\\*")) {
|
|
||||||
if (!v.trim().isEmpty()) {
|
|
||||||
rs *= Long.parseLong(v.trim());
|
|
||||||
flag = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return flag ? rs : -1;
|
|
||||||
} else if (value.indexOf('#') == 0) {
|
|
||||||
try {
|
|
||||||
String fieldName = value.substring(1);
|
|
||||||
Exception ex = null;
|
|
||||||
Field field = null;
|
|
||||||
Class clazz = service.getClass();
|
|
||||||
do {
|
|
||||||
try {
|
|
||||||
field = clazz.getDeclaredField(fieldName);
|
|
||||||
field.setAccessible(true);
|
|
||||||
RedkaleClassLoader.putReflectionField(clazz.getName(), field);
|
|
||||||
break;
|
|
||||||
} catch (NoSuchFieldException fe) {
|
|
||||||
ex = fe;
|
|
||||||
}
|
|
||||||
} while ((clazz = clazz.getSuperclass()) != Object.class);
|
|
||||||
if (field == null) {
|
|
||||||
throw ex;
|
|
||||||
}
|
|
||||||
return ((Number) field.get(service)).longValue();
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RedkaleException(e);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return Long.parseLong(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int start(String scheduleName) {
|
public int start(String scheduleName) {
|
||||||
int c = 0;
|
int c = 0;
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ public interface DataSource extends Resourcable {
|
|||||||
//-------------------------deleteAsync--------------------------
|
//-------------------------deleteAsync--------------------------
|
||||||
/**
|
/**
|
||||||
* 删除指定主键值的记录, 多对象必须是同一个Entity类且必须在同一张表中 <br>
|
* 删除指定主键值的记录, 多对象必须是同一个Entity类且必须在同一张表中 <br>
|
||||||
等价SQL: DELETE FROM {table} WHERE {primary} IN {getValues.id} <br>
|
* 等价SQL: DELETE FROM {table} WHERE {primary} IN {getValues.id} <br>
|
||||||
*
|
*
|
||||||
* @param <T> 泛型
|
* @param <T> 泛型
|
||||||
* @param entitys Entity对象
|
* @param entitys Entity对象
|
||||||
@@ -175,7 +175,7 @@ public interface DataSource extends Resourcable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除指定主键值的记录, 多对象必须是同一个Entity类且必须在同一张表中 <br>
|
* 删除指定主键值的记录, 多对象必须是同一个Entity类且必须在同一张表中 <br>
|
||||||
等价SQL: DELETE FROM {table} WHERE {primary} IN {getValues.id} <br>
|
* 等价SQL: DELETE FROM {table} WHERE {primary} IN {getValues.id} <br>
|
||||||
*
|
*
|
||||||
* @param <T> 泛型
|
* @param <T> 泛型
|
||||||
* @param entitys Entity对象
|
* @param entitys Entity对象
|
||||||
@@ -191,7 +191,7 @@ public interface DataSource extends Resourcable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除指定主键值的记录, 多对象必须是同一个Entity类且必须在同一张表中 <br>
|
* 删除指定主键值的记录, 多对象必须是同一个Entity类且必须在同一张表中 <br>
|
||||||
等价SQL: DELETE FROM {table} WHERE {primary} IN {getValues.id} <br>
|
* 等价SQL: DELETE FROM {table} WHERE {primary} IN {getValues.id} <br>
|
||||||
*
|
*
|
||||||
* @param <T> 泛型
|
* @param <T> 泛型
|
||||||
* @param entitys Entity对象
|
* @param entitys Entity对象
|
||||||
@@ -207,7 +207,7 @@ public interface DataSource extends Resourcable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除指定主键值的记录, 多对象必须是同一个Entity类且必须在同一张表中 <br>
|
* 删除指定主键值的记录, 多对象必须是同一个Entity类且必须在同一张表中 <br>
|
||||||
等价SQL: DELETE FROM {table} WHERE {primary} IN {getValues.id} <br>
|
* 等价SQL: DELETE FROM {table} WHERE {primary} IN {getValues.id} <br>
|
||||||
*
|
*
|
||||||
* @param <T> 泛型
|
* @param <T> 泛型
|
||||||
* @param entitys Entity对象
|
* @param entitys Entity对象
|
||||||
@@ -218,7 +218,7 @@ public interface DataSource extends Resourcable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除指定主键值的记录, 多对象必须是同一个Entity类且必须在同一张表中 <br>
|
* 删除指定主键值的记录, 多对象必须是同一个Entity类且必须在同一张表中 <br>
|
||||||
等价SQL: DELETE FROM {table} WHERE {primary} IN {getValues.id} <br>
|
* 等价SQL: DELETE FROM {table} WHERE {primary} IN {getValues.id} <br>
|
||||||
*
|
*
|
||||||
* @param <T> 泛型
|
* @param <T> 泛型
|
||||||
* @param entitys Entity对象
|
* @param entitys Entity对象
|
||||||
@@ -234,7 +234,7 @@ public interface DataSource extends Resourcable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除指定主键值的记录, 多对象必须是同一个Entity类且必须在同一张表中 <br>
|
* 删除指定主键值的记录, 多对象必须是同一个Entity类且必须在同一张表中 <br>
|
||||||
等价SQL: DELETE FROM {table} WHERE {primary} IN {getValues.id} <br>
|
* 等价SQL: DELETE FROM {table} WHERE {primary} IN {getValues.id} <br>
|
||||||
*
|
*
|
||||||
* @param <T> 泛型
|
* @param <T> 泛型
|
||||||
* @param entitys Entity对象
|
* @param entitys Entity对象
|
||||||
|
|||||||
@@ -60,11 +60,25 @@ public class Environment implements java.io.Serializable {
|
|||||||
if (val == null || val.isBlank()) {
|
if (val == null || val.isBlank()) {
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
char last = 0;
|
||||||
|
char[] chars = val.toCharArray();
|
||||||
|
int startIndex = -1;
|
||||||
|
int endIndex = -1;
|
||||||
|
for (int i = 0; i < chars.length; i++) {
|
||||||
|
char ch = chars[i];
|
||||||
|
if (ch == '{' && last == '$') {
|
||||||
|
startIndex = i - 1;
|
||||||
|
} else if (last != '\\' && ch == '}' && startIndex >= 0) {
|
||||||
|
endIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
last = ch;
|
||||||
|
}
|
||||||
|
|
||||||
//${domain}/${path}/xxx ${aa${bbb}}
|
//${domain}/${path}/xxx ${aa${bbb}}
|
||||||
int pos2 = val.indexOf("}");
|
//school_#{name}_${haha_${age}}_${bb}_#{dd} -> school_#{name}_xxx_xxx_#{dd}
|
||||||
int pos1 = val.lastIndexOf("${", pos2);
|
if (startIndex >= 0 && endIndex > 0) {
|
||||||
if (pos1 >= 0 && pos2 > 0) {
|
String key = val.substring(startIndex + 2, endIndex);
|
||||||
String key = val.substring(pos1 + 2, pos2);
|
|
||||||
int pos3 = key.lastIndexOf(':');
|
int pos3 = key.lastIndexOf(':');
|
||||||
String defVal = null;
|
String defVal = null;
|
||||||
if (pos3 > 0) {
|
if (pos3 > 0) {
|
||||||
@@ -77,13 +91,13 @@ public class Environment implements java.io.Serializable {
|
|||||||
String subVal = properties.getProperty(key);
|
String subVal = properties.getProperty(key);
|
||||||
if (subVal != null) {
|
if (subVal != null) {
|
||||||
String newVal = getPropertyValue(subVal, envs);
|
String newVal = getPropertyValue(subVal, envs);
|
||||||
return getPropertyValue(val.substring(0, pos1) + newVal + val.substring(pos2 + 1));
|
return getPropertyValue(val.substring(0, startIndex) + newVal + val.substring(endIndex + 1));
|
||||||
} else {
|
} else {
|
||||||
for (Properties prop : envs) {
|
for (Properties prop : envs) {
|
||||||
subVal = prop.getProperty(key);
|
subVal = prop.getProperty(key);
|
||||||
if (subVal != null) {
|
if (subVal != null) {
|
||||||
String newVal = getPropertyValue(subVal, envs);
|
String newVal = getPropertyValue(subVal, envs);
|
||||||
return getPropertyValue(val.substring(0, pos1) + newVal + val.substring(pos2 + 1));
|
return getPropertyValue(val.substring(0, startIndex) + newVal + val.substring(endIndex + 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pos3 > 0) {
|
if (pos3 > 0) {
|
||||||
@@ -91,8 +105,6 @@ public class Environment implements java.io.Serializable {
|
|||||||
}
|
}
|
||||||
throw new RedkaleException("Not found '" + key + "' value");
|
throw new RedkaleException("Not found '" + key + "' value");
|
||||||
}
|
}
|
||||||
} else if ((pos1 >= 0 && pos2 < 0) || (pos1 < 0 && pos2 >= 0 && val.indexOf("#{") < 0)) {
|
|
||||||
throw new RedkaleException(val + " is illegal naming");
|
|
||||||
}
|
}
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ public interface MultiHashKey {
|
|||||||
public String keyFor(Object... args);
|
public String keyFor(Object... args);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* key只支持带#{}的表达式, 且不能嵌套, 如:name_#{key_#{id}}
|
* key只支持带#{}的表达式, 且不能嵌套,错误示例:name_#{key_#{id}}
|
||||||
*
|
*
|
||||||
* @param paramNames 参数名
|
* @param paramNames 参数名
|
||||||
* @param key key表达式
|
* @param key key表达式
|
||||||
|
|||||||
@@ -39,9 +39,15 @@ class MultiHashKeys {
|
|||||||
}
|
}
|
||||||
sb.delete(0, sb.length());
|
sb.delete(0, sb.length());
|
||||||
paraming = true;
|
paraming = true;
|
||||||
|
} else if (last == '\\') {
|
||||||
|
sb.deleteCharAt(sb.length() - 1);
|
||||||
|
sb.append(ch);
|
||||||
} else {
|
} else {
|
||||||
throw new RedkaleException(MultiHashKey.class.getSimpleName() + " parse error, key: " + key);
|
throw new RedkaleException(MultiHashKey.class.getSimpleName() + " parse error, key: " + key);
|
||||||
}
|
}
|
||||||
|
} else if (last == '\\' && ch == '}') {
|
||||||
|
sb.deleteCharAt(sb.length() - 1);
|
||||||
|
sb.append(ch);
|
||||||
} else if (ch == '}') {
|
} else if (ch == '}') {
|
||||||
if (!paraming) {
|
if (!paraming) {
|
||||||
throw new RedkaleException(MultiHashKey.class.getSimpleName() + " parse error, key: " + key);
|
throw new RedkaleException(MultiHashKey.class.getSimpleName() + " parse error, key: " + key);
|
||||||
|
|||||||
38
src/test/java/org/redkale/test/util/EnvironmentTest.java
Normal file
38
src/test/java/org/redkale/test/util/EnvironmentTest.java
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package org.redkale.test.util;
|
||||||
|
|
||||||
|
import java.util.Properties;
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.redkale.util.Environment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author zhangjx
|
||||||
|
*/
|
||||||
|
public class EnvironmentTest {
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Throwable {
|
||||||
|
EnvironmentTest test = new EnvironmentTest();
|
||||||
|
test.run1();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void run1() throws Exception {
|
||||||
|
Properties properties = new Properties();
|
||||||
|
properties.put("age", "18");
|
||||||
|
properties.put("haha_18", "test");
|
||||||
|
properties.put("bb", "tt");
|
||||||
|
|
||||||
|
Environment env = new Environment(properties);
|
||||||
|
String val = env.getPropertyValue("school_#{name}_${haha_${age}}_${bb}_#{dd}");
|
||||||
|
System.out.println(val);
|
||||||
|
Assertions.assertEquals("school_#{name}_test_tt_#{dd}", val);
|
||||||
|
|
||||||
|
val = env.getPropertyValue("${haha_${age}}");
|
||||||
|
System.out.println(val);
|
||||||
|
Assertions.assertEquals("test", val);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user