[版权申明:本文系作者原创,转载请注明出处]

文章出处:http://blog.csdn.net/sdksdk0/article/details/52106690

作者:朱培 ID:sdksdk0 邮箱: zhupei@tianfang1314.cn


一、简介

Webservice:跨语言跨平台的远程调用技术。Web service 即web服务,它是一种跨编程语言和跨操作系统平台的远程调用技术即跨平台远程调用技术。

JAVA 中共有三种WebService 规范,分别是JAX-WS(JAX-RPC)、JAXM&SAAJ、JAX-RS。

webService三要素:soap、wsdl、uddi

JAX-WS 的全称为 Java API for XML-Based Webservices ,早期的基于SOAP 的JAVA 的Web 服务规范JAX-RPC(Java API For XML-Remote Procedure Call).

JAXM(JAVA API For XML Message)主要定义了包含了发送和接收消息所需的API,SAAJ(SOAP With Attachment API For Java,JSR 67)是与JAXM 搭配使用的API,为构建SOAP 包和解析SOAP 包提供了重要的支持,支持附件传输等.

JAX-RS 是JAVA 针对REST(Representation State Transfer)风格制定的一套Web 服务规范.

二、应用场景

在做企业整体信息化时,企业中一般都或多或少的存在一些既存系统,这些各种各样的系统不可能全部推翻,重新规划和开发,因为很多供应商在某一领域也做的很专业,博众家之长并进行集成应该是一个比较现实和可取的做法。各个系统之间通过WebService进行集成,不仅缩短了开发周期,降低了风险,还减少了代码复杂度,并能够增强应用程序的可维护性,因为webservice支持跨平台且遵循标准协议(soap)。

将一个软件的功能以webservice方式暴露出来,达到软件重用。例如上边分析的天气预报,将天气查询功能以webservice接口方式暴露出来非常容易集成在其它系统中;再比如一个第三方物流系统将快递查询、快递登记暴露出来,从而集成在电子商务系统中。

三、soap协议

SOAP 是一种网络通信协议

SOAP即Simple Object Access Protocol简易对象访问协议

SOAP 用于跨平台应用程序之间的通信

SOAP 被设计用来通过因特网(http)进行通信

SOAP = HTTP+XML,其实就是通过HTTP发xml数据

SOAP 很简单并可扩展支持面向对象

SOAP 允许您跨越防火墙

Socket是所有通信的基础也是语言个无关平台无关。

Socket使用的是tcp协议,传输效率高。适合传递大数据高并发场景,高并发的情况需要实现多线程并且使用到线程池,编码复杂。Sockt的高并发框架mina。

Socket只是流的传输,传输的格式需要程序员自己定义。

Webservice使用的是soap协议,soap协议基于http协议的应用层协议,本质就是http+xml。Soap协议是w3c标准,传输效率低。使用传输数据不是太大的场合,也是支持高并发的,受限于web容器。支持soap协议和wsdl两者都是国际通用标准,不需要自定义数据格式,只需要面向对象开发。

四、WSDL

Webservice的使用说明书。描述了webservice的服务地址以及webservice服务接口、参数、返回值。

阅读方法:从下往上读。

  1. 先找service节点:每个wsdl中,有且只有一个service节点。也叫服务视图节点。service中有port节点服务端端口。
  2. 根据port节点的binding属性找binding节点。根据binding节点的type属性找portType节点。
  3. portType节点就是我们定义的SEI服务的接口类型。Prottype中的operation 节点就是方法名称。
  4. operation 节点的input就是参数的定义,output就是返回值的定义。
  5. Input有个属性叫做message,message属性对应message节点。其中有一个element,对应element节点。
  6. Element节点定义中xsd中。定义了数据的类型。参数和返回值都在其中定义。

五、天气查询系统(基础)

到这里,对于webservice的基本概念都已经了解了,那么就开始我们愉快的编码步骤吧!这个的话我们需要新建两个java工程,一个做服务端,一个作为客户端。源码可以通过文末的链接下载。

5.1 服务端

1、编写一个SEI,也就是一个接口

 public interface WeatherInterface {

        String queryWeather(String cityName);
}

2、编写一个SEI实现类,需要实现SEI接口,而且还需要在这个实现类上面添加一个@Webservice注解

    @Webservice
public class WeatherInterfaceImpl implements WeatherInterface { public String queryWeather(String cityName) {
System.out.println("接收到客户端发送的城市名称:"+cityName);
String result="晴,高温预警";
return result;
}
}

在这一步,如果你因为webservice的添加注解系统报错的话,可以先按照报错提示的先转变为jase-1.5,然后自己再去build path中重新变回你原来许需要的java1.7或者1.8.

3、发布服务。使用Endpoint的静态方法publish。

    public class WeatherServer {

        public static void main(String[] args) {
//发布服务
Endpoint.publish("http://127.0.0.1:11111/weather", new WeatherInterfaceImpl());
} }

访问地址:http://127.0.0.1:11111/weather

http://127.0.0.1:11111/weather?wsdl中看到portType。

看到效果则说明启动成功了。

5.2 客户端

对于客户端,我们可利用只用java中的wsimport来自动生成客户端代码。

使用Wsimport生成客户端调用代码,

在jdk的安装目录的bin目录中,有一个wsimport命令。

可以根据wsdl文档生成客户端调用代码。

新建一个java工程WebServiceClient,然后到这个工程的src目录下面,在src目录下通过cmd运行以下命令:(注意空格)

wsimport -s . http://127.0.0.1:11111/weather?wsdl



生成好之后我们就可以直接调用了:

1、创建一个服务视图对象

2、从服务试图获得porttype(SEI)对象

3、调用服务端方法

4、打印结果

    public class WeatherClient {

    public static void main(String[] args) {
WeatherInterfaceImplService service=new WeatherInterfaceImplService();
WeatherInterfaceImpl portType=service.getWeatherInterfaceImplPort();
String result=portType.queryWeather("衡阳");
System.out.println(result); }
}

六、天气查询(公网)

刚才使用的方法是我们自己定义了,但是往往生活中,我们需要时时更新的天气信息,所以这个时候我们就可以调用公网来处理了,和前面的一样,我们也需要服务端和客户端。

6.1 服务端

服务端使用第三方的,导入其已经生成好的多个类,cn.com.webxml.这个可以在我提供的源码中直接下载。

6.2 客户端

public static void main(String[] args) {
//创建服务视图
//WeatherWebService service=new WeatherWebService(); URL url = null;
try {
url = new URL("http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?WSDL");
} catch (MalformedURLException e) {
e.printStackTrace();
}
QName qName=new QName("http://WebXml.com.cn/", "WeatherWebService"); Service service=Service.create(url,qName);
WeatherWebServiceSoap portType=service.getPort(WeatherWebServiceSoap.class);
//service.getWeatherWebServiceSoap(); ArrayOfString arrayOfString=portType.getWeatherbyCityName("衡阳");
for (String string : arrayOfString.getString()) {
System.out.println(string);
}
}

七、区域查询系统

创建区域查询服务系统,对外发布WebService服务,供客户端调用,根据parentid查询区域信息。客户端向服务端传递xml格式数据,服务端向客户端响应xml格式数据。

传递xml数据的原因:

  • 1、跨语言时可能会花费很多时间去调试,如果直接传递xml会节省调试的时间。参数和返回值都是字符串类型,非常简单。
  • 2、如果参数发生变化后,可以不要修改接口,不能重新生成客户端代码。
  • 3、xml格式的数据是跨平台的。

实现步骤

- 创建一个java工程。
- 导入mysql数据库驱动及其相关的jar包。
- 创建一个SEI。
- 创建一个SEI实现类,调用dao查询区域列表。
- 发布服务,使用Endpoint的publish方法发布服务。

客户端:

  • 生成客户端调用代码
  • 创建服务视图
  • 从服务视图获得portType
  • 调用服务端方法

7.1 服务端

1、新建一个区域信息接口,AreaModel .java

private String areaid;

private String areaname;

private String parentid;

private String arealevel;

实现其get\set方法

2、新建一个AreaDao.java,用于访问mysql数据库中的区域信息,这个数据库的sql脚本已放到源码中,读者可自行下载。就是一个连接数据库的功能。

public List<AreaModel> queryArea(String parentid, int start, int end) {
Connection connection = null;
PreparedStatement pstmt = null;
ResultSet resultSet = null;
List<AreaModel> areaList = new ArrayList<>();
try {
//加载数据库驱动
Class.forName("com.mysql.jdbc.Driver");
//获得connection
connection = DriverManager.getConnection("jdbc:mysql:///day15", "zp", "a");
String sql="select *from area where parentid=? limit ?,? ";
pstmt=connection.prepareStatement(sql); pstmt.setString(1,parentid);
pstmt.setInt(2, start-1);
pstmt.setInt(3, end-start-1); resultSet=pstmt.executeQuery(); while(resultSet.next()){ AreaModel model=new AreaModel();
model.setAreaid(resultSet.getString("areaid"));
model.setAreaname(resultSet.getString("areaname"));
model.setArealevel(resultSet.getString("arealevel"));
model.setParentid(resultSet.getString("parentid"));
//添加到区域列表
areaList.add(model); } }catch(Exception e){
e.printStackTrace();
}finally{
try {
resultSet.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
pstmt.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
connection.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return areaList; }

3、写一个区域查询SEI

public interface AreaInterface {

    String queryArea(String area);

}

4、实现其Sei的dao方法。

@WebService
public class AreaInterfaceImpl implements AreaInterface { @Override
public String queryArea(String area) { //解析xml查询条件
AreaModel model = null;
try {
model = parseXml(area);
} catch (DocumentException e) {
e.printStackTrace();
}
AreaDao dao=new AreaDao();
List<AreaModel> list=dao.queryArea(model.getParentid(), model.getStart(), model.getEnd());
String result = null;
try {
result = list2xml(list);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} return result;
} private AreaModel parseXml(String xml) throws DocumentException{ Document document=DocumentHelper.parseText(xml);
String parentid=document.selectSingleNode("/queryarea/parentid").getText();
String start=document.selectSingleNode("/queryarea/start").getText();
String end=document.selectSingleNode("/queryarea/end").getText(); AreaModel model=new AreaModel();
model.setParentid(parentid);
model.setStart(Integer.parseInt(start));
model.setEnd(Integer.parseInt(end));
return model; }
private String list2xml(List<AreaModel> list) throws Exception {
Document document = DocumentHelper.createDocument();
//添加以根节点
Element root = document.addElement("areas"); for (AreaModel areaModel : list) {
Element area = root.addElement("area");
area.addElement("areaid").setText(areaModel.getAreaid());
area.addElement("areaname").setText(areaModel.getAreaname());
area.addElement("arealevel").setText(areaModel.getArealevel());
area.addElement("parentid").setText(areaModel.getParentid());
} return document.asXML();
} }

5、发布服务

public class AreaServer {

    public static void main(String[] args) {
Endpoint.publish("http://127.0.0.1:11111/area", new AreaInterfaceImpl());
}
}

通过浏览器访问看到这个界面就说明运行成功了。

7.2 客户端

和之前同样的方法,使用wsimport来自动生成客户端代码。

在java工程的src目录中运行cmd。

wsimport -s . http://127.0.0.1:11111/area?wsdl

生成好之后如下所示:

客户端进行调用

public class AreaClient {

    public static void main(String[] args) {
AreaInterfaceImplService service=new AreaInterfaceImplService(); AreaInterfaceImpl portType=service.getAreaInterfaceImplPort();
String result=portType.queryArea(getQueryXml("1.1.",1,10));
System.out.println(result);
} private static String getQueryXml(String parentid,int start,int end){
String xml="<?xml version=\"1.1\" encoding=\"utf-8\"?>\n" +
"<queryarea>\n"+
"<parentid>"+parentid+"</parentid>\n"+
"<start>"+start+"</start>\n"+
"<end>"+end+"</end>\n"+
"</queryarea>";
return xml;
}
}

输出结果:

总结:本篇文章关于webservice的内容都是非常非常基础的,里面涉及到的一些协议或者使用方法估计有些人是不知道的,我们一方面需要扩展自己的视野,了解更多的新东西,内心不要对一些自己不是很常见的东西去抵触,有的朋友会说“嗯,你讲的这些东西都太基础了,我们在实际项目中要如何应用”,有的直接是调用第三方的url和参考文档就搞定了,其实是比较方便的,那么我们在使用别人的东西的时候有没有考虑过其底层的实现原理,深入到其骨髓才是真的掌握了,不然我们依然是那种只会复制黏贴、只会盲目的调用各种第三方API来的人了。共勉!下次会带来更加实用的cxf实现jax-ws。欢迎关注!

源码下载:

https://github.com/sdksdk0/WebWeather-BaseDemo-

https://github.com/sdksdk0/AreaWebService

WebService案例入门(基础篇)的更多相关文章

  1. Linux入门基础篇

    Linux入门基础篇 Linux诞生 Linux发行版本说明 Linux官方网站 Linux内核官方网站 比较有名的Linux发行版 虚拟机(Virtual Machine),一个虚拟的系统,安装在系 ...

  2. 智普教育Python视频教程之入门基础篇,python笔记

    智普教育Python视频教程之入门基础篇,python笔记 print id()内存地址 type()变量类型 windows命令行下edit命令 python数据类型不需要指定类型 定义hostna ...

  3. Java正则表达式入门基础篇

    正则表达式是一种可以用于模式匹配和替换的规范,一个正则表达式就是由普通的字符(例如字符a到z)以及特殊字符(元字符)组成的文字模式,它 用以描述在查找文字主体时待匹配的一个或多个字符串.正则表达式作为 ...

  4. CSS快速入门基础篇,让你快速上手(附带代码案例)

    1.什么是CSS 学习思路 CSS是什么 怎么去用CSS(快速上手) CSS选择器(难点也是重点) 网页美化(文字,阴影,超链接,列表,渐变等) 盒子模型 浮动 定位 网页动画(特效效果) 项目格式: ...

  5. object-c 入门基础篇

    原地址:http://www.cnblogs.com/moonvan/archive/2011/10/13/2210498.html 一.Objective-C与C的渊源 Objective-C诞生于 ...

  6. 牛客SQL刷题第一趴——非技术入门基础篇

    user_profile表: id device_id gender age university province 1 2138 male 21 北京大学 Beijing 2 3214 male   ...

  7. React入门----基础篇

    React 背景介绍 React 起源于 Facebook 的内部项目,因为该公司对市场上所有 JavaScript MVC 框架,都不满意,就决定自己写一套,用来架设 Instagram 的网站.做 ...

  8. Spring Boot 入门之基础篇(一)

    原文地址:Spring Boot 入门之基础篇(一) 博客地址:http://www.extlight.com 一.前言 Spring Boot 是由 Pivotal 团队提供的全新框架,其设计目的是 ...

  9. Java入门到精通——基础篇之多线程实现简单的PV操作的进程同步

    Java入门到精通——基础篇之多线程实现简单的PV操作的进程同步 一.概述     PV操作是对信号量进行的操作.     进程同步是指在并发进程之间存在一种制约关系,一个进程的执行依赖另一个进程的消 ...

随机推荐

  1. 前端开发必备之Chrome开发者工具(下篇)

    本文介绍的 Chrome 开发者工具基于 Chrome 65版本,如果你的 Chrome 开发者工具没有下文提到的那些内容,请检查下 Chrome 的版本 本文是 前端开发必备之Chrome开发者工具 ...

  2. MySQL中的数值函数

    加减乘除(+.-.*./)均可用于数值计算. SELECT (1 + 1) / (1 * 2.2 - 3) 执行算术函数 单参数数值函数举例: acos(x), asin(x), atan(x), c ...

  3. 学习React系列(二)——深入了解JSX

    1.JX实际上是React.createElement(component,props,...children)的语法糖 2.JSX判断是否为react组件的依据是标签首字母为大写(所以要求用户自定义 ...

  4. ios11,弹出层内的input框光标错位 键盘弹出时,输入信息,光标一直乱跳

      之前开发了一个微信项目,维护期中苹果手机突然出现光标错位现象,经过排查,发现是最新的ios11系统的锅. 具体情况:弹出层使用position: fixed:弹出层内附带input/textare ...

  5. 超级好用的前端开发测试Chrome插件-基于REST的Web服务客户端

    基于REST的Web服务客户端是一款功能强大的谷歌浏览器插件,使用基于REST的Web服务客户端(模拟REST客户端)可以让用户使用谷歌浏览器模拟REST请求来测试REST风格. 基于REST的Web ...

  6. Oracle RAC环境下定位并杀掉最终阻塞的会话-续

    之前在<Oracle RAC环境下定位并杀掉最终阻塞的会话>中,最终使用一个SQL查询出RAC实例之间的所有阻塞关系.但是实际在某些极端的生产环境,是不允许执行复杂的SQL语句,即使允许执 ...

  7. cogs 619. [金陵中学2007] 传话

    提交地址:http://cojs.tk/cogs/problem/problem.php?pid=619 619. [金陵中学2007] 传话 ★☆   输入文件:messagez.in   输出文件 ...

  8. [ZJOI2009]染色游戏

    Description 一共n × m 个硬币,摆成n × m 的长方形.dongdong 和xixi 玩一个游戏, 每次可以选择一个连通块,并把其中的硬币全部翻转,但是需要满足存在一个 硬币属于这个 ...

  9. [HNOI2012]双十字

    题目描述 在C 部落,双十字是非常重要的一个部落标志.所谓双十字,如下面两个例子,由两条水平的和一条竖直的”1“线段组成,要求满足以下几个限制: ![] 我们可以找到 5 个满足条件的双十字,分别如下 ...

  10. ●BZOJ 3143 [Hnoi2013]游走

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=3143题解: 期望dp,高斯消元 首先有这样一种贪心分配边的编号的方案:(然后我没想到,233 ...