diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/message/service/impl/PendingMessageNewServiceImpl.java b/inside-notices/src/main/java/cn/axzo/msg/center/message/service/impl/PendingMessageNewServiceImpl.java index 69d93b0b..945ff427 100644 --- a/inside-notices/src/main/java/cn/axzo/msg/center/message/service/impl/PendingMessageNewServiceImpl.java +++ b/inside-notices/src/main/java/cn/axzo/msg/center/message/service/impl/PendingMessageNewServiceImpl.java @@ -93,6 +93,7 @@ import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.support.SFunction; import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -785,6 +786,9 @@ public class PendingMessageNewServiceImpl implements PendingMessageNewService { .orElse(null); // 解析并替换掉路由地址中的动态参数变量 JSONObject routerParam = JSONObjectUtil.parseObject(adapter.getRouterParams()); + routerParam.put(MessageRouterUtil.CTX, ImmutableMap.of( + "business", adapter.getTodoBusiness(), + "todo", adapter.getTodo())); JSONObject authParam = new JSONObject(); if (!routerParam.containsKey("ouId")) { authParam.put("ouId", adapter.getOuId()); diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/message/service/todo/TodoRecordAdapter.java b/inside-notices/src/main/java/cn/axzo/msg/center/message/service/todo/TodoRecordAdapter.java index 87a2aac4..ca1b6347 100644 --- a/inside-notices/src/main/java/cn/axzo/msg/center/message/service/todo/TodoRecordAdapter.java +++ b/inside-notices/src/main/java/cn/axzo/msg/center/message/service/todo/TodoRecordAdapter.java @@ -13,12 +13,14 @@ import cn.axzo.msg.center.service.enums.PendingMessageStateEnum; import cn.axzo.msg.center.service.enums.TodoType; import cn.axzo.msg.center.service.enums.YesOrNo; import com.alibaba.fastjson.JSONObject; +import lombok.Getter; import java.util.Date; /** * @author yanglin */ +@Getter public class TodoRecordAdapter implements PendingRecordAdapter { private final TodoBusiness business; @@ -226,4 +228,9 @@ public class TodoRecordAdapter implements PendingRecordAdapter { public Boolean isRead() { return getState() == PendingMessageStateEnum.READ; } + + @Override + public TodoBusiness getTodoBusiness() { + return business; + } } diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/utils/MessageRouterUtil.java b/inside-notices/src/main/java/cn/axzo/msg/center/utils/MessageRouterUtil.java index 84e102f1..b923431a 100644 --- a/inside-notices/src/main/java/cn/axzo/msg/center/utils/MessageRouterUtil.java +++ b/inside-notices/src/main/java/cn/axzo/msg/center/utils/MessageRouterUtil.java @@ -47,6 +47,7 @@ import java.util.stream.Collectors; public final class MessageRouterUtil { public static final String DETAIL_ROUTER_DESC = "详情"; + public static final String CTX = "ctx"; /** * 获取业务详情路由策略 @@ -227,11 +228,13 @@ public final class MessageRouterUtil { } private static String concatRouterParam(String originalUrl, JSONObject routerParam) { - if (routerParam.isEmpty()) { + JSONObject copy = new JSONObject(routerParam); + copy.remove(CTX); + if (copy.isEmpty()) { return originalUrl; } StringBuilder paramBuilder = new StringBuilder(); - for (Map.Entry entry : routerParam.entrySet()) { + for (Map.Entry entry : copy.entrySet()) { if (originalUrl.contains(entry.getKey() + "=")) { continue; } diff --git a/msg-center-common/pom.xml b/msg-center-common/pom.xml index c33a1671..1377b619 100644 --- a/msg-center-common/pom.xml +++ b/msg-center-common/pom.xml @@ -19,6 +19,10 @@ + + org.springframework + spring-expression + cn.axzo.framework axzo-auth-spring-boot-starter diff --git a/msg-center-common/src/main/java/cn/axzo/msg/center/common/utils/TemplateParser.java b/msg-center-common/src/main/java/cn/axzo/msg/center/common/utils/TemplateParser.java index 0e1eaf16..ec5ea245 100644 --- a/msg-center-common/src/main/java/cn/axzo/msg/center/common/utils/TemplateParser.java +++ b/msg-center-common/src/main/java/cn/axzo/msg/center/common/utils/TemplateParser.java @@ -1,11 +1,18 @@ package cn.axzo.msg.center.common.utils; -import lombok.RequiredArgsConstructor; -import org.apache.ibatis.ognl.NullHandler; -import org.apache.ibatis.ognl.OgnlRuntime; -import org.apache.ibatis.parsing.GenericTokenParser; -import org.apache.ibatis.parsing.TokenHandler; -import org.apache.ibatis.scripting.xmltags.OgnlCache; +import cn.axzo.basics.common.exception.ServiceException; +import com.alibaba.fastjson.JSON; +import lombok.extern.slf4j.Slf4j; +import org.apache.ibatis.builder.BuilderException; +import org.springframework.context.expression.MapAccessor; +import org.springframework.expression.EvaluationContext; +import org.springframework.expression.Expression; +import org.springframework.expression.TypedValue; +import org.springframework.expression.common.TemplateParserContext; +import org.springframework.expression.spel.standard.SpelExpressionParser; +import org.springframework.expression.spel.support.ReflectivePropertyAccessor; +import org.springframework.expression.spel.support.StandardEvaluationContext; +import org.springframework.lang.NonNull; import java.util.Map; @@ -14,59 +21,53 @@ import java.util.Map; * * @author yanglin */ +@Slf4j public class TemplateParser { - static { - OgnlRuntime.setNullHandler(Map.class, new MapPropertyHandler()); - } - public static String parseNumberSign(String expression, Object root) { - if (expression == null || root == null) - return expression; - GenericTokenParser parser = new GenericTokenParser("#{", "}", new OgnlTokenHandler(root)); - return parser.parse(expression); + return parseImpl("#{", "}", expression, root); } public static String parseDollarSign(String expression, Object root) { + return parseImpl("${", "}", expression, root); + } + + @SuppressWarnings("SameParameterValue") + private static String parseImpl(String openToken, String closeToken, String expression, Object root) { if (expression == null || root == null) return expression; - GenericTokenParser parser = new GenericTokenParser("${", "}", new OgnlTokenHandler(root)); - return parser.parse(expression); + try { + StandardEvaluationContext evalContext = new StandardEvaluationContext(root); + evalContext.addPropertyAccessor(new NullableMapAccessor()); + evalContext.addPropertyAccessor(new ReflectivePropertyAccessor()); + TemplateParserContext templateContext = new TemplateParserContext(openToken, closeToken); + Expression exp = new SpelExpressionParser().parseExpression(expression, templateContext); + return exp.getValue(evalContext, String.class); + } catch (BuilderException e) { + log.warn("无效的模版内容, 请检查格式是否正确. expression={}, value={}", + expression, JSON.toJSONString(root), e); + throw new ServiceException(String.format("无效的模版内容, 请检查格式是否正确. expression=%s, value=%s", + expression, JSON.toJSONString(root))); + } } - @RequiredArgsConstructor - private static class OgnlTokenHandler implements TokenHandler { - - private final Object root; + private static class NullableMapAccessor extends MapAccessor { @Override - public String handleToken(String content) { - Object value = OgnlCache.getValue(content, root); - return value == null ? "" : String.valueOf(value); + public boolean canRead(@NonNull EvaluationContext context, Object target, @NonNull String name) { + return target instanceof Map; } - } - - private static class MapPropertyHandler implements NullHandler { - @Override - public Object nullMethodResult(Map context, Object target, String methodName, Object[] args) { - return null; + @NonNull + public TypedValue read(@NonNull EvaluationContext context, Object target, @NonNull String name) { + Map map = (Map) target; + Object value = map.get(name); + if (value == null) + return TypedValue.NULL; + return new TypedValue(value); } - /** - * 支持流程的 [_PENDING_VARIABLES] 的写法. 只支持顶层的这种写法, 不然词法解析不了 - */ - @Override - public Object nullPropertyValue(Map context, Object target, Object property) { - if (target instanceof Map && property instanceof String) { - String key = (String) property; - String bracketsKey = String.format("[%s]", key.trim()); - if (((Map) target).containsKey(bracketsKey)) - return bracketsKey; - } - return null; - } } } \ No newline at end of file diff --git a/msg-center-domain/src/main/java/cn/axzo/msg/center/domain/entity/PendingRecordAdapter.java b/msg-center-domain/src/main/java/cn/axzo/msg/center/domain/entity/PendingRecordAdapter.java index 3de2df64..e58a307a 100644 --- a/msg-center-domain/src/main/java/cn/axzo/msg/center/domain/entity/PendingRecordAdapter.java +++ b/msg-center-domain/src/main/java/cn/axzo/msg/center/domain/entity/PendingRecordAdapter.java @@ -102,4 +102,12 @@ public interface PendingRecordAdapter { default Long getPromoterOuId() { return 0L; } + + default Todo getTodo() { + return null; + } + + default TodoBusiness getTodoBusiness() { + return null; + } } \ No newline at end of file