用webservice发布自己的天气预报服务

来源:互联网 发布:软件工程硕士全日制 编辑:程序博客网 时间:2024/05/21 18:48

一   JAX-WS简介

1.1  什么是JAX-WS

      JAX-WS的全称是JavaAPI for XML Web Service,目前流行的版本是JAX-WS 2.1。JAX-WS是用来简化使用Java构造Web服务和Web服务客户端的工作的技术。它提供了完整的'Web服务堆栈,可以减少开发和部署Web服务的难度。Java EE 6和JDK l.6.0_17及以上版本都支持JAX-WS 2.1。因此,使用常规的JDK就可以发布服务端点,这使得Web服务的发布变得非常简单。

     JAX-WS中集成了JAXB  (Java Architecture for XML Binding)。JAXB主要用于将XML映射为Java代码,便捷地支持数据绑定功能。在我的前一篇博文的介绍中,调用者和已发布的Web服务之间通过SOAP传递数据,因此,通过JAX.B,开发者不需要自己将SOAP消息中的XML模式的消息转换为Java代码,也不必全面了解XML和SOAP解析,这使得Web服务的开发变得异常简单。下面通过一个具体的示例来说明JAX-WS如何使用。

1.2  使用JAX-WS发布天气预报服务

      某网站要发布一个Web服务,主要提供全国各地的天气预报信息,包括最高气温、最低气温、平均气温、天气描述(如晴、阴、多云等)。该服务允许用户查询近3天的天气状况。

     要发布一个Web服务供第三方来使用,我们可以通过JAX-WS来完成。开发Web服务的基本思路是,设计并实现提供的服务接口,然后将服务接口“暴露”出去。下面就逐步完成天气预报服务的发布。

1.设计并实现服务接口

针对天气预报服务,我们提供用户可以针对城市和日期查询具体的天气的服务,因为允许查询近3天的天气状况,因此,接口设计如示例1所示。

示例1

@WebService(targetNamespace ="http://www.mytest.cn/ws/weather")

public interface WeatherService {

       @WebMethod

       List<TemperatureInfo>getWeathers(String city, List<Date> dates);

}

 

示例1中定义WeatherService接口,在该接口中提供的方法为getWeathers(),该方法允许传人String类型参数city和List<Date>类型日期列表dates。返回的结果是一个由Temperaturelnfo对象组成的List。具体的实现如示例2所示。

示例2

@WebService(targetNamespace ="http://www.mytest.cn/ws/weather")

public class WeatherServiceImpl implementsWeatherService {

       @WebMethod(operationName= "getWeathers")

       publicList<TemperatureInfo> getWeathers(String city, List<Date> dates) {

              List<TemperatureInfo>list = new ArrayList<TemperatureInfo>();

              for(Date date : dates) {

                     list.add(getTemperature(city,date));

              }

              returnlist;

       }

 

       @WebMethod(exclude= true)

       publicTemperatureInfo getTemperature(String city, Date date) {

              //模拟根据城市和日期获取天气信息

              returnnew TemperatureInfo(city, date, 28, 33, 31, "晴");

       }

}

 

实体类Temperaturelnfo如何定义呢?如示例3所示。

 

示例3

@XmlRootElement(name ="TemperatureInfo")

public class TemperatureInfo {

       //城市

       privateString city;

       //日期

       privateDate date;

       //最低温度

       privateint min;

       //最高温度

       privateint max;

       //平均气温

       privateint average;

       //描述

       privateString desc;

 

       //省略getter和setter方法

}

 

WeatherServiceImpl类提供了天气预报的具体实现。到现在为止,已经实现了天气预报服务,如果在同一个应用程序(或系统)中,我们可以轻松地调用该服务,但是如果我们希望其他的远程应用程序也能够像调用本地服务一样调用这个天气服务,应该怎么办呢?、下面就需要利用注解,将需要“暴露”的服务标识出来。注解描述如何将服务器端的服务实现作为Web服务来访问或者客户端的Java类如何访问Web服务,在示例l和示例2中,我们使用了@WebService和@WebMethod来完成这项工作。

@javax.jws.WebService注解,标识一个Java类或一个Java接口作为一个VVeb服务。一旦标注了@WebService,它就不再是一个普通的接口,它被称为服务端点接口(Service Endpoint Interface)。当然,也可以仅仅在Java类中通过@WebService来进行标识。@WebService注解有一系列属性,用来设置Web服务的详细描述信息;包括:在示例l和示例2一-已使用的targetNamespace属性,用来设置目标命名空间;serviceName属性设置服务名;portName属性设置端口名(Endpoint的名称)等。

 

●         问题:设置属性和不设置属性的区别是什么?

●         解答:注解用来标识服务,在服务发布时会产生WSDL文件。如果不通过属性具体描述要发布的服务,在WSDL文件中都是系统默认自动添加的信息;如果通过属性进行描述,WSDL文件中就是属性自定义的信息,如服务名等。

 

尽管注解的属性不是必须设置,但是,为了保证名称的可读性和发布服务的正确性,建议设置targetNamespace属性、serviceName属性和portName属性。

默认情况下,@WebService注解后的类的所有公共方法都会在WSDL文件中被“暴露”出去,因此,需要通过@javax.jws.WebMethod进行标注。@WebMethod允许通过operationName设置发布方法的名称,如@WebMethod(operationName=”getWeathers”)。另外,在示例2中,公共方法getTemperature()不希望被暴露,因此,通过设置exclude属性为true来实现。

在示例3中,对于实体类Tem peraturelnfo使用了@XmIRootElement注解。该注解是JAXB注解。JAXB提供了从XMLSchema到Java类的转换机制。示例3中,@XmIRootElement注解映射Java类Temperaturelnfo到XML的根元素。在Temperatruelnfo类中的属性默认映射为XML中的元素,即@XmIElement。@XmIRootElement和@XmlElement注解允许开发者定义XML元素的命名空间(通过namespace属性)和名字(通过name属性)。如果没有特别的定义,JAXB运行时会默认使用类的名称和类属性的名称作为XML元素的名称。

除此之外,还有其他的注解,包括@WebResult和@WebParam等,若感兴趣可以深入学习。

 

2.发布天气服务

在完成服务的开发之后,如何将其发布出去昵?通过JAX-WS来发布Web服务,最简单的方式是通过Endpoint.publish()方法。具体如示例4所示。

 

示例4

 

public class Server {

       //发布服务

       protectedServer() throws Exception {

              System.out.println("启动服务");

              WeatherServiceImplweatherServiceImpl = new WeatherServiceImpl();

              Stringaddress = "http://localhost:8084/WeatherService";

              Endpoint.publish(address,weatherServiceImpl);

       }

 

       publicstatic void main(String args[]) throws Exception {

              newServer();

              System.out.println("服务准备就绪...");

              Thread.sleep(2* 60 * 1000);

              System.out.println("服务退出...");

              System.exit(0);

       }

}

 

示例4中,通过javax.xml.ws.Endpoint的API publish()方法来发布Web服务,该方法接收两个参数,分别是需要发布的服务类和服务要发布的位置。publish()方法默认使用一个轻量级的HTTP服务器,该服务器对应com.sun.net.httpserver类。

示例4中将天气服务发布出去了,因此,我们可以通过访问该地址来请求服务。在浏览器中输入http://localhost:8084/WeatherService?wsdl可以看到生成的WSDL文件,如图9所示。



成功生成了WSDL文件,表示我们的天气服务已经发布成功了。其他应用程序就可以访问我们发布的Web服务了。

 

1.2.3  使用JAX-WS调用服务

在http://localhost:8084/WeatherService发布了一个Web服务,调用Web服务,并输出天气信息。

有了Web服务,下面如何来调用它呢?对于调用Web服务的应用程序而言,可以得到的只有WSDL文件及描述数据类型的XSD (XMLSchema'Definition,XML结构定义)1文件,如图所示,通过访问http://localhost:8084/WeatherService?xsd=l进行查看。


客户端调用Web服务,需要基于XSD文件和WSDL文件来完成。它的实现原理如图所示。


如图所示,通过JAX-WS,开发人员可以像调用本地服务一样调用一个远程服务。当客户端通过代理(Proxy)调用一个方法时,它将方法的参数转换为SOAP消息,作为请求发送到服务器端,即Web Service Endpoint。当收到返回结果时,客户端通过代理将SOAP转换为返回类型的实例对象。因此,服务端代理帮助我们完成了所有的工作,我们需要做的就是创建Service Endpoint Interface(SEI)来获得代理类。

=========================================================

二  具体案例:

sql脚本

CREATE TABLE WeatherTable(  weatherId INT PRIMARY KEY AUTO_INCREMENT,  weatherDate DATE NOT NULL,  city VARCHAR(50) NOT NULL,  minDegrees DOUBLE,  maxDegrees DOUBLE,  avgDegrees DOUBLE,  weatherDesc VARCHAR(50));INSERT INTO WeatherTable(weatherDate,city,minDegrees,maxDegrees,avgDegrees,weatherDesc)VALUES('2016-01-02','长沙',5,12,8,'晴');INSERT INTO WeatherTable(weatherDate,city,minDegrees,maxDegrees,avgDegrees,weatherDesc)VALUES('2016-01-03','长沙',4,11,7,'阴天');INSERT INTO WeatherTable(weatherDate,city,minDegrees,maxDegrees,avgDegrees,weatherDesc)VALUES('2016-01-04','长沙',3,10,6,'小雨');INSERT INTO WeatherTable(weatherDate,city,minDegrees,maxDegrees,avgDegrees,weatherDesc)VALUES('2016-01-02','株洲',5,12,8,'晴转多云');INSERT INTO WeatherTable(weatherDate,city,minDegrees,maxDegrees,avgDegrees,weatherDesc)VALUES('2016-01-03','株洲',4,11,7,'阴有小雨');INSERT INTO WeatherTable(weatherDate,city,minDegrees,maxDegrees,avgDegrees,weatherDesc)VALUES('2016-01-04','株洲',3,10,6,'小雨转阴天');
实体类WeatherEntity.java

package com.obtk.entitys;import java.io.Serializable;public class WeatherEntity implements Serializable{private static final long serialVersionUID = 2343174111180306664L;private Integer weatherId;private String city;private String weatherDate;private double minDegrees;private double maxDegrees;private double avgDegrees;private String weatherDesc;public Integer getWeatherId() {return weatherId;}public void setWeatherId(Integer weatherId) {this.weatherId = weatherId;}public String getCity() {return city;}public void setCity(String city) {this.city = city;}public String getWeatherDate() {return weatherDate;}public void setWeatherDate(String weatherDate) {this.weatherDate = weatherDate;}public double getMinDegrees() {return minDegrees;}public void setMinDegrees(double minDegrees) {this.minDegrees = minDegrees;}public double getMaxDegrees() {return maxDegrees;}public void setMaxDegrees(double maxDegrees) {this.maxDegrees = maxDegrees;}public double getAvgDegrees() {return avgDegrees;}public void setAvgDegrees(double avgDegrees) {this.avgDegrees = avgDegrees;}public String getWeatherDesc() {return weatherDesc;}public void setWeatherDesc(String weatherDesc) {this.weatherDesc = weatherDesc;}}
mybatis映射文件

<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE mapper  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"  "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.obtk.dao.WeatherDao">    <select id="getWeather" parameterType="map" resultType="weatherEntity">  select * from WeatherTable where weatherDate=#{weatherDate} and city=#{city}  </select></mapper>
接口

package com.obtk.dao;import java.util.HashMap;import java.util.Map;import com.obtk.entitys.WeatherEntity;public interface WeatherDao {WeatherEntity getWeather(Map parmaMap);}
服务类

package com.obtk.serv;import java.util.HashMap;import java.util.Map;import javax.jws.WebService;import org.apache.ibatis.session.SqlSession;import com.obtk.dao.WeatherDao;import com.obtk.entitys.WeatherEntity;import com.obtk.utils.MybatisUtil;@WebServicepublic class WeatherServ {public WeatherEntity getWeather(String dateStr,String city){SqlSession session=null;Map parmaMap=new HashMap();parmaMap.put("weatherDate", dateStr);parmaMap.put("city", city);WeatherEntity theWeather=null;try {session=MybatisUtil.getSession();WeatherDao weatherDao = session.getMapper(WeatherDao.class);theWeather=weatherDao.getWeather(parmaMap);} catch (Exception e) {e.printStackTrace();}finally{MybatisUtil.closeSession();}return theWeather;}}
发布服务

package com.obtk.test;import javax.xml.ws.Endpoint;import com.obtk.serv.WeatherServ;public class Mytest {public static void main(String[] args) {WeatherServ theServ=new WeatherServ();//System.out.println(theServ.getWeather("2016-01-03","长沙").getWeatherDesc());Endpoint.publish("http://192.168.1.105:911/weatherServ", theServ);System.out.println("服务发布成功...");}}
客户端的操作请参考我的上一篇博文












原创粉丝点击