前言
最近做需求要写几个接口与另外一个系统进行对接,本想按照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配置
web.xml配置
最后通过访问服务地址就可以看到具体的服务信息
(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进行调用服务接口,一整套还是比较方便的,没有其它复杂的过程,不过每个人的需求不一样,我这个各位看官简单看看就好( •̀ ω •́ )✧