需求如图:
说明:
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 + "]";
}
}
- 大小: 6.5 KB
分享到:
相关推荐
【决不重新发明轮子】这个概念源于创新策略中的一种智慧,即避免不必要的重复劳动,有效利用已有资源进行改进和优化。在IT行业中,这一理念尤为关键,因为技术更新迅速,不断有新的产品和服务出现,而大部分创新往往...
【小班科学——轮子】活动旨在引导幼儿通过观察、猜测和讲述,了解不同类型的车辆是由不同数量的轮子组成的,并在游戏中认识到轮子的主要功能——滚动。活动设计了一系列互动环节,帮助孩子们在轻松愉快的氛围中学习...
活动中,教师通过展示自行车,引导幼儿发现自行车快速行驶的秘密——轮子的存在,并寻找自行车上的轮子,包括脚蹬处的齿轮,让幼儿理解轮子在运动中的重要性。 2. **轮子的异同与分类**:在游戏环节,孩子们通过...
【了不起的轮子——小班科学教学内容】 在幼儿教育阶段,科学启蒙是非常重要的一个环节,它能够激发孩子们对周围世界的探索兴趣,培养他们的观察力和思考能力。本课件“了不起的轮子”旨在让小班的孩子们了解轮子的...
libxml2是由 GNOME 项目开发的一个强大的XML解析库,它提供了多种XML处理功能,包括解析、序列化、XPath查询、XInclude处理、XML Schema验证以及DTD处理等。libxml2库因其高效、跨平台的特性,在许多操作系统和应用...
【教案名称】:了不起的轮子——幼儿园教学设计 【教学目标】: 1. 让幼儿通过实际观察和互动,感知轮子...同时,通过添画轮子的环节,激发幼儿的创造力,使他们在快乐学习中认识并欣赏这个看似简单却至关重要的发明。
在IT行业中,"重新发明轮子"通常是指在已有成熟解决方案的情况下,重新设计或实现一个功能,这在面试中常用来考察候选人的基础理解、问题解决能力以及编程思维。本篇将围绕Go语言,深入探讨可能出现在面试中的相关...
【小班主题活动设计思路——不起的轮子】 在幼儿教育中,主题活动是一种有效的教学方法,它结合了多种学科,激发孩子们的兴趣,促进他们的全面发展。在这个名为“不起的轮子”的小班主题活动设计中,教师充分利用...
通过阅读博客文章"发明轮子之“红黑树 二”",我们可以期待作者对红黑树的深入解析,包括更复杂的操作如旋转和颜色调整,以及如何在实际编程中应用这些概念。"redblacktree"这个文件名可能是该系列教程的源代码示例...
"StopWatch:随博文重新发明轮子的游戏"这个项目就是一个很好的例子,它鼓励开发者通过实践来理解和掌握JavaScript中的时间管理与性能测试技巧。这篇博客文章的标题和描述暗示了作者希望通过一个有趣的编程游戏来帮助...
军刀 小型辅助框架,因此您不必担心小事并专注于代码背后的主要逻辑,而不必一遍又一遍地重新发明轮子。 有几个有用的基类和助手,如典型的保护类、序列化助手、参数解析器(例如静态主)、扩展方法的负载等等.........
【描述】中的内容简单直接,再次强调了这个项目的核心理念——避免"重新发明轮子",即不必要地从头开始创建已经存在的工具或功能。";)"符号暗示该项目可能以友好和轻松的方式呈现,易于理解和使用。 【标签】...
轮子是人类历史上的一项重大发明,极大地推动了交通运输和生产力的发展。在PPT的第一部分,讲述了原始人如何从滚动重物如圆木的过程中得到灵感,将滚木切割成轮子,从而减少了搬运的难度。这一创新体现了人类对工具...
造轮子的目的,不是去重复的发明轮子,而是实际的去动手制作轮子。把一些公认的算法,优秀的思想,用自己的方式表达一下,锻炼一下,让知识成为自己思想的一部分。而不总是去google去百度,xxx好还是zzz好,而是能够...
我的2cents 小而有用的工具和技术,可以节省您重新发明轮子:) 项目描述: Historytrigger:一种基于触发器的方法,用于在 cassandra 上实施历史记录或审计跟踪。
接着,展示不同类型的车辆模型,让孩子们找出共同点——轮子,并通过实际玩耍,理解轮子如何使玩具前进。通过图片展示,孩子们会发现不仅是交通工具,许多生活用品也依赖于轮子,从而拓宽他们的认知视野。 进一步,...
我现在知道,这听起来像是在重新发明轮子,与它的进化后代相比,这太糟糕了,但这只是一个旨在自动化移动应用安全评估的更大项目的一部分。 现在要能够使用转发器,您只需要安装mimtproxy python模块即可。 到那里...
Hutool是一款强大的Java工具类库,其设计目标是简化常见的开发任务,避免开发者重复编写通用的工具类。Hutool由" Hu"+"tool"组成,"Hu"来源于作者对前公司的致敬,"tool"代表工具,同时也巧妙地取了"糊涂"的谐音,...