3

我开始使用 JAX WS 研究 Java Web 服务。我正在阅读的这本书的第一章展示了如何仅使用 java SE 构建和部署一个简单的 jax ws Web 服务。特别是,Web 服务是通过 Endpoint 类发布的。发布 Web 服务后,作者指定“开箱即用,端点发布者一次处理一个客户端请求......如果给定请求的处理应该挂起,那么所有其他客户端请求都被有效阻止。一个示例本章末尾展示了 Endpoint 如何同时处理请求,以便一个挂起的请求不会阻塞其他请求。”

为了看到这一点,我尝试向具有 2 个线程的 Web 服务发送两个请求。这是代码:

@WebService(endpointInterface = "ProveVelociJava.WS.MyWsWithJavaSE.SayHello")
public class SayHelloImpl implements SayHello {
    public String greetings(String param) {
        System.out.println("\nStarting " + param + "...\n");    
        if(param.equals("miao")) {      
            try {           
                Thread.sleep(9000);
            }
            catch(Exception e) {}
        }
        System.out.println("Ended " + param + "\n\n");
        return "Hi, " + param;
    }
}

public class SayHelloPublisher {
    public static void main(String[ ] args) {   
        // 1st argument is the publication URL
        // 2nd argument is an SIB instance
        Endpoint.publish("http://127.0.0.1:9899/say", new SayHelloImpl());
    }
}

class MyClient extends Thread {
    private static URL url;
    private static QName qname;
    private static Service service;
    private static SayHello eif;

    static {
        try {
            url = new URL("http://127.0.0.1:9899/say?wsdl");
            qname = new QName("http://MyWsWithJavaSE.WS.ProveVelociJava/", "SayHelloImplService");
            service = Service.create(MyClient.url, MyClient.qname);
            // Extract the endpoint interface, the service "port".
            eif = service.getPort(SayHello.class);
        }
        catch(Exception e) {}
    }
    private String name;
    public MyClient(String n) {
        name = n;
    }
    public void run() {
        System.out.println(MyClient.eif.greetings(this.name));
    }
    public static void main(String args[ ]) throws Exception {  
        MyClient t1 = new MyClient("miao");
        MyClient t2 = new MyClient("bau");
        t1.start();
        t2.start();
    }
}

如果我启动 MyClient 类,名为“miao”的线程会发送它的请求,然后进入睡眠状态。但是,名为“bau”的线程不会等待前一个线程,它的请求会立即得到满足。

我错过了什么吗?java线程可以用来模拟多个请求吗?

非常感谢你的帮助,尼科。

4

3 回答 3

2

我下载了 JAX-WS 2.0 规范,它反驳了我正在阅读的书所说的内容:

“一个端点由一个充当 Web 服务实现的对象(这里称为实现器)加上一些配置信息组成……端点通常会被调用来服务并发请求,因此应该编写它的实现器以支持多线程。可以像往常一样使用 synchronized 关键字来控制对代码关键部分的访问。为了更好地控制用于分派传入请求的线程,应用程序可以直接设置要使用的执行器"

http://jcp.org/aboutJava/communityprocess/final/jsr224/index.html,第 5.2.2 节“发布”,第 67 页)

这本书谈到了 JAX-WS 2.1,但我没有设法下载该版本的规范。无论如何,JAX-WS 2.2 规范(当前版本)确认了 Endpoint 类的并发性质(它包含与上述相同的语句)。

我不知道这本书的作者到底是什么意思。

于 2012-07-28T16:48:55.607 回答
2

默认情况下,Endpoint 同时处理多个请求,并为每个新的并发请求创建单独的线程。您可以在 WebMethod 实现中插入以下行,以查看线程 ID:

System.out.println(Thread.currentThread().toString());

如果您逐个请求,这将打印相同的线程信息,因为终止的线程将在下一个 http 请求中重用。但是,如果您同时发出多个请求,那么您会看到不同的线程将调用您的 web 方法。

只要您的 webmethod 没有同步块、整个 webmethod 未同步或您使用某种信号量,一个请求就不会阻塞任何其他并发请求。

于 2015-05-22T22:00:36.867 回答
1

为时已晚,但可能会有所帮助。

Endpoint.publish(Url, ServiceImplObj) 在给定的 url 发布 web 服务。没有。分配给请求处理的线程确实在 jvm 的控制之下,因为这是一个由 jvm 本身处理的轻量级部署。

为了更好地说明,您可以在服务端打印当前线程名称,您可以看到服务线程是从由 jvm 管理的线程池分配的。

[pool-1-thread-1]: Response[57]:
[pool-1-thread-5]: Response[58]:
[pool-1-thread-4]: Response[59]:
[pool-1-thread-3]: Response[60]:
[pool-1-thread-6]: Response[61]:
[pool-1-thread-6]: Response[62]:
于 2012-12-12T16:35:34.697 回答