本身实现的一个过滤器的例子

    工做中要开发一个小的功能,我并没用立刻去实现,而是想了想看看能不能作的更有扩展性一些。固然思考的结果有多是过分的设计了。java

     如今把功能要求简单描述一下,而后在说实现方法:node

     系统接受到一个XML格式的消息体,而后须要根据一些需求把XML消息作一些过滤,修改,而后存储起来。spring

     实现的大概思路就是用过滤器的思想再加上逻辑插件化。apache

     下面就是代码骨架:    dom

public interface XMLAdapter {
    public boolean update(XMLDocument targetDocument);
}

     上面的接口是咱们的逻辑要实现。XMLDocument 是XML用dom4j解析以后的类。相似于一个java bean。ide

import org.apache.log4j.Logger;

public class ExampleAdapter implements XMLAdapter {
    
	private String nodesValue;	
	private String nodeValue;
	private static Logger logger = Logger.getLogger(ExampleAdapter.class);
	

	@Override
	public boolean update(XMLDocument targetDocument) {
            //our logic is implemented here
	}
	

	public String getNodesValue() {
		return nodesValue;
	}

	public void setNodesValue(String nodesValue) {
		this.nodesValue = nodesValue;
	}

	public String getNodeValue() {
		return nodeValue;
	}

	public void setNodeValue(String nodeValue) {
		this.nodeValue = nodeValue;
	}
	
}

这是一个实现类。对XML的操做:过滤节点,删除节点,修改节点的工做都在update方法里面实现。这个类有两个成员。update方法里面用这两个成员来作一些逻辑。这里咱们用注入的方式来给这两个成员赋值。

下面是注入的一个简单实现:this

<?xml version="1.0" encoding="UTF-8"?>
<beans>
    <bean id="exampleAdapter" class="com.example.ExampleAdapter">
        <property name="nodesValue">
            <value>XXX</value>
        </property>
        <property name="nodeValue">
            <value>YYY</value>
        </property>
    </bean>
</beans>

对spring熟悉的人看到这个XML配置文件应该很熟悉了。下面是这个XML文件对应的工厂类。

import java.io.FileInputStream;
import java.io.InputStream;
import java.lang.reflect.Method;

import java.util.concurrent.ConcurrentHashMap;
import java.util.Iterator;
import java.util.Map;

import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.dom4j.Attribute;
public class AdapterFactory {

    private Map<String, Object> adapterMap = new ConcurrentHashMap<String, Object>();
    private static Logger logger = Logger.getLogger(AdapterFactory.class);
	
	/**
	 * init AdapterFactory. parse adapter.xml to bean map.
	 * @param filePath Adaptor configuration file path.
	 */
    public void init(String filePath) {
        if (filePath == null || filePath.length() == 0) {
            logger.warn("empty configuration file path and name!");
            return;
        }
        try {
            SAXReader reader = new SAXReader();
            InputStream ins = new FileInputStream(filePath);
            Document doc = reader.read(ins);
            Element root = doc.getRootElement();  
            Element attributeElement;
            for (Iterator i = root.elementIterator("bean"); i.hasNext();) {
		attributeElement = (Element) i.next();
                Attribute id = attributeElement.attribute("id");  
                Attribute cls = attributeElement.attribute("class");
               
                Class adaptor = Class.forName(cls.getText());
                java.beans.BeanInfo info = java.beans.Introspector.getBeanInfo(adaptor);
                java.beans.PropertyDescriptor[] pd = info.getPropertyDescriptors();
                Method mSet = null;
                Object obj = adaptor.newInstance();
               
                for (Iterator ite = attributeElement.elementIterator("property"); ite.hasNext();) {  
                    Element propertyElement = (Element) ite.next();
                    Attribute name = propertyElement.attribute("name");
                    String value = null;
                      
                    for (Iterator ite1 = propertyElement.elementIterator("value"); ite1.hasNext();) {
                        Element node = (Element) ite1.next();
                        value = node.getText();
                        break;
                    }
                      
                    for (int k = 0; k < pd.length; k++) {
                        if (pd[k].getName().equalsIgnoreCase(name.getText())) {
                            mSet = pd[k].getWriteMethod();
                            mSet.invoke(obj, value);
                        }
                    }
                }
                adapterMap.put(id.getText(), obj);
            }
        } catch (Exception e) {
            logger.warn("init AdaptorFactory failed", e);
        }
		
    }
	
    public Map<String, Object> getAdapterMap() {
        return adapterMap;
    }
}

这个类说白了就是经过反射把XML文件配置的类load到一个Map中。

 能够参考下面这篇blog对这个类的说明spa

http://blog.csdn.net/wwww1988600/article/details/7286887.net

这样经过AdapterFactory咱们就能够拿到全部的咱们配置的类。下面就是在咱们的主逻辑中把咱们XML配置的这些类调起来。这里有一个想法:当咱们有新需求时,在XML配置文件添加一些实现类时,咱们的主逻辑代码可不能够不修改?插件

因此就引入下面这个类:

import java.util.Map;
import org.apache.log4j.Logger;
public class ExampleFilterChain {
	
    private static Logger logger = Logger.getLogger(ExampleFilterChain.class);
    private static AdapterFactory adapterFactory;
    private static ExampleFilterChain filterChain ;
	
    private ExampleFilterChain(String filePath) {
        init(filePath);
    }

    public static synchronized ExampleFilterChain getInstance(String filePath) {
        if(filterChain == null) {
	    filterChain = new ExampleFilterChain(filePath);
	}
	return filterChain;
    }

    /**
     * 
     * @param filePath AdapterFactory configuration files
     */
	private void init(String filePath) {
	    adapterFactory = new AdapterFactory();
	    adapterFactory.init(filePath);
	}
	
	/**
	 * this method will issue all adapter instances which defined in adapter.xml
	 */
	public void filter(XMLDocument targetDocument){
	    Map<String,Object> maps = adapterFactory.getAdapterMap();
	    if(maps == null || maps.size() == 0){
                logger.info("can not find any adapter instances");
		return;
	    }
	    Object[] keys = maps.keySet().toArray();
	    for(Object key : keys){
	        ((XMLAdapter)maps.get(key)).update(target);
	    }
	}
}

这个类的做用就是初始化咱们的AdaperFactory。他有一个public方法:filter()。这个方法把咱们load进来的全部的实现类都执行一遍。这里留下一些问题:当一个实现类执行失败后,后面的实现类要不要继续执行,等等吧。之后在考虑。

下面的工做就简单了,在主逻辑里面调用这个ExampleFilterChain的filter方法就能够了。

private ExampleFilterChain chain = ExampleFilterChain.getInstance(adapter.xml");

.....
chain.filter(xmlDocument);
.....

OK。结束。

这种实现的一个好处是:当咱们有新的需求时,只要实现XMLAdaper接口,并把实现类配置到adapter.xml中就能够了。实现者不须要去修改主逻辑和其余代码。

相关文章
相关标签/搜索