Heim >Java >javaLernprogramm >Apache Commons Digester

Apache Commons Digester

巴扎黑
巴扎黑Original
2017-06-26 09:17:071532Durchsuche

Vorwort

Der vorherige Artikel gab eine grundlegende Einführung in Digester, und wir haben die grundlegende Verwendung von Digester bereits verstanden. Als Nächstes werden wir die damit verbundenen Funktionen weiter erlernen.

  1. Regelmodulbindung, Vervollständigen Sie die Vorbindung von Regeln durch Definieren einer RulesModule-Schnittstellenimplementierungsklasse und verwenden Sie sie zur Laufzeit wieder

  2. Asynchrone Analyse xml

  3. Variablen in XML analysieren, z. B. ${sys.user}

  4. Verwenden Sie den Konstruktor mit Parametern, um Objekte und Parameter zu erstellen stammen aus XML-Knotendaten

Regelmodule sind vorgebunden – RulesModule-Schnittstelle

Zuvor bestand unser grundlegender Prozess bei der Verwendung von Digester darin, die Regeln bei jedem Programmstart zu binden läuft und analysiert sie dann ;

Tatsächlich können wir den Parsing-Prozess von Digester ändern, den Regelsatz beim Start vordefinieren und die vordefinierten Regeln dann zur Laufzeit wiederverwenden

Vielleicht Das ist etwas vage. Sie können sich das folgende Webanwendungsszenario ansehen und sollten ein tieferes Verständnis haben.

Servlet-Szenariobeispiel

Wer mit der Webentwicklung vertraut ist, sollte dies bereits tun Ich kenne das Servlet, daher werde ich hier nicht auf Details eingehen. Angenommen, es gibt ein EmployeeServlet, wie unten gezeigt:

Da das Servlet ein Singleton und der Digester kein Thread ist. sicher, wir werden bei jeder Anforderung ein neues Dgester-Objekt ausgeben, um die Thread-Sicherheit zu gewährleisten, das wie folgt geschrieben ist:

public class EmployeeServlet  extends HttpServlet
{public void doGet(HttpServletRequest req, HttpServletResponse res)throws ServletException, IOException
    {
        Digester digester = new Digester();
        digester.setNamespaceAware( true );
        digester.setXIncludeAware( true );
        digester.addObjectCreate( "employee", Employee.class );
        digester.addCallMethod( "employee/firstName", "setFirstName", 0 );
        digester.addCallMethod( "employee/lastName", "setLastName", 0 );

        digester.addObjectCreate( "employee/address", Address.class );
        digester.addCallMethod( "employee/address/type", "setType", 0 );
        digester.addCallMethod( "employee/address/city", "setCity", 0 );
        digester.addCallMethod( "employee/address/state", "setState", 0 );
        digester.addSetNext( "employee/address", "addAddress" );

        Employee employee = digester.parse( openStream( req.getParameter( "employeeId" ) ) );
        ...
}
Wir können das leicht finden Mängel des oben genannten Programms: Der Code wird nicht jedes Mal wiederverwendet. Jede Anforderung muss wiederholt an die Regel gebunden werden. Wir können jedoch

RuleSet
verwenden, um das Problem der Nicht-Wiederverwendung zu lösen Wie unten gezeigt, definieren Sie eine EmployeeRuleSet-RegelsatzimplementierungRuleSetSchnittstelle:

public class EmployeeRuleSet  implements RuleSet
{public void addRuleInstances( Digester digester )
    {
        digester.addObjectCreate( "employee", Employee.class );
        digester.addCallMethod( "employee/firstName", "setFirstName", 0 );
        digester.addCallMethod( "employee/lastName", "setLastName", 0 );

        digester.addObjectCreate( "employee/address", Address.class );
        digester.addCallMethod( "employee/address/type", "setType", 0 );
        digester.addCallMethod( "employee/address/city", "setCity", 0 );
        digester.addCallMethod( "employee/address/state", "setState", 0 );
        digester.addSetNext( "employee/address", "addAddress" );
    }

}
Dann verwenden Sie es wie folgt im Servlet:

public class EmployeeServlet  extends HttpServlet
{private final RuleSet employeeRuleSet = new EmployeeRuleSet();public void doGet(HttpServletRequest req, HttpServletResponse res)throws ServletException, IOException
    {
        Digester digester = new Digester();
        digester.setNamespaceAware( true );
        digester.setXIncludeAware( true );

        employeeRuleSet.addRuleInstances( digester );

        Employee employee = digester.parse( openStream( req.getParameter( "employeeId" ) ) );
        ...
    }

}
Natürlich gibt es keine Möglichkeit, dies falsch zu machen (tatsächlich denke ich persönlich, dass es besser ist, direkt eine private Methode zu schreiben und Regeln hinzuzufügen, haha), aber es hat Folgendes Nachteile:

    RuleSet ist eigentlich keine Konfiguration, sondern nur für
  1. Der Digester ist lediglich an die Regeln gebunden; 🎜>

    digesterDas Objekt ist stark mit dem Client gekoppelt und wird direkt vom Client erstellt;

  2. Vor jedem Parsing-Aufruf , die verbindlichen Regeln müssen wiederholt werden

  3. Bei der Bindung der Regeln ist die Semantik schlecht und die Lesbarkeit schlecht; 🎜>Was ist also die beste Vorgehensweise? Verwenden Sie die RulesModule-Schnittstelle, um beim Start Regeln vorab zu binden, und verwenden Sie dann beim Ausführen einfach die vorgebundenen Regeln wieder, wie unten gezeigt: Definieren Sie eine RulesModule-Schnittstellenimplementierungsklasse:

  4. Dann wird das Servlet wie folgt verwendet:

Die Vorteile sind offensichtlich:

class EmployeeModuleextends AbstractRulesModule
{

    @Overrideprotected void configure()
    {
        forPattern( "employee" ).createObject().ofType( Employee.class );
        forPattern( "employee/firstName" ).setBeanProperty();
        forPattern( "employee/lastName" ).setBeanProperty();

        forPattern( "employee/address" ).createObject().ofType( Address.class ).then().setNext( "addAddress");
        forPattern( "employee/address/type" ).setBeanProperty();
        forPattern( "employee/address/city" ).setBeanProperty();
        forPattern( "employee/address/state" ).setBeanProperty();
    }

}
RulesModule
Die API für die Regelbindung ist sehr semantisch, einfach zu verwenden und gut lesbar; Die Konfiguration der Regelbindung wird in die Startphase verschoben.

public class EmployeeServletextends HttpServlet
{private final DigesterLoader loader = newLoader( new EmployeeModule() )
        .setNamespaceAware( true )
        .setXIncludeAware( true );public void doGet(HttpServletRequest req, HttpServletResponse res)throws ServletException, IOException
    {
        Digester digester = loader.newDigester()

        Employee employee = digester.parse( openStream( req.getParameter("employeeId") ) );
        ...
    }

}

Das Digester-Objekt wird nicht vom Client erstellt, sondern

    von
  1. DigesterLoader;

  2. FromXmlRulesModule
  3. Zusätzlich zum Schreiben Ihrer eigenen Klasse Implementieren Sie die RulesModule-Schnittstelle, digester selbst stellt eine FromXmlRulesModule-Klasse

bereit, die RulesModule-Schnittstelle. Wir können

wie folgt verwenden:

Vollständiges BeispielAngenommen, es gibt eine XML-Datei wie folgt, die analysiert werden sollStarten Sie die Codierung. Definieren Sie zunächst eine RulesModule-Schnittstellenimplementierungsklasse: Client-Klasse schreiben:

            DigesterLoader loader = DigesterLoader.newLoader(  .getResource( "myrule.xml"

Ergebnisdruck:

Pi Chen, CITY, HangZhou, 2

Asynchron Parsen von XML
<employee>
    <firstName>Pi</firstName>
    <lastName>Chen</lastName>
    <address>
        <type>CITY</type>
        <city>HangZhou</city>
        <state>2</state>
    </address>
</employee>
Wenn Sie asynchron analysieren möchten, rufen Sie einfach die asyncParse-Methode direkt auf. Sie müssen jedoch besonders darauf achten, da

digester
package apache.commons.digester3.example.rulesbinder.module;import org.apache.commons.digester3.binder.AbstractRulesModule;import apache.commons.digester3.example.rulesbinder.pojo.Address;import apache.commons.digester3.example.rulesbinder.pojo.Employee;/**
 * 
 * 
 * @author    
 * @version   2017年6月5日 */public class EmployeeModule extends AbstractRulesModule {

    @Overrideprotected void configure() {
        forPattern("employee").createObject().ofType(Employee.class);
        forPattern("employee/firstName").setBeanProperty();
        forPattern("employee/lastName").setBeanProperty();

        forPattern("employee/address").createObject().ofType(Address.class).then().setNext("addAddress");
        forPattern("employee/address/type").setBeanProperty();
        forPattern("employee/address/city").setBeanProperty();
        forPattern("employee/address/state").setBeanProperty();
    }

}
Objekte nicht threadsicher sind . Das Folgende ist ein einfaches API-Verwendungsbeispiel:

Folgen Sie dem vorherigen Beispiel und verwenden Sie dasselbe XML und RulesModule, um die Klasse zu implementieren;

Client-Klasse:
package apache.commons.digester3.example.rulesbinder;import java.io.IOException;import org.apache.commons.digester3.Digester;import org.apache.commons.digester3.binder.DigesterLoader;import org.xml.sax.SAXException;import apache.commons.digester3.example.rulesbinder.module.EmployeeModule;import apache.commons.digester3.example.rulesbinder.pojo.Address;import apache.commons.digester3.example.rulesbinder.pojo.Employee;import apache.commons.digester3.example.simpletest.ExampleMain;/**
 * 
 * 
 * @author    
 * @version   2017年6月5日 */public class DigesterLoaderMain {private static DigesterLoader dl = DigesterLoader.newLoader(new EmployeeModule())
            .setNamespaceAware(false);public static void main(String[] args) {try {
            
            Digester digester = dl.newDigester();
            Employee employee = digester.parse(ExampleMain.class.getClassLoader().getResourceAsStream("employee.xml"));

            System.out.print(employee.getFirstName() + " ");
            System.out.print(employee.getLastName() + ", ");for (Address a : employee.getAddressList()) {
                System.out.print(a.getType() + ", ");
                System.out.print(a.getCity() + ", ");
                System.out.println(a.getState());
            }

        } catch (IOException e) {

            e.printStackTrace();
        } catch (SAXException e) {

            e.printStackTrace();
        }
    }
}

XML-Variablenanalyse-Substitutor-Abstraktklasse

Dies ist relativ einfach. Definieren Sie eine VariableSubstitutor-Implementierungsklasse, und der Benutzer konvertiert die im Körper definierten Attribute und Variablenwerte;

Angenommen, es gibt eine XML-Datei wie unten gezeigt (wobei ${type} eine Variable ist):

那么可以这样解析如上xml:

package apache.commons.digester3.example.rulesbinder;import java.io.IOException;import java.util.HashMap;import java.util.Map;import org.apache.commons.digester3.Digester;import org.apache.commons.digester3.Substitutor;import org.apache.commons.digester3.binder.DigesterLoader;import org.apache.commons.digester3.substitution.MultiVariableExpander;import org.apache.commons.digester3.substitution.VariableSubstitutor;import org.xml.sax.SAXException;import apache.commons.digester3.example.rulesbinder.module.EmployeeModule;import apache.commons.digester3.example.rulesbinder.pojo.Address;import apache.commons.digester3.example.rulesbinder.pojo.Employee;import apache.commons.digester3.example.simpletest.ExampleMain;/**
 * 
 * 
 * @author 
 * @version 2017年6月5日 */public class SubstitutionMain
{private static DigesterLoader dl = DigesterLoader.newLoader(new EmployeeModule())
        .setNamespaceAware(false);public static void main(String[] args)
    {try{// set up the variables the input xml can referenceMap<String, Object> vars = new HashMap<String, Object>();
            vars.put("user.name", "me");
            vars.put("type", "boss");// map ${varname} to the entries in the var mapMultiVariableExpander expander = new MultiVariableExpander();
            expander.addSource("$", vars);// allow expansion in both xml attributes and element textSubstitutor substitutor = new VariableSubstitutor(expander);

            Digester digester = dl.newDigester();
            digester.setSubstitutor(substitutor);

            Employee employee = digester
                .parse(ExampleMain.class.getClassLoader().getResourceAsStream("employee$.xml"));

            System.out.print(employee.getFirstName() + " ");
            System.out.print(employee.getLastName() + ", ");for (Address a : employee.getAddressList())
            {
                System.out.print(a.getType() + ", ");
                System.out.print(a.getCity() + ", ");
                System.out.println(a.getState());
            }

        }catch (IOException e)
        {

            e.printStackTrace();
        }catch (SAXException e)
        {

            e.printStackTrace();
        }
    }
}

带参构造方法使用示例

简单地说,就是在使用ObjectCreateRule规则的时候,能够传递xml中的值(属性值、body值)给构造方法使用;

如下是一个待解析的xml:

<root>
  <bean super="false"><rate>9.99</rate>
  </bean></root>

那么可以这样解析:

package apache.commons.digester3.example.rulesbinder;import java.io.IOException;import org.apache.commons.digester3.Digester;import org.apache.commons.digester3.ObjectCreateRule;import org.apache.commons.digester3.binder.DigesterLoader;import org.xml.sax.SAXException;import apache.commons.digester3.example.rulesbinder.module.EmployeeModule;import apache.commons.digester3.example.rulesbinder.pojo.Address;import apache.commons.digester3.example.rulesbinder.pojo.Employee;import apache.commons.digester3.example.rulesbinder.pojo.MyBean;import apache.commons.digester3.example.simpletest.ExampleMain;/**
 * 
 * 
 * @author 
 * @version 2017年6月5日 */public class ConstructorParamsMain
{public static void main(String[] args)
    {try{

            ObjectCreateRule createRule = new ObjectCreateRule(MyBean.class);
            createRule.setConstructorArgumentTypes(Double.class, Boolean.class);

            Digester digester = new Digester();
            digester.addRule("root/bean", createRule);
            digester.addCallParam("root/bean", 1, "super");
            digester.addCallParam("root/bean/rate", 0);

            MyBean myBean = digester.parse(ConstructorParamsMain.class.getClassLoader()
                .getResourceAsStream("constructor-params.xml"));

            System.out.println(myBean.getRate());
            System.out.println(myBean.isSuper_());

        }catch (IOException e)
        {

            e.printStackTrace();
        }catch (SAXException e)
        {

            e.printStackTrace();
        }
    }
}

结果打印:

9.99
false

参考资料


代码参考


Das obige ist der detaillierte Inhalt vonApache Commons Digester. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn