JAX-WS小试

JAX-WS

Java API for XML-Based Web Services

Java™ API for XML-based web services (JAX-WS), which is also known as JSR-224, is the next generation web services programming model that extends the foundation provided by the Java API for XML-based RPC (JAX-RPC) programming model. Using JAX-WS, developing web services and clients is simplified with greater platform independence for Java applications by the use of dynamic proxies and Java annotations. The web services tools included in this product support JAX-WS 2.0, 2.1, and 2.2.


JAX-WS主要的包结构

Package Description
javax.xml.ws Has the Core JAX-WS APIs
javax.xml.ws.http Has APIs specific to XML/HTTP Binding
javax.xml.ws.soap Has APIs specific to SOAP/HTTP Binding
javax.xml.ws.handler Has APIs for message handlers
javax.xml.ws.spi defines SPIs for JAX-WS
javax.xml.ws.spi.http Provides HTTP SPI that is used for portable deployment of JAX-WS in containers
javax.xml.ws.wsaddressing Has APIs related to WS-Addressing
javax.jws Has APIs specific to Java to WSDL mapping annotations
javax.jws.soap Has APIs for mapping the Web Service onto the SOAP protocol


1、编写服务端

使用注解把一个类暴露成服务类

package com.lyx.ws;

import java.util.ArrayList;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.jws.WebParam.Mode;
import javax.jws.soap.SOAPBinding;

/**
 * 提供WebService服务的类
 */
@WebService(name = "Example", targetNamespace = "http://www.jsoso.com/wstest", serviceName = "Example")
@SOAPBinding(style = SOAPBinding.Style.RPC)
public class Example {
    private ArrayList<Person> persons = new ArrayList<Person>();

    /**
     * 返回一个字符串
     *
     * @param userName
     * @return
     */
    @WebMethod(operationName = "toSayHello", action = "sayHello", exclude = false)
    @WebResult(name = "returnWord")//自定义该方法返回值在WSDL中相关的描述
    public String sayHello(@WebParam(name = "userName") String userName) {
        return "Hello:" + userName;
    }

    /**
     * web services 方法的返回值与参数的类型不能为接口
     *
     * @param person
     * @return
     * @throws HelloException
     */
    @WebMethod(operationName = "sayHello", action = "sayHello")
    @WebResult(partName = "personList")
    public Person[] sayHello(@WebParam(partName = "person", mode = Mode.IN) Person person,
                             String userName) throws HelloException {
        if (person == null || person.getName() == null) {
            throw new HelloException("说hello出错,对像为空");
        }
        System.out.println(person.getName() + " 对 " + userName + " 说:Hello,我今年" + person.getAge() + "岁");
        persons.add(person);
        return persons.toArray(new Person[0]);
    }
}

启动服务端的类(使用JavaAPI即发布服务)

package com.lyx.ws;

import java.util.LinkedList;
import java.util.List;
import javax.xml.ws.Binding;
import javax.xml.ws.Endpoint;
import javax.xml.ws.handler.Handler;

/**
 * @author zsy 启动web services服务
 */
public class StartServer {

    /**
     * @param args
     */
    public static void main(String[] args) {
        /**
         * 生成Example 服务实例
         */
        Example serverBean = new Example();
        /**
         * 发布Web Service到http://localhost:8080/hello地址
         */
        Endpoint endpoint = Endpoint.publish("http://localhost:8080/hello", serverBean);
        Binding binding = endpoint.getBinding();
        /**
         * 设置一个SOAP协议处理栈
         * 这里就简单得打印SOAP的消息文本
         */
        List<Handler> handlerChain = new LinkedList<Handler>();
        binding.setHandlerChain(handlerChain);
        System.out.println("服务已启动 http://localhost:8080/hello");
    }
}

发布服务成功在浏览器访问http://localhost:8080/hello


2、生成客户端代码

D:\JetBrains\HelloWS\src>wsimport -p com.lyx.ws.client -keep http://localhost:8080/hello?wsdl    
parsing WSDL...

Generating code...    
Compiling code...

wsimport    
wsimport也是在JDK的bin目录下的一个exe文件(Windows版),主要功能是根据服务端发布的wsdl文件生成客户端存根及框架,负责 与Web Service 服务器通信,并在将其封装成实例,客户端可以直接使用,就像使用本地实例一样。对Java而言,wsimport帮助程序员生存调用web service所需要的客户端类文件.java和.class。要提醒指出的是,wsimport可以用于非Java的服务器端,如:服务器端也许是C# 编写的web service,通过wsimport则生成Java的客户端实现。    


命令参数说明:

  • -d 生成客户端执行类的class文件的存放目录

  • -s 生成客户端执行类的源文件的存放目录

  • -p 定义生成类的包名


成功,生成的目录及各种类:

JAX-WS小试_第1张图片


3、编写客户端的测试类

package com.lyx.ws;

import com.lyx.ws.client.*;
import com.lyx.ws.client.Example;

/**
 * 测试Java6 WS生成的客户端代码
 */
public class TestClient {
    public static void main(String[] args) {
        //创建一个客户端服务对象
        Example exampleService = new Example_Service().getExamplePort();
        //调用服务方法,并得到方法返回值
        String result = exampleService.toSayHello("hello world~~~~~~~~~~");
        //打印服务的返回值
        System.out.println(result);
    }
}

执行就可以调用服务器端的代码。

除了这一种方法调用之外还有其他方式调用。

image


4、使用HttpClient方式来调用Web Service

这里使用soapui构建soap请求,使用过程截图:

JAX-WS小试_第2张图片

代码:

CallWebServiceByHttpClient.java

package com.lyx.ws;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.impl.client.DefaultHttpClient;

import java.io.*;

/**
 * Created with IntelliJ IDEA.
 * User: ASUS
 * Date: 14-4-13
 * Time: 下午1:19
 * To change this template use File | Settings | File Templates.
 */
public class CallWebServiceByHttpClient {

    public static void main(String args[]) throws IOException {


        //通过soapui构建的soap请求字符串
        String soapRequest = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:wst=\"http://www.jsoso.com/wstest\">\n" +
                "   <soapenv:Header/>\n" +
                "   <soapenv:Body>\n" +
                "      <wst:toSayHello>\n" +
                "         <userName>lyx</userName>\n" +
                "      </wst:toSayHello>\n" +
                "   </soapenv:Body>\n" +
                "</soapenv:Envelope>";
        HttpPost post = new HttpPost("http://localhost:8080/hello");

        byte[] b = soapRequest.getBytes("utf-8");
        ByteArrayEntity entity = new ByteArrayEntity(b, 0, b.length, ContentType.create("text/xml", "utf-8"));
        post.setEntity(entity);
        HttpClient httpClient = new DefaultHttpClient();

        HttpResponse response = httpClient.execute(post);

        //HTTP 415 错误 – 不 支持的媒体类型application/soap+xml
        System.out.println("返回的状态码:" + response.getStatusLine().getStatusCode());
        //200

        //读取返回结果
        if (response.getStatusLine().getStatusCode() == 200) {
            HttpEntity responseEntity = response.getEntity();
            InputStream in = responseEntity.getContent();
            BufferedReader r = new BufferedReader(new InputStreamReader(in));
            StringBuilder total = new StringBuilder();
            String line;
            while ((line = r.readLine()) != null) {
                total.append(line);
            }

            //最终返回的也是xml格式的数据,这里数据未进行格式化显示和处理
            System.out.println(total.toString());

//            得到返回的xml文本,可以使用
//            String result = "<?xml version=\"1.0\" ?>\n" +
//                    "<S:Envelope xmlns:S=\"http://schemas.xmlsoap.org/soap/envelope/\">\n" +
//                    "    <S:Body>\n" +
//                    "        <ns2:toSayHelloResponse xmlns:ns2=\"http://www.jsoso.com/wstest\">\n" +
//                    "            <returnWord>Hello:lyx</returnWord>\n" +
//                    "        </ns2:toSayHelloResponse>\n" +
//                    "    </S:Body>\n" +
//                    "</S:Envelope>";

        }
    }
}


5、WebService的发布方式之二

实际中Web服务的发布常常伴随着Web容器的启动而发布,而在Java,我们没法直接像Axis2

那样直接去发布,但是可以通过变通的方法,通过Servlet来和容器绑定起来,在容器启动的时候发布服务。

xml中要配置该Servlet

开发发布服务的Servlet,为了通用性,最好选择GenericServlet来继承

package com.lyx.ws;

import javax.servlet.*;
import javax.xml.ws.Endpoint;
import java.io.IOException;

/**
 * WebService的Servlet,
 */
public class WSServlet extends GenericServlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        super.init(servletConfig);
        System.out.println("准备启动WebService服务:http://localhost:8080/hello");
        //发布一个WebService
        //Endpoint.publish是一个后台线程,一旦发布了就会一直等待处理Web服务的请求,只有当main方法退出,或者容器关闭的时候,才自动退出。
        //其实除了这种方式,也可以整合Spring来实现服务的发布,这就和Spring的Ioc容器整合在一起了。不管什么,道理就一个,调用Endpoint.publish()方法来实现服务的发布。
        //在发布服务的时候,应该避免使用Tomcat容器的端口,以免发生冲突
        Endpoint.publish("http://localhost:8080/hello", new Example());
        System.out.println("已成功启动WebService服务:http://localhost:8080/hello");
    }

    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("此Servlet不处理任何业务逻辑,仅仅发布一个Web服务:http://localhost:8080/hello");
    }
}


====END====


你可能感兴趣的:(JAX-WS小试)