java动态选择要执行的类

java动态选择要执行的类,java,parsing,dynamic,reflection,classloader,Java,Parsing,Dynamic,Reflection,Classloader,我很确定这对专家来说是很基本的,但对我来说,作为一个新手,这让我很难接受 我有3个解析器,每个都有自己的功能,将来还会有更多的解析器。现在我要做的是:我希望我的应用程序在运行时根据要出现的页面选择正确的解析器 为了实现这一点,我做了以下工作:我有一个接口(IWebParser): 公共接口IWebParser{ 公共抽象对象执行(字符串页、URL); 公共摘要列表解析(字符串页、URL、列表标记); 公共抽象布尔canExecute(URL); } 我的每个解析器都实现了这个接口。我有另一个名

我很确定这对专家来说是很基本的,但对我来说,作为一个新手,这让我很难接受

我有3个解析器,每个都有自己的功能,将来还会有更多的解析器。现在我要做的是:我希望我的应用程序在运行时根据要出现的页面选择正确的解析器

为了实现这一点,我做了以下工作:我有一个接口(IWebParser):

公共接口IWebParser{
公共抽象对象执行(字符串页、URL);
公共摘要列表解析(字符串页、URL、列表标记);
公共抽象布尔canExecute(URL);
}
我的每个解析器都实现了这个接口。我有另一个名为ParserControl的类,其中有一个submit方法(stringpage,URL)-每当有页面要解析时,我的程序总是调用这个方法。此类ParserControl从xml文件中获取可用的解析器,并尝试(在while语句中)是否有任何解析器可以解析相关页面。这是通过canExecute(URL)方法完成的。现在,在canExecute上接收到true后,我想执行特定的解析器

我的类ParserControl如下所示:

public class ParserControl {
    private static final Logger logger = Logger.getLogger("de.comlineag.snc.parser.ParserControl");
// the list of operational web parser as taken from the properties file is stored within this structure
private static List<IWebParser> webParser; 
// the ParserControl instance - used during instantiation of the class and later to retrieve the list 
private static ParserControl pc = null;

// ParserControl is not to be directly instantiated by other classes
private ParserControl() {
    try {
        webParser = getAllParser();
    } catch (XPathExpressionException | IOException
            | ParserConfigurationException | SAXException e) {
        logger.error("EXCEPTION :: error during parser execution " + e.getMessage());
        e.printStackTrace();
    }
};

// Static 'instance' method - this method is called every time
// the submit method is called but can also be called implicitely to get
// an instance of ParserControl
public static ParserControl getInstance() throws XPathExpressionException, ParserConfigurationException, SAXException, IOException {
    if (pc == null) {pc = new ParserControl();}
    return pc;
}


public static List<SimpleWebPosting> submit(String page, URL url, ArrayList<String> tTerms) throws XPathExpressionException, ParserConfigurationException, SAXException, IOException{
    logger.trace("ParserControl called");
    pc = getInstance();

    while (pc.webParser.iterator().hasNext()) {
        logger.trace("trying parser " + pc.webParser.iterator().getClass().getSimpleName().toString());
        if (((IWebParser) pc.webParser.iterator().getClass().getClassLoader()).canExecute(url)) {
            return ((IWebParser) pc.webParser.iterator().getClass().getClassLoader()).parse(page, url, tTerms);
        } else {
            logger.trace("parser " + pc.webParser.iterator().getClass().getSimpleName().toString() + " returned false to canExecute()" );
        }
    }

    return null;
}


// retrieves all configured parser from the properties file and creates the parser list 
@SuppressWarnings("unchecked")
private <T> ArrayList<T> getAllParser() throws IOException, ParserConfigurationException, SAXException, XPathExpressionException {
    String fileName = "webapp/WEB-INF/properties/webparser.xml";
    ArrayList<T> ar = new ArrayList<T>();

    File file = new File(fileName);
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    DocumentBuilder db = dbf.newDocumentBuilder();
    Document doc = db.parse(file);

    XPathFactory xPathfactory = XPathFactory.newInstance();
    XPath xpath = xPathfactory.newXPath();

    String expression = "//parser[@type='webparser']/value";
    NodeList nodeList= (NodeList) xpath.compile(expression).evaluate(doc, XPathConstants.NODESET);
    for (int i = 0 ; i < nodeList.getLength() ; i++) {
        ar.add((T) nodeList.item(i).getTextContent());
        logger.trace("found parser " + nodeList.item(i).getTextContent().toString() + " in configuration file " + fileName);
    }
    return ar;
}
}
公共类解析控件{
私有静态最终记录器Logger=Logger.getLogger(“de.comlineag.snc.parser.ParserControl”);
//从属性文件中获取的可操作web解析器列表存储在此结构中
私有静态列表网页源;
//ParserControl实例-在类实例化期间以及以后检索列表时使用
专用静态ParserControl pc=null;
//ParserControl不能由其他类直接实例化
私有ParserControl(){
试一试{
WebPasser=getAllParser();
}catch(XPathExpressionException | IOException
|ParserConfiguration异常(SAXE异常){
error(“异常::解析器执行期间出错”+e.getMessage());
e、 printStackTrace();
}
};
//静态“实例”方法-每次调用此方法
//已调用submit方法,但也可以隐式调用以获取
//ParserControl的一个实例
公共静态ParserControl getInstance()抛出XPathExpressionException、ParserConfiguration异常、SAXException、IOException{
如果(pc==null){pc=new ParserControl();}
返回pc;
}
公共静态列表提交(字符串页、URL URL、ArrayList tTerms)抛出XPathExpressionException、ParserConfiguration异常、SAXException、IOException{
trace(“调用ParserControl”);
pc=getInstance();
while(pc.webpasser.iterator().hasNext()){
trace(“正在尝试解析器”+pc.webParser.iterator().getClass().getSimpleName().toString());
if(((IWebParser)pc.webParser.iterator().getClass().getClassLoader()).canExecute(url)){
return((IWebParser)pc.webParser.iterator().getClass().getClassLoader()).parse(页面、url、tTerms);
}否则{
trace(“解析器”+pc.webpasser.iterator().getClass().getSimpleName().toString()+“返回false给canExecute()”;
}
}
返回null;
}
//从属性文件检索所有配置的解析器,并创建解析器列表
@抑制警告(“未选中”)
私有ArrayList getAllParser()引发IOException、ParserConfiguration Exception、SAXException、XPathExpressionException{
String fileName=“webapp/WEB-INF/properties/webpasser.xml”;
ArrayList ar=新的ArrayList();
文件=新文件(文件名);
DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance();
DocumentBuilder db=dbf.newDocumentBuilder();
文档doc=db.parse(文件);
XPathFactory XPathFactory=XPathFactory.newInstance();
XPath=xPathfactory.newXPath();
字符串表达式=“//解析器[@type='webpasser']/value”;
NodeList NodeList=(NodeList)xpath.compile(expression.evaluate(doc,XPathConstants.NODESET);
for(int i=0;i
现在,在这冗长的介绍之后,我的问题是:在执行此操作时,我不能实例化解析器类,而是得到一个NullPointerException。while循环中的logger.trace返回以下内容:

TRACE ParserControl - trying parser Itr   <--- I would expect the class name here!!!
    ERROR SimpleWebCrawler - WEBCRAWLER-Crawler Exception java.lang.NullPointerException

TRACE ParserControl-tryingparser Itr这里发生了一些奇怪的事情。我看到的问题:

  • 您得到了某种单例设计模式,但仍然使用静态变量
  • 您使用的迭代器是错误的
  • 在泛型不需要的地方有泛型
  • 您的
    IWebParser
    接口可以返回一个
    布尔值,该值可以为空。它应该能够返回null吗?或者它应该是一个基本类型(
    boolean
    )。如果它返回null,并且在If语句中有它,那么您将得到一个NPE。例如:
    Boolean b=null;如果(b){}//NPE
修正:

  • webpasser
    变量中删除
    static
  • getAllParser
    中去掉泛型,这样构造函数将读取
    List getAllParser()
    (您也可以看到,我将
    ArrayList
    替换为
    List
  • 修复迭代器的使用,现在获取迭代器的
    ClassLoader
    ,并尝试将其转换为
    IWebParser
    ,显然是行不通的。这是循环的工作版本,正如您所看到的,我在外部声明了迭代器,并使用
    .next()
    在循环中获取下一个
    IWebParser

Iterator it=pc.webpasser.Iterator();
while(it.hasNext()){
IWebParser=it.next();
trace(“正在尝试解析器”+parser.getClass().getSimpleName().toString());
if(parser.canExecute(url)){
返回parser.parse(第页
TRACE ParserControl - trying parser Itr   <--- I would expect the class name here!!!
    ERROR SimpleWebCrawler - WEBCRAWLER-Crawler Exception java.lang.NullPointerException
Iterator<IWebParser> it = pc.webParser.iterator();
while (it.hasNext()) {
    IWebParser parser = it.next();
    logger.trace("trying parser " + parser.getClass().getSimpleName().toString());
    if (parser.canExecute(url)) {
        return parser.parse(page, url, tTerms);
    } else {
        logger.trace("parser " + parser.getClass().getSimpleName().toString() + " returned false to canExecute()" );
    }
}