1. 程式人生 > >WebService開發(C#)+Java呼叫-教程

WebService開發(C#)+Java呼叫-教程

 

注:1.本文重點講如何實現

        2.本文包括WebService介面開發、JavaWeb呼叫等問題

        3.原始碼已提交到github,Webservice介面:https://github.com/Bobo-peng/WebService

                                                      JavaWeb呼叫:

https://github.com/Bobo-peng/JavaWebService     

一、WebService簡介

1.什麼是WebService?

        WebService是一種跨語言、誇平臺的遠端呼叫技術,或者說叫作一種技術標準。之所以叫WebService,是因為和Web服務類似,基於http協議(使用抓包就可以看到是http傳送請求和接收結果),其主要作用在於向外暴露介面。

       說直白一點,就是這個技術標準想要達到的目的是:開啟一個服務,並留出介面,讓其他人來呼叫(重點是可以遠端呼叫)。舉例:使用者檢視一個網站的資料,一般就是檢視該網站就完了;但是使用者不喜歡用該網站公司的網頁佈局,想自己做一個炫酷的網頁來展示一下資料,但是獲取不到網站公司的資料庫(資料庫不可能對外公開),這時就用WebService開發幾個介面提供給使用者,這些介面返回使用者想要的資料(資料格式可以自定義,使用json或者xml等),使用者就像調函式一樣間接獲取了想要的資料,然後去開發自己的網頁、展示。

2.WebService介面體驗

       看一下常用的WebService介面-天氣預報,這是國家氣象局提供的天氣預報介面:

http://www.webxml.com.cn/WebServices/WeatherWebService.asmx

第一個介面:

不傳引數,返回所以可查詢的城市:

    其他的介面可以自己點開根據說明看看。

    在連線的後面加上?wsdl

http://www.webxml.com.cn/webservices/weatherwebservice.asmx?wsdl

     這個相當於介面的說明檔案,上面有每個介面的介面名稱,介面引數等資訊,通過檢視這個檔案,就知道怎呼叫的時候填什麼引數(後面詳細介紹)。

所以,自己開發一個天氣預報的網站其實很簡單(從這裡呼叫介面即可)。

二、C# 開發WebService介面

       這裡用C#開發,是因為剛做了個專案用的是C#,後面呼叫使用Java開發,後面介紹。

1.新建工程

開發環境:VS2013

自動生成一個介面:HelloWorld()

[WebMethod]的意思是向外暴露介面

什麼都不用開發,點選執行:

點選呼叫:返回Hello World

2.新增介面函式

新增一個兩個int型的數相加的函式介面,感受一下:

[WebMethod]
        public int Add(int a, int b)
        {
            return a + b;
        }

傳入引數、呼叫:

3.介面返回資料庫資料

為了讓功能更豐富一些,通過介面獲取資料庫的資料。大概步驟是:

(1)介面傳進引數

(2)WebService服務連線收據庫,根據傳入的引數查詢資料庫

(3)將資料封裝成xml返回給使用者

舉例:使用者輸入"Tom"同學的名字,想要查詢他的成績。

為了說明問題,用sqlserver建一張表:

假設資料庫資料是這樣的(沒有實際意義,只說明問題):

目標是將根據Name查詢資料並以Xml的資料格式返回。

首先定義函式介面:

 [WebMethod]
        public string GetdbData(string Name)
        {
            //資料庫操作
            string strcon = "server = localhost,1433;uid = sa; pwd = 123456; database = MyDataBase";
            string strSQL = "select Name,Chinese,Math,English from Student where Name = @name";
            SqlConnection con = new SqlConnection(strcon);
            SqlCommand cmd = new SqlCommand(strSQL, con);
            cmd.Parameters.Add("@name", SqlDbType.VarChar);
            cmd.Parameters["@name"].Value = Name;
            DataSet ds = new DataSet();
            try
            {
                SqlDataAdapter DA = new SqlDataAdapter(cmd);
                DA.Fill(ds, "tb");
            }
            catch (SqlException E)
            {
                throw new Exception(E.Message);
            }
            con.Close();//關閉資料庫
            
            //封裝xml
             XDocument xDoc = new XDocument();
             //建立一個根節點
             XElement root = new XElement("Root");
             xDoc.Add(root); //將根節點加入到XML物件中
             try
             {
                 for (int i = 0; ds.Tables.Count > 0 && i < ds.Tables[0].Rows.Count; i++)
                 {
                     //建立一個子節點
                     XElement xele = new XElement("Data" + (i + 1).ToString());
                     root.Add(xele);
                     for (int j = 0; j < e.Length; j++)
                     {
                         xele.SetElementValue(e[j], ds.Tables[0].Rows[i].ItemArray[j]);
                     }
                 }
                 //儲存xml檔案   
                 LogWriteLock.EnterWriteLock();
                 xDoc.Save(CurrPath + "student.xml");
                 LogWriteLock.ExitWriteLock();

             }
             catch (SqlException E)
             {
                 throw new Exception(E.Message);
             }

             return xDoc.ToString();
        
            
        }

    }

測試:

並儲存為student.xml檔案

查詢的結果和資料庫裡的資料相符合,資料庫有4個Tom,查詢到4個。

這裡的資料庫連線操作可以檢視另外一篇:C# SqlCommand 資料庫連線操作

4.部署服務

開題說了WebService介面可以遠端呼叫,這是它的優勢或者說是主要的功能。首先得把開發好的部署起來,這裡只說明在C#開發,部署在Windows平臺,其他的形式的貨平臺的開發和部署不做講述。

步驟:

  (1)開啟IIS: 計算機管理->服務和應用程式->Internet資訊服務(IIS)管理器;

(2)新增網站: 在網站選項上右鍵->新增網站… 。鍵入網站名稱,選擇webservice釋出檔案包的路徑,分配埠,點選確定即可。

(3)設定.NET版本:(開發的時候選的4.0)

(4)開啟目錄瀏覽許可權

緊接著就和除錯的時候一樣了:

三、Java呼叫

1.Java的簡單呼叫

開發環境:Eclipse

新建一個Java工程:

新建一個類:WebServiceTest

Java呼叫WebService需要依賴幾個jar包:

在工程下建一個lib資料夾,將依賴的jar包放進去(依賴包可以下載本文Java工程需要的所有jar包

然後需要把路徑也需要新增進來:

路徑加進來,圖示和沒加是有區別的:

定義一個方法:public static void GetStudent()

public static void GetStudent()
	{  
        try {
        	    String url ="http://localhost:9999/WebService.asmx";
        	    String namespace = "http://tempuri.org/";
		        Service service = new Service();  
		        Call call = (Call) service.createCall(); 
		        QName qname = new QName(namespace, "GetdbData"); //設定名稱空間和需要呼叫的方法名
		        call.setOperationName(qname);
		        call.setTargetEndpointAddress(url);  
		        call.setSOAPActionURI(namespace + "GetdbData");
		        call.addParameter(new QName(namespace,"Name"), org.apache.axis.encoding.XMLType.XSD_STRING, javax.xml.rpc.ParameterMode.IN);// 介面的引數  
		        call.setReturnType(org.apache.axis.encoding.XMLType.XSD_STRING);//設定返回型別
		        String result = (String) call.invoke(new Object[] {"Tom"});  
		        System.out.println("結果: \n" + result);  
              } catch (Exception e) {  
             System.err.println(e.toString());  
	       }
	}

說明:(1)url是剛才部署的路徑,這裡如果部署在遠端,就填遠端的IP和埠

             (2)namespace是C#開發WebService介面時候自動生成的,也可以自己任意修改,兩邊保持一致即可。

                    

              (3)"GetdbData"是介面名,"Name"是引數名,"Tom"是引數值,如果沒有引數就不需要call.addParameter這個函式,而invoke函式變為:String result = (String) call.invoke(new Object[] {});  如果有多個引數,就需要call.addParameter多次,然後

call.invoke(new Object[] {“引數1”,"引數2"}

執行結果:

2.JavaWeb簡單的展示

     既然都做到這了,索性做個頁面展示一下。

     (1)新建一個Web工程(選擇動態Web工程):

工程名:StudentShow

新建完,工程包含這麼多:

(2)在src下新建一個Class,命名為Student

編寫Get和Set方法:

package com.service.entity;

public class Student {
	    private String Name;//學生姓名
	    private String Chinese;//語文
	    private String Math;//數學
	    private String English;//英語
	    public String getName() {  
	        return Name;  
	    }  
	    public void setName(String name) {  
	        this.Name = name;  
	    } 
	    public String getChinese() {  
	        return Chinese;  
	    }  
	    public void setChinese(String chinese) {  
	        this.Chinese = chinese;  
	    }   
	    public String getMath() {  
	        return Math;  
	    }  
	    public void setMath(String math) {  
	        this.Math = math;  
	    }  
	    public String getEnglish() {  
	        return English;  
	    }  
	    public void setEnglish(String english) {  
	        this.English = english;  
	    }  

}

(3)再新建一個Class,命名為:StudentService

作用:呼叫WebService介面,解析xml檔案

package com.service;

import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;

import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import com.service.entity.Student;

public class StudentService {
	
	public List<Student> GetStudentInfo(String Name)
	{
		List<Student> stulist = new ArrayList<Student>(); 
		   try {  
				    String url ="http://localhost:9999/WebService.asmx";
	       	        String namespace = "http://tempuri.org/";
			        Service service = new Service();  
			        Call call = (Call) service.createCall(); 
			        QName qname = new QName(namespace, "GetdbData"); //設定名稱空間和需要呼叫的方法名
			        call.setOperationName(qname);
			        call.setTargetEndpointAddress(url);  
			        call.setSOAPActionURI(namespace + "GetdbData");
			        call.addParameter(new QName(namespace,"Name"), org.apache.axis.encoding.XMLType.XSD_STRING, javax.xml.rpc.ParameterMode.IN);// 介面的引數  
			        call.setReturnType(org.apache.axis.encoding.XMLType.XSD_STRING);//設定返回型別
			        String result = (String) call.invoke(new Object[] {Name});  
			        System.out.println("結果: \n" + result);  
				    stulist = PreaseXml(result);
                } 
	          catch (Exception e) {  
	            System.err.println(e.toString());  
	    	}
		return stulist;

        }
	//解析Xml
	private List<Student> PreaseXml(String resxml)
	{
		List<Student> tlist = new ArrayList<Student>(); 
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        try {
            DocumentBuilder builder = factory.newDocumentBuilder();  
            StringReader sr = new StringReader(resxml);
            InputSource is = new InputSource(sr);
            Document document = builder.parse(is);
            //獲取所有Root所有節點的集合
            NodeList rootList = document.getElementsByTagName("Root");
            //通過NodeList的getLength()
            int rootCnt = rootList.getLength();
            for(int i = 0; i < rootCnt; i++){
                Node root = rootList.item(i);
                NodeList childNodes = root.getChildNodes();
                //遍歷childNodes獲取每隔節點的節點名和節點值
                for(int j = 1; j < childNodes.getLength();){
                	Student mlist=new Student(); 
                    if(childNodes.item(j).getNodeType() == Node.ELEMENT_NODE){
                        //獲取節點的節點名
                        System.out.print("第"+ (j+1) + "節點:"+childNodes.item(j).getNodeName()+"  ");
                        //獲取型別節點的節點值
                        System.out.println("節點值:" + childNodes.item(j).getTextContent());
                         mlist.setName(childNodes.item(j).getChildNodes().item(1).getTextContent());
                         mlist.setChinese(childNodes.item(j).getChildNodes().item(3).getTextContent());
                         mlist.setMath(childNodes.item(j).getChildNodes().item(5).getTextContent());
                         mlist.setEnglish(childNodes.item(j).getChildNodes().item(7).getTextContent());
                        j +=2;
                    } 
                    tlist.add(mlist); 
                } 
                
            }
        } catch (ParserConfigurationException e) {          
            e.printStackTrace();
        } catch (SAXException e) {   
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
	  return tlist;
	}

}

(4)再新建一個Class,命名為:StudentServlet

作用:接收jsp請求

package com.service.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import javax.servlet.annotation.WebServlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.service.StudentService;
@WebServlet("/StudentServlet")
public class StudentServlet extends HttpServlet{
	 private static final long serialVersionUID = 1L;  
	    
	    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  
	        // TODO Auto-generated method stub 
	    	// 處理響應資料的格式和編碼,通知瀏覽器資料的顯示方式
	     response.setCharacterEncoding("utf-8");
	     response.setContentType("text/html;charset=utf-8");
	     PrintWriter pw = response.getWriter();  
         pw.println("doGet!"); 
         System.out.println ("doGet1");  
         String Name=request.getParameter("name");   
         StudentService ws = new StudentService();
	     List list =  ws.GetStudentInfo(Name); 
	     request.setAttribute("list",list);  
	     request.getRequestDispatcher("/student.jsp").forward(request, response);  
	    }  

	    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  
	        // TODO Auto-generated method stub  
	    }  


}

(5)新建student.jsp檔案,style是從網上找的

<%@ page language="java" contentType="text/html; charset=utf-8"  pageEncoding="utf-8" import="com.service.entity.*,java.util.*"%>  
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>  
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>學生資訊</title>
</head>
<body>
<style type="text/css">
table.dataintable {
	margin-top:15px;
	border-collapse:collapse;
	border:1px solid #aaa;
	width:100%;
	}

table.dataintable th {
	vertical-align:baseline;
	padding:5px 15px 5px 6px;
	background-color:#3F3F3F;
	border:1px solid #3F3F3F;
	text-align:left;
	color:#fff;
	}

table.dataintable td {
	vertical-align:text-top;
	padding:6px 15px 6px 6px;
	border:1px solid #aaa;
	}

table.dataintable tr:nth-child(odd) {
	background-color:#F5F5F5;
}

table.dataintable tr:nth-child(even) {
	background-color:#fff;
}
</style>
<form action ="StudentServlet" method="get">
輸入姓名:<input type="text" name="name"/>
<input type="submit" value="查詢" />
</form>
&nbsp;
&nbsp;</div>
<table class="dataintable">
<tr>
  <th>姓名</th>
  <th>語文</th>
  <th>數學</th>
  <th>英語</th>
</tr>

<c:forEach items="${list}" var="stu">  
    <tr>  
        <td><b>${stu.getName()}</b></td>  	
		<td>${stu.getChinese()}</td>  
        <td>${stu.getMath()}</td>   
    	<td>${stu.getEnglish()}</td>  
    </tr>  
</c:forEach> 
</body>
</html>

對於JavaWeb中頁面請求和servlet返回請求結果可以參考Jsp頁面請求-Servlet返回結果

(6)最後的效果: