ruby和python_Ruby,Python和Java中的Web服务

ruby和python

今天,我不得不准备一些示例来说明Web服务是可互操作的。 因此,我已经使用Metro使用Java创建了一个简单的Web服务,并在Tomcat上启动了它。

然后尝试使用Python和Ruby消耗它们。 这是全部完成的过程…

Java中的Web服务

我从Java中的简单Web服务开始:

package com.wordpress.jdevel.ws;

import java.io.File;
import java.io.FileFilter;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.List;
import javax.jws.WebService;
import javax.jws.WebMethod;
import javax.jws.WebParam;

@WebService(serviceName = "Music")
public class Music {

    private static final File FOLDER = new File("D:/TEMP/SONGS");

    @WebMethod(operationName = "listSongs")
    public Song[] listSongs(@WebParam(name = "artist") String artist) {

        List<Song> songs = new ArrayList<Song>();
        System.out.println("ARTIST: " + artist);
        if (artist != null) {
            File folder = new File(FOLDER, artist);
            if (folder.exists() && folder.isDirectory()) {
                File[] listFiles = folder.listFiles(new FilenameFilter() {

                    public boolean accept(File dir, String name) {
                        return name.toUpperCase().endsWith(".MP3");
                    }
                });

                for (File file : listFiles) {
                    String fileName = file.getName();
                    String author = file.getParentFile().getName();
                    int size = (int) (file.length() / 1048576); //Megabytes
                    Song song = new Song(fileName, author, size);
                    songs.add(song);
                }
            }
        }

        return songs.toArray(new Song[songs.size()]);
    }

    @WebMethod(operationName = "listArtists")
    public String[] listArtists() {
        File[] folders = getFolders(FOLDER);
        List<String> artists = new ArrayList<String>(folders.length);
        for (File folder : folders) {
            artists.add(folder.getName());
        }
        return artists.toArray(new String[artists.size()]);
    }

    private File[] getFolders(File parent) {
        FileFilter filter = new FileFilter() {

            public boolean accept(File pathname) {
                return pathname.isDirectory();
            }
        };

        File[] folders = parent.listFiles(filter);

        return folders;
    }

    public static void main(String[] args) {
        Music listFiles = new Music();
        String[] artists = listFiles.listArtists();
        System.out.println("Artists: " + artists);
        for (String artist : artists) {
            Song[] listSongs = listFiles.listSongs(artist);
            for (Song song : listSongs) {
                System.out.println(song.getArtist() + " : " + song.getFileName() + " : " + song.getSize() + "MB");
            }
        }
    }
}

还需要一个简单的bean来获取一些更复杂的类型:

package com.wordpress.jdevel.ws;

import java.io.Serializable;

public class Song implements Serializable {
    String fileName;
    String artist;
    int size;

    public Song() {
    }

    public Song(String fileName, String artist, int size) {
        this.fileName = fileName;
        this.artist = artist;
        this.size = size;
    }

    public String getArtist() {
        return artist;
    }

    public void setArtist(String artist) {
        this.artist = artist;
    }

    public String getFileName() {
        return fileName;
    }

    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

    public int getSize() {
        return size;
    }

    public void setSize(int size) {
        this.size = size;
    }
}

它只是在硬编码的FOLDER目录中列出所有子目录,并将其视为音乐收藏中的艺术家列表。 然后,您可以执行listSongs方法并在artist子文件夹中获取mp3文件的列表。

要使其成为Web服务,您要做的就是使用@WebService(serviceName =“ Music”)注释类,并且要公开为Web服务操作的每个方法都必须使用@WebMethod(operationName =“ listArtists”)进行标记。

如果您要在GlassFish上部署它,那么应该就这些了,但是我已经使用了Tomcat,因此还需要3个步骤:

1.将Metro 2.0罐子添加到WEB-INF / lib
2.将Metro servlet和侦听器添加到web.xml:

<listener>
	<listener-class>
		com.sun.xml.ws.transport.http.servlet.WSServletContextListener
	</listener-class>
</listener>
<servlet>
	<servlet-name>Music</servlet-name>
	<servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
	<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
	<servlet-name>Music</servlet-name>
	<url-pattern>/Music</url-pattern>
</servlet-mapping>

您可能不应在此处进行任何更改。 只需将其粘贴到web-app节点中的web.xml中即可。

3.使用端点声明将sun-jaxws.xml文件添加到WEB-INF:

<?xml version="1.0" encoding="UTF-8"?>
<endpoints version="2.0" xmlns="http://java.sun.com/xml/ns/jax-ws/ri/runtime">
	<endpoint implementation="com.wordpress.jdevel.ws.Music" name="Music" url-pattern="/Music"/>
</endpoints>
  • 实现必须匹配您的@WebService类
  • 名称必须与@WebService批注中的serviceName匹配
  • url-pattern必须与您在servlet映射中声明的url-pattern匹配

如果您在NetBeans中创建XML文件,那么也不必编辑它们。

现在启动Tomcat并部署您的应用程序。 您应该可以通过类似以下方式访问服务

http:// localhost:8080 / WSServer /音乐

并看到这样的事情:

可以通过以下方式访问WSDL

http:// localhost:8080 / WSServer / Music?wsdl

复杂类型的架构:

http:// localhost:8080 / WSServer / Music?xsd = 1

如果您能正常工作,则可以从以下客户端开始。

Python客户端
我已经开始搜寻一些不错的python网络服务库,并找到了Suds。 我还没有真正使用过这样的东西。 实施WS客户大约花了15分钟。 当然,支持复杂类型的课程和上一次我使用Python编写大于5行的内容大约是3年前。 您真的必须尝试一下。

所以这是代码:

import suds

class Client:
    def __init__(self):
        self.client = suds.client.Client("http://localhost:8080/WSServer/Music?wsdl")

    def get_artists(self):
        return self.client.service.listArtists()

    def get_songs(self, artist):
        return self.client.service.listSongs(artist)

if(__name__ == "__main__"):
    client = Client()
    artists = client.get_artists()
    for artist in artists:
        print artist
        songs = client.get_songs(artist)
        for song in songs:
            print "\t%s : %s : %d%s" % (song.fileName, song.artist, song.size, "MB")

而已。 简单明了。 WSDL被解析,复杂类型被动态生成。 美丽的东西。 对我来说,要实现这样的事情有点困难。

Ruby客户端
使用SOAP4R库。 只需执行

宝石安装soap4r

要获得它(真的很喜欢这个工具)。首先让我们从代码开始:

require 'soap/rpc/driver'
require 'soap/wsdlDriver'

class Client
  def initialize
    factory = SOAP::WSDLDriverFactory.new("http://localhost:8080/WSServer/Music?wsdl")
    @driver = factory.create_rpc_driver
  end

  def get_songs(artist)
    songs = @driver.listSongs(:artist => artist)
    return songs
  end

  def get_artists
    artists = @driver.listArtists(nil)
    return artists
  end
end

def print_songs(songs)
  if songs

  end
end

client = Client.new
artists = client.get_artists
artists["return"].each{|artist|
  puts artist
  songs = client.get_songs(artist)["return"];
  songs.each {|song| puts "\t%s : %s : %d%s" % [song.fileName, song.artist, song.size, "MB"]}
}

它的功能完全相同。 调用Web服务以获取艺术家列表,然后为每个艺术家调用mp3文件。 然后只需将所有内容打印到控制台即可。

我花了相当长的时间才能开始工作。 首先–很难找到任何文档。 其次– SOAP4R在没有一点黑客的情况下不能与ruby 1.9一起工作:

http://railsforum.com/viewtopic.php?id=41231

下一步–当您不使用WSDL创建驱动程序对象时,结果会稍微好一些,但是您必须确切地知道拥有什么并想要执行哪些服务。 在这个简单的示例中这不是问题,但是如果您需要使其更通用一些……您将会遇到麻烦。

我说“好一点”是什么意思? 一,代码:

@driver = SOAP::RPC::Driver.new("http://localhost:8080/WSServer/Music", "http://ws.jdevel.wordpress.com/");
@driver.add_method(ARTISTS_METHOD)
@driver.add_method(SONGS_METHOD, "artist")

这样,我负责声明要使用的服务的端点和名称空间。 我还需要声明我将要使用的所有操作以及参数(“作者”)。 有什么不同? 当我不使用WSDL时,SOAP4R库会从调用服务中提供更好的返回类型。 我可以简单地省略[“ return”]并得到类似使用Python的信息。

我需要在Ruby中知道的是每种复杂类型的外观如何,从而使我的实现对Web服务更改更加敏感。 如何知道应该使用哪个键来获取复杂类型的数据? 检查WSDL并查找要调用的操作:

<operation name="listArtists">
    <input wsam:Action="http://ws.jdevel.wordpress.com/Music/listArtistsRequest" message="tns:listArtists"/>
    <output wsam:Action="http://ws.jdevel.wordpress.com/Music/listArtistsResponse" message="tns:listArtistsResponse"/>
</operation>

接下来在xsd中找到输出复杂类型

<xs:complexType name="listArtistsResponse">
    <xs:sequence>
        <xs:element name="return" type="xs:string" nillable="true" minOccurs="0" maxOccurs="unbounded"/>
    </xs:sequence>
</xs:complexType>

您需要的是name属性的值。 无论如何,这两种实现看起来都非常不错,而且更重要的是,它们可以正常工作。 Ruby和Python都有不错的Web服务库,可以处理复杂类型和WSDL解析。

参考:我们的JCG合作伙伴“ Development world story”博客上 提供了Ruby,Python和Java的Web服务

相关文章 :

翻译自: https://www.javacodegeeks.com/2011/08/web-services-ruby-python-java.html

ruby和python

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值