前言

最近做需求要写几个接口与另外一个系统进行对接,本想按照api接口的方式做了就好了,没想到一看接口规范文档,还必须要求我们这边开发webService接口,我们调用他们也是webService接口的方式。好家伙,这又是强行准备让我回顾老知识了,webService以前也是接触过,写过几个demo就完事了,没想到这个年头还有人在用。本着技多不压身(也不算技)的原则,还是一起回顾回顾吧,以后用到着也方便翻阅。

一、WebService的介绍

关于WebService,大家可以去看看这个大佬的文章,写的非常详细,这里就不多做介绍了。

WebService介绍及使用(Java)

二、WebService的使用

这里提一手,关于webService框架的选择,下面是几个比较常用的框架介绍

  • CXF
    Apache CXF 是一个开源的 Services 框架,CXF 帮助您利用 Frontend 编程 API 来构建和开发 Services ,像 JAX-WS 。这些 Services 可以支持多种协议,比如:SOAP、XML/HTTP、RESTful HTTP 或者 CORBA ,并且可以在多种传输协议上运行,比如:HTTP、JMS 或者 JBI,CXF 大大简化了 Services 的创建,同时它继承了 XFire 传统,一样可以天然地和 Spring 进行无缝集成。
  • JAX-WS
    JAX-WS 的全称为 Java API forXML-Based Webservices ,早期的基于SOAP 的JAVA 的Web 服务规范JAX-RPC(Java API For XML-RemoteProcedure Call)目前已经被JAX-WS 规范取代。从java5开始支持JAX-WS2.0版本,Jdk1.6.0_13以后的版本支持2.1版本,jdk1.7支持2.2版本
  • Axis
    Axis2是继Axis后由Apache公司推出的新的Web Service模型。Axis2实际上就是一个Servlet,因此它的运行必须依赖Servlet容器。Axis2本身就有Web应用服务器,同时它也适用其他的Servlet容器。Axis2是Apache下的一个重量级WebService框架,准确说它是一个Web Services/ SOAP / WSDL的引擎,它比较全面的集成了Web Service框架。

这里我就不说孰优孰劣,按照自己的喜欢或者技术要求进行框架选型,这里的webService服务端,我使用的是JaxWS,刚开始想用CXF来着,但是后来发现JaxWS更轻便,上手要快一点,所以嘿嘿嘿。。。。。。

(1)、webService服务端

第一步:引入jar包依赖

<dependency>
   <groupId>com.sun.xml.ws</groupId>
   <artifactId>jaxws-rt</artifactId>
   <version>2.2.10</version>
   <scope>runtime</scope>
</dependency>

第二步:编写接口和接口实现类

这里先创建一个服务接口,记得加上@WebService
看过webService介绍的应该知道webService服务有targetNamespace命名空间,服务名称name,服务方法名称operationName等各个属性
如果想自己命名可以加上这些注解或者指定属性值,这里我就加了一个@WebService 其它的全是生成的默认值,到时候看wsdl就可以知道这些默认值是什么了
@WebMethod注解表明这个方法是服务方法,operationName属性制定这个服务方法名称,这个名称必须和服务实现类中的服务方法名称一致,否则,客户端调用会找不到这个服务方法。

package com.numberone.master.modules.oa.ws;

import javax.jws.WebParam;
import javax.jws.WebService;

// @WebService(targetNamespace="http://ws.oa.modules.master.numberone.com/", name="fourAServiceImpService")
@WebService
public interface fourAService {

	// @WebMethod(operationName="UpdateAppAcctSoap")
    public String UpdateAppAcctSoap(@WebParam(name = "RequestInfo") String RequestInfo);

	// @WebMethod(operationName="CheckAiuapTokenSoap")
    public String CheckAiuapTokenSoap(@WebParam(name = "RequestInfo") String RequestInfo);
}

接下来就是接口实现类
这里可以看到我在实现类上同样加了@WebService注解,这个要发布服务不能少,然后还可以看到有个endpointInterface属性,这个属性的解释是:指定用于定义服务的抽象 Web Service 约定的服务端点接口的限定名。如果指定了此限定名,那么会使用该服务端点接口来确定抽象 WSDL 约定。具体通俗点解释就是:如果没加这个属性那么生成的WebService服务是根据实现类来生成的,比如实现类有三个实现方法,那么就有三个。如果加了这个属性,那么生成的WebService服务是根据接口来生成的,如果实现类有三个,接口有两个,那么生成的服务只有两个

package com.numberone.master.modules.oa.ws;

import com.numberone.master.common.xml.KsocketSend;

import com.numberone.master.modules.api.service.ApiWorkOrderService;

import org.springframework.stereotype.Service;
import org.springframework.web.context.ContextLoaderListener;

import javax.jws.WebService;
import java.util.Map;

@Service
@WebService(endpointInterface = "com.numberone.master.modules.oa.ws.fourAService",targetNamespace = "http://ws.oa.modules.master.numberone.com/")
public class fourAServiceImp implements fourAService {

    @Override
    public String UpdateAppAcctSoap( String RequestInfo) {
        // 因为@webService问题 导致不能使用 @autoWire注解的方式获取bean 所以用下面这个运行时获取上下文的bean方法
        ApiWorkOrderService apiWorkOrderService =  ContextLoaderListener.getCurrentWebApplicationContext().getBean(ApiWorkOrderService.class);
        KsocketSend ksocketSend = new KsocketSend();
        String returnMsg = "";
        try {
            Map map = ksocketSend.unpackXml(RequestInfo, "BOCM-4A-0001.xml");
            returnMsg = apiWorkOrderService.UpdateAppAcctSoap(map, ksocketSend);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return returnMsg;
    }

    @Override
    public String CheckAiuapTokenSoap(String RequestInfo) {
        KsocketSend ksocketSend = new KsocketSend();
        String returnMsg = "";
        try {
            Map map = ksocketSend.unpackXml(RequestInfo, "BOCM-4A-0004.xml");
            map.put("CODE", map.get("CODE"));
            map.put("SID", map.get("SID"));
            map.put("TIMESTAMP", map.get("TIMESTAMP"));
            map.put("SERVICEID", map.get("SERVICEID"));

            map.put("RSP", "0");
            map.put("MAINACCTID", "admin");
            map.put("APPACCTID", "admin");
            returnMsg = ksocketSend.packXml(map, "BOCM-4A-0005.xml");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return returnMsg;
    }
}

以上就是webService代码方面的,下面还需要进行一些对应的配置

sun-jaxws.xml配置

java service manager 示例_webservice


web.xml配置

java service manager 示例_java_02


最后通过访问服务地址就可以看到具体的服务信息

java service manager 示例_xml_03

(2)、webService客户端

这里的客户端我就简单的使用了axis进行服务接口调用,按照我下面这个代码基本上就可以调用了

// 这里把需要引入的jar包也注明一下 防止引错其它的jar包
// import org.apache.axis.client.Call;
// import org.apache.axis.encoding.XMLType;
// import javax.xml.namespace.QName;
// import javax.xml.rpc.ParameterMode;
// import java.net.URL;
@RequestMapping(value = "/checkLogin", method = RequestMethod.GET)
	public String checkSso(@RequestParam(value = "token")String token ,
						   @RequestParam(value = "appAcctId")String appAcctId ,
						   @RequestParam(value = "flag")String flag,
						   HttpServletRequest request, HttpServletResponse response) {

		Map map = new HashMap();
		KsocketSend ksocketSend = new KsocketSend();
		map.put("TIMESTAMP", DateUtils.getDate("yyyyMMddHHmmss"));
		map.put("APPACCTID",appAcctId);
		map.put("TOKEN",token);
		try {
			String wsUrl = apiWorkOrderDao.getApiUrlByName("http://127.0.0.1:8080/numberone_war_exploded/UpdateAppAcctSoap?wsdl");
			String nameSpaceUrl = apiWorkOrderDao.getApiUrlByName("http://ws.oa.modules.master.numberone.com/");

			// 通过xml封装方法得到xml格式的数据
			String params = ksocketSend.packXml(map,"BOCM-4A-0004.xml");
			Object[] obj = new Object[]{params};

			org.apache.axis.client.Service  service = new org.apache.axis.client.Service();
			Call call = (Call) service.createCall();
			QName resId= new QName(nameSpaceUrl, "CheckAiuapTokenSoap"); // WSDL里面描述的接口名称
			call.setTargetEndpointAddress(new URL(wsUrl));
			call.setOperationName(resId);
			call.addParameter("RequestInfo", XMLType.XSD_STRING, ParameterMode.IN);// 接口的参数
			call.setReturnType(XMLType.XSD_STRING);// 设置返回类型 
			call.setUseSOAPAction(true);
			// 给方法传递参数,并且调用方法 ,如果无参,则new Obe
			String result = (String) call.invoke(obj);
			System.out.println(result);
			// 解析 token 验证的报文信息
			Map resultMap = ksocketSend.unpackXml(result, "BOCM-4A-0005.xml");
			String rsp = (String) resultMap.get("RSP");
			// 获得从账号的名称
			String userName = (String) resultMap.get("APPACCTID");
			String passWord = "A09466658E990EC2"; 
			if ("0".equals(rsp)){
				return "redirect:/fourA/ssoLogin?username=" + userName + "&password=" + passWord;
			}
		}catch (Exception e){
			e.printStackTrace();
		}
		return "error/authenticationFail";
	}

直接访问接口地址就可以调用服务接口了

到此webService的使用就差不多完成了,从生成服务端,然后使用axis进行调用服务接口,一整套还是比较方便的,没有其它复杂的过程,不过每个人的需求不一样,我这个各位看官简单看看就好( •̀ ω •́ )✧