zoukankan      html  css  js  c++  java
  • 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);
        }
    
    }
    
  • 相关阅读:
    Android 打开相册拍照选择多张图片显示
    Mac 打开、编辑 .bash_profile 文件
    Ionic app IOS 在Xcode 模拟运行 真机调试
    android studio 把 ionic 打包时修改应用名称、修改应用图标、修改启动画面,升级打包
    Android studio 运行打包 Ionic 项目
    ionic4 路由跳转、ionic4 路由跳转传值 NavController 返回上一页 、NavController 回到根
    Ionic4.x ion-refresher 下拉更新
    Ionic4.x ion-infinite-scroll 上拉分页加载更多
    Ionic4.x ion-infinite-scroll 上拉分页加载更多
    Ionic4.x Modal模态对话框以及 Modal 传值
  • 原文地址:https://www.cnblogs.com/itplay/p/12322315.html
Copyright © 2011-2022 走看看