(一)解析第三方接口封装为对象

     最近做了一个还算可以上手的外包项目,就是解析第三方接口的数据然后展示在页面中,整个项目做下来还是有很多收获的,学到的有很多,包括xml的解析,echarts曲线的应用,video标签的应用及添加定时任务器定时刷新数据库等,耗时将近两个月,在这里先做一个简单的整理,后续还会继续完善。
     1、得到第三方给的开放接口说明文档。
           1)、接口地址:
              http://对方ip:8080/my/service/TestService?wsdl
           2)、接口安全:
            出于安全的考虑:接收到的接口消息都会检验用户名和密码,故接口都需要带Head。
           3)、接口方法:
            接口方法中都会给出参数和返回值。如:
           sendMsg:
                      参数:account String 用户登录名
                          返回值:unitId  单元UUID                   
                                         unitName 单元名称

              WSDL是Web Services Description Language的缩写,是一个用来描述Web服务和说明如何与Web服务通信的XML 语言。它的工具是wsdl2java,这时就需要用wsdl2java生成客户端代码。
              生成客户端常用的大概就是三种方式:CXF、axis2、axis,Axis2 是Axis的后续版本,是新一代的SOAP引擎。使用axis提供的工具类org.apache.axis.wsdl.WSDL2Java先生成客户端stub,然后像使用本地方法一样调用远程接口。这里我用到的是CXF,生成一大堆java文件,具体我也没怎么看明白都是什么 ,后来领导让我用axis2来生成,再后来也还是没有用到,直接问第三方人员要了两个文件进行wsdl接口实现,拉出了第三方的xml数据。

 CXF生成客户端的过程: 引用
1、下载apache-cxf-3.1.7工具
2、环境配置path及CXF-HOME路径。
3、cmd中输入wsdl2java验证是否配置成功。
4、输入命令wsdl -d +(生成代码所在目录) -client +(路径)

附录:
-d:指定生成的客户端生成  目录
-p:指定生成的客户端包名
-client:指定生成客户端调用类, 即包含main方法调用客户端方法的类
-t:为代码生成测试用例
-g:生成服务端和客户端代码
-ssi:为服务端实现代码生成接口类
2、wsdl生成xml文档
1>将URL及账户信息封装到properties文件。利用ResourceBundle调用。
Java code
?
1
2
3
4
5
config.properties:
 
uri=http: //对方ip:8080/my/service/TestService?wsdl
otherAccount=me
otherPassword= 123456
2>
Java code
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
ClientAuthInterceptor:
 
import  org.apache.cxf.binding.soap.SoapMessage;
import  org.apache.cxf.binding.soap.interceptor.AbstractSoapInterceptor;
import  org.apache.cxf.headers.Header;
import  org.apache.cxf.helpers.DOMUtils;
import  org.apache.cxf.interceptor.Fault;
import  org.apache.cxf.phase.Phase;
import  org.w3c.dom.Document;
import  org.w3c.dom.Element;
import  javax.xml.namespace.QName;
import  java.util.List;
 
public  class  ClientAuthInterceptor  extends  AbstractSoapInterceptor
{
     private  String    userName;
     private  String    password;
     
     public  ClientAuthInterceptor()
     {
         super (Phase.WRITE);
     }
     
     public  ClientAuthInterceptor(String userName, String password)
     {
         super (Phase.PREPARE_SEND);
         this .userName = userName;
         this .password = password;
     }
     
     public  String getUserName()
     {
         return  userName;
     }
     
     public  void  setUserName(String userName)
     {
         this .userName = userName;
     }
     
     public  String getPassword()
     {
         return  password;
     }
     
     public  void  setPassword(String password)
     {
         this .password = password;
     }
     
     public  void  handleMessage(SoapMessage msg)  throws  Fault
     {
         List
 headers = msg.getHeaders();
         // 创建Document对象
         Document doc = DOMUtils.createDocument();
         Element ele = doc.createElement( "authHeader" );
         // 配置服务器端Head信息的用户密码
         Element eleId = doc.createElement( "username" );
         eleId.setTextContent(userName);
         Element elePass = doc.createElement( "password" );
         elePass.setTextContent(password);   
         ele.appendChild(eleId);
         ele.appendChild(elePass);
         // 生成的XML文档
         /**
         
          用户名
          密码
         
          */
         headers.add( new  Header( new  QName( "" ), ele));
     }
}

3>
Java code
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
OpenInterface:
 
import  org.apache.cxf.endpoint.Client;
import  org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;
public  class  OpenInterface {
           public  static  final  String CONFIG_FILE_NAME =  "config" ;  
           //自动扫描properties文件名为“config”的文件
      ResourceBundle bundle = PropertyResourceBundle.getBundle(CONFIG_FILE_NAME);  
          //将“config.properties”文件封装到bundle中。
           public  void  getMsg() {
         JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
         Client client = dcf.createClient(bundle.getString( "uri" ));    
                  //引用bundle获取config中的uri即wsdl的地址。
         client.getOutInterceptors().add( new  ClientAuthInterceptor(bundle.getString( "otherAccount" ),   
                 bundle.getString( "otherCmpLoginPassword" ))); 
                 //调用ClientAuthInterceptor,获取到设定的用户名和密码
         try  {
             Object array = client.invoke( "sendMsg" "xxx" );  
                 //sendMsg为第三方的接口方法,“xxx”为此方法所传入的参数。
             int  length = java.lang.reflect.Array.getLength(array);
             List list =  new  ArrayList();
             for  ( int  i =  0 ; i < length; i++) {
                 list.add(java.lang.reflect.Array.get(array, i));
             }
             String str = (length ==  0  ""  : list.get( 0 ).toString());
                         System.out.print{str};
}
}

此时,就会在控制台输出一个xml文件,接口测试也就成功,接下来就该解析xml了。

3、解析xml
        解析xml有很多种方式,有DOM,DOM4J,SAX,jaxb等,我用到的是DOM4J和jaxb,jaxb可以快速解析xml,DOM4J可以从遍历节点来一个一个解析着手。如:
引用



       
          --
          01
          温度器



(1)每个数据都有所对应的节点名称故用jaxb。
引用


      11223243342345
      
        
          time
          
            2016-08-31 00:00:47
            2016-08-31 08:28:07
          

        

        
          温度器2
        

        
          value
          
            33.0
            33.0
          

        

      

    

  
(2)
这时节点名称与关键字重合,无法建立对应的对象,故使用DOM4J解析。 这里,我先讲jaxb的解析:
1>
Java code
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
JaxbUtil:
 
import  javax.xml.bind.JAXBContext;
import  javax.xml.bind.Marshaller;
import  javax.xml.bind.Unmarshaller;
import  java.io.StringReader;
import  java.io.StringWriter;
/**
  * Jaxb2工具类
  */
public  class  JaxbUtil {
     /**
      * JavaBean转换成xml
      * 默认编码UTF-8
      * @param obj
      * @param writer
      * @return
      */
     public  static  String convertToXml(Object obj) {
         return  convertToXml(obj,  "UTF-8" );
     }
     /**
      * JavaBean转换成xml
      * @param obj
      * @param encoding
      * @return
      */
     public  static  String convertToXml(Object obj, String encoding) {
         String result =  null ;
         try  {
             JAXBContext context = JAXBContext.newInstance(obj.getClass());
             Marshaller marshaller = context.createMarshaller();
             marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,  true );
             marshaller.setProperty(Marshaller.JAXB_ENCODING, encoding);
 
             StringWriter writer =  new  StringWriter();
             marshaller.marshal(obj, writer);
             result = writer.toString();
         catch  (Exception e) {
             e.printStackTrace();
         }
 
         return  result;
     }
 
     /**
      * xml转换成JavaBean
      * @param xml
      * @param c
      * @return
      */
     @SuppressWarnings ( "unchecked" )
     public  static   T converyToJavaBean(String xml, Class c) {
         T t =  null ;
         try  {
             JAXBContext context = JAXBContext.newInstance(c);
             Unmarshaller unmarshaller = context.createUnmarshaller();
             t = (T) unmarshaller.unmarshal( new  StringReader(xml));
         catch  (Exception e) {
             e.printStackTrace();
         }
         return  t;
     }
}

2>创建xml所对应的对象类。
Java code
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
EnvionmentType:
 
import  javax.xml.bind.annotation.*;
import  java.util.List;
@XmlAccessorType (XmlAccessType.FIELD)
@XmlRootElement (name = "DeviceType" )    //xml的根目录
@XmlType (propOrder ={ "combo" })   // 解析xml所有的对象属性
public  class  EnvionmentType {
     @XmlElementWrapper (name =  "combos" )    //此对象属性包含于combos中
     @XmlElement (name =  "Combo" )    // 此对象属性在xml中的映射
     private  List combo;      //属性combo
     public  List getCombo() {
         return  combo;
     }
     public  void  setCombo(List combo) {
         this .combo = combo;
     }
     @Override
     public  String toString() {
         return  "DeviceTypeResponse" +combo;
     }
}

Java code
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
Combo:
 
import  javax.xml.bind.annotation.XmlAccessType;
import  javax.xml.bind.annotation.XmlAccessorType;
import  javax.xml.bind.annotation.XmlElement;
import  javax.xml.bind.annotation.XmlType;
@XmlAccessorType (XmlAccessType.FIELD)
@XmlType (propOrder = {  "id" , "text" , "attr"  })
public  class  Combo  {
     @XmlElement (name =  "id" )
     private  String id;      //编号
     @XmlElement (name =  "text" )
     private  String text;    //名称
     @XmlElement (name =  "attr" )
     private  String attr;   //单位
     public  String getAttr() {
         return  attr;
     }
     public  void  setAttr(String attr) {
         this .attr = attr;
     }
     public  String getId() {
         return  id;
     }
     public  void  setId(String id) {
         this .id = id;
     }
     public  String getText() {
         return  text;
     }
     public  void  setText(String text) {
         this .text = text;
     }
     @Override
     public  String toString() {
         return  "Combo [id="  + id +  ",text="  + text +  ",attr="  + attr+ "]" ;
     }
}

注:对象属性一定要与xml的节点名所对应,否则就会报错,若想新建一个属性不存在xml中,则在属性上加 @XmlTransient或者@XmlAttribute。
3>解析
Java code
?
1
2
3
4
OpenInterface:
 
  EnvionmentType envionmentType = JaxbUtil.converyToJavaBean(str, EnvionmentType. class );
  System.out.println(envionmentType);

此时数据就已解析出来,封装为envionmentType对象。
4>将对象存入数据库中
Java code
?
1
2
3
4
5
6
7
8
9
10
OpenInterface:
@Autowired
     private  EnvionmenttypeService    envionmenttypeService;
for  (Combo m : envionmentType.getCombo()) {
                     Combo combo =  new  Combo();
                     combo.setId(m.getId());
                     combo.setText(m.getText());
                     combo.setAttr(m.getAttr());
                     envionmenttypeService.save(combo);
                 }

你可能感兴趣的:((一)解析第三方接口封装为对象)