博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JAX-WS(JWS)发布WebService
阅读量:6375 次
发布时间:2019-06-23

本文共 23493 字,大约阅读时间需要 78 分钟。

WebService历来都很受重视,特别是Java阵营,WebService框架和技术层出不穷。知名的XFile(新的如CXF)、Axis1、Axis2等。

  而Sun公司也不甘落后,从早期的JAX-RPC到现在成熟的、支持RPC调用与消息传递的JAX-WS都经过了市场的考验,十分成熟,而且使用JAX-WS开发WebService的收益是很大的,它是轻量级的。 

一、WebService的开发方法

使用Java开发WebService时可以使用以下两种开发手段

    1、 使用JDK开发(1.6及以上版本)

    2、使用第三方组件,如CXF框架开发

二、使用JDK开发WebService

JAX-WS 2.0 有两种开发过程:自顶向下和自底向上。自顶向下方式指通过一个 WSDL 文件来创建Web Service,自底向上是从 Java 类出发创建 Web Service。两种开发过程最终形成的文件包括:

1.SEI(Service Endpoint Interface 发布的服务接口)。一个SEI对应WSDL中WebService的一个port,在Java中是一个Java接口。

2.SEI实现类。

3.WSDL和XSD文件。

 

我们使用JAX-WS开发WebService只需要很简单的几个步骤:写接口和实现=>发布=>生成客户端(测试或使用)。

2.1、开发WebService服务器端

  而在开发阶段我们也不需要导入外部jar包,因为这些api都是现成的。首先是接口的编写(接口中只需要把类注明为@WebService,把要暴露给客户端的方法注明为@WebMethod即可,其余如@WebResult、@WebParam等都不是必要的,而客户端和服务端的通信用RPC和Message-Oriented两种,区别和配置以后再说):

注解说明:

@WebService 注释在了Class之上,这告诉了JAXWS,此类为Webservice。@WebService注解让系统知道我们希望使用哪个接口来创建WSDL,本例中就是

HelloWService接口。

@WebMethod 注释在了public方法上,这告诉了JAXWS,此方法为soap方法。

接口:

package com.server.ws;import java.util.Date;import javax.jws.WebService;import com.server.domain.PersonModel;/** * WebService接口 */@WebService(name = "HelloWS", targetNamespace = "http://www.client.com/ws/hello")public interface HelloWService {    /**     * 返回字符串     *      * @return     */    String index();    /**     * 两个整数相加     *      * @param x     * @param y     * @return 相加后的值     */    Integer add(Integer x, Integer y);    /**     * 返回当前时间     *      * @return     */    Date now();    /**     * 获取复杂类型     *      * @param name     *            用户姓名     * @param age     *            用户年龄     * @return 返回用户类     */    PersonModel getPerson(String name, Integer age);}

 

实现类(注解@WebService及其endpointInterface属性是必要的):

package com.server.ws.impl;import java.util.Date;import javax.jws.HandlerChain;import javax.jws.WebService;import com.server.domain.PersonModel;import com.server.ws.HelloWService;@WebService(    endpointInterface = "com.server.ws.HelloWService",    portName = "HelloWSPort",    serviceName = "HelloWSService",    targetNamespace = "http://www.client.com/ws/hello")@HandlerChain(file="handler-chain.xml")public class HelloWServiceImpl implements HelloWService {    public String index() {        return "hello";    }    public Integer add(Integer x, Integer y) {        return x + y;    }    public Date now() {        return new Date();    }        public PersonModel getPerson(String name, Integer age) {        PersonModel person = new PersonModel();        person.setAge(age);        person.setName(name);                return person;    }}

实体对象:

package com.server.domain;import java.io.Serializable;public class PersonModel implements Serializable {    private static final long serialVersionUID = -7211227324542440039L;        private String name;    private Integer age;        public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public Integer getAge() {        return age;    }    public void setAge(Integer age) {        this.age = age;    }}

handler:

package com.server.ws.handler;import java.io.IOException;import java.util.Set;import javax.xml.namespace.QName;import javax.xml.soap.SOAPException;import javax.xml.soap.SOAPMessage;import javax.xml.ws.handler.MessageContext;import javax.xml.ws.handler.soap.SOAPHandler;import javax.xml.ws.handler.soap.SOAPMessageContext;/** * 记录SOAP请求及响应 * */public class LoggerSOAPHandler implements SOAPHandler
{ @Override public void close(MessageContext context) { } @Override public boolean handleFault(SOAPMessageContext context) { return true; } @Override public boolean handleMessage(SOAPMessageContext context) { // 判断消息是输入还是输出 Boolean output = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY); System.out.println(output ? "响应SOAP:" : "请求SOAP:"); SOAPMessage message = context.getMessage(); try { message.writeTo(System.out); } catch (SOAPException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } System.out.println(""); System.out.println(""); return true; } @Override public Set
getHeaders() { return null; }}
package com.server.ws.handler;import java.util.Iterator;import java.util.Set;import javax.xml.namespace.QName;import javax.xml.soap.SOAPBody;import javax.xml.soap.SOAPElement;import javax.xml.soap.SOAPEnvelope;import javax.xml.soap.SOAPException;import javax.xml.soap.SOAPFault;import javax.xml.soap.SOAPHeader;import javax.xml.soap.SOAPMessage;import javax.xml.ws.handler.MessageContext;import javax.xml.ws.handler.soap.SOAPHandler;import javax.xml.ws.handler.soap.SOAPMessageContext;/** * 服务端请求校验Handler  * */public class ValidateAuthHandler implements SOAPHandler
{ @Override public void close(MessageContext context) { } @Override public boolean handleFault(SOAPMessageContext context) { return true; } @Override public boolean handleMessage(SOAPMessageContext context) { // 判断消息是请求还是响应 Boolean output = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY); boolean result = false; SOAPMessage message = context.getMessage(); //如果是请求,则执行校验 if(!output){ result = validate(message); if(!result){ validateFail(message); } } System.out.println(output ? "服务端响应:" : "服务端接收:"); try { message.writeTo(System.out); } catch (Exception e) { e.printStackTrace(); } System.out.println("\r\n"); return result; } /** * 授权校验失败,在SOAPBody中添加SOAPFault * @param message */ private void validateFail(SOAPMessage message) { try { SOAPEnvelope envelop = message.getSOAPPart().getEnvelope(); envelop.getHeader().detachNode(); envelop.addHeader(); envelop.getBody().detachNode(); SOAPBody body = envelop.addBody(); SOAPFault fault = body.getFault(); if (fault == null) { fault = body.addFault(); } fault.setFaultString("授权校验失败!"); message.saveChanges(); } catch (SOAPException e) { e.printStackTrace(); } } /** * 授权校验 * @param message * @return 校验成功返回true,校验失败返回false */ private boolean validate(SOAPMessage message){ boolean result = false; try { SOAPEnvelope envelop = message.getSOAPPart().getEnvelope(); SOAPHeader header = envelop.getHeader(); if(header != null){ Iterator iterator = header.getChildElements(new QName("http://www.client.com/auth", "auth")); SOAPElement auth = null; if(iterator.hasNext()){ //获取auth auth = (SOAPElement)iterator.next(); //获取name Iterator it = auth.getChildElements(new QName("http://www.client.com/auth", "name")); SOAPElement name = null; if(it.hasNext()){ name = (SOAPElement)it.next(); } //获取password it = auth.getChildElements(new QName("http://www.client.com/auth", "password")); SOAPElement password = null; if(it.hasNext()){ password = (SOAPElement)it.next(); } //判断name和password是否符合要求 if(name != null && password != null && "admin".equals(name.getValue()) && "admin".equals(password.getValue())){ result = true; } } } } catch (SOAPException e) { e.printStackTrace(); } return result; } @Override public Set
getHeaders() { return null; }}

2.2、发布

发布一般有两种方式:

方式一:Endpoint.publish

A、通过运行WebServicePublish类,就可以将编写好的WebService发布
package com.server.publish;import javax.xml.ws.Endpoint;import com.server.ws.impl.HelloWServiceImpl;/** * 发布Web Service * */public class WebServicePublish {    public static void main(String[] args) {        // 定义WebService的发布地址,这个地址就是提供给外界访问Webervice的URL地址,URL地址格式为:http://ip:端口号/xxxx        // String address = "http://192.168.1.100:8989/";这个WebService发布地址的写法是合法的        // String address =        // "http://192.168.1.100:8989/Webservice";这个WebService发布地址的是合法的        String address = "http://localhost:8989/WS_Server/Webservice";        // 使用Endpoint类提供的publish方法发布WebService,发布时要保证使用的端口号没有被其他应用程序占用        Endpoint.publish(address, new HelloWServiceImpl());        System.out.println("发布webservice成功!");    }}

访问上面配置的地址http://localhost:8989/WS_Server/Webservice结果如下:

我的java工程结构是:

B、如果是Web项目,那么我们可以使用监听器或者Servlet来发布WebService,如下:

B.1、使用ServletContextListener监听器发布WebService

package com.server.publish;import javax.servlet.ServletContextEvent;import javax.servlet.ServletContextListener;import javax.xml.ws.Endpoint;import com.server.ws.impl.HelloWServiceImpl;public class WebServicePublishListener implements ServletContextListener {    @Override    public void contextDestroyed(ServletContextEvent arg0) {        // TODO Auto-generated method stub    }    @Override    public void contextInitialized(ServletContextEvent arg0) {        // 定义WebService的发布地址,这个地址就是提供给外界访问Webervice的URL地址,URL地址格式为:http://ip:端口号/xxxx        // String address = "http://192.168.1.100:8989/";这个WebService发布地址的写法是合法的        // String address =        // "http://192.168.1.100:8989/Webservice";这个WebService发布地址的是合法的        String address = "http://localhost:8081/WS_Server/Webservice";        // 使用Endpoint类提供的publish方法发布WebService,发布时要保证使用的端口号没有被其他应用程序占用        Endpoint.publish(address, new HelloWServiceImpl());        System.out.println("发布webservice成功!");    }}

xml配置如下:

com.server.publish.WebServicePublishListener

打包成war,部署到tomcat,并启动tomcat,访问及结果如下:

B.2、使用Servlet监听器发布WebService

package com.server.publish;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.xml.ws.Endpoint;import com.server.ws.impl.HelloWServiceImpl;/** *  用于发布WebService的Servlet,使用Servlet3.0提供的@WebServlet注解将继承HttpServlet类的普通Java类标注为一个Servlet, *  将value属性设置为空字符串,这样WebServicePublishServlet就不提供对外访问的路径 *  loadOnStartup属性设置WebServicePublishServlet的初始化时机 * *///@WebServlet(value="",loadOnStartup=0)public class WebServicePublishServlet extends HttpServlet {         public void init() throws ServletException {             //WebService的发布地址             String address = "http://localhost:8888/WebService";             //发布WebService,HelloWServiceImpl类是WebServie接口的具体实现类             Endpoint.publish(address , new HelloWServiceImpl());             System.out.println("使用WebServicePublishServlet发布webservice成功!");         }}

xml配置:

  
jaxws
com.server.publish.WebServicePublishServlet
1
jaxws
/start

打包成war,部署到tomcat,并启动tomcat,访问及结果如下:

C、通过WebService配置文件sun-jaxws.xml

C.1、在WEB-INF中创建WebService配置文件sun-jaxws.xml,配置文件中一个WebService对应一个Endpoint。,如下: 

sun-jaxws.xml文件:

C.2、在web.xml中添加WSServlet,如果Web项目使用Servlet 3.0则不需要以下配置,如下:

web.xml文件:

com.sun.xml.ws.transport.http.servlet.WSServletContextListener
jaxws
com.sun.xml.ws.transport.http.servlet.WSServlet
1
jaxws
/services

打包成war,部署到tomcat,并启动tomcat,访问及结果如下:

 

2.2、生成客户端

最后是客户端使用,由于WebService是平台和语言无关的基于xml的,所以我们完全可以使用不同语言来编写或生成客户端。

一般有三种方式来使用(对于Java语言而言):

一、使用jdk自带工具wsimport生成客户端:

  

  jdk自带的wsimport工具生成,上图我是把客户端文件生成到了桌面src文件中(-d),并保留了源文件(-keep),指定了包名(-p)。

  然后我们就可以使用生成的文件来调用服务器暴露的方法了:

 

值得一提的是你生成使用的jdk和你客户端的jre需要配套!

  从上面的目录结构我们可以发现:服务端的每个webmethod都被单独解析成为了一个类(如果使用了实体,实体也会被解析到客户端,并且是源码,所以建议使用实体时慎重)。

而我们的service则被生成了一个代理类来调用服务,接下来我们看看使用情况,在客户端调用服务:

package com.client;import com.client.wsdl.hello.HelloWS;import com.client.wsdl.hello.HelloWSService;import com.client.wsdl.hello.PersonEntity;/** * 调用WebService的客户端 * */public class WSClient {    public static void main(String[] args) {        // 创建一个用于产生WebServiceImpl实例的工厂,WebServiceImplService类是wsimport工具生成的        HelloWSService factory = new HelloWSService();        // 通过工厂生成一个WebServiceImpl实例,WebServiceImpl是wsimport工具生成的        HelloWS wsImpl = factory.getHelloWSPort();        // 调用WebService的add方法        Integer resResult = wsImpl.add(10, 22);        System.out.println("调用WebService的add方法返回的结果是:" + resResult);        System.out.println("---------------------------------------------------");        // 调用WebService的save方法        PersonEntity pm = wsImpl.getPerson("孤傲苍狼", 123);        System.out.println("调用WebService的getPerson方法返回的结果是:" + pm.getName() + ",age=" + pm.getAge());    }}

handler

package com.client.handler;import java.util.Set;import javax.xml.namespace.QName;import javax.xml.soap.SOAPElement;import javax.xml.soap.SOAPException;import javax.xml.soap.SOAPHeader;import javax.xml.soap.SOAPMessage;import javax.xml.ws.handler.MessageContext;import javax.xml.ws.handler.soap.SOAPHandler;import javax.xml.ws.handler.soap.SOAPMessageContext;public class AddAuthHandler implements SOAPHandler
{ @Override public boolean handleMessage(SOAPMessageContext context) { // 判断消息是请求还是响应 Boolean output = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY); SOAPMessage message = context.getMessage(); if (output) { try { SOAPHeader header = message.getSOAPHeader(); if (header == null) { header = message.getSOAPPart().getEnvelope().addHeader(); } SOAPElement auth = header.addChildElement(new QName("http://www.client.com/auth", "auth")); SOAPElement name = auth.addChildElement("name"); name.addTextNode("admin"); SOAPElement password = auth.addChildElement("password"); password.addTextNode("admin"); message.saveChanges(); } catch (SOAPException e) { e.printStackTrace(); } } System.out.println(output ? "校验" : "不校验"); try { message.writeTo(System.out); } catch (Exception e) { e.printStackTrace(); } System.out.println("\r\n"); return true; } @Override public boolean handleFault(SOAPMessageContext context) { return true; } @Override public void close(MessageContext context) { } @Override public Set
getHeaders() { return null; }}

看看服务器的输出,我们是否调用成功:

成功了!

2 client端的servlet方式

 

package com.client.servlet.hello;import java.io.IOException;import java.net.URL;import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import com.client.wsdl.hello.HelloWS;import com.client.wsdl.hello.HelloWSService;@WebServlet("/hello/add/servlet")public class AddServlet extends HttpServlet {    private static final long serialVersionUID = 1L;    public AddServlet() {        super();    }    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        URL wsdlUrl = new URL("http://localhost:8080/jaxwsserver-0.0.1-SNAPSHOT/services/hello?wsdl");        HelloWSService helloWSS = new HelloWSService(wsdlUrl);                HelloWS helloWS = helloWSS.getHelloWSPort();                Integer x = 3;        Integer y = 5;        Integer add = helloWS.add(x, y);                response.setCharacterEncoding("utf-8");        response.setContentType("text/plain;charset=utf-8");        response.getWriter().write(x.toString() + y.toString() + "=" + add.toString());    }}

 

Ayncnow方法

package com.client.servlet.hello;import java.io.PrintWriter;import java.net.URL;import javax.servlet.AsyncContext;import javax.servlet.http.HttpServletResponse;import com.client.wsdl.hello.HelloWS;import com.client.wsdl.hello.HelloWSService;public class AsyncNowServletProcessor extends Thread {    private AsyncContext ac;        public AsyncNowServletProcessor(AsyncContext ac){        this.ac = ac;    }        public void run() {        HttpServletResponse response = (HttpServletResponse)ac.getResponse();        response.setCharacterEncoding("utf-8");        response.setContentType("text/plain;charset=utf-8");                try {            URL wsdlUrl = new URL("http://localhost:8080/jaxwsserver-0.0.1-SNAPSHOT/services/hello?wsdl");            HelloWSService helloWSS = new HelloWSService(wsdlUrl);            HelloWS helloWS = helloWSS.getHelloWSPort();            helloWS.now();            PrintWriter out = response.getWriter();            String now = helloWS.now().toGregorianCalendar().toString();            out.write(now);            out.flush();        } catch (Exception e) {            e.printStackTrace();        }finally{            ac.complete();        }    }    }

index方法

package com.client.servlet.hello;import java.io.IOException;import java.net.URL;import java.util.ArrayList;import java.util.List;import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.xml.ws.handler.Handler;import javax.xml.ws.handler.HandlerResolver;import javax.xml.ws.handler.PortInfo;import com.client.wsdl.hello.HelloWS;import com.client.wsdl.hello.HelloWSService;import com.client.handler.AddAuthHandler;/** * Servlet implementation class IndexServlet */@WebServlet("/hello/index/servlet")public class IndexServlet extends HttpServlet {    private static final long serialVersionUID = 1L;           /**     * @see HttpServlet#HttpServlet()     */    public IndexServlet() {        super();        // TODO Auto-generated constructor stub    }    /**     * @see HttpServlet#service(HttpServletRequest request, HttpServletResponse response)     */    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        URL wsdlUrl = new URL("http://localhost:8080/jaxwsserver-0.0.1-SNAPSHOT/services/hello?wsdl");        HelloWSService helloWSS = new HelloWSService(wsdlUrl);                //通过HandlerResolver添加Handler                helloWSS.setHandlerResolver(new HandlerResolver(){            @Override            @SuppressWarnings("rawtypes")                        public List
getHandlerChain(PortInfo portInfo) { List
handlerChain = new ArrayList
(); handlerChain.add(new AddAuthHandler()); return handlerChain; } }); HelloWS helloWS = helloWSS.getHelloWSPort(); response.setCharacterEncoding("utf-8"); response.setContentType("text/plain;charset=utf-8"); response.getWriter().write(helloWS.index()); }}

now方法

package com.client.servlet.hello;import java.io.IOException;import java.io.PrintWriter;import java.net.URL;import javax.servlet.AsyncContext;import javax.servlet.AsyncEvent;import javax.servlet.AsyncListener;import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import com.client.wsdl.hello.HelloWS;import com.client.wsdl.hello.HelloWSService;/** * Servlet implementation class NowServlet */@WebServlet(value = "/hello/now/servlet", asyncSupported = true)public class NowServlet extends HttpServlet {    private static final long serialVersionUID = 1L;           /**     * @see HttpServlet#HttpServlet()     */    public NowServlet() {        super();        // TODO Auto-generated constructor stub    }    /**     * @see HttpServlet#service(HttpServletRequest request, HttpServletResponse response)     */    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {                URL wsdlUrl = new URL("http://localhost:8080/jaxwsserver-0.0.1-SNAPSHOT/services/hello?wsdl");        HelloWSService helloWSS = new HelloWSService(wsdlUrl);        HelloWS helloWS = helloWSS.getHelloWSPort();        String now = helloWS.now().toGregorianCalendar().toString();                response.setCharacterEncoding("utf-8");        response.setContentType("text/plain;charset=utf-8");        //new AsyncNowServletProcessor(null).start();                        PrintWriter out = response.getWriter();                out.write(now);        out.flush();        /*        AsyncContext ac = request.startAsync(request, response);        ac.addListener(new AsyncListener(){                        public void onComplete(AsyncEvent arg0) throws IOException {                            }                        public void onError(AsyncEvent arg0) throws IOException {            }                        public void onStartAsync(AsyncEvent arg0) throws IOException {            }                        public void onTimeout(AsyncEvent arg0) throws IOException {            }                    }, request, response);                new AsyncNowServletProcessor(ac).start();        */    }}

person

package com.client.servlet.hello;import java.io.IOException;import java.net.URL;import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import com.client.wsdl.hello.HelloWS;import com.client.wsdl.hello.HelloWSService;import com.client.wsdl.hello.PersonEntity;/** * Servlet implementation class PersonServlet */@WebServlet("/hello/person/servlet")public class PersonServlet extends HttpServlet {    private static final long serialVersionUID = 1L;           /**     * @see HttpServlet#HttpServlet()     */    public PersonServlet() {        super();        // TODO Auto-generated constructor stub    }    /**     * @see HttpServlet#service(HttpServletRequest request, HttpServletResponse response)     */    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        URL wsdlUrl = new URL("http://localhost:8080/jaxwsserver-0.0.1-SNAPSHOT/services/hello?wsdl");        HelloWSService helloWSS = new HelloWSService(wsdlUrl);        HelloWS helloWS = helloWSS.getHelloWSPort();                PersonEntity person = helloWS.getPerson("年龄", 18);                response.setCharacterEncoding("utf-8");        response.setContentType("text/plain;charset=utf-8");        response.getWriter().write("名字;" + person.getName() + ",年龄;" + person.getAge());    }}

 

 

 

   

转载地址:http://nltqa.baihongyu.com/

你可能感兴趣的文章
二叉树递归与非递归遍历(附完整源码)
查看>>
ios开发系列-UITableController-动态页面
查看>>
sublime中BracketHighlighter 插件使用
查看>>
ROS 2编写包并用colcon编译
查看>>
gitlab重置root的密码
查看>>
关于C/C++中,对static关键字的理解
查看>>
Tomcat 5常用优化和配置
查看>>
几个性能测试工具
查看>>
(转)丰田公司精益管理的14项原则- [Lean and Agile]
查看>>
开发进度——2
查看>>
Java基础语法之Java初识
查看>>
Java Socket编程基础知识
查看>>
jenkins忘记管理员账号密码的补救方法-转
查看>>
jQuery基础三
查看>>
已Access为支持,书写一个C#写入的记录的方案
查看>>
JavaScript自适应调整文字大小
查看>>
实验报告一:网络侦查与网络扫描
查看>>
.net 接入微信商户企业支付API 问题总结
查看>>
防止SQL注入
查看>>
java中的动态代理(三)
查看>>