diff --git a/docs/cached.md b/docs/cached.md index b3f7e38a6..3cfdcdf72 100644 --- a/docs/cached.md +++ b/docs/cached.md @@ -11,8 +11,8 @@ | --- | --- | --- | |key|未定义|缓存的key,支持参数动态组合,比如"key_#{id}"| |hash|```DEFAULT_HASH```|缓存的hash, 不能含有':'、'#'、'@'字符| -|localExpire|-1|本地缓存过期时长, 0表示永不过期, -1表示不作本地缓存。
参数值支持方式:
 100: 设置数值
 5*60: 乘法表达式,值为300
 ${env.cache.expires}: 读取系统配置项
 #delays: 读取宿主对象的delays字段值作为值,
      字段类型必须是int、long数值类型 | -|remoteExpire|-1|远程缓存过期时长, 0表示永不过期, -1表示不作远程缓存。
参数值支持方式:
 100: 设置数值
 5*60: 乘法表达式,值为300
 ${env.cache.expires}: 读取系统配置项
 #delays: 读取宿主对象的delays字段值作为值,
      字段类型必须是int、long数值类型 | +|localExpire|-1|本地缓存过期时长, 0表示永不过期, -1表示不作本地缓存。
参数值支持方式:
 100: 设置数值
 ${env.cache.expires}: 读取系统配置项 | +|remoteExpire|-1|远程缓存过期时长, 0表示永不过期, -1表示不作远程缓存。
参数值支持方式:
 100: 设置数值
 ${env.cache.expires}: 读取系统配置项 | |nullable|false|是否可以缓存null值| |timeUnit|```TimeUnit.SECONDS```|时间单位TimeUnit| |comment|未定义|备注描述| diff --git a/docs/scheduled.md b/docs/scheduled.md index b8b560e91..d8c207eb2 100644 --- a/docs/scheduled.md +++ b/docs/scheduled.md @@ -7,9 +7,9 @@ |name|未定义|名称, 可用于第三方实现的定时任务组件的key, 比如xxl-job的任务标识| |cron|未定义|cron表达式,也可以使用常量值:
 @yearly、@annually、@monthly、@weekly、
 @daily、@midnight、@hourly、@minutely
 @1m、@2m、@3m、@5m、@10m、@15m、@30m
 @1h、@2h、@3h、@6h
 ${env.scheduling.cron}: 读取系统配置项| |zone|未定义|时区,```cron```有值才有效, 例如: "Asia/Shanghai"| -|fixedDelay|-1|延迟时间,负数为无效值,支持参数配置、乘法表达式和对象字段值
参数值支持方式:
 100: 设置数值
 5*60: 乘法表达式,值为300
 ${env.scheduling.fixedDelay}: 读取系统配置项
 #delays: 读取宿主对象的delays字段值作为值,
     字段类型必须是int、long数值类型
值大于0且fixedRate小于0则使用 ScheduledThreadPoolExecutor.scheduleWithFixedDelay | -|fixedRate|-1|周期时间,负数为无效值,支持参数配置、乘法表达式和对象字段值
参数值支持方式:
 100: 设置数值
 5*60: 乘法表达式,值为300
 ${env.scheduling.fixedRate}: 读取系统配置项
 #intervals: 读取宿主对象的intervals字段值作为值,
       字段类型必须是int、long数值类型
值大于0且fixedRate小于0则使用 ScheduledThreadPoolExecutor.scheduleAtFixedRate | -|initialDelay|-1|起始延迟时间,负数为无效值,支持参数配置、乘法表达式和对象字段值
参数值支持方式:
 100: 设置数值
 5*60: 乘法表达式,值为300
 ${env.scheduling.initialDelay}: 读取系统配置项
 #inits: 读取宿主对象的inits字段值作为值,
    字段类型必须是int、long数值类型
值大于0且fixedRate和fixedDelay小于0则使用 ScheduledThreadPoolExecutor.schedule | +|fixedDelay|-1|延迟时间,负数为无效值,支持参数配置、乘法表达式和对象字段值
参数值支持方式:
 100: 设置数值
 ${env.scheduling.fixedDelay}: 读取系统配置项
值大于0且fixedRate小于0则使用 ScheduledThreadPoolExecutor.scheduleWithFixedDelay | +|fixedRate|-1|周期时间,负数为无效值,支持参数配置、乘法表达式和对象字段值
参数值支持方式:
 100: 设置数值
 ${env.scheduling.fixedRate}: 读取系统配置项
值大于0且fixedRate小于0则使用 ScheduledThreadPoolExecutor.scheduleAtFixedRate | +|initialDelay|-1|起始延迟时间,负数为无效值,支持参数配置、乘法表达式和对象字段值
参数值支持方式:
 100: 设置数值
 ${env.scheduling.initialDelay}: 读取系统配置项
值大于0且fixedRate和fixedDelay小于0则使用 ScheduledThreadPoolExecutor.schedule | |timeUnit|```TimeUnit.SECONDS```|时间单位TimeUnit| |comment|未定义|备注描述| |mode|```LoadMode.LOCAL```|作用于Service模式,默认值为:LOCAL,
LOCAL: 表示远程模式的Service对象中的定时任务不起作用| @@ -23,6 +23,14 @@ } ``` +  数值配置, 系统启动后延迟10分钟后每60分钟执行一次, +```java + @Scheduled(fixedDelay = "10", fixedRate = "60", timeUnit = TimeUnit.MINUTES) + private void task3() { + System.out.println(Times.nowMillis() + "执行一次"); + } +``` +   环境配置, 定时间隔时间由环境变量```env.schedule.fixedRate```配置,没配置采用默认值60秒) ```java @Scheduled(fixedRate = "${env.schedule.fixedRate:60}") @@ -32,13 +40,6 @@ } ``` -  支持乘法表达式, 系统启动后延迟10分钟后每60分钟执行一次, -```java - @Scheduled(fixedDelay = "10", fixedRate = "2*30", timeUnit = TimeUnit.MINUTES) - private void task3() { - System.out.println(Times.nowMillis() + "执行一次"); - } -``` ## 基本配置 ```xml diff --git a/src/main/java/org/redkale/cache/Cached.java b/src/main/java/org/redkale/cache/Cached.java index 80e98c80b..1418ee80f 100644 --- a/src/main/java/org/redkale/cache/Cached.java +++ b/src/main/java/org/redkale/cache/Cached.java @@ -44,9 +44,7 @@ public @interface Cached { * 本地缓存过期时长, 0表示永不过期, -1表示不作本地缓存。
* 参数值支持方式:
* 100: 设置数值 - * 5*60: 乘法表达式,值为300 * ${env.cache.expires}: 读取系统配置项 - * #delays: 读取宿主对象的delays字段值作为值,字段类型必须是int、long数值类型 * * @return 过期时长 */ @@ -56,9 +54,7 @@ public @interface Cached { * 远程缓存过期时长, 0表示永不过期, -1表示不作远程缓存。
* 参数值支持方式:
* 100: 设置数值 - * 5*60: 乘法表达式,值为300 * ${env.cache.expires}: 读取系统配置项 - * #delays: 读取宿主对象的delays字段值作为值,字段类型必须是int、long数值类型 * * @return 过期时长 */ diff --git a/src/main/java/org/redkale/mq/MessageConext.java b/src/main/java/org/redkale/mq/MessageConext.java index df40a2289..c2d050370 100644 --- a/src/main/java/org/redkale/mq/MessageConext.java +++ b/src/main/java/org/redkale/mq/MessageConext.java @@ -13,6 +13,8 @@ import org.redkale.convert.json.JsonConvert; *

* 详情见: https://redkale.org * + * @see org.redkale.mq.MessageConsumer + * * @author zhangjx * * @since 2.8.0 diff --git a/src/main/java/org/redkale/mq/MessageConsumer.java b/src/main/java/org/redkale/mq/MessageConsumer.java index 29a8aeb6a..35c22d600 100644 --- a/src/main/java/org/redkale/mq/MessageConsumer.java +++ b/src/main/java/org/redkale/mq/MessageConsumer.java @@ -3,10 +3,10 @@ */ package org.redkale.mq; +import org.redkale.annotation.ClassDepends; import org.redkale.annotation.Component; import org.redkale.service.Local; import org.redkale.util.AnyValue; -import org.redkale.annotation.ClassDepends; /** * MQ消费器, 实现类必须标记{@link org.redkale.mq.ResourceConsumer} @@ -14,8 +14,11 @@ import org.redkale.annotation.ClassDepends; *

* 详情见: https://redkale.org * + * @see org.redkale.mq.MessageConext + * @see org.redkale.mq.ResourceConsumer + * * @author zhangjx - * @param 泛型 + * @param T * * @since 2.8.0 */ diff --git a/src/main/java/org/redkale/mq/ResourceProducer.java b/src/main/java/org/redkale/mq/ResourceProducer.java index 23e5ee8ba..9e950d150 100644 --- a/src/main/java/org/redkale/mq/ResourceProducer.java +++ b/src/main/java/org/redkale/mq/ResourceProducer.java @@ -14,6 +14,8 @@ import org.redkale.convert.ConvertType; *

* 详情见: https://redkale.org * + * @see org.redkale.mq.MessageProducer + * * @author zhangjx * * @since 2.8.0 diff --git a/src/main/java/org/redkale/schedule/Scheduled.java b/src/main/java/org/redkale/schedule/Scheduled.java index 8d4264644..6ec5cf167 100644 --- a/src/main/java/org/redkale/schedule/Scheduled.java +++ b/src/main/java/org/redkale/schedule/Scheduled.java @@ -52,9 +52,7 @@ public @interface Scheduled { * 延迟时间,支持参数配置、乘法表达式和对象字段值
* 参数值支持方式:
* 100: 设置数值 - * 5*60: 乘法表达式,值为300 * ${env.scheduling.fixedDelay}: 读取系统配置项 - * #delays: 读取宿主对象的delays字段值作为值,字段类型必须是int、long数值类型 * * 值大于0且fixedRate小于0则使用 ScheduledThreadPoolExecutor.scheduleWithFixedDelay * @@ -66,9 +64,7 @@ public @interface Scheduled { * 周期时间,支持参数配置、乘法表达式和对象字段值
* 参数值支持方式:
* 100: 设置数值 - * 5*60: 乘法表达式,值为300 * ${env.scheduling.fixedRate}: 读取系统配置项 - * #intervals: 读取宿主对象的intervals字段值作为值,字段类型必须是int、long数值类型 * * 值大于0则使用 ScheduledThreadPoolExecutor.scheduleAtFixedRate * @@ -80,9 +76,7 @@ public @interface Scheduled { * 起始延迟时间,支持参数配置、乘法表达式和对象字段值
* 参数值支持方式:
* 100: 设置数值 - * 5*60: 乘法表达式,值为300 * ${env.scheduling.initialDelay}: 读取系统配置项 - * #inits: 读取宿主对象的inits字段值作为值,字段类型必须是int、long数值类型 * * 值大于0且fixedRate和fixedDelay小于0则使用 ScheduledThreadPoolExecutor.schedule * diff --git a/src/main/java/org/redkale/schedule/spi/ScheduleManagerService.java b/src/main/java/org/redkale/schedule/spi/ScheduleManagerService.java index e0411dcb9..18068286f 100644 --- a/src/main/java/org/redkale/schedule/spi/ScheduleManagerService.java +++ b/src/main/java/org/redkale/schedule/spi/ScheduleManagerService.java @@ -6,7 +6,6 @@ package org.redkale.schedule.spi; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.ref.WeakReference; -import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.time.Duration; @@ -221,9 +220,9 @@ public class ScheduleManagerService implements ScheduleManager, Service { CronExpression cronExpr = CronExpression.parse(cron); return new CronTask(ref, name, method, cronExpr, zoneId); } else { - long fixedDelayLong = getLongValue(ref.get(), fixedDelay); - long fixedRateLong = getLongValue(ref.get(), fixedRate); - long initialDelayLong = getLongValue(ref.get(), initialDelay); + long fixedDelayLong = Long.parseLong(fixedDelay); + long fixedRateLong = Long.parseLong(fixedRate); + long initialDelayLong = Long.parseLong(initialDelay); return new FixedTask(ref, name, method, fixedDelayLong, fixedRateLong, initialDelayLong, timeUnit); } } @@ -270,46 +269,6 @@ public class ScheduleManagerService implements ScheduleManager, Service { 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 public int start(String scheduleName) { int c = 0; diff --git a/src/main/java/org/redkale/source/DataSource.java b/src/main/java/org/redkale/source/DataSource.java index 4c591f50f..bc04ebf81 100644 --- a/src/main/java/org/redkale/source/DataSource.java +++ b/src/main/java/org/redkale/source/DataSource.java @@ -164,7 +164,7 @@ public interface DataSource extends Resourcable { //-------------------------deleteAsync-------------------------- /** * 删除指定主键值的记录, 多对象必须是同一个Entity类且必须在同一张表中
- 等价SQL: DELETE FROM {table} WHERE {primary} IN {getValues.id}
+ * 等价SQL: DELETE FROM {table} WHERE {primary} IN {getValues.id}
* * @param 泛型 * @param entitys Entity对象 @@ -175,7 +175,7 @@ public interface DataSource extends Resourcable { /** * 删除指定主键值的记录, 多对象必须是同一个Entity类且必须在同一张表中
- 等价SQL: DELETE FROM {table} WHERE {primary} IN {getValues.id}
+ * 等价SQL: DELETE FROM {table} WHERE {primary} IN {getValues.id}
* * @param 泛型 * @param entitys Entity对象 @@ -191,7 +191,7 @@ public interface DataSource extends Resourcable { /** * 删除指定主键值的记录, 多对象必须是同一个Entity类且必须在同一张表中
- 等价SQL: DELETE FROM {table} WHERE {primary} IN {getValues.id}
+ * 等价SQL: DELETE FROM {table} WHERE {primary} IN {getValues.id}
* * @param 泛型 * @param entitys Entity对象 @@ -207,7 +207,7 @@ public interface DataSource extends Resourcable { /** * 删除指定主键值的记录, 多对象必须是同一个Entity类且必须在同一张表中
- 等价SQL: DELETE FROM {table} WHERE {primary} IN {getValues.id}
+ * 等价SQL: DELETE FROM {table} WHERE {primary} IN {getValues.id}
* * @param 泛型 * @param entitys Entity对象 @@ -218,7 +218,7 @@ public interface DataSource extends Resourcable { /** * 删除指定主键值的记录, 多对象必须是同一个Entity类且必须在同一张表中
- 等价SQL: DELETE FROM {table} WHERE {primary} IN {getValues.id}
+ * 等价SQL: DELETE FROM {table} WHERE {primary} IN {getValues.id}
* * @param 泛型 * @param entitys Entity对象 @@ -234,7 +234,7 @@ public interface DataSource extends Resourcable { /** * 删除指定主键值的记录, 多对象必须是同一个Entity类且必须在同一张表中
- 等价SQL: DELETE FROM {table} WHERE {primary} IN {getValues.id}
+ * 等价SQL: DELETE FROM {table} WHERE {primary} IN {getValues.id}
* * @param 泛型 * @param entitys Entity对象 diff --git a/src/main/java/org/redkale/util/Environment.java b/src/main/java/org/redkale/util/Environment.java index f3b04b065..a10c834d4 100644 --- a/src/main/java/org/redkale/util/Environment.java +++ b/src/main/java/org/redkale/util/Environment.java @@ -60,11 +60,25 @@ public class Environment implements java.io.Serializable { if (val == null || val.isBlank()) { 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}} - int pos2 = val.indexOf("}"); - int pos1 = val.lastIndexOf("${", pos2); - if (pos1 >= 0 && pos2 > 0) { - String key = val.substring(pos1 + 2, pos2); + //school_#{name}_${haha_${age}}_${bb}_#{dd} -> school_#{name}_xxx_xxx_#{dd} + if (startIndex >= 0 && endIndex > 0) { + String key = val.substring(startIndex + 2, endIndex); int pos3 = key.lastIndexOf(':'); String defVal = null; if (pos3 > 0) { @@ -77,13 +91,13 @@ public class Environment implements java.io.Serializable { String subVal = properties.getProperty(key); if (subVal != null) { 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 { for (Properties prop : envs) { subVal = prop.getProperty(key); if (subVal != null) { 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) { @@ -91,8 +105,6 @@ public class Environment implements java.io.Serializable { } 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; } diff --git a/src/main/java/org/redkale/util/MultiHashKey.java b/src/main/java/org/redkale/util/MultiHashKey.java index 71ecc1965..5ea86e86e 100644 --- a/src/main/java/org/redkale/util/MultiHashKey.java +++ b/src/main/java/org/redkale/util/MultiHashKey.java @@ -19,7 +19,7 @@ public interface MultiHashKey { public String keyFor(Object... args); /** - * key只支持带#{}的表达式, 且不能嵌套, 如:name_#{key_#{id}} + * key只支持带#{}的表达式, 且不能嵌套,错误示例:name_#{key_#{id}} * * @param paramNames 参数名 * @param key key表达式 diff --git a/src/main/java/org/redkale/util/MultiHashKeys.java b/src/main/java/org/redkale/util/MultiHashKeys.java index bc85daf97..c73b60d77 100644 --- a/src/main/java/org/redkale/util/MultiHashKeys.java +++ b/src/main/java/org/redkale/util/MultiHashKeys.java @@ -39,9 +39,15 @@ class MultiHashKeys { } sb.delete(0, sb.length()); paraming = true; + } else if (last == '\\') { + sb.deleteCharAt(sb.length() - 1); + sb.append(ch); } else { 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 == '}') { if (!paraming) { throw new RedkaleException(MultiHashKey.class.getSimpleName() + " parse error, key: " + key); diff --git a/src/test/java/org/redkale/test/util/EnvironmentTest.java b/src/test/java/org/redkale/test/util/EnvironmentTest.java new file mode 100644 index 000000000..e3e00e38e --- /dev/null +++ b/src/test/java/org/redkale/test/util/EnvironmentTest.java @@ -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); + } +}