注:1.本文重点讲如何实现
2.本文包括WebService接口开发、JavaWeb调用等问题
3.源代码已提交到github,Webservice接口:https://github.com/Bobo-peng/WebService
JavaWeb调用:https://github.com/Bobo-peng/JavaWebService
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#开发,是因为刚做了个项目用的是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)开启目录浏览权限
紧接着就和调试的时候一样了:
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 GetStudentInfo(String Name)
{
List stulist = new ArrayList();
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 PreaseXml(String resxml)
{
List tlist = new ArrayList();
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"%>
学生信息
姓名 | 语文 | 数学 | 英语 |
---|---|---|---|
${stu.getName()} | ${stu.getChinese()} | ${stu.getMath()} | ${stu.getEnglish()} |