REQ-2135: 提供更加强大的模版内容解析
This commit is contained in:
parent
c3042796a5
commit
8bfdc54d20
@ -93,6 +93,7 @@ import com.alibaba.fastjson.JSONObject;
|
|||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
||||||
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
|
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -785,6 +786,9 @@ public class PendingMessageNewServiceImpl implements PendingMessageNewService {
|
|||||||
.orElse(null);
|
.orElse(null);
|
||||||
// 解析并替换掉路由地址中的动态参数变量
|
// 解析并替换掉路由地址中的动态参数变量
|
||||||
JSONObject routerParam = JSONObjectUtil.parseObject(adapter.getRouterParams());
|
JSONObject routerParam = JSONObjectUtil.parseObject(adapter.getRouterParams());
|
||||||
|
routerParam.put(MessageRouterUtil.CTX, ImmutableMap.of(
|
||||||
|
"business", adapter.getTodoBusiness(),
|
||||||
|
"todo", adapter.getTodo()));
|
||||||
JSONObject authParam = new JSONObject();
|
JSONObject authParam = new JSONObject();
|
||||||
if (!routerParam.containsKey("ouId")) {
|
if (!routerParam.containsKey("ouId")) {
|
||||||
authParam.put("ouId", adapter.getOuId());
|
authParam.put("ouId", adapter.getOuId());
|
||||||
|
|||||||
@ -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.TodoType;
|
||||||
import cn.axzo.msg.center.service.enums.YesOrNo;
|
import cn.axzo.msg.center.service.enums.YesOrNo;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author yanglin
|
* @author yanglin
|
||||||
*/
|
*/
|
||||||
|
@Getter
|
||||||
public class TodoRecordAdapter implements PendingRecordAdapter {
|
public class TodoRecordAdapter implements PendingRecordAdapter {
|
||||||
|
|
||||||
private final TodoBusiness business;
|
private final TodoBusiness business;
|
||||||
@ -226,4 +228,9 @@ public class TodoRecordAdapter implements PendingRecordAdapter {
|
|||||||
public Boolean isRead() {
|
public Boolean isRead() {
|
||||||
return getState() == PendingMessageStateEnum.READ;
|
return getState() == PendingMessageStateEnum.READ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TodoBusiness getTodoBusiness() {
|
||||||
|
return business;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -47,6 +47,7 @@ import java.util.stream.Collectors;
|
|||||||
public final class MessageRouterUtil {
|
public final class MessageRouterUtil {
|
||||||
|
|
||||||
public static final String DETAIL_ROUTER_DESC = "详情";
|
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) {
|
private static String concatRouterParam(String originalUrl, JSONObject routerParam) {
|
||||||
if (routerParam.isEmpty()) {
|
JSONObject copy = new JSONObject(routerParam);
|
||||||
|
copy.remove(CTX);
|
||||||
|
if (copy.isEmpty()) {
|
||||||
return originalUrl;
|
return originalUrl;
|
||||||
}
|
}
|
||||||
StringBuilder paramBuilder = new StringBuilder();
|
StringBuilder paramBuilder = new StringBuilder();
|
||||||
for (Map.Entry<String, Object> entry : routerParam.entrySet()) {
|
for (Map.Entry<String, Object> entry : copy.entrySet()) {
|
||||||
if (originalUrl.contains(entry.getKey() + "=")) {
|
if (originalUrl.contains(entry.getKey() + "=")) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,6 +19,10 @@
|
|||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework</groupId>
|
||||||
|
<artifactId>spring-expression</artifactId>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cn.axzo.framework</groupId>
|
<groupId>cn.axzo.framework</groupId>
|
||||||
<artifactId>axzo-auth-spring-boot-starter</artifactId>
|
<artifactId>axzo-auth-spring-boot-starter</artifactId>
|
||||||
|
|||||||
@ -1,11 +1,18 @@
|
|||||||
package cn.axzo.msg.center.common.utils;
|
package cn.axzo.msg.center.common.utils;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import cn.axzo.basics.common.exception.ServiceException;
|
||||||
import org.apache.ibatis.ognl.NullHandler;
|
import com.alibaba.fastjson.JSON;
|
||||||
import org.apache.ibatis.ognl.OgnlRuntime;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.ibatis.parsing.GenericTokenParser;
|
import org.apache.ibatis.builder.BuilderException;
|
||||||
import org.apache.ibatis.parsing.TokenHandler;
|
import org.springframework.context.expression.MapAccessor;
|
||||||
import org.apache.ibatis.scripting.xmltags.OgnlCache;
|
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;
|
import java.util.Map;
|
||||||
|
|
||||||
@ -14,59 +21,53 @@ import java.util.Map;
|
|||||||
*
|
*
|
||||||
* @author yanglin
|
* @author yanglin
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
public class TemplateParser {
|
public class TemplateParser {
|
||||||
|
|
||||||
static {
|
|
||||||
OgnlRuntime.setNullHandler(Map.class, new MapPropertyHandler());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String parseNumberSign(String expression, Object root) {
|
public static String parseNumberSign(String expression, Object root) {
|
||||||
if (expression == null || root == null)
|
return parseImpl("#{", "}", expression, root);
|
||||||
return expression;
|
|
||||||
GenericTokenParser parser = new GenericTokenParser("#{", "}", new OgnlTokenHandler(root));
|
|
||||||
return parser.parse(expression);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String parseDollarSign(String expression, Object 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)
|
if (expression == null || root == null)
|
||||||
return expression;
|
return expression;
|
||||||
GenericTokenParser parser = new GenericTokenParser("${", "}", new OgnlTokenHandler(root));
|
try {
|
||||||
return parser.parse(expression);
|
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 NullableMapAccessor extends MapAccessor {
|
||||||
private static class OgnlTokenHandler implements TokenHandler {
|
|
||||||
|
|
||||||
private final Object root;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String handleToken(String content) {
|
public boolean canRead(@NonNull EvaluationContext context, Object target, @NonNull String name) {
|
||||||
Object value = OgnlCache.getValue(content, root);
|
return target instanceof Map;
|
||||||
return value == null ? "" : String.valueOf(value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class MapPropertyHandler implements NullHandler {
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object nullMethodResult(Map context, Object target, String methodName, Object[] args) {
|
@NonNull
|
||||||
return null;
|
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -102,4 +102,12 @@ public interface PendingRecordAdapter {
|
|||||||
default Long getPromoterOuId() {
|
default Long getPromoterOuId() {
|
||||||
return 0L;
|
return 0L;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default Todo getTodo() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
default TodoBusiness getTodoBusiness() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user