重新发明轮子——解析xml并实例化类_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > 重新发明轮子——解析xml并实例化类

重新发明轮子——解析xml并实例化类

 2015/3/11 21:16:00  bylijinnan  程序员俱乐部  我要评论(0)
  • 摘要:需求如图:说明:blackListFilter要等envFilter完成后才能开始执行statisticFilter可以和envFilter同时开始执行ruleEngineFilter要等blackListFilter和statisticFilter都执行完之后才能开始执行所有的xxFilter都是Filter的子类xml配置文件filters.xml:<?xmlversion="1.0"encoding="UTF-8"?><channels><
  • 标签:实例 XML 解析
需求如图:



说明:
blackListFilter要等envFilter完成后才能开始执行
statisticFilter可以和envFilter同时开始执行
ruleEngineFilter要等blackListFilter和statisticFilter都执行完之后才能开始执行
所有的xxFilter都是Filter的子类

xml配置文件filters.xml:
class="java"><?xml version="1.0" encoding="UTF-8"?>
<channels>
    <channel>
        <id>loginChannel</id>
        <filterInfo>
            <id>envFilter</id>
            <clazz>com.ljn.risk.front.filter.EnvFilter</clazz>
        </filterInfo>

        <filterInfo>
            <id>blackListFilter</id>
            <clazz>com.ljn.risk.front.filter.BlacklistFilter</clazz>
            <dependency>envFilter</dependency>
            <returnNeeded>true</returnNeeded>
            <returnOrder>1</returnOrder>
        </filterInfo>
        <filterInfo>
            <id>statisticFilter</id>
            <clazz>com.ljn.risk.front.filter.StatisticFilter</clazz>
        </filterInfo>
        <filterInfo>
            <id>ruleEngineFilter</id>
            <clazz>com.ljn.risk.front.filter.RuleEngineFilter</clazz>
            <dependency>blackListFilter</dependency>
            <dependency>statisticFilter</dependency>
            <returnNeeded>true</returnNeeded>
            <returnOrder>2</returnOrder>
        </filterInfo>
    </channel>

</channels>


为什么会有returnNeeded和returnOrder?
我们的架构是,在一个方法调用里,需要多线程异步执行上述Filter,其中blackListFilter可以提前返回,也就是在一定条件下,向调用方返回blackListFilter的执行结果,但仍然会执行ruleEngineFilter;否则,等待ruleEngineFilter的执行结果。
returnNeeded表示是否可以提前返回,returnOrder表示顺序(当中间有多个Filter可以提前回时,需要指定优先级)。

解析xml时用JAXB
代码:
public class FilterLoader {

    private static final Logger logger = LoggerFactory.getLogger(FilterLoader.class);

    //key是channelId,values是该channel下所有Filter(已实例化)
    private static Map<String, List<Filter>> channelToFiltersMap;

    private static Channels channels ;

    static {
        reload();
    }

    public static List<Filter> getFilters(String channelId) {
        if (channelToFiltersMap == null){
            reload();
        }
        return channelToFiltersMap.get(channelId);
    }

    private static void reload() {
        try {
            channelToFiltersMap = new HashMap<String, List<Filter>>();

            //lib目录
            URL url = FilterLoader.class.getResource("/");

            String packageName = FilterLoader.class.getPackage().getName();
            String location = FilenameUtils.concat(url.getPath(), packageName.replace(".", "/"));
            String filePath = FilenameUtils.concat(location, "filters.xml");
            File file = new File(filePath);
            JAXBContext jaxbContext = JAXBContext.newInstance(Channels.class);
            Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
            channels = (Channels) jaxbUnmarshaller.unmarshal(file);
            instanceAll();
            logger.info("load and init filter ok");
        } catch (Exception e) {
            logger.error("fail", e);
        }
    }

    private static void instanceAll() throws Exception {

        List<Channel> channelList = channels.getChannels();

        for (Channel channel : channelList) {
            channelToFiltersMap.put(channel.getId(), instanceFilters(channel));
        }
    }

    private static List<Filter> instanceFilters(Channel channel) throws Exception {
        Map<String, Filter> idToFilterMap = new HashMap<String, Filter>();
        for (FilterInfo filterInfo : channel.getFilterInfos()) {
            initFilter(channel.getId(), filterInfo, idToFilterMap);
        }
        ArrayList<Filter> list = new ArrayList<Filter>();
        list.addAll(idToFilterMap.values());
        return list;
    }

    //这里用到了递归,把已经实例化好的Filter保存在Map<String, Filter>
    private static void initFilter(final String channelId, final FilterInfo filterInfo, Map<String, Filter> maps) throws Exception {
        if (maps.get(filterInfo.getId()) != null) {
            return;
        }
        Filter filter = toFilter(filterInfo);
        List<String> dependencies = filterInfo.getDependencies();
        if (dependencies == null || dependencies.isEmpty()) {
            maps.put(filterInfo.getId(), filter);
        } else {
            for (String filterId : dependencies) {
                FilterInfo info = findFilterInfo(channelId, filterId);
                initFilter(channelId, info, maps);
                filter.addDependency(maps.get(filterId));
            }

            maps.put(filterInfo.getId(), filter);
        }

    }

    //根据channelId + filterId找到filters.xml里定义的FilterInfo。可以考虑保存在map里,这样查找速度就快了
    private static FilterInfo findFilterInfo(String channelId, String filterId) {
        List<Channel> channelList = channels.getChannels();
        Channel channel = null;
        for (Channel c : channelList) {
            if (c.getId().equals(channelId)) {
                channel = c;
                break;
            }
        }
        if (channel != null) {
            List<FilterInfo> filterInfos = channel.getFilterInfos();
            for (FilterInfo f : filterInfos) {
                if (f.getId().equals(filterId)) {
                    return f;
                }
            }
        }
        return null;
    }


    private static Filter toFilter(FilterInfo filterInfo) throws Exception {
    	String filterId = filterInfo.getId();
    	String clazz = filterInfo.getClazz();
    	int returnOrder = filterInfo.getReturnOrder();
    	boolean returnNeeded = filterInfo.isReturnNeeded();

    	Filter filter = (Filter) Class.forName(clazz).newInstance();
    	filter.setId(filterId);
    	filter.setReturnOrder(returnOrder);
    	filter.setReturnNeeded(returnNeeded);

    	return filter;

    }

    public static void main(String[] args) {
    	for (Entry<String, List<Filter>> item : channelToFiltersMap.entrySet()) {
    		System.out.println("channelId=" + item.getKey() + ", its filters are:");
    		for (Filter filter : item.getValue()) {
    			System.out.println(filter);
    		}
    	}
        //System.out.println(channelToFiltersMap);
    }
}


输出:
channelId=loginChannel, its filters are:
Filter [id=ruleEngineFilter, returnNeeded=true, returnOrder=2, dependencies=[Filter [id=blackListFilter, returnNeeded=true, returnOrder=1, dependencies=[Filter [id=envFilter, returnNeeded=false, returnOrder=0, dependencies=null]]], Filter [id=statisticFilter, returnNeeded=false, returnOrder=0, dependencies=null]]]
Filter [id=statisticFilter, returnNeeded=false, returnOrder=0, dependencies=null]
Filter [id=blackListFilter, returnNeeded=true, returnOrder=1, dependencies=[Filter [id=envFilter, returnNeeded=false, returnOrder=0, dependencies=null]]]
Filter [id=envFilter, returnNeeded=false, returnOrder=0, dependencies=null]


可见,得到了如期的结果。其实,这个解析xml并实例化类的思路,跟spring是一样的。当然,spring做得更强大和全面。这里算是重新发明了轮子,也算练手吧。

上述代码用到的其他类:
@XmlRootElement(name = "channel")
@XmlAccessorType (XmlAccessType.FIELD)
public class Channel {

    private String id;

    @XmlElement(name = "filterInfo")
    private List<FilterInfo> filterInfos;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public List<FilterInfo> getFilterInfos() {
        return filterInfos;
    }

    public void setFilterInfos(List<FilterInfo> filterInfos) {
        this.filterInfos = filterInfos;
    }

    @Override
    public String toString() {
        return "Channel [id=" + id + ", filterInfos=" + filterInfos + "]";
    }

}



@XmlRootElement(name = "channels")
@XmlAccessorType(XmlAccessType.FIELD)
public class Channels {
    @XmlElement(name = "channel")
    private List<Channel> channels;

    public List<Channel> getChannels() {
        return channels;
    }

    public void setChannels(List<Channel> channels) {
        this.channels = channels;
    }

    @Override
    public String toString() {
        return "Channels [channels=" + channels + "]";
    }
}


@XmlRootElement(name = "filterInfo")
@XmlAccessorType(XmlAccessType.FIELD)
public class FilterInfo {

    private String id;
    private String clazz;
    private boolean returnNeeded;
    private int returnOrder;
    @XmlElement(name = "dependency")
    private List<String> dependencies;

    public FilterInfo(String id, boolean returnNeeded, int returnOrder) {
        super();
        this.id = id;
        this.returnNeeded = returnNeeded;
        this.returnOrder = returnOrder;
    }

    public FilterInfo() {
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getClazz() {
        return clazz;
    }

    public void setClazz(String clazz) {
        this.clazz = clazz;
    }

    public boolean isReturnNeeded() {
        return returnNeeded;
    }

    public void setReturnNeeded(boolean returnNeeded) {
        this.returnNeeded = returnNeeded;
    }

    public int getReturnOrder() {
        return returnOrder;
    }

    public void setReturnOrder(int returnOrder) {
        this.returnOrder = returnOrder;
    }

    public List<String> getDependencies() {
        return dependencies;
    }

    public void setDependencies(List<String> dependencies) {
        this.dependencies = dependencies;
    }

    @Override
    public String toString() {
        return "FilterInfo [id=" + id + ", clazz=" + clazz + ", returnNeeded=" + returnNeeded + ", returnOrder=" + returnOrder + ", dependencies=" + dependencies + "]";
    }

}
  • 大小: 6.5 KB
  • 查看图片附件
发表评论
用户名: 匿名