java由JABXContext注解讀取xml配置文件方式
1. 本篇內(nèi)容
在用java作開發(fā)時(shí),一般會(huì)選擇使用xml文件作為配置文件,故而通過java工程讀取配置文件則是必須掌握的知識(shí);
傳統(tǒng)的C/C++通過File文件的方式或者說通過流的方式進(jìn)行讀寫,過分的浪費(fèi)內(nèi)存與效率,且讀寫及其不方便,不適用于java的靈活配置,而java的注解方式成功的解決了該問題。
作者在從事相關(guān)的開發(fā)中學(xué)習(xí)了一下注解的方式,并成功開發(fā)了項(xiàng)目;雖然現(xiàn)在網(wǎng)上關(guān)于此知識(shí)已經(jīng)鋪天蓋地,而我仍舊希望將自己的經(jīng)驗(yàn)與大家分享。
2. 選擇要讀取的配置文件
下面的配置文件雖說是作者編纂,但仍可代表一般的配置,讀者姑妄觀之,見下
<?xml version="1.0" encoding="UTF-8"?> <cham formatversion="1.14"> ? <servers> ? ? <centers> ?? ? ?<center id="1" name="center1"> ?? ? ? ?<main> ?? ??? ? ?<iphost>127.0.0.1</iphost> ?? ??? ? ?<port>8443</port> ?? ??? ? ?<byte-sequence>BigEndian</byte-sequence> ?? ??? ?</main> ?? ??? ?<preparation> ?? ??? ? ?<iphost>10.10.10.1</iphost> ?? ??? ? ?<port>8080</port> ?? ??? ? ?<byte-sequence>BigEndian</byte-sequence> ?? ??? ?</preparation> ?? ??? ?<argument-ref>ccsArg</argument-ref> ?? ? ?</center> ?? ?</centers> ? </servers> </cham>
上文中的配置文件格式是標(biāo)準(zhǔn)的配置文件格式,配置文件中其實(shí)只包含了一個(gè)數(shù)組,記<centers></centers>節(jié)點(diǎn),而我們此次的主要目的也是講解該節(jié)點(diǎn)。
3. 基本注解講解
從嚴(yán)格意義上來講,XML文件常用的注解共有四個(gè):
1) @XmlRootElement(name="") 用于注解根節(jié)點(diǎn),即XML的起點(diǎn)
2)@XmlAttribute(name="") 用于注釋attribute,例如<center id="1" name="center1"/>中的id和name兩個(gè)屬性
2)@XmlElement(name="") 最常用的注釋方式,用于注釋節(jié)點(diǎn),例如<port>8080</port>
4)@XmlTransient 用于放置在get方法上,放置報(bào)錯(cuò)。
4. java相應(yīng)文件的寫作
分析上述的cham.xml配置文件,很容易產(chǎn)清楚它的結(jié)構(gòu),它有以下幾個(gè)部分組成
1. cham.xml文件由一個(gè)<servers/>節(jié)點(diǎn)組成
2. servers節(jié)點(diǎn)由<centers/>節(jié)點(diǎn)組成,而<centers/>節(jié)點(diǎn)是個(gè)數(shù)組,用于可以在其中配置多個(gè)<center/>,而本帖中只包含了一個(gè)元素。
3. <center/>節(jié)點(diǎn)由兩部分組成,即<main/><preparation/> 和 <argument-ref/>節(jié)點(diǎn)。
我們的分析方式采用的由內(nèi)及外的讀取方式
4.1 最基本的<main/>單元
查看上述cham.xml文件,則可以發(fā)現(xiàn)<main/>和<preparation/>是最基本的配置單元,沒有比它更小的單元了,我們不妨先從它開始注解
我們可以建立一個(gè)名字叫做ServerPoint.java的文件來表示該節(jié)點(diǎn)
package com.china.domain.config; import java.io.Serializable; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlTransient; public class ServerPoint implements Serializable { ?? ?private static final long serialVersionUID = 3623939598540009923L; ?? ?@XmlElement(name="iphost") ?? ?private String iphost; ?? ?@XmlElement(name="port") ?? ?private int port; ?? ?@XmlElement(name="byte-sequence") ?? ?private String byteSequence; ?? ?@XmlTransient ?? ?public String getIphost() { ?? ??? ?return iphost; ?? ?} ?? ?public void setIphost(String iphost) { ?? ??? ?this.iphost = iphost; ?? ?} ?? ?@XmlTransient ?? ?public int getPort() { ?? ??? ?return port; ?? ?} ?? ?public void setPort(int port) { ?? ??? ?this.port = port; ?? ?} ?? ?@XmlTransient ?? ?public String getByteSequence() { ?? ??? ?return byteSequence; ?? ?} ?? ?public void setByteSequence(String byteSequence) { ?? ??? ?this.byteSequence = byteSequence; ?? ?} ?? ?@Override ?? ?public String toString() { ?? ??? ?return " [iphost=" + iphost + ", port=" + port + ", byteSequence=" + byteSequence + "]"; ?? ?} }
讀者很容易看出來,該文件和之前<main/>或者<preparation/>節(jié)點(diǎn)的內(nèi)容正好一一對(duì)應(yīng)。所涉及的注釋有兩個(gè),即@XmlElement 和 @XmlTransient,它們的功能此處不再贅述。
4.2 <center/>節(jié)點(diǎn)講解
從之前的分析可以知道,<center/>節(jié)點(diǎn)共包含兩個(gè)部分或者說三個(gè)部分,即<main/><preparation/>和 <argument-ref/>節(jié)點(diǎn)。從內(nèi)容上看,需要用到的注釋有三個(gè),即@XmlElement 、@XmlAttribute 、@XmlTransient
我們可以用一個(gè)Center.java 文件來表示該節(jié)點(diǎn),如下所示:
package com.china.domain.config; import java.io.Serializable; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlTransient; public class Center implements Serializable { ?? ?private static final long serialVersionUID = 4568925940918840647L; ?? ?@XmlAttribute(name="id") ?? ?private int id; ?? ?@XmlAttribute(name="name") ?? ?private String name; ?? ?@XmlElement(name="main") ?? ?private ServerPoint serverPoint; ?? ?@XmlElement(name="preparation") ?? ?private ServerPoint back; ?? ?@XmlElement(name="argument-ref") ?? ?private String argumentRef; ?? ?@XmlTransient ?? ?public int getId() { ?? ??? ?return id; ?? ?} ?? ?public void setId(int id) { ?? ??? ?this.id = id; ?? ?} ?? ?@XmlTransient ?? ?public String getName() { ?? ??? ?return name; ?? ?} ?? ?public void setName(String name) { ?? ??? ?this.name = name; ?? ?} ?? ?@XmlTransient ?? ?public ServerPoint getServerPoint() { ?? ??? ?return serverPoint; ?? ?} ?? ?public void setServerPoint(ServerPoint serverPoint) { ?? ??? ?this.serverPoint = serverPoint; ?? ?} ?? ?@XmlTransient ?? ?public ServerPoint getBack() { ?? ??? ?return back; ?? ?} ?? ?public void setBack(ServerPoint back) { ?? ??? ?this.back = back; ?? ?} ?? ?@XmlTransient ?? ?public String getArgumentRef() { ?? ??? ?return argumentRef; ?? ?} ?? ?public void setArgumentRef(String argumentRef) { ?? ??? ?this.argumentRef = argumentRef; ?? ?} ?? ?@Override ?? ?public String toString() { ?? ??? ?return "Center [id=" + id + ", name=" + name + ", serverPoint=" + serverPoint + ", back=" + back ?? ??? ??? ??? ?+ ", argumentRef=" + argumentRef + "]"; ?? ?} }
從上文中可以看出,用@XmlAttribute可以注釋<center id="1" name="center1"/>的場(chǎng)景,由于代碼和注釋一一匹配,此處不再多言。
4.3 <servers/>節(jié)點(diǎn)及數(shù)組的注釋方式
前面分析已知:<servers/>節(jié)點(diǎn)下是一個(gè)包含了多個(gè)(本例中只有一個(gè))<center/>的<centers/>數(shù)組,則我們創(chuàng)建和<servers/>節(jié)點(diǎn)相對(duì)應(yīng)的java文件時(shí)要考慮數(shù)組的因素。
一般來講,我們是通過@XmlElementWrapper 來注釋數(shù)組,用法如下
package com.china.domain.config; import java.io.Serializable; import java.util.Arrays; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlTransient; public class Servers implements Serializable { ?? ?private static final long serialVersionUID = 8836963744878452510L; ?? ?@XmlElementWrapper(name="centers")//用于注釋<centers/>數(shù)組,表示這是個(gè)數(shù)組 ?? ?@XmlElement(name="center")//用于注釋數(shù)組的子元素 ?? ?private Center[] centers; ?? ?@XmlTransient ?? ?public Center[] getCenters() { ?? ??? ?return centers; ?? ?} ?? ?public void setCenters(Center[] centers) { ?? ??? ?this.centers = centers; ?? ?} ?? ?@Override ?? ?public String toString() { ?? ??? ?return " [centers=" + Arrays.toString(centers) + "]"; ?? ?} }
4.4 注釋根節(jié)點(diǎn)
XML注釋中有 @XmlRootElement(name="cham")注釋根節(jié)點(diǎn),其中 cham是xml文件根節(jié)點(diǎn)的名稱,在本例中的name,即<cham formatversion="1.14"/>中的cham
用@XmlAccessorType(XmlAccessType.FIELD)注解表示當(dāng)前所注解內(nèi)容的類型,除FIELD以外還有其他數(shù)種,但最長(zhǎng)用的是FIELD,至于其他的含義,讀者請(qǐng)搜索相關(guān)資料。
我們可以創(chuàng)建一個(gè)名字叫做 SystemConfig.java的文件來存放該內(nèi)容:
package com.china.domain.config; import java.io.Serializable; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlTransient; @XmlAccessorType(XmlAccessType.FIELD) @XmlRootElement(name="cham") public class SystemConfig implements Serializable { ?? ?private static final long serialVersionUID = -7667130896271777648L; ?? ?@XmlAttribute(name="formatversion") ?? ?private String formatVersion; ?? ?@XmlElement(name="servers") ?? ?private Servers servers; ?? ?@XmlTransient ?? ?public String getFormatVersion() { ?? ??? ?return formatVersion; ?? ?} ?? ?public void setFormatVersion(String formatVersion) { ?? ??? ?this.formatVersion = formatVersion; ?? ?} ?? ?@XmlTransient ?? ?public Servers getServers() { ?? ??? ?return servers; ?? ?} ?? ?public void setServers(Servers servers) { ?? ??? ?this.servers = servers; ?? ?} ?? ?@Override ?? ?public String toString() { ?? ??? ?return "SystemConfig {formatVersion=" + formatVersion + ", servers=" + servers + "}"; ?? ?} }
至此,注解部分已經(jīng)完成。
5. XML文件的位置
一般來講,無論C/C++還是java,都會(huì)將配置文件放置在工程的某個(gè)目錄之下。由于作者開發(fā)中使用到了tomcat容器,根據(jù)習(xí)慣,故將配置文件放置在tomacat下的/conf/目錄下
java提供 getProperty 方法獲取/conf/上層路徑,即我們可以通過 String configPath = System.getProperty("catalina.base"); 方式來獲取到/conf/的路徑,其中catalina.base即為/conf/上層路徑,讀者可以查看相關(guān)tomcat文檔中的定義
6. 分隔符的講解
該部分是作者在開發(fā)過程中碰到的一個(gè)小陷阱,特拿出來和大家分享;作者在獲取到路徑后卻始終不能讀取文件,后來發(fā)現(xiàn)是缺少分隔符
我們可以通過如下代碼獲取/conf/路徑并添加分隔符
if(!this.configPath.endsWith(File.separator)) { ?? ??? ??? ?this.configPath = this.configPath + File.separatorChar + "conf" + File.separatorChar; ?? ??? ?}else { ?? ??? ??? ?this.configPath = this.configPath + "conf" + File.separatorChar; ?? ??? ?}
如果我們?cè)賱?chuàng)建一個(gè) configFile變量來存儲(chǔ)cham.xml文件,則configFile=configPath+"cham.xml";
7.java中讀取xml注解的方式
這段代碼比較固定,讀者可以再網(wǎng)上任意搜到
package com.china.domain.comm.basicread; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import javax.xml.bind.JAXBContext; import org.xml.sax.InputSource; import com.china.domain.config.SystemConfig; import javax.xml.bind.Unmarshaller; public class XmlReaders { ?? ?private String configPath; ?? ?private String configFile; ?? ?private SystemConfig config; ?? ?public XmlReaders(String configPath) { ?? ??? ?super(); ?? ??? ?this.configPath = configPath; ?? ??? ?initConfigPath(); ?? ??? ?initSystemConfig(); ?? ?} ?? ?private void initConfigPath() { ?? ??? ?if(null == this.configPath) { ?? ??? ??? ?System.out.println("configPath is null"); ?? ??? ??? ?return; ?? ??? ?} ?? ??? ?if(!this.configPath.endsWith(File.separator)) { ?? ??? ??? ?this.configPath = this.configPath + File.separatorChar + "conf" + File.separatorChar; ?? ??? ?}else { ?? ??? ??? ?this.configPath = this.configPath + "conf" + File.separatorChar; ?? ??? ?} ?? ??? ?this.configFile = this.configPath + "cham.xml"; ?? ?} ?? ?private void initSystemConfig() { ?? ??? ?if(null == this.configFile) { ?? ??? ??? ?System.out.println("configFile is null"); ?? ??? ??? ?return; ?? ??? ?} ?? ??? ?try { ?? ??? ? ? ?JAXBContext context = JAXBContext.newInstance(SystemConfig.class);//首先創(chuàng)建SystemConfig.java的模型 ?? ??? ? ? ?Unmarshaller umar = context.createUnmarshaller(); ?? ??? ? ? ?File file = new File(this.configFile); ?? ??? ? ? ?InputStream inputStream = new FileInputStream(file);//通過輸入流讀取配置文件 ?? ??? ? ? ?InputSource source = new InputSource(inputStream); ?? ??? ? ? ?source.setEncoding("UTF-8");//設(shè)置讀取字節(jié)的方式 ?? ??? ? ? ?this.config = (SystemConfig)umar.unmarshal(inputStream); ?? ??? ?}catch(Exception e) { ?? ??? ??? ?System.out.println("Exceptions : " + e.toString()); ?? ??? ?} ?? ?} ?? ?public String getConfigPath() { ?? ??? ?return configPath; ?? ?} ?? ?public void setConfigPath(String configPath) { ?? ??? ?this.configPath = configPath; ?? ?} ?? ?public String getConfigFile() { ?? ??? ?return configFile; ?? ?} ?? ?public void setConfigFile(String configFile) { ?? ??? ?this.configFile = configFile; ?? ?} ?? ?public SystemConfig getConfig() { ?? ??? ?return config; ?? ?} ?? ?public void setConfig(SystemConfig config) { ?? ??? ?this.config = config; ?? ?} }
只要調(diào)用XmlReaders.java這個(gè)類的構(gòu)造函數(shù),則可以成功的將配置文件讀取到SystemConfig.java類中
8.結(jié)果展示
SystemConfig = SystemConfig {formatVersion=1.14, servers= [centers=[Center [id=1, name=center1, serverPoint= [iphost=127.0.0.1, port=8443, byteSequence=BigEndian], back= [iphost=10.10.10.1, port=8080, byteSequence=BigEndian], argumentRef=ccsArg]]]}
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java位集合之BitMap、BitSet和布隆過濾器示例解析
這篇文章主要介紹了Java中位集合的基本概念、實(shí)現(xiàn)方法以及應(yīng)用場(chǎng)景,包括Bit-Map、BitSet和BloomFilter,Bit-Map通過位操作高效地存儲(chǔ)和查詢?cè)貭顟B(tài),文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-12-12SpringBoot接口實(shí)現(xiàn)百萬并發(fā)的代碼示例
隨著互聯(lián)網(wǎng)的發(fā)展,越來越多的應(yīng)用需要支持高并發(fā),在這種情況下,如何實(shí)現(xiàn)高并發(fā)成為了一個(gè)重要的問題,Spring Boot是一個(gè)非常流行的Java框架,它提供了很多方便的功能來支持高并發(fā),本文將介紹如何使用Spring Boot來實(shí)現(xiàn)百萬并發(fā)2023-10-10Java統(tǒng)計(jì)50個(gè)10到50之間整數(shù)的隨機(jī)出現(xiàn)次數(shù)
這篇文章主要為大家詳細(xì)介紹了Java統(tǒng)計(jì)50個(gè)10到50之間整數(shù)的隨機(jī)出現(xiàn)次數(shù),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-07-07IDEA安裝阿里巴巴編碼規(guī)范插件的兩種方式詳解(在線安裝和離線安裝)
這篇文章主要介紹了IDEA安裝阿里巴巴編碼規(guī)范插件的兩種方式詳解(在線安裝和離線安裝),本文通過截圖給大家展示的非常詳細(xì),需要的朋友可以參考下2021-09-09JavaCV實(shí)現(xiàn)讀取視頻信息及自動(dòng)截取封面圖詳解
javacv可以幫助我們?cè)趈ava中很方便的使用OpenCV以及FFmpeg相關(guān)的功能接口。本文將利用Javacv實(shí)現(xiàn)在視頻網(wǎng)站中常見的讀取視頻信息和自動(dòng)獲取封面圖的功能,感興趣的可以了解一下2022-06-06Spring Boot中利用JavaMailSender發(fā)送郵件的方法示例(附源碼)
這篇文章主要介紹了Spring Boot中利用JavaMailSender發(fā)送郵件的方法示例, 相信使用過Spring的眾多開發(fā)者都知道Spring提供了非常好用的JavaMailSender接口實(shí)現(xiàn)郵件發(fā)送。在Spring Boot的Starter模塊中也為此提供了自動(dòng)化配置。需要的朋友可以參考借鑒。2017-02-02