java 为什么 JAX-WS 需要包装类?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3708631/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 03:05:09  来源:igfitidea点击:

Why does JAX-WS need wrapper classes?

javaweb-servicesjax-ws

提问by Christian Strempfer

I created a simple webservice, which implements an add operation, and created some client files with wsimport. Now I want to include as less as possible wsdl specific artifacts. Here is an example of how the web service will be called:

我创建了一个简单的 web 服务,它实现了添加操作,并使用 wsimport 创建了一些客户端文件。现在我想包含尽可能少的 wsdl 特定工件。以下是如何调用 Web 服务的示例:

String serviceNamespace = "http://jws.samples.geronimo.apache.org/";
String serviceName = "CalculatorServiceService";
QName serviceQN = new QName(serviceNamespace, serviceName);
Service service = Service.create(new URL("http://localhost:8080/WebService/calculator?wsdl"), serviceQN);

String portNamespace = "http://jws.samples.geronimo.apache.org/";
String portName = "CalculatorServicePort";
QName portQN = new QName(portNamespace, portName);
Calculator myProxy = (Calculator) service.getPort(portQN, Calculator.class);

But it seems like I have to include wrapper classes for every message. For example the result message of the add operation:

但似乎我必须为每条消息都包含包装类。例如添加操作的结果消息:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "addResponse", propOrder = { "_return" })
public class AddResponse {
    @XmlElement(name = "return")
    protected int _return;
    public int getReturn() {
        return _return;
    }
    public void setReturn(int value) {
        this._return = value;
    }
}

These wrappers are used within annotations in the service interface:

这些包装器在服务接口的注解中使用:

@WebService(name = "Calculator", targetNamespace = "http://jws.samples.geronimo.apache.org/")
public interface Calculator {
    @WebMethod
    @RequestWrapper(className = "org.example.webservices.clients.dynamicproxy.Add")
    @ResponseWrapper(className = "org.example.webservices.clients.dynamicproxy.AddResponse")
    public int add(
        @WebParam(name = "value1", targetNamespace = "")
        int value1,
        @WebParam(name = "value2", targetNamespace = "")
        int value2);
}

If the annotations are removed, the web service won't run.

如果注释被删除,Web 服务将不会运行。

com.sun.xml.ws.model.RuntimeModelerException: runtime modeler error: Wrapper class org.example.webservices.clients.dynamicproxy.jaxws.Add is not found. Have you run APT to generate them?

com.sun.xml.ws.model.RuntimeModelerException:运行时建模器错误:未找到包装类 org.example.webservices.clients.dynamicproxy.jaxws.Add。你有没有运行 APT 来生成它们?

But why do I need those wrappers? Couldn't JAX-WS create those wrappers on-the-fly? Do you see any information, which couldn't be retrieved from the wsdl file?

但是为什么我需要这些包装器?JAX-WS 不能即时创建这些包装器吗?您是否看到了无法从 wsdl 文件中检索到的任何信息?

采纳答案by bmargulies

By default, your service is WRAPPED, not BARE, and so the top-level item in the message has to be a type with the same name as the operation. In 'classic' JAX-WS, this requires you to add a wrapper type.

默认情况下,您的服务是 WRAPPED,而不是 BARE,因此消息中的顶级项必须是与操作同名的类型。在“经典”JAX-WS 中,这需要您添加包装器类型。

If you use Apache CXF, it will automatically generate these wrappers with ASM.

如果您使用Apache CXF,它会使用 ASM 自动生成这些包装器。

回答by kaushik

In the service interface if you have an entry:

在服务界面中,如果您有一个条目:

@WebResult(targetNamespace = "http://jws.samples.geronimo.apache.org/")

before the addmethod in the Calculator interface, then you can get the wrapper classes created by the JAX-WS client on-the-fly using the following code:

在Calculator 接口中的add方法之前,您可以使用以下代码即时获取 JAX-WS 客户端创建的包装类:

import java.net.URL;

import javax.xml.namespace.QName;

import javax.xml.ws.Service;

public class TestWS{

  public static void main(String args[]) throws Exception
  {
     URL url = "url to wsdl"

     QName qname = new QName("http://jws.samples.geronimo.apache.org/", "Name of your service" );
     Service service = Service.create(url, qname);
     Calculator calcPort = service.getPort(Calculator.class);
     System.out.println("Result of 1+2 is " + calcPort.add(1,2));     
  }
}