Spring Spel 解析工具类


import com.amp.base.exception.BusinessException;
import org.springframework.util.PropertyPlaceholderHelper;

import java.lang.reflect.Field;
import java.util.Date;
import java.util.Map;

/**
 * 占位符解析器
 *
 * @author system
 * @version 1.0.0
 * @date 2020-02-17 11:14
 */
public class PlaceholderResolver {

    private static final PropertyPlaceholderHelper defaultHelper = new PropertyPlaceholderHelper("${", "}");
    private static PlaceholderResolver defaultResolver = new PlaceholderResolver();

    private PropertyPlaceholderHelper propertyPlaceholderHelper;


    private PlaceholderResolver() {
        propertyPlaceholderHelper = defaultHelper;
    }

    private PlaceholderResolver(String placeholderPrefix, String placeholderSuffix) {
        propertyPlaceholderHelper = new PropertyPlaceholderHelper(placeholderPrefix, placeholderSuffix);
    }

    /**
     * 获取默认的占位符解析器,即占位符前缀为"${", 后缀为"}"
     *
     * @return
     */
    public static PlaceholderResolver getDefaultResolver() {
        return defaultResolver;
    }

    public static PlaceholderResolver getResolver(String placeholderPrefix, String placeholderSuffix) {
        return new PlaceholderResolver(placeholderPrefix, placeholderSuffix);
    }

    /**
     * 解析带有指定占位符的模板字符串
     * 如:content =  ${0}今年${1}岁<br/>
     * values = {"xiaoming", "18"}<br/>
     * result 小明今年18岁<br/>
     *
     * @param content 要解析的带有占位符的模板字符串
     * @param values  按照模板占位符索引位置设置对应的值
     * @return
     */
    public String resolve(String content, String... values) {
        return propertyPlaceholderHelper.replacePlaceholders(content, placeholderName -> {
            return values[Integer.valueOf(placeholderName)];
        });
    }

    /**
     * 解析带有指定占位符的模板字符串
     * 如:content =  ${0}今年${1}岁<br/>
     * values = {"xiaoming", "18"}<br/>
     * result 小明今年18岁<br/>
     *
     * @param content 要解析的带有占位符的模板字符串
     * @param values  按照模板占位符索引位置设置对应的值
     * @return
     */
    public String resolve(String content, Object[] values) {
        return propertyPlaceholderHelper.replacePlaceholders(content, placeholderName -> {
            return String.valueOf(values[Integer.valueOf(placeholderName)]);
        });
    }

    /**
     * 根据替换规则来替换指定模板中的占位符值
     *
     * @param content             要解析的字符串
     * @param placeholderResolver 解析规则回调
     * @return
     */
    public String resolveByRule(String content, PropertyPlaceholderHelper.PlaceholderResolver placeholderResolver) {
        return propertyPlaceholderHelper.replacePlaceholders(content, placeholderResolver);
    }

    /**
     * 替换模板中占位符内容,占位符的内容即为map key对应的值,key为占位符中的内容。<br/><br/>
     * 如:content = ${name}今年${age}岁<br/>
     * valueMap = name -> 小明; age -> 18<br/>
     * result 小明今年18岁<br/>
     *
     * @param content  模板内容。
     * @param valueMap 值映射
     * @return 替换完成后的字符串。
     */
    public String resolveByMap(String content, final Map<String, Object> valueMap) {
        return propertyPlaceholderHelper.replacePlaceholders(content, placeholderName -> {
            return String.valueOf(valueMap.get(placeholderName));
        });
    }

    /**
     * 根据对象中字段路径(即类似js访问对象属性值)替换模板中的占位符 <br/><br/>
     * 如 content = product:${id}:detail:${detail.id} <br/>
     * obj = Product.builder().id(1).detail(Detail.builder().id(2).build()).build(); <br/>
     * 经过解析返回 product:1:detail:2 <br/>
     *
     * @param content 要解析的内容
     * @param obj     填充解析内容的对象(如果是基本类型,则所有占位符都替换为当前基本类型)
     * @return
     */
    public String resolveByObject(String content, final Object obj) {
        if (obj instanceof Map) {
            return resolveByMap(content, (Map) obj);
        }
        return propertyPlaceholderHelper.replacePlaceholders(content, placeholderName -> {
            return String.valueOf(getValueByFieldPath(obj, placeholderName));
        });
    }

    /**
     * 获取指定对象中指定字段路径的值
     * $(user.name)
     *
     * @param obj       取值对象
     * @param fieldPath 字段路径(形如 user.name)
     * @return
     */
    private Object getValueByFieldPath(Object obj, String fieldPath) {
        String[] fieldNames = fieldPath.split("\\.");
        Object result = null;
        for (String fieldName : fieldNames) {
            result = getFieldValue(obj, fieldName);
            if (result == null) {
                throw new BusinessException(fieldName + "为空!");
            }
            obj = result;
        }
        return result;
    }

    private Object getFieldValue(Object obj, String fieldName) {
        Class clazz = obj.getClass();
        if (isBaseType(clazz)) {
            return obj;
        }
        while (clazz != Object.class && clazz != null) {
            try {
                Field field = clazz.getDeclaredField(fieldName);
                field.setAccessible(true);
                return field.get(obj);
            } catch (NoSuchFieldException e) {
                clazz = clazz.getSuperclass();
            } catch (IllegalAccessException e) {
                throw new BusinessException("无法访问 " + fieldName);
            }
        }
        throw new IllegalStateException(fieldName + "字段不存在!");

    }

    /**
     * 判断class是否为常用类型
     *
     * @param clazz
     * @return
     */
    private boolean isBaseType(Class clazz) {
        return Enum.class.isAssignableFrom(clazz) || CharSequence.class.isAssignableFrom(clazz)
                || Number.class.isAssignableFrom(clazz) || Date.class.isAssignableFrom(clazz);
    }

}
posted @ 2020-02-17 16:23  是谁扭曲了时空  阅读(1626)  评论(0编辑  收藏  举报