??xml version="1.0" encoding="utf-8" standalone="yes"?> Trigger是一个抽象类Q?span style="font-family: Calibri">Quartz提供?jin)两个比较常用的触发?span style="font-family: Calibri">SimpleTrigger?span style="font-family: Calibri">CronTrigger。它们都?span style="font-family: Calibri">Trigger的子c?/span> q是一个简单的触发器,通过它我们可以定义触发的旉Qƈ选择性的讑֮重复的次数和间隔旉。它有以下常用的属?/span> 参数?/span> 参数cd 备注 name String 触发器名U?/span> group String 触发器组名称 repeatCount int 重复ơ数Q注意:(x)如果?span style="font-family: Calibri">0表示不执行,-1表示不限制次敎ͼ直到q期Q,默认?span style="font-family: Calibri">0 repeatInterval long 间隔旉Q注意:(x)是以毫秒为单?/span> startTime Date 开始时_(d)默认当前旉 endTime Date q期旉Q默认一直执行(直到执行ơ数已达?span style="font-family: Calibri">repeatCountQ?/span> q个触发器的功能非常强大Q而且非常灉|Q但需要掌握有关的Cron表达式知?/span> 参数?/span> 参数cd 备注 name String 触发器名U?/span> group String 触发器组名称 cronEx CronExpression 规则表达?/span> startTime Date 开始时_(d)默认当前旉 endTime Date q期旉Q默认一直执行(直到执行ơ数已达?span style="font-family: Calibri">repeatCountQ?/span> 触发器规则表辑ּ配置Q?/span> 格式: [U?span>] [分] [时] [日] [月] [周] [q] 格式说明Q?/span> 位置 旉域名 是否必须 允许?/span> 允许通配W?/span> 1 U?/span> ?/span> 0-59 , - * / 2 ?/span> ?/span> 0-59 , - * / 3 时 ?/span> 0-23 , - * / 4 ?/span> ?/span> 1-31 , - * ? / L W 5 ?/span> ?/span> 1-12 , - * / 6 ?/span> ?/span> 1-7?span style="font-family: Calibri">MON-SUN , - * ? / L # 7 q?/span> ?/span> empty?span style="font-family: Calibri">1970-2099 , - * / 通配W说明:(x) * 可用在所有字D中Q表C对应时间域的每一个时刻,例如Q?span style="font-size: 9pt">*在分钟字D|Q表C?span style="font-size: 9pt">“每分?span style="font-size: 9pt">” ? 该字W只在日期和星期字段中用,它通常指定?span style="font-size: 9pt">“无意义的?span style="font-size: 9pt">”Q相当于点位W?/p> - 表示区间。例?在小时上讄 "10-12",表示 10,11,12炚w?x)触?/span> , 表示指定多个|例如在周字段上设|?span> "MON,WED,FRI" 表示周一Q周三和周五触发 / x/y表达一个等步长序列Q?span style="font-size: 9pt">xv始|y为增量步长倹{如在分钟字D中使用0/15Q则表示?span style="font-size: 9pt">0,15,30?span style="font-size: 9pt">45U,?span style="font-size: 9pt">5/15在分钟字D中表示5,20,35,50Q你也可以?span style="font-size: 9pt">*/yQ它{同?span style="font-size: 9pt">0/y L 该字W只在日期和星期字段中用,代表“Last”的意思,但它在两个字D中意思不同?span style="font-size: 9pt">L在日期字D中Q表C个月份的最后一天,如一月的31P非闰q二月的28P如果L用在星期中,则表C星期六Q等同于7。但是,如果L出现在星期字D里Q而且在前面有一个数?span style="font-size: 9pt">XQ则表示“q个月的最?span style="font-size: 9pt">X?span style="font-size: 9pt">”Q例如,6L表示该月的最后星期五 W 该字W只能出现在日期字段里,是对前导日期的修饎ͼ表示该日期最q的工作日。例?span style="font-size: 9pt">15W表示该?span style="font-size: 9pt">15hq的工作日,如果该月15h星期六,则匹?span style="font-size: 9pt">14h期五Q如?span style="font-size: 9pt">15日是星期日,则匹?span style="font-size: 9pt">16h期一Q如?span style="font-size: 9pt">15h星期二,那结果就?span style="font-size: 9pt">15h期二。但必须注意兌的匹配日期不能够跨月Q如你指?span style="font-size: 9pt">1WQ如?span style="font-size: 9pt">1h星期六,l果匚w的是3h期一Q而非上个月最后的那天?span style="font-size: 9pt">W字符串只能指定单一日期Q而不能指定日期范?/p> # 该字W只能在星期字段中用,表示当月某个工作日。如6#3表示当月的第三个星期?span style="font-size: 9pt">(6表示星期五,#3表示当前的第三个)Q?span style="font-size: 9pt">4#5表示当月的第五个星期三,假设当月没有W五个星期三Q忽略不触发 SimpleJob.java package com.test.job; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; public class SimpleJob implements Job{ public void execute(JobExecutionContext context) throws JobExecutionException { // your business logic // ... System.out.println("simpleJob running ...."); } } TestSimpleJob.java package com.test.job; import java.text.ParseException; import org.quartz.CronExpression; import org.quartz.CronTrigger; import org.quartz.JobDetail; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.SimpleTrigger; import org.quartz.impl.StdSchedulerFactory; public class TestSimpleJob { public static void main(String[] args){ try { Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); String jobName = "simpleJob"; String groupName = "DEFAULT"; //删除作业 if(scheduler.getJobDetail(jobName,groupName) != null){ scheduler.deleteJob(jobName, groupName); } //作业的详l信?/p>
//d名称QQ务组名称QQ务实现类 JobDetail jobDetail = new JobDetail(jobName,groupName,SimpleJob.class); //创徏单触发器 SimpleTrigger simpleTrigger = new SimpleTrigger("simpleTrigger",null); simpleTrigger.setRepeatCount(100); // 调用100?/p>
simpleTrigger.setRepeatInterval(5*1000); //?span style="font-family: 'Courier New'; color: #3f7f5f; font-size: 10pt">5U钟调用一?/p>
//注册作业 scheduler.scheduleJob(jobDetail, simpleTrigger); CronTrigger cronTrigger = new CronTrigger("cronTrigger",null); CronExpression cronExpression = null; try { cronExpression = new CronExpression("0 0 12 * * ?"); //每天12点运?/p>
cronTrigger.setCronExpression(cronExpression); //注册作业 scheduler.scheduleJob(jobDetail, cronTrigger); if(! scheduler.isShutdown()){ scheduler.start(); } } catch (ParseException e) { e.printStackTrace(); } } catch (SchedulerException e) { e.printStackTrace(); } } }
]]>
]]>
]]>
-Dcom.sun.management.jmxremote.port=9999 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false
然后可用如下代码q行q接Q?br />
JMXConnector jmxc = JMXConnectorFactory.connect(url);
mbs = jmxc.getMBeanServerConnection();
参考:(x)
]]>Java同步文g到Jboss虚拟目录
]]>SimpleTrigger
CronTrigger
]]>
]]>
Scheduler负责理Quartz的运行环境,Quartz它是Z多线E架构的Q它启动的时候会(x)初始化一套线E,q套U程?x)用来执行一些预|的作业?/span>
要创Z个作业ƈ能够被触发调用,必须?span style="font-family: Calibri">Scheduler上面注册一?span style="font-family: Calibri">JobDetail?span style="font-family: Calibri">Trigger?/span>
Scheduler提携?jin)所?span style="font-family: Calibri">Trigger?span style="font-family: Calibri">JobDetailQ它们协调工作。这?span style="font-family: Calibri">Trigger?span style="font-family: Calibri">JobDetail通过自n?span style="font-family: Calibri">name?span style="font-family: Calibri">group属性区?span>?/span>
Scheduler ?span style="font-family: Calibri">SchedulerFactory产生Q我们可以通过以下方式获取Scheduler的实例:(x)
//?span style="background: #d9d9d9">ServletContext
SchedulerFactory factory = (SchedulerFactory)
ServletActionContext.getServletContext().getAttribute("org.quartz.impl.StdSchedulerFactory.KEY");
//获取Scheduler对象
Scheduler defScheduler = factory.getScheduler();
dQ其实就是一个接口。要创徏一个Q务,必须得实现这个接口。该接口只有一个executeҎ(gu)QQ务每ơ被调用的时候都?x)执行这个executeҎ(gu)的逻辑?/span>
public class TestJob impletemens org.quartz.Job{
@Override
public void execute(JobExecutionContext context) throws JobExecutionException{
// you business logic
// …
System.out.println("########### this is testJob running ############");
}
}
JobDetail 用来保存我们作业的详l信息。一个JobDetail可以有多个TriggerQ但是一个Trigger只能对应一个JobDetail。下面是JobDetail的一些常用的属性和含义
参数?/span> |
cd |
备注 |
name |
String |
d的名Uͼ必须 |
group |
String |
d所在组Q默认ؓ(f)DEFAULT |
jobClass |
Class |
d的实现类Q必?/span> |
description |
String |
描述 |
jobDataMap |
JobDataMap |
用来l作业提供数据支持的数据l构 |
volatility |
Boolean |
重启应用之后是否删除d的相关信息,默认false |
durability |
Boolean |
d完成之后是否依然保留到数据库Q默?span style="font-family: Calibri">false |
shouldRecover |
Boolean |
应用重启之后时候忽略过期Q务,默认false |
jobListeners |
Set |
监听?/span> |
q是一个给作业提供数据支持的数据结构,使用Ҏ(gu)和java.util.Map一P非常方便。当一个作业被分配l调度器ӞJobDataMap实例随之生成?/p>
Job有一个StatefulJob子接口,代表有状态的dQ该接口是一个没有方法的标签接口Q其目的是让Quartz知道d的类型,以便采用不同的执行方案。无状态Q务在执行时拥有自qJobDataMap拯Q对JobDataMap的更改不?x)?jing)响下ơ的执行。而有状态Q务共享共享同一个JobDataMap实例Q每ơQ务执行对JobDataMap所做的更改?x)保存下来,后面的执行可以看到这个更改,也即每次执行d后都?x)对后面的执行发生?jing)响?/p>
正因个原因,无状态的Job可以q发执行Q而有状态的StatefulJob不能q发执行Q这意味着如果前次的StatefulJobq没有执行完毕,下一ơ的d阻塞等待,直到前次d执行完毕。有状态Q务比无状态Q务需要考虑更多的因素,E序往往拥有更高的复杂度Q因此除非必要,应该量使用无状态的Job?/p>
如果Q(jng)uartz使用?jin)数据库持久化Q务调度信息,无状态的JobDataMap仅会(x)在Scheduler注册d时保持一ơ,而有状态Q务对应的JobDataMap在每ơ执行Q务后都会(x)q行保存?/p>
JobDataMap实例也可以与一个触发器相关联。这U情况下Q对于同一作业的不同触发器Q我们可以在JobDataMap中添加不同的数据Q以便作业在不同旉执行时能够提供更为灵zȝ数据支持Q学校上午放g健操录音W一版,下午攄二版Q?/p>
不管是有状态还是无状态的dQ在d执行期间对Trigger的JobDataMap所做的更改都不?x)进行持久,也即不?x)对下ơ的执行产生影响?/p>
看你当前的JVM最大可用到多少内存Q用如下命o(h)Q?java -Xmx多大内存m -version
一定要在多大内存后面加上m哦,要不它认为是字节KB呢,?x)抛错?br />
首先创徏CZ的环境,
下面介绍的是最基础的{换器Q首先创Z个Personc:(x)
package com.thoughtworks.xstream.examples; public class Person { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }
接着Q我们创Z个实例,q{化他Q?/p>
package com.thoughtworks.xstream.examples; import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.io.xml.DomDriver; public class PersonTest { public static void main(String[] args) { Person person = new Person(); person.setName("Guilherme"); XStream xStream = new XStream(new DomDriver()); System.out.println(xStream.toXML(person)); } }
如你所料,得到下面的结果:(x)
<com.thoughtworks.xstream.examples.Person> <name>Guilherme</name> </com.thoughtworks.xstream.examples.Person>
下面我们为personcdZ个别名:(x)
XStream xStream = new XStream(new DomDriver()); xStream.alias("person", Person.class); System.out.println(xStream.toXML(person));
现在的结果就很易M(jin)Q?/font>
<person> <name>Guilherme</name> </person>
到此Q我们已l徏立好一个可以供我们实验的基例子?jin),下面我们来看看XStream的{换器能ؓ(f)我们做些什么:(x)
2Q创Z个Person转换器:(x)
下面我们来创Z个简单的转换器,它能Q?br />
1Q用来{换Personc?br />
2Q将Person实例转换成XML
3Q将xml转换为Person实例
首先创徏一个PersonConverterc,q让q个cd现Converter接口Q?/p>
package com.thoughtworks.xstream.examples; import com.thoughtworks.xstream.converters.Converter; import com.thoughtworks.xstream.converters.MarshallingContext; import com.thoughtworks.xstream.converters.UnmarshallingContext; import com.thoughtworks.xstream.io.HierarchicalStreamReader; import com.thoughtworks.xstream.io.HierarchicalStreamWriter; public class PersonConverter implements Converter { public boolean canConvert(Class clazz) { return false; } public void marshal(Object value, HierarchicalStreamWriter writer, MarshallingContext context) { } public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { return null; } }
下面Q我们首先告诉{换器Q我们只能{换Personc,而不是别的类Q包括其子类Q?/font>
public boolean canConvert(Class clazz) { return clazz.equals(Person.class); }
q一步很单,除非你是用来处理泛型的{换器是会(x)困难一炏V?/font>
MarshalҎ(gu)是用来将对象转换为XML的,他有三个参数Q?br />
1Q我们准备{换的对象
2Q我们准备输出对象的writer
3Q当前的marshaling context
首先我们object转换成Person
Person person = (Person) value;
接着Q我们就可以开始输出数据了(jin)Q首先我们创Z个叫做fullname的节点,q将person的名字传l他Q?/font>
writer.startNode("fullname"); writer.setValue(person.getName()); writer.endNode();
呵呵~很单吧Q?/font>
public void marshal(Object value, HierarchicalStreamWriter writer, MarshallingContext context) { Person person = (Person) value; writer.startNode("fullname"); writer.setValue(person.getName()); writer.endNode(); }
我们可以Lơ数的调用start/end nodeҎ(gu)Q但需要记住,你必d打开一个节点之后记住关闭它。一般来_(d)执行转换的操作在setValueҎ(gu)调用时发生?br /> 下面Q我们进入unmarshalҎ(gu)Q我们用moveDown和moveUpҎ(gu)在节Ҏ(gu)(wi)层次中移动,所以,q里我们只需要简单的moveDownQ得到|再moveUpQ?/font>
Person person = new Person(); reader.moveDown(); person.setName(reader.getValue()); reader.moveUp();
最后,我们得到?jin)一个这L(fng)转换器:(x)
package com.thoughtworks.xstream.examples; import com.thoughtworks.xstream.converters.Converter; import com.thoughtworks.xstream.converters.MarshallingContext; import com.thoughtworks.xstream.converters.UnmarshallingContext; import com.thoughtworks.xstream.io.HierarchicalStreamReader; import com.thoughtworks.xstream.io.HierarchicalStreamWriter; public class PersonConverter implements Converter { public boolean canConvert(Class clazz) { return clazz.equals(Person.class); } public void marshal(Object value, HierarchicalStreamWriter writer, MarshallingContext context) { Person person = (Person) value; writer.startNode("fullname"); writer.setValue(person.getName()); writer.endNode(); } public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { Person person = new Person(); reader.moveDown(); person.setName(reader.getValue()); reader.moveUp(); return person; } }
接着Q我们在我们的mainҎ(gu)中注册这个{化器Q?/p>
package com.thoughtworks.xstream.examples; import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.io.xml.DomDriver; public class PersonTest { public static void main(String[] args) { Person person = new Person(); person.setName("Guilherme"); XStream xStream = new XStream(new DomDriver()); xStream.registerConverter(new PersonConverter()); xStream.alias("person", Person.class); System.out.println(xStream.toXML(person)); } }
注意到我们怎么注册我们的{换器?jin)么Q只需要下面简单的一句:(x)
xStream.registerConverter(new PersonConverter());
最l得到的l果是:(x)
<person>
<fullname>Guilherme</fullname>
</person>
也许你会(x)_(d)(x)q只改变?jin)我输出的?wi)Q我需要用它来转换数据?br />
下面我们来尝试在person标签中创Z个叫做fullname的属性,而不是新创徏一个节点:(x)
3Q一U可选的方式Q?br />
首先Qؓ(f)Person创徏一个toStringҎ(gu)Q里面包含了(jin)所有能用来重新创徏一个Person实例的数据:(x)
package com.thoughtworks.xstream.examples; public class Person { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public String toString() { return getName(); } }
现在Q我们就能把我们的{化器写ؓ(f)Q?/font>
package com.thoughtworks.xstream.examples; import com.thoughtworks.xstream.converters.basic.AbstractSingleValueConverter; public class PersonConverter extends AbstractSingleValueConverter { public boolean canConvert(Class clazz) { return clazz.equals(Person.class); } public Object fromString(String str) { Person person = new Person(); person.setName(string); return person; } }
现在Q输出的XML也会(x)变得更易读(为person创徏别名person之后Q:(x)
<person>Guilherme</person>
名字变成?jin)一个内|的|而不是一个单独的节点?br />
4Q{换DateQ?br />
我们已经知道Converter接口是怎样工作的了(jin)Q现在我们来创徏一个用Locale对象转换旉的{换器Q?br />
在我们的转换器构造方法中Q我们将传入一个Locale对象Q该Locale对象?x)作Z个成员属性被转换器持有:(x)
package com.thoughtworks.xstream.examples; import java.util.Locale; import com.thoughtworks.xstream.converters.Converter; import com.thoughtworks.xstream.converters.MarshallingContext; import com.thoughtworks.xstream.converters.UnmarshallingContext; import com.thoughtworks.xstream.io.HierarchicalStreamReader; import com.thoughtworks.xstream.io.HierarchicalStreamWriter; public class DateConverter implements Converter { private Locale locale; public DateConverter(Locale locale) { super(); this.locale = locale; } public boolean canConvert(Class clazz) { return false; } public void marshal(Object value, HierarchicalStreamWriter writer, MarshallingContext context) { } public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { return null; } }
现在Q让我们能{换Q何承了(jin)Calendar对象的类Q?/font>
public boolean canConvert(Class clazz) {
return Calendar.class.isAssignableFrom(clazz);
}
首先Q我们来Calendar转换成本地化的字W串Q首先我们把object转化成Calendar,得到Date对象Qƈ使用DataFormatter来得C个本地化的时_(d)(x)
public void marshal(Object value, HierarchicalStreamWriter writer, MarshallingContext context) { Calendar calendar = (Calendar) value; // grabs the date Date date = calendar.getTime(); // grabs the formatter DateFormat formatter = DateFormat.getDateInstance(DateFormat.FULL, this.locale); // formats and sets the value writer.setValue(formatter.format(date)); }
另一斚wQ在unmarshallҎ(gu)中,我们创徏?jin)一个GregorianCalendarQ得到本地化的DataFormat实例Q将字符串{换成Date对象Qƈ赋值给GregorianCalendar?/font>
public Object unmarshal(HierarchicalStreamReader reader,
UnmarshallingContext context) {
// creates the calendar
GregorianCalendar calendar = new GregorianCalendar();
// grabs the converter
DateFormat formatter = DateFormat.getDateInstance(DateFormat.FULL,
this.locale);
// parses the string and sets the time
try {
calendar.setTime(formatter.parse(reader.getValue()));
} catch (ParseException e) {
throw new ConversionException(e.getMessage(), e);
}
// returns the new object
return calendar;
}
注意Q?br /> 1Q记住一些DataFormat实现不是U程安全的,所以,不要让你的{换器持有DataFormat的引?br /> 2Q在l过?jin)保存和加蝲的过E后Q该转换器可以将其他Calendar实现转换为GregorianCalendar。如果这不是你希望的Q只需要修改canConvertҎ(gu)Qƈ在类型只有ؓ(f)GregorianCalendar的时候再q回true?br /> 现在Q我们得C(jin)下面q个转换器:(x)
package com.thoughtworks.xstream.examples; import java.text.DateFormat; import java.text.ParseException; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.Locale; import com.thoughtworks.xstream.converters.ConversionException; import com.thoughtworks.xstream.converters.Converter; import com.thoughtworks.xstream.converters.MarshallingContext; import com.thoughtworks.xstream.converters.UnmarshallingContext; import com.thoughtworks.xstream.io.HierarchicalStreamReader; import com.thoughtworks.xstream.io.HierarchicalStreamWriter; public class DateConverter implements Converter { private Locale locale; public DateConverter(Locale locale) { super(); this.locale = locale; } public boolean canConvert(Class clazz) { return Calendar.class.isAssignableFrom(clazz); } public void marshal(Object value, HierarchicalStreamWriter writer, MarshallingContext context) { Calendar calendar = (Calendar) value; Date date = calendar.getTime(); DateFormat formatter = DateFormat.getDateInstance(DateFormat.FULL, this.locale); writer.setValue(formatter.format(date)); } public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { GregorianCalendar calendar = new GregorianCalendar(); DateFormat formatter = DateFormat.getDateInstance(DateFormat.FULL, this.locale); try { calendar.setTime(formatter.parse(reader.getValue())); } catch (ParseException e) { throw new ConversionException(e.getMessage(), e); } return calendar; } }
现在Q我们来试一下,创徏一个mainҎ(gu)Q?br />
1Q创Z个calendarQ?br />
2Q创建XStream对象
3Q注册该转换器,q用Brazilian Portuguese本地化对?br />
4Q将对象转化成XML
代码如下Q?/font>
package com.thoughtworks.xstream.examples; import java.util.Calendar; import java.util.GregorianCalendar; import java.util.Locale; import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.io.xml.DomDriver; public class DateTest { public static void main(String[] args) { // grabs the current date from the virtual machine Calendar calendar = new GregorianCalendar(); // creates the xstream XStream xStream = new XStream(new DomDriver()); // brazilian portuguese locale xStream.registerConverter(new DateConverter(new Locale("pt", "br"))); // prints the result System.out.println(xStream.toXML(calendar)); } }
可以得到cM如下的结果:(x)
<gregorian-calendar>Sexta-feira, 10 de Fevereiro de 2006</gregorian-calendar>
注意Q我们没有ؓ(f)GregorianCalendar创徏M别名Q而gregorian-calendar是默认的名字?br />
下面我们来试试unmarshal Ҏ(gu)Q?/p>
// loads the calendar from the string
Calendar loaded = (Calendar) xStream
.fromXML("<gregorian-calendar>Sexta-feira, 10 de Fevereiro de 2006</gregorian-calendar>");
然后打印?gu)日期Q?/p>
// prints using the system defined locale
System.out.println(DateFormat.getDateInstance(DateFormat.SHORT).format(
loaded.getTime()));
得到的结果ؓ(f)Q?/p>
2/10/06
5Q复杂的转换器:(x)
创徏另一个例子:(x)
我们已经创徏?jin)两个对象?jin)Q现在把它们l合hQ?/p>
package com.thoughtworks.xstream.examples; public class Birthday { private Person person; private Calendar date; public Person getPerson() { return person; } public void setPerson(Person person) { this.person = person; } public Calendar getDate() { return date; } public void setDate(Calendar date) { this.date = date; } }
要{换该c,XStream一炚w题都没有。这里,我们实现自己的{换器主要是ؓ(f)?jin)验证,在这里,我们想重用我们刚才的PersonConverter和CalendarConverter。canConvert仍然很简单,不过q里Q我们不需要再为每一个属性重新写转换Ҏ(gu)?jin),我们只需要用已l注册了(jin)的{换器来完成{换:(x)
package com.thoughtworks.xstream.examples; import java.util.Calendar; import com.thoughtworks.xstream.converters.Converter; import com.thoughtworks.xstream.converters.MarshallingContext; import com.thoughtworks.xstream.converters.UnmarshallingContext; import com.thoughtworks.xstream.io.HierarchicalStreamReader; import com.thoughtworks.xstream.io.HierarchicalStreamWriter; public class BirthdayConverter implements Converter { public boolean canConvert(Class clazz) { return Birthday.class == clazz; } public void marshal(Object value, HierarchicalStreamWriter writer, MarshallingContext context) { Birthday birthday = (Birthday)value; if (value.getPerson() != null) { writer.startNode("person"); context.convertAnother(value.getPerson()); writer.endNode(); } if (value.getDate() != null) { writer.startNode("birth"); context.convertAnother(value.getDate()); writer.endNode(); } } public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { Birthday birthday = new Birthday(); while (reader.hasMoreChildren()) { reader.moveDown(); if ("person".equals(reader.getNodeName())) { Person person = (Person)context.convertAnother(birthday, Person.class); birthday.setPerson(person); } else if ("birth".equals(reader.getNodeName())) { Calendar date = (Calendar)context.convertAnother(birthday, Calendar.class); birthday.setDate(date); } reader.moveUp(); } return birthday; } }
如果birthday实例能够保不会(x)出现null|那么我们可以去掉marshal和unmarshalҎ(gu)中对null情况的判断,也不需要@环,而直接根据tag的名字进行解析:(x)
package com.thoughtworks.xstream.examples; import java.util.Calendar; import com.thoughtworks.xstream.converters.Converter; import com.thoughtworks.xstream.converters.MarshallingContext; import com.thoughtworks.xstream.converters.UnmarshallingContext; import com.thoughtworks.xstream.io.HierarchicalStreamReader; import com.thoughtworks.xstream.io.HierarchicalStreamWriter; public class BirthdayConverter implements Converter { public boolean canConvert(Class clazz) { return Birthday.class == clazz; } public void marshal(Object value, HierarchicalStreamWriter writer, MarshallingContext context) { Birthday birthday = (Birthday)value; writer.startNode("person"); context.convertAnother(value.getPerson()); writer.endNode(); writer.startNode("birth"); context.convertAnother(value.getDate()); writer.endNode(); } public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { Birthday birthday = new Birthday(); reader.moveDown(); Person person = (Person)context.convertAnother(birthday, Person.class); birthday.setPerson(person); reader.moveUp(); reader.moveDown(); Calendar date = (Calendar)context.convertAnother(birthday, Calendar.class); birthday.setDate(date); reader.moveUp(); return birthday; } }