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

需求如图:

[img]http://dl2.iteye.com/upload/attachment/0106/5987/e2f0d65f-6de7-3db0-aa20-38a501c53019.png[/img]

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

xml配置文件filters.xml:
<?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 + "]";
}

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值