今天,复习黑马第6天学习的pull解析XML文档,结合第10天讲的JavaBean,突然了有了新的思考。
以下是我创建的XML文档:
<?xmlversion="1.0"encoding="UTF-8"?> <!--定义一个演示文档,存储黑马的所有班级,以及每个班级的信息 利用XML的功能之一:XML用来表示生活中有关系的数据 --> <itheima> <class> <name>Anroid70期</name> <teacher>于俏</teacher> <time>2015年6月21日</time> <count>77</count> </class> <class> <name>JavaEE70期</name> <teacher>张子艺</teacher> <time>2015年7月2日</time> <count>83</count> </class> </itheima>
下面是XML解析的Java代码:
//pull解析xml文档开始。。。。。 try{ //第1步:导入pull解析的包,得到pull解析工厂对象 XmlPullParserFactoryfactory=XmlPullParserFactory.newInstance(); //第2步:通过pull解析工厂得到pull解析器 XmlPullParserparser=factory.newPullParser(); //将XML文档的输入流引入pull解析器 InputStreamin=newFileInputStream("D:\\HeiMaDairy\\Other\\MyWorkSpace\\JDBCPractice\\WebRoot\\xml\\itheima.xml"); //指定解析器的输入流和编码集 parser.setInput(in,"utf-8"); //第4步:开始解析 //创建一个List集合,用来存储javabean,javabean会封装班级信息。 List<HeiMaClass>hmClassList=null; HeiMaClasshmClass=null; inttype=0; //标记解析的位置 while((type=parser.getEventType())!=XmlPullParser.END_DOCUMENT) //到了XML的文档末尾就结束解析 { //得到标签名,以作相应的判断。 StringtagName=parser.getName(); //用switch来判断解析的具体位置,比对标签名,采取相应的操作。 switch(type) { caseXmlPullParser.START_TAG: //开始标签 if("itheima".equals(tagName)) { //创建封装班级javabean的集合对象 hmClassList=newArrayList<HeiMaClass>(); } elseif("class".equals(tagName)) { //创建班级javabean,以封装数据 hmClass=newHeiMaClass(); } else { //得到标签内容,用来封装进javabeanhmClass中去。 StringtagText=parser.nextText(); //利用内省,直接用标签文本,也即Javabean的属性来获取对应 //写入方法来赋值。 try{ //内省重要代码************ //构造一个PropertyDescriptor对象 PropertyDescriptorpd=newPropertyDescriptor (tagName,hmClass.getClass()); //内省重要代码************//得到属性的写入方法 MethodwriteMethod=pd.getWriteMethod(); try{ //内省重要代码************ writeMethod.invoke(hmClass,tagText); }catch(Exceptione){ e.printStackTrace(); } }catch(IntrospectionExceptione){ e.printStackTrace(); } } break; caseXmlPullParser.END_TAG: //结束标签 if("class".equals(tagName)) { //将班级对象封装进List集合 hmClassList.add(hmClass); } break; } parser.next(); } //先在控制台上将List集合打印查看一下 for(HeiMaClasscla:hmClassList) { System.out.println(cla.toString()); } //将List集合写到Session域中,供请求页面获取输出 request.getSession().setAttribute("hmClassList2",hmClassList); //转发到请求页面 request.getRequestDispatcher("/pra/jdbc.jsp").forward(request,response); }catch(XmlPullParserExceptione){ e.printStackTrace(); }
在设计代码的时候,我采用的是javabean封装数据,XML文档中class这个标签对应的javabean代码如下:
//黑马班级类,用来演示pull解析XML,将XML中的班级数据封装到黑马班级类中。 publicclassHeiMaClass{ privateStringname,teacher,time,count; publicStringgetName(){ returnname; } publicvoidsetName(Stringname){ this.name=name; } publicStringgetTeacher(){ returnteacher; } publicvoidsetTeacher(Stringteacher){ this.teacher=teacher; } publicStringgetTime(){ returntime; } publicvoidsetTime(Stringtime){ this.time=time; } publicStringgetCount(){ returncount; } publicvoidsetCount(Stringcount){ this.count=count; } publicStringtoString() { returnthis.name+":"+this.teacher+":"+this.time+":"+this.count; } }
在用else if语句判断对应javabean中的属性标签名时,我发现继续都是用属性名对应的方法来封装数据。那么,有没有可能通过javabean的属性名称(即对应xml文档的标签名称),得到这个属性的set方法呢?
后来我看了一下张孝祥老师的高新技术最后几个视频,发现这个正是内省技术,于是众多的else if语句通过javabean就很轻松的完成了。内省的简单操作是通过java.beans下的PropertyDescriptor类来实现的,构造这个类的对象需传递属性名称和字节码文件,然后通过getWriteMethod即可得到属性对应的写入方法,然后利用反射的原理即可封装数据至javabean中。
-------------------------------------------------------------------------------------------
以前看了反射和内省,当时还是朦朦胧胧,不知道它们到底有什么了不起的。现在我慢慢地发现这些技术如果明白了话,真的是非常实用的,真的像老师所说的,可以让我们少写很多的代码。
同理,pull序列化(将内存中的集合、对象)写到xml文档中去,可以使用反射和内省来减写很多的代码。代码如下:
//从域中得到List集合,hmClassList2。 List<HeiMaClass>hmClassList=(List<HeiMaClass>)request.getSession().getAttribute("hmClassList2"); //准备进行集合的序列化 try{ //第1步:得到解析器工厂 XmlPullParserFactoryfactory=XmlPullParserFactory.newInstance(); //第2步:从解析器工厂得到序列化的接口 XmlSerializerserializer=factory.newSerializer(); //第3步:将文件输出流引入到序列化的接口 OutputStreamout=newFileOutputStream("C:\\Users\\LENOVO\\Desktop\\serializer.xml"); serializer.setOutput(out,"utf-8"); //第4步:正式开始序列化 //1。生成文档声明和文档结束 serializer.startDocument(null,true); //2.生成根标签<itheima> serializer.startTag(null,"itheima"); //3.遍历生成字标签 for(HeiMaClasshmClass:hmClassList) { //4.生成班级的开始和结束标签 serializer.startTag(null,"class"); //利用反射+内省技术,获取HeiMaClass这个javabean的所有属性,并获取它们的值写入xml文档。 Field[]fields=hmClass.getClass().getDeclaredFields(); //遍历字段 for(Fieldfield:fields) { //获取字段的属性名 StringpropertyName=field.getName(); //得到属性描述器 try{ PropertyDescriptorpd=newPropertyDescriptor(propertyName,hmClass.getClass()); //通过属性描述器得到字段对应的读取方法,获取得它的值并写入XML文档。 MethodreadMethod=pd.getReadMethod(); //调用方法获取属性值 try{ StringpropertyValue=(String)readMethod.invoke(hmClass); //生成开始和结束标签,并插入标签文本。 serializer.startTag(null,propertyName); serializer.text(propertyValue); serializer.endTag(null,propertyName); }catch(Exceptione){ e.printStackTrace(); } }catch(IntrospectionExceptione){ e.printStackTrace(); } } serializer.endTag(null,"class"); } serializer.endTag(null,"itheima"); serializer.endDocument(); //序列化成功,返回一个提示信息到request域中去 request.setAttribute("tipXML","XML文档创建成功,已保存到桌面。"); }catch(XmlPullParserExceptione){ //序列化失败,返回一个提示信息到request域中去,因为只想失败的一次请求提醒,所以不需要将提示写至session域中去。 request.setAttribute("tipXML","XML文档创建失败!"); e.printStackTrace(); }finally { //转发至请求页面 request.getRequestDispatcher("/pra/jdbc.jsp").forward(request,response); }
内省在WEB中的一个小小的应用,
原文链接:https://www.f2er.com/xml/296520.html