java_webservice

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/RowanIT3/article/details/86537996

之前项目需要与客户方进行接口交接,选择了webservice接口。这里记录下如何创建服务端,客户端。

  • 服务端
    关于发布webservice,其实主要使用了javax.xml.ws.Endpoint类提供的静态方法publish进行发布,但形式可以使用多种方式,比如:
    ①通过一个类的main方法+publish方法

    ②BS项目中的使用Servlet3.0提供的@WebListener注解将实现了ServletContextListener接口的WebServicePublishListener类标注为一个Listener

    ③通过servlet的init()方法,且在注解中@webService设置loadOnStartup=0:@WebServlet(value="",loadOnStartup=0)意思就是启动服务器是首先启动。

在项目中我主要采用的是第三种方式,通过init()在初始化servlet的时候就发布webService接口。
定义一个主类,里面是对外公布的public接口方法:

package test;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.xml.ws.Endpoint;


@WebServlet(value="",loadOnStartup=0)
public class publishWS extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public publishWS() {
          super();
        // TODO Auto-generated constructor stub
    }
    
    public void init() throws ServletException {
        //自定义服务器端接口地址,如果是本地的话,ip需要自己查,后面的路径是自己
        //来定义,这里最好做成xml配置文件来取,部署的时候方便
        String Address = "http://192.168.103.145:9527/Service/Contract/WebService";
        //publish第二个参数是我们的实现类
        Endpoint.publish(Address , new mainInterface());
        System.out.println("webService接口发布成功!");
	 }
}

主要对外接口方法,需要注解@WebService

package test;

import javax.jws.WebService;

@WebService
public class mainInterface {

	public String func1(String xx...) {
		return 
	}
	

	public String func2(String xx ...) {
	    return 
	}
	
	public String func3(String xx...) {
		return 
	}
}

在这里插入图片描述
在浏览器中输入url地址:
在这里插入图片描述
查看接口的报文格式:
在这里插入图片描述
这里我使用的soapUI这款软件,加载带wsdl的报文地址,可以看到接口的方法及它request请求的soap格式,可以用来测试接口:
在这里插入图片描述

  • 客户端
    一般对方接口人员也会给你个webService地址,此时我们可以查看带?wsdl的url来查看它的报文xml结构,里面会显示对方公布的方法。生产客户端代码的方式有很多种,比如jdk自带的wsimport,apache cxf等,项目里我选择了jdk这种方式:
wsimport -d '指定生成代码的路径' -keep '对方的webservice地址+?wsdl'

个别参数含义:
-d : 表示输出的目录,目录必须事先存在,否则导出失败
-keep : 表示生成客户端执行类的源代码
-p : 定义客户端生成类的包名称
-s : 指定客户端执行类的源文件存放目录
-b : 指定jaxws/jaxb绑定文件或额外的schemas
-verbose : verbose表示详细信息
-extension : 使用扩展来支持SOAP1.2

这里再记录下,当时对方的接口需要权限认证,就是要求用户名,密码,但是我生成的代码里面没有设置这类的方法,后面查询了很多资料,需要重写指定方法:

//这里的SZAOIECONTRACTWSSService类是根据wsdl自动解析生成的
SZAOIECONTRACTWSSService xx= new SZAOIECONTRACTWSSService();
		xx.setHandlerResolver(new HandlerResolver() {
			@Override
			public List<Handler> getHandlerChain(PortInfo arg0) {
				List<Handler> handlerList = new ArrayList<Handler>();
				// 添加认证信息
				handlerList.add(new setHeader());
				return handlerList;
			}
		});

setHeader.class

package test;

import java.util.Set;

import javax.xml.namespace.QName;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPHeaderElement;
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 setHeader implements SOAPHandler<SOAPMessageContext> {

	@Override
	public void close(MessageContext arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public boolean handleFault(SOAPMessageContext arg0) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean handleMessage(SOAPMessageContext ctx) {
		// TODO Auto-generated method stub
		
		// 出站,即客户端发出请求前,添加表头信息
		Boolean request_p = (Boolean) ctx.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
		if (request_p) {
			try {
				SOAPMessage msg = ctx.getMessage();
				SOAPEnvelope env = msg.getSOAPPart().getEnvelope();
				SOAPHeader hdr = env.getHeader();
				if (hdr == null)
					hdr = env.addHeader();

				// 添加认证信息头
				QName name = new QName(
						"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd",
						"Security", "wsse");
				SOAPHeaderElement header = hdr.addHeaderElement(name);
				SOAPElement UsernameToken = header.addChildElement("UsernameToken", "wsse");
				SOAPElement userElement = UsernameToken.addChildElement("Username", "wsse");
				userElement.addTextNode("你的用户名");
				SOAPElement passElement = UsernameToken.addChildElement("Password", "wsse");
				passElement.addTextNode("你的密码");

				msg.saveChanges();

				// 把SOAP消息输出到System.out,即控制台
				//msg.writeTo(System.out);

				return true;
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return false;
	}

	@Override
	public Set<QName> getHeaders() {
		// TODO Auto-generated method stub
		return null;
	}
}

其余的就是根据实际业务来进行编码。对于webservcie还有很多方法可以实现,这里我只是简单记录下自己在项目中使用到的几点。但是我感觉这种根据别人的wsdl地址来生成代码很受限制,如果对方更改了webservice地址或者接口 方法我都需要重新切生成一遍,可能是我不清楚或者还没找到合适的方式来适应这种,都是这种笨办法重新生成。

参考资料:
初识webservice

猜你喜欢

转载自blog.csdn.net/RowanIT3/article/details/86537996