概述
xmlconfiguration是jetty中用來實作使用xml檔案配置webappcontext執行個體的架構,事實上,他可以用來配置任何的object。類似digester可以将一個xml配置檔案直接執行個體化成一個類執行個體,xmlconfiguration可以使用一個xml檔案初始化一個object執行個體,它支援屬性設定、方法調用、建立新執行個體等。
xmlconfiguration實作
在xmlconfiguration的實作中,可以使用url、configuration字元串、inputstream作為構造函數傳入xmlconfiguration中,在xmlconfiguration的構造函數初始化時,它初始化xmlparser執行個體,使用xmlparser對xml檔案進行解析成一個node樹,并将該樹的根節點指派給config字段;在初始化config字段的同時初始化processor字段,processor字段是configurationprocessor類型,他用于解析xmlparser解析出的node樹的處理類,如果根節點的tag是configure,則processor使用jetty中的預設實作:jettyxmlconfiguration類,否則使用serviceloader查找到的configurationprocessorfactory執行個體,并調用其getconfigurationprocessor方法,傳入dtd和tag作為參數,直到找到一個非null的configurationprocessor;在建立出configurationprocessor執行個體後,首先調用其init方法,在jettyxmlconfiguration類的實作中,init方法隻是将傳入的參數儲存:node樹的config執行個體、以及兩個idmap、propertymap執行個體用于傳遞參數,其中idmap用于儲存解析過程中所有id屬性對應的執行個體,也可以用它來傳遞xml檔案用于配置的執行個體以及其他ref引用的執行個體,而propertymap用于定義一些xml檔案中用到的屬性對應的值。
可以使用帶object執行個體的參數或不帶參數兩種方式調用configure方法,帶參數表示将xml中内容配置執行個體中的屬性,不帶參數則先在内部建立class屬性指定的類執行個體,然後使用xml的内容配置該新建立的執行個體的屬性,如果根元素定義了id屬性,則可以設定要配置的執行個體是idmap中該id值對應的執行個體。
在configure方法的真正實作中,它周遊根節點的所有子節點,判斷tag值(在這個過程中對任何有id定義的元素,将該id屬性的值做為key,該元素對應的執行個體儲存在idmap中):
set => 用于設定name屬性指定的set方法或字段的值,在查找方法中會有各種嘗試:1. 嘗試目前值執行個體作為參數的set方法;2. 使用class執行個體的type字段作為參數類型的set方法;3. 嘗試查找public類型的字段;4. 嘗試所有隻有一個參數的對應的set方法;5. 嘗試是否可以将其轉換成set或數組類型的參數;6. 嘗試裝箱後的參數。
put => 要使用該方法,配置類型必須繼承自map接口,使用name屬性作為key,擷取其值執行個體,調用put方法。
call => 指定class屬性表示調用其靜态方法;讀取所有的arg子節點(arg節點必須緊跟call節點),并且解析這些arg的值類型,name屬性指定方法名,在傳回後如果其他節點定義,則使用它們配置傳回的執行個體。
get => 使用name屬性指定的get無參數方法,如果沒有找到get方法,則從name屬性指定的字段中擷取值,如果還有子元素,則對傳回的執行個體進行配置。
new => 建立一個class指定的類執行個體,可以使用arg指定構造函數參數。如果有除了arg以外的節點定義,則使用它們對新建立的執行個體配置。
array => 建立數組執行個體,type指定數組類型,支援以下列舉的所有的值類型,使用item指定它的元素。
ref => 為傳入的ref引用執行個體配置。
property => 從傳入的propertymap中擷取值,可以指定default屬性。可以通過定義子元素繼續配置傳回的值。
map => 建立新的map執行個體,使用entry/item, item指定key、value的值。
對于所有值類型,可以指定其type屬性,jetty預設支援的類型有string、java.lang.string、url、java.net.url、inetaddress、java.net.inetaddress、boolean、byte、char、double、float、int、long、short、void、java.lang.boolean.type、java.lang.byte.type、java.lang.character.type、java.lang.double.type、java.lang.float.type、java.lang.integer.type、java.lang.long.type、java.lang.short.type、java.lang.void.tppe、boolean、byte、character、double、float、integer、long、short、null、string等。另外值類型還可以使用call、get、new、ref、array、map、property、systemproperty定義。其中systemproperty可以定義name和default屬性用于表示prop名和default的值。ref引用必須先定義,因而這裡無法處理循環引用的問題。
可以使用xmlconfiguration,給定一個或多個properties、xml檔案參數,在command line中直接啟動jetty伺服器。
xmlconfiguration也可以用于envconfiguration中,用于進一步配置webappcontext,可以手動設定jettyenvxmlurl屬性,或預設使用web-inf/jetty-env.xml檔案。
xmlconfiguration還用于jettywebxmlconfiguration,他預設查找web-inf目錄下的jetty8-web.xml、jetty-web.xml、web-jetty.xml作為配置檔案對webappcontext做進一步的配置。
附錄
xmlconfiguration支援的xml檔案格式使用configure_6_0.dtd檔案定義:
<?xml version="1.0" encoding="iso-8859-1"?>
<!--
this is the document type descriptor for the
org.eclipse.xmlconfiguration class. it allows a java object to be
configured by with a sequence of set, put and call elements. these tags are
mapped to methods on the object to be configured as follows:
<set name="test">value</set> == obj.settest("value");
<put name="test">value</put> == obj.put("test","value");
<call name="test"><arg>value</arg></call> == obj.test("value");
values themselves may be configured objects that are created with the
<new> tag or returned from a <call> tag.
values are matched to arguments on a best effort approach, but types
my be specified if a match is not achieved.
-->
<!entity % config "set|get|put|call|new|ref|array|map|property">
<!entity % value "#pcdata|get|call|new|ref|array|map|systemproperty|property">
<!entity % typeattr "type cdata #implied " > <!-- string|character|short|byte|integer|long|boolean|float|double|char|short|byte|int|long|boolean|float|double|url|inetaddress|inetaddrport| #classname -->
<!entity % impliedclassattr "class nmtoken #implied" >
<!entity % classattr "class nmtoken #required" >
<!entity % nameattr "name nmtoken #required" >
<!entity % impliednameattr "name nmtoken #implied" >
<!entity % defaultattr "default cdata #implied" >
<!entity % idattr "id nmtoken #implied" >
<!entity % requiredidattr "id nmtoken #required" >
configure element.
this is the root element that specifies the class of object that
can be configured:
<configure class="com.acme.myclass">
</configure>
<!element configure (%config;)* >
<!attlist configure %impliedclassattr; %idattr; >
set element.
this element maps to a call to a setter method or field on the current object.
the name and optional type attributes are used to select the setter
method. if the name given is xxx, then a setxxx method is used, or
the xxx field is used of setxxx cannot be found.
a set element can contain value text and/or the value objects returned
by other elements such as call, new, systemproperty, etc.
if no value type is specified, then white
space is trimmed out of the value. if it contains multiple value
elements they are added as strings before being converted to any
specified type.
a set with a class attribute is treated as a static set method invocation.
<!element set ( %value; )* >
<!attlist set %nameattr; %typeattr; %impliedclassattr; >
get element.
this element maps to a call to a getter method or field on the current object.
the name attribute is used to select the get method.
if the name given is xxx, then a getxxx method is used, or
the xxx field is used if getxxx cannot be found.
a get element can contain other elements such as set, put, call, etc.
which act on the object returned by the get call.
a get with a class attribute is treated as a static get method or field.
<!element get (%config;)*>
<!attlist get %nameattr; %impliedclassattr; %idattr; >
put element.
this element maps to a call to a put method on the current object,
which must implement the map interface. the name attribute is used
as the put key and the optional type attribute can force the type
of the value.
a put element can contain value text and/or value elements such as call,
new, systemproperty, etc. if no value type is specified, then white
<!element put ( %value; )* >
<!attlist put %nameattr; %typeattr; >
call element.
this element maps to an arbitrary call to a method on the current object,
the name attribute and arg elements are used to select the method.
a call element can contain a sequence of arg elements followed by
a sequence of other elements such as set, put, call, etc. which act on any object
returned by the original call:
<call id="o2" name="test">
<arg>value1</arg>
<set name="test">value2</set>
</call>
this is equivalent to:
object o2 = o1.test("value1");
o2.settest("value2");
a call with a class attribute is treated as a static call.
<!element call (arg*,(%config;)*)>
<!attlist call %nameattr; %impliedclassattr; %idattr;>
arg element.
this element defines a positional argument for the call element.
the optional type attribute can force the type of the value.
an arg element can contain value text and/or value elements such as call,
<!element arg ( %value; )* >
<!attlist arg %typeattr; %impliednameattr; >
new element.
this element allows the creation of a new object as part of a
value for elements such as set, put, arg, etc. the class attribute determines
the type of the new object and the contained arg elements
are used to select the constructor for the new object.
a new element can contain a sequence of arg elements followed by
a sequence of elements such as set, put, call, etc. elements
which act on the new object:
<new id="o" class="com.acme.myclass">
</new>
object o = new com.acme.myclass("value1");
o.settest("value2");
<!element new (arg*,(%config;)*)>
<!attlist new %classattr; %idattr;>
ref element.
this element allows a previously created object to be referenced by id.
a ref element can contain a sequence of elements such as set, put, call, etc.
which act on the referenced object:
<ref id="myobject">
<!element ref ((%config;)*)>
<!attlist ref %requiredidattr;>
array element.
this element allows the creation of a new array as part of a
value of elements such as set, put, arg, etc. the type attribute determines
the type of the new array and the contained item elements
are used for each element of the array:
<array type="java.lang.string">
<item>value0</item>
<item><new class="java.lang.string"><arg>value1</arg></new></item>
</array>
string[] a = new string[] { "value0", new string("value1") };
<!element array (item*)>
<!attlist array %typeattr; %idattr; >
map element.
this element allows the creation of a new map as part of a
<map>
<entry>
<item>keyname</item>
<item><new class="java.lang.string"><arg>value1</arg></new></item>
</entry>
</map>
map m = new hashmap();
m.put("keyname", new string("value1"));
<!element map (entry*)>
<!attlist map %idattr; >
<!element entry (item,item)>
item element.
this element defines an entry for the array or map entry elements.
an item element can contain value text and/or the value object of
elements such as call, new, systemproperty, etc. if no value type
is specified, then white space is trimmed out of the value.
if it contains multiple value elements they are added as strings
before being converted to any specified type.
<!element item ( %value; )* >
<!attlist item %typeattr; %idattr; >
system property element.
this element allows jvm system properties to be retrieved as
part of the value of elements such as set, put, arg, etc.
the name attribute specifies the property name and the optional
default argument provides a default value.
<systemproperty name="test" default="value" />
system.getproperty("test","value");
<!element systemproperty empty>
<!attlist systemproperty %nameattr; %defaultattr; %idattr;>
property element.
this element allows arbitrary properties to be retrieved by name.
a property element can contain a sequence of elements such as set, put, call, etc.
which act on the retrieved object:
<property name="server">
<call id="jdbcidmgr" name="getattribute">
<arg>jdbcidmgr</arg>
</call>
</property>
<!element property ((%config;)*)>
<!attlist property %nameattr; %defaultattr; %idattr;>
一個簡單的例子(摘自:http://www.blogjava.net/xylz/archive/2012/04/12/372999.html):
<configure id="server" class="org.eclipse.jetty.server.server">
<set name="threadpool">
<new class="org.eclipse.jetty.util.thread.queuedthreadpool">
<set name="minthreads">10</set>
<set name="maxthreads">200</set>
<set name="detaileddump">false</set>
</new>
</set>
<call name="addconnector">
<arg>
<new class="org.eclipse.jetty.server.nio.selectchannelconnector">
<set name="host"><property name="inside in jetty.host" /></set>
<set name="port"><property name="inside in jetty.port" default="8080"/></set>
<set name="maxidletime">300000</set>
<set name="acceptors">2</set>
<set name="statson">false</set>
<set name="confidentialport">8443</set>
<set name="lowresourcesconnections">20000</set>
<set name="lowresourcesmaxidletime">5000</set>
</new>
</arg>
</call>
<set name="handler">
<new id="handlers" class="org.eclipse.jetty.server.handler.handlercollection">
<set name="handlers">
<array type="org.eclipse.jetty.server.handler">
<item>
<new id="contexts" class="org.eclipse.jetty.server.handler.contexthandlercollection"/>
</item>
<new id="defaulthandler" class="org.eclipse.jetty.server.handler.defaulthandler"/>
</array>
</set>
<set name="stopatshutdown">true</set>
<set name="sendserverversion">true</set>
<set name="senddateheader">true</set>
<set name="gracefulshutdown">1000</set>
<set name="dumpafterstart">false</set>
<set name="dumpbeforestop">false</set>
</configure>