Java Axis2 1.6.3+JDK1.7.0_13+Tomcat7.0.65+eclipse搭建web service

  • 安装文件下载:

jdk1.7.0_13

安装步骤参考文章:http://jingyan.baidu.com/article/6dad5075d1dc40a123e36ea3.html

tomcat7.0.65

安装步骤参考文章:http://jingyan.baidu.com/article/870c6fc33e62bcb03fe4be90.html

axis2 1.6.3,官网http://axis.apache.org/axis2/java/core/download.cgi下载:WAR Distribution zip

下载到文件为:axis2-1.6.3-war.zip

sqljdbc4.jar

百度搜索sqljdbc,找到Microsoft JDBC Driver for SQL Server(微软官网)点开链接,建议下载sqljdbc_4.0.2206.100_enu.tar.gz,解压后把

参考文章:http://www.open-open.com/lib/view/1329999223671

http://blog.csdn.net/keenweiwei/article/details/7332261

eclipse,到官网下载即可。

  • 安装及配置:

1,)安装Java Jdk到E:JavaJava_Jdk1.7目录

2,)解压tomcat到E:Javaapache-tomcat-7.0.65

3,)sqljdbc.jar文件存放路径为:E:Javasqljdbcsqljdbc4.jar

4,)将axis2-1.6.3-war.zip加压,将解压出来的axis2.war文件拷贝到E:Javaapache-tomcat-7.0.65webapps下

5,)环境变量配置:

CLASSPATH
.;%JAVA_HOME%lib;%JAVA_HOME%lib ools.jar;E:Javasqljdbcsqljdbc4.jar
JAVA_HOME
E:JavaJava_Jdk1.7jdk1.7.0_13
CATALINA_HOME
E:Javaapache-tomcat-7.0.65
Path
追加%JAVA_HOME%in;%JAVA_HOME%jrein;

6,)安装tomcat7.0,cmd进入目录E:Javaapache-tomcat-7.0.65in 执行service.bat install命令,等待安装完成双击E:Javaapache-tomcat-7.0.65in omcat7w.exe,并运行该服务

7,)浏览器中输入地址:http:\localhost:8080回车,如果出现tomcat首页说明环境配置成功

8,)访问地址http:\localhost:8080axis2出现axis2页面说明axis2安装成功

9,)解压eclipse文件,并创建桌面快捷方式。

10,)拷贝E:Javasqljdbcsqljdbc4.jar到E:Javaapache-tomcat-7.0.65lib下

  • 开发

1,)运行eclipse,配置运行java jdk为为当前jdk,sever为当前tomcat7.0;

2,)创建web站点(webdynamic web project),起名为test.

3,)将E:Javaapache-tomcat-7.0.65workappsaxis2WEB-INF下的lib、conf、modules、services文件夹拷贝到test工程的WEB-INF下。

4,)清空工程WEB-INFservices下的文件,新建目录testMETA-INF\,再在WEB-INFservices estMETA-INF下新建文件services.xml,内容填写为:

<?xml version="1.0" encoding="UTF-8"?>
<service name="AccountService">  
    <description>  
        HelloWorld Service Example
    </description>  
    <parameter name="ServiceClass">  
        com.dt.webservices.AccountService
    </parameter>  
    <operation name="addUserInfo">  
        <messageReceiver class="org.apache.axis2.rpc.receivers.RPCMessageReceiver" />  
    </operation>
    <operation name="modifyUserInfo">  
        <messageReceiver class="org.apache.axis2.rpc.receivers.RPCMessageReceiver" />  
    </operation>
    <operation name="delUser">  
        <messageReceiver class="org.apache.axis2.rpc.receivers.RPCMessageReceiver" />  
    </operation>
    <operation name="modifyPwd">  
        <messageReceiver class="org.apache.axis2.rpc.receivers.RPCMessageReceiver" />  
    </operation>
    <operation name="queryUsers">  
        <messageReceiver class="org.apache.axis2.rpc.receivers.RPCMessageReceiver" />  
    </operation>
</service>

5,)修改工程下WEB-INFweb.xml内容为:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    id="WebApp_ID" version="3.0">
    <servlet>
        <servlet-name>AxisServlet</servlet-name>
        <servlet-class>org.apache.axis2.transport.http.AxisServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>AxisServlet</servlet-name>
        <url-pattern>/services/*</url-pattern>
    </servlet-mapping>
    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.htm</welcome-file>
        <welcome-file>index.jsp</welcome-file>
        <welcome-file>default.html</welcome-file>
        <welcome-file>default.htm</welcome-file>
        <welcome-file>default.jsp</welcome-file>
    </welcome-file-list>
</web-app>

6,)src下新建包com.dt.webservices,新建类AccountService.java

7,)新加入包E:Javasqljdbcsqljdbc4.jar

8,)编辑AccountService.java为:

  1 package com.dt.webservices;
  2 
  3 import java.sql.Connection;
  4 import java.sql.DriverManager;
  5 import java.sql.ResultSet;
  6 import java.sql.SQLException;
  7 import java.sql.Statement;
  8 
  9 import java.io.StringReader;
 10 
 11 import javax.xml.parsers.DocumentBuilder;
 12 import javax.xml.parsers.DocumentBuilderFactory;
 13 
 14 import org.w3c.dom.Document;
 15 import org.w3c.dom.Element;
 16 import org.w3c.dom.Node;
 17 import org.w3c.dom.NodeList;
 18 
 19 import org.xml.sax.InputSource;
 20 
 21 public class AccountService {
 22     /**
 23      * 新增接口
 24      * 
 25      * @param userInfos
 26      * @return 返回參數信息 xml格式。
 27      */
 28     public String addUserInfo(String userInfos) {
 29         String result = "";
 30 
 31         Boolean hasAnyError = false;
 32         String accId = "";
 33         String userPassword = "";
 34         String name = "";
 35         String email = "";
 36         StringBuffer accIds = new StringBuffer();
 37 
 38         try {
 39             DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
 40             DocumentBuilder builder = factory.newDocumentBuilder();
 41             Document doc = builder.parse(new InputSource(new StringReader(userInfos)));
 42 
 43             Element root = doc.getDocumentElement();
 44             NodeList accounts = root.getChildNodes();
 45             if (accounts != null) {
 46                 Class.forName(SQL2008R2Config.SQL2008R2_JDBC_DIRVER);
 47                 Connection connection = DriverManager.getConnection(SQL2008R2Config.SQL2008R2_JDBC_URL,
 48                         SQL2008R2Config.SQL2008R2_ACCOUNT, SQL2008R2Config.SQL2008R2_PWD);
 49                 Statement stmt = connection.createStatement();
 50 
 51                 for (int i = 0; i < accounts.getLength(); i++) {
 52                     Node accountNode = accounts.item(i);
 53                     //...
 54                 }
 55 
 56                 stmt.close();
 57                 connection.close();
 58             } else {
 59                 hasAnyError = true;
 60             }
 61         } catch (Exception ex) {
 62             hasAnyError = true;
 63             ex.printStackTrace();
 64         }
 65 
 66         if (hasAnyError) {
 67             result = "...";
 68         } else {
 69             result = "...";
 70         }
 71 
 72         return result;
 73     }
 74 
 75     /**
 76      * 修改接口
 77      * 
 78      * @param userInfos
 79      * @return 返回操作是否成功信息 xml格式。
 80      */
 81     public String modifyUserInfo(String userInfos) {
 82         String result = "";
 83         Boolean hasAnyError = false;
 84         String accId = "";
 85         String name = "";
 86         String email = "";
 87         StringBuffer accIds = new StringBuffer();
 88 
 89         try {
 90             DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
 91             DocumentBuilder builder = factory.newDocumentBuilder();
 92             Document doc = builder.parse(new InputSource(new StringReader(userInfos)));
 93 
 94             Element root = doc.getDocumentElement();
 95             NodeList accounts = root.getChildNodes();
 96             if (accounts != null) {
 97                 Class.forName(SQL2008R2Config.SQL2008R2_JDBC_DIRVER);
 98                 Connection connection = DriverManager.getConnection(SQL2008R2Config.SQL2008R2_JDBC_URL,
 99                         SQL2008R2Config.SQL2008R2_ACCOUNT, SQL2008R2Config.SQL2008R2_PWD);
100                 Statement stmt = connection.createStatement();
101 
102                 for (int i = 0; i < accounts.getLength(); i++) {
103                     Node accountNode = accounts.item(i);
104                     //....
105                 }
106 
107                 stmt.close();
108                 connection.close();
109             } else {
110                 hasAnyError = true;
111             }
112         } catch (Exception ex) {
113             hasAnyError = true;
114             ex.printStackTrace();
115         }
116 
117         if (hasAnyError) {
118             result = "...";
119         } else {
120             result = "...";
121         }
122 
123         return result;
124     }
125 
126     /**
127      * 删除接口
128      * 
129      * @param userIDs
130      * @return 返回操作状态信息 xml格式。
131      */
132     public String delUser(String userIDs) {
133         String result = "";
134         Boolean hasAnyError = false;
135         String accId = "";
136         StringBuffer accIds = new StringBuffer();
137 
138         try {
139             DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
140             DocumentBuilder builder = factory.newDocumentBuilder();
141             Document doc = builder.parse(new InputSource(new StringReader(userIDs)));
142 
143             Element root = doc.getDocumentElement();
144             NodeList accounts = root.getChildNodes();
145             if (accounts != null) {
146                 Class.forName(SQL2008R2Config.SQL2008R2_JDBC_DIRVER);
147                 Connection connection = DriverManager.getConnection(SQL2008R2Config.SQL2008R2_JDBC_URL,
148                         SQL2008R2Config.SQL2008R2_ACCOUNT, SQL2008R2Config.SQL2008R2_PWD);
149                 Statement stmt = connection.createStatement();
150 
151                 for (int i = 0; i < accounts.getLength(); i++) {
152                     Node accountNode = accounts.item(i);
153                     //....
154                 }
155 
156                 stmt.close();
157                 connection.close();
158             } else {
159                 hasAnyError = true;
160             }
161         } catch (Exception ex) {
162             hasAnyError = true;
163             ex.printStackTrace();
164         }
165 
166         if (hasAnyError) {
167             result = "xxxx";
168         } else {
169             result = "xxxx";
170         }
171 
172         return result;
173     }
174 
175     /**
176      * 修改
177      * 
178      * @param userInfos
179      * @return 操作信息结果 xml
180      */
181     public String modifyPwd(String userInfos) {
182         String result = "";
183         Boolean hasAnyError = false;
184         String accId = "";
185         String userPassword = "";
186 
187         try {
188             DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
189             DocumentBuilder builder = factory.newDocumentBuilder();
190             Document doc = builder.parse(new InputSource(new StringReader(userInfos)));
191 
192             Element root = doc.getDocumentElement();
193             NodeList accounts = root.getChildNodes();
194             if (accounts != null) {
195                 Class.forName(SQL2008R2Config.SQL2008R2_JDBC_DIRVER);
196                 Connection connection = DriverManager.getConnection(SQL2008R2Config.SQL2008R2_JDBC_URL,
197                         SQL2008R2Config.SQL2008R2_ACCOUNT, SQL2008R2Config.SQL2008R2_PWD);
198                 Statement stmt = connection.createStatement();
199 
200                 for (int i = 0; i < accounts.getLength(); i++) {
201                     Node accountNode = accounts.item(i);
202                     if (accountNode.getNodeName() == "account") {
203                         NodeList accountMembers = accountNode.getChildNodes();
204                         accId = "";
205                         userPassword = "";
206 
207                         // ........
208                     }
209                 }
210 
211                 stmt.close();
212                 connection.close();
213             } else {
214                 hasAnyError = true;
215             }
216         } catch (Exception ex) {
217             hasAnyError = true;
218             ex.printStackTrace();
219         }
220 
221         if (hasAnyError) {
222             result = "/....";           
223         } else {
224             result = "/....";          
225         }
226 
227         return result;
228     }
229 
230     /**
231      * 
232      * @param233      * @return String
234      */
235     public String queryUsers() {
236         String result = "";
237 
238         Connection connection = null;
239         Statement stmt = null;
240         ResultSet rs = null;
241 
242         try {
243             Class.forName(SQL2008R2Config.SQL2008R2_JDBC_DIRVER);
244             connection = DriverManager.getConnection(SQL2008R2Config.SQL2008R2_JDBC_URL,
245                     SQL2008R2Config.SQL2008R2_ACCOUNT, SQL2008R2Config.SQL2008R2_PWD);
246 
247             String sql = "select * from dbo.test";
248 
249             stmt = connection.createStatement();
250             rs = stmt.executeQuery(sql);
251 
252             result = "<?xml version="1.0" encoding="UTF-8"?>";
253             result += "<as>";
254 
255             if (!rs.wasNull()) {
256                 while (rs.next()) {
257                     result += "    <a>";
258                     result += "        <name>" + rs.getString("RealName") + "</name>";
259                     result += "    </a>";
260                 }
261             }
262             result += "</as>";
263 
264             rs.close();
265             stmt.close();
266             connection.close();
267         } catch (Exception ex) {
268             ex.printStackTrace();
269         }
270 
271         return result;
272     }
273 }
View Code
 1 package com.dt.webservices;
 2 
 3 import java.sql.*;
 4 
 5 public class SQL2008R2Config {
 6     public static final String SQL2008R2_SERVER = "17.1.1.1\dk";
 7     public static final String SQL2008R2_DBNAME = "db_test";
 8     public static final String SQL2008R2_ACCOUNT = "sa";
 9     public static final String SQL2008R2_PWD = "123";
10     public static final String SQL2008R2_JDBC_URL = "jdbc:sqlserver://"+SQL2008R2_SERVER+";databaseName="+SQL2008R2_DBNAME;
11     public static final String SQL2008R2_JDBC_DIRVER = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
12 };
View Code

9,)发布服务到tomcat7.0下

10,)访问地址http://localhost:8080/test/services/AccountService?wsdl

  • 客户端调用测试

1,)使用svcutil.exe生成client.cs,和app.config

app.config

 1 <?xml version="1.0"?>
 2 <configuration>
 3 <startup>
 4   <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
 5 </startup>
 6   <system.serviceModel>
 7     <bindings>
 8       <basicHttpBinding>
 9         <binding name="AccountServiceSoap11Binding" />
10       </basicHttpBinding>
11       <customBinding>
12         <binding name="AccountServiceSoap12Binding">
13           <textMessageEncoding messageVersion="Soap12" />
14           <httpTransport />
15         </binding>
16       </customBinding>
17     </bindings>
18     <client>
19       <endpoint address="http://localhost:8080/test/services/AccountService.AccountServiceHttpSoap11Endpoint/"
20           binding="basicHttpBinding" bindingConfiguration="AccountServiceSoap11Binding"
21           contract="AccountServicePortType" name="AccountServiceHttpSoap11Endpoint" />
22       <endpoint address="http://localhost:8080/test/services/AccountService.AccountServiceHttpSoap12Endpoint/"
23           binding="customBinding" bindingConfiguration="AccountServiceSoap12Binding"
24           contract="AccountServicePortType" name="AccountServiceHttpSoap12Endpoint" />
25     </client>
26   </system.serviceModel>
27 </configuration>
View Code

client.cs

 1 //------------------------------------------------------------------------------
 2 // <auto-generated>
 3 //     此代码由工具生成。
 4 //     运行时版本:4.0.30319.18408
 5 //
 6 //     对此文件的更改可能会导致不正确的行为,并且如果
 7 //     重新生成代码,这些更改将会丢失。
 8 // </auto-generated>
 9 //------------------------------------------------------------------------------
10 
11 
12 
13 [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
14 [System.ServiceModel.ServiceContractAttribute(Namespace="http://webservices.dt.com", ConfigurationName="AccountServicePortType")]
15 public interface AccountServicePortType
16 {
17     
18     [System.ServiceModel.OperationContractAttribute(Action="urn:queryUsers", ReplyAction="urn:queryUsersResponse")]
19     [return: System.ServiceModel.MessageParameterAttribute(Name="return")]
20     string queryUsers();
21     
22     [System.ServiceModel.OperationContractAttribute(Action="urn:addUserInfo", ReplyAction="urn:addUserInfoResponse")]
23     [return: System.ServiceModel.MessageParameterAttribute(Name="return")]
24     string addUserInfo(string userInfos);
25     
26     [System.ServiceModel.OperationContractAttribute(Action="urn:modifyPwd", ReplyAction="urn:modifyPwdResponse")]
27     [return: System.ServiceModel.MessageParameterAttribute(Name="return")]
28     string modifyPwd(string userInfos);
29     
30     [System.ServiceModel.OperationContractAttribute(Action="urn:modifyUserInfo", ReplyAction="urn:modifyUserInfoResponse")]
31     [return: System.ServiceModel.MessageParameterAttribute(Name="return")]
32     string modifyUserInfo(string userInfos);
33     
34     [System.ServiceModel.OperationContractAttribute(Action="urn:delUser", ReplyAction="urn:delUserResponse")]
35     [return: System.ServiceModel.MessageParameterAttribute(Name="return")]
36     string delUser(string userIDs);
37 }
38 
39 [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
40 public interface AccountServicePortTypeChannel : AccountServicePortType, System.ServiceModel.IClientChannel
41 {
42 }
43 
44 [System.Diagnostics.DebuggerStepThroughAttribute()]
45 [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
46 public partial class AccountServicePortTypeClient : System.ServiceModel.ClientBase<AccountServicePortType>, AccountServicePortType
47 {
48     
49     public AccountServicePortTypeClient()
50     {
51     }
52     
53     public AccountServicePortTypeClient(string endpointConfigurationName) : 
54             base(endpointConfigurationName)
55     {
56     }
57     
58     public AccountServicePortTypeClient(string endpointConfigurationName, string remoteAddress) : 
59             base(endpointConfigurationName, remoteAddress)
60     {
61     }
62     
63     public AccountServicePortTypeClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) : 
64             base(endpointConfigurationName, remoteAddress)
65     {
66     }
67     
68     public AccountServicePortTypeClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) : 
69             base(binding, remoteAddress)
70     {
71     }
72     
73     public string queryUsers()
74     {
75         return base.Channel.queryUsers();
76     }
77     
78     public string addUserInfo(string userInfos)
79     {
80         return base.Channel.addUserInfo(userInfos);
81     }
82     
83     public string modifyPwd(string userInfos)
84     {
85         return base.Channel.modifyPwd(userInfos);
86     }
87     
88     public string modifyUserInfo(string userInfos)
89     {
90         return base.Channel.modifyUserInfo(userInfos);
91     }
92     
93     public string delUser(string userIDs)
94     {
95         return base.Channel.delUser(userIDs);
96     }
97 }
View Code

2,)测试调用代码:

 1 static void Main(string[] args)
 2         {
 3             using (AccountServicePortTypeClient client = new AccountServicePortTypeClient("AccountServiceHttpSoap11Endpoint"))
 4             {
 5                 string addUserInfoParameter = "<?xml version="1.0" encoding="UTF-8"?>";
 6                 addUserInfoParameter += "<accounts>";
 7                 addUserInfoParameter += "   <account>";
 8                 addUserInfoParameter += "       <accId>test22</accId>";
 9                 addUserInfoParameter += "       <userPassword>z3ux4rpW0H3QbY47pjZa6w==</userPassword>";
10                 addUserInfoParameter += "       <name>test22</name>";
11                 addUserInfoParameter += "       <description>描述</description>";
12                 addUserInfoParameter += "       <email>test22@catt.cn</email>";
13                 addUserInfoParameter += "       <nation>汉族</nation>";
14                 addUserInfoParameter += "   </account>";
15                 addUserInfoParameter += "   <account>";
16                 addUserInfoParameter += "       <accId>test23</accId>";
17                 addUserInfoParameter += "       <userPassword>z3ux4rpW0H3QbY47pjZa6w==</userPassword>";
18                 addUserInfoParameter += "       <name>test23</name>";
19                 addUserInfoParameter += "       <description>描述</description>";
20                 addUserInfoParameter += "       <email>test23@catt.cn</email>";
21                 addUserInfoParameter += "       <nation>汉族</nation>";
22                 addUserInfoParameter += "   </account>";
23                 addUserInfoParameter += "</accounts>";
24                 Console.WriteLine("addUserInfo:{0}", client.addUserInfo(addUserInfoParameter));
25 
26                 string modifyUserInfoParameter = "<?xml version="1.0" encoding="UTF-8"?>";
27                 modifyUserInfoParameter += "<accounts>";
28                 modifyUserInfoParameter += "   <account>";
29                 modifyUserInfoParameter += "       <accId>test22</accId>";
30                 modifyUserInfoParameter += "       <userPassword>z3ux4rpW0H3QbY47pjZa6w==</userPassword>";
31                 modifyUserInfoParameter += "       <name>test232</name>";
32                 modifyUserInfoParameter += "       <description>描述</description>";
33                 modifyUserInfoParameter += "       <email>test232@catt.cn</email>";
34                 modifyUserInfoParameter += "       <nation>汉族</nation>";
35                 modifyUserInfoParameter += "   </account>";
36                 modifyUserInfoParameter += "   <account>";
37                 modifyUserInfoParameter += "       <accId>test23</accId>";
38                 modifyUserInfoParameter += "       <userPassword>z3ux4rpW0H3QbY47pjZa6w==</userPassword>";
39                 modifyUserInfoParameter += "       <name>test233</name>";
40                 modifyUserInfoParameter += "       <description>描述</description>";
41                 modifyUserInfoParameter += "       <email>test233@catt.cn</email>";
42                 modifyUserInfoParameter += "       <nation>汉族</nation>";
43                 modifyUserInfoParameter += "   </account>";
44                 modifyUserInfoParameter += "</accounts>";
45                 Console.WriteLine("modifyUserInfo:{0}", client.modifyUserInfo(modifyUserInfoParameter));
46 
47                 string modifyParameter = "<?xml version="1.0" encoding="UTF-8"?>";
48                 modifyParameter += "<accounts>";
49                 modifyParameter += "    <account>";
50                 modifyParameter += "        <accId>admin</accId>";
51                 modifyParameter += "        <userPassword>z3ux4rpW0H3QbY47pjZa6w==</userPassword>";
52                 modifyParameter += "    </account>";
53                 modifyParameter += "</accounts>";
54 
55                 Console.WriteLine("modifyPwd:{0}", client.modifyPwd(modifyParameter));
56 
57                 string delUserParameter = "<?xml version="1.0" encoding="UTF-8"?>";
58                 delUserParameter += "<accounts>";
59                 delUserParameter += "   <accId>test</accId>";
60                 delUserParameter += "   <accId>admin</accId>";
61                 delUserParameter += "</accounts>";
62                 Console.WriteLine("delUser:{0}", client.delUser(delUserParameter));
63 
64                 Console.WriteLine("queryUsers:{0}", client.queryUsers());
65 
66             }
67 
68             Console.ReadKey();
69         }

参考文章:

axis2 1.6.3+tomcat7.0+jdk7.0+sqlserver
tomcat
http://jingyan.baidu.com/article/870c6fc33e62bcb03fe4be90.html
jdk
http://jingyan.baidu.com/article/6dad5075d1dc40a123e36ea3.html
demo
http://www.cnblogs.com/javawebsoa/archive/2013/05/19/3087234.html
http://jingyan.baidu.com/article/a3761b2bbe092c1576f9aa29.html
map foreach
http://blog.csdn.net/tjcyjd/article/details/11111401
客户端调用:
http://m.blog.csdn.net/blog/jiqiujia/37097249
http://blog.csdn.net/yhhah/article/details/4158487

原文地址:https://www.cnblogs.com/yy3b2007com/p/4943593.html