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);
    }

}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM