今天在对接的客户用到了webservice,最终采用wsimport生成本地代理方式以SDK的形式对接,但是想的完整的总结一下ws的几种调用方式。

  发布服务的IP地址是:192.168.125.116

  客户端访问ws服务的IP是:192.168.125.115

1.发布ws服务:

  参考:https://www.cnblogs.com/qlqwjy/p/9644078.html

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/jaxws http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <jaxws:endpoint id="userServiceWS"
implementor="cn.xm.exam.service.impl.webservice.UserWebServiceImpl" address="/userServiceWS">
</jaxws:endpoint> </beans>

web.xml如下:

    <servlet>
<servlet-name>CXFServlet</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/WS/*</url-pattern>
</servlet-mapping>
package cn.xm.exam.service.webservice;

import java.util.Set;

import javax.jws.WebService;

import cn.xm.exam.bean.system.User;

@WebService
public interface UserWebService { /**
* 根据用户身份证号码查询用户信息及其角色信息及其权限信息
*
* @param useridcard
* @return user
*/
public User getUserByUseridcard(String useridcard) throws Exception; /**
* 根据用户编号查询角色code的集合
*
* @param userid
* @return 角色集合
*/
public Set<String> getRoleByUserid(String userid) throws Exception; }
package cn.xm.exam.service.impl.webservice;

import java.util.Set;

import javax.annotation.Resource;
import javax.jws.WebService; import org.springframework.stereotype.Service; import cn.xm.exam.bean.system.User;
import cn.xm.exam.mapper.system.UserMapper;
import cn.xm.exam.service.webservice.UserWebService;
import cn.xm.exam.utils.ValidateCheck; @Service
@WebService(targetNamespace = "http://webservice.service.exam.xm.cn")
public class UserWebServiceImpl implements UserWebService {
@Resource
private UserMapper userMapper; @Override
public User getUserByUseridcard(String useridcard) {
if (ValidateCheck.isNull(useridcard)) {
return null;
}
User user = null;
try {
user = userMapper.getUserByUseridcard(useridcard);
} catch (Exception e) {
e.printStackTrace();
}
return user;
} @Override
public Set<String> getRoleByUserid(String userid) {
if (ValidateCheck.isNull(userid)) {
return null;
}
Set<String> role = null;
try {
role = userMapper.getRoleByUserid(userid);
} catch (Exception e) {
e.printStackTrace();
}
return role;
} }

启动之后查看ws服务:

查看wsdl:

2.访问ws的几种方式

1.wsimport生成本地代理的方式(简单--类似于SDK访问)

生成本地代码(如果需要下载源码,加上 -keep 参数即可)

wsimport http://192.168.125.116:85/Exam/WS/userServiceWS?wsdl

发现虽然我们只是发布了一个webservice,但是下载的时候会将接口中依赖的bean等信息也一起发布。

打包

jar cvf ./test.jar ./

放入eclipse进行测试

import java.net.MalformedURLException;
import java.net.URL; import javax.xml.namespace.QName; import cn.xm.exam.service.webservice.Exception_Exception;
import cn.xm.exam.service.webservice.User;
import cn.xm.exam.service.webservice.UserWebService;
import cn.xm.exam.service.webservice.UserWebServiceImplService; public class Test {
public static void main(String[] args) throws Exception_Exception,
MalformedURLException {
// 创建的时候用URL指定WSDL的地址;用QName指定targetNamespace和name。当然可以不指定,不指定使用的是默认值
// UserWebServiceImplService userWebServiceImplService = new UserWebServiceImplService();
UserWebServiceImplService userWebServiceImplService = new UserWebServiceImplService(
new URL("http://192.168.125.116:85/Exam/WS/userServiceWS?wsdl"),
new QName("http://webservice.service.exam.xm.cn",
"UserWebServiceImplService"));
UserWebService userWebServiceImplPort = userWebServiceImplService
.getUserWebServiceImplPort();
User userByUseridcard = userWebServiceImplPort
.getUserByUseridcard("140581197705070518");
System.out.println(userByUseridcard.getUsername());
}
}

结果:

  返回从192.168.125.116返回数据库查询的信息。 也就是说我们调用ws接口的时候实际底层是http+xml,因此我们可以通过ws接口调用到服务器的信息。

2.  CXF动态调用:(推荐这种)

依赖的包:

测试代码如下:

import javax.xml.namespace.QName;

import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;

public class Test2 {
public static void main(String[] args) {
JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance(); org.apache.cxf.endpoint.Client client = dcf.createClient("http://localhost:85/Exam/WS/userServiceWS?wsdl"); // url为调用webService的wsdl地址 QName name = new QName("http://webservice.service.exam.xm.cn/", "getUserByUseridcard");// namespace是命名空间,methodName是方法名 Object[] objects;
try {
objects = client.invoke(name, "140581197705070518");// 第一个参数是上面的QName,第二个开始为参数,可变数组
System.out.println(objects);
} catch (Exception e) {
e.printStackTrace();
}
}
}

注意:

(1)QName的第一个参数必须带斜杠,也就是必须写为http://webservice.service.exam.xm.cn/,否则会报下面异常:

org.apache.cxf.common.i18n.UncheckedException: No operation was found with the name {http://webservice.service.exam.xm.cn}getUserByUseridcard.
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:331)
at Test2.main(Test2.java:15)

(2)发布的webservice的接口和实现类要在同一个包,或者在实现类用注解声明发布的webservice地址。

  CXF发布用的是业务类(xxxServiceImpl.java),那么默认的命名空间就会是业务类所在包(路径),而对外界暴露的则是接口类(XXXService.java),那么对于客户端(第三方)调用访问时,需要按照接口类所在包(路径)进行命名空间的定义。所以需要接口与实现在同一个包或者在实现类指定接口地址。

如下:(最好以/结尾---下面没有以斜杠结尾)

@Service
@WebService(targetNamespace = "http://webservice.service.exam.xm.cn")
public class UserWebServiceImpl implements UserWebService {
  。。。

(3)查看namespace相关信息:(两两相同是因为上面发布的时候没有以/结尾,最好以/结尾四个namespace就会相同)

3.通过axis包访问(简单)

  所需5个jar包 axis-1.4.jar axis-jaxrpc-1.4.jar commons-logging-1.2.jar  commons-discovery-0.2.jar wsdl4j-1.6.3.jar

这个在测试的时候直接返回bean报错(解决办法就是加类型转换器),因此我返回的是String数据。接口和实现类修改如下:

package cn.xm.exam.service.webservice;

import java.util.Set;

import javax.jws.WebResult;
import javax.jws.WebService; import cn.xm.exam.bean.system.User; @WebService
public interface UserWebService { /**
* 根据用户身份证号码查询用户信息及其角色信息及其权限信息
*
* @param useridcard
* @return user
*/
public String getUsernameByUseridcard(String useridcard) throws Exception; /**
* 根据用户编号查询角色code的集合
*
* @param userid
* @return 角色集合
*/
public Set<String> getRoleByUserid(String userid) throws Exception; }
package cn.xm.exam.service.impl.webservice;

import java.util.Set;

import javax.annotation.Resource;
import javax.jws.WebService;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; import org.springframework.stereotype.Service; import cn.xm.exam.bean.system.User;
import cn.xm.exam.mapper.system.UserMapper;
import cn.xm.exam.service.webservice.UserWebService;
import cn.xm.exam.utils.ValidateCheck; @Service
@WebService(targetNamespace = "http://webservice.service.exam.xm.cn")
public class UserWebServiceImpl implements UserWebService {
@Resource
private UserMapper userMapper; @Override
public String getUsernameByUseridcard(String useridcard) {
if (ValidateCheck.isNull(useridcard)) {
return null;
}
User user = null;
try {
user = userMapper.getUserByUseridcard(useridcard);
} catch (Exception e) {
e.printStackTrace();
}
return user == null ? "" : user.getUsername();
} @Override
public Set<String> getRoleByUserid(String userid) {
if (ValidateCheck.isNull(userid)) {
return null;
}
Set<String> role = null;
try {
role = userMapper.getRoleByUserid(userid);
} catch (Exception e) {
e.printStackTrace();
}
return role;
} }

测试代码:

代码一:

package zd.dms.wbws;

import java.net.MalformedURLException;
import java.net.URL;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map; import javax.xml.namespace.QName;
import javax.xml.rpc.ParameterMode;
import javax.xml.rpc.ServiceException; import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.apache.axis.encoding.XMLType; public class AxisClient {
public static void main(String[] args) {
String webServiceURL = "http://localhost:85/Exam/WS/userServiceWS?wsdl";
String namespaceURI = "http://webservice.service.exam.xm.cn/";
String method = "getUsernameByUseridcard";
List<Map<String, Object>> params = new ArrayList<Map<String, Object>>();
Map<String, Object> map = new HashMap<String, Object>();
map.put("paramName", "arg0");
map.put("paramType", XMLType.XSD_STRING);
map.put("paramValue", "140581197705070518");
params.add(map);
String result = (String) AxisClient.getResult(webServiceURL, namespaceURI, method, null, params,
XMLType.XSD_STRING);
System.out.println(result);
} /**
* Axis方式访问WebService接口
*
* @param webServiceURL
* webService地址,末尾为?wsdl时不需要写
* @param namespaceURI
* 命名空间
* @param method
* 方法名称
* @param soapAction
* soapAction
* @param params
* 参数
* @param returnType
* 返回值类型
* @return
*/
public static Object getResult(String webServiceURL, String namespaceURI, String method, String soapAction,
List<Map<String, Object>> params, QName returnType) {
if (null == params || params.size() == 0)
return null;
// 创建客户端
Service service = new Service();
Call call = null;
try {
call = (Call) service.createCall();
// 设置访问地址
call.setTargetEndpointAddress(new URL(webServiceURL));
// 是否使用SOAPAction
if (null == soapAction || "".equals(soapAction)) {
call.setUseSOAPAction(false);
} else {
call.setUseSOAPAction(true);
// 设置SOAPAction地址
call.setSOAPActionURI(soapAction);
}
// 设置访问方法名称
call.setOperationName(new QName(namespaceURI, method));
// 添加解析类型的地址
call.setEncodingStyle(namespaceURI);
// 设置返回值类型
call.setReturnType(returnType);
// 添加参数名称
Object[] obj = new Object[params.size()];
for (int i = 0; i < params.size(); i++) {
Map<String, Object> map = params.get(i);
call.addParameter(new QName((String) map.get("paramName")), (QName) map.get("paramType"),
ParameterMode.IN);
obj[i] = map.get("paramValue");
}
return call.invoke(obj);
} catch (ServiceException e) {
e.printStackTrace();
return null;
} catch (MalformedURLException e) {
e.printStackTrace();
return null;
} catch (RemoteException e) {
e.printStackTrace();
return null;
}
}
}

代码二:

package zd.dms.wbws;

import javax.xml.namespace.QName;
import javax.xml.rpc.ParameterMode; import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.apache.axis.encoding.XMLType; public class TestUseWebservice2 {
public static void main(String[] args) {
Object ticket = testWS();
System.out.println(ticket);
} public static Object testWS() {
try {
// wsdl的地址
String endpoint = "http://localhost:85/Exam/WS/userServiceWS?wsdl";
// 直接引用远程的wsdl文件
// 以下都是固定格式
Service service = new Service();
Call call = (Call) service.createCall();
call.setTargetEndpointAddress(endpoint); // WSDL里面描述的方法名称 填写方法名是需加上命名空间,否则会找不到对应的方法
call.setOperationName(new QName("http://webservice.service.exam.xm.cn/", "getUsernameByUseridcard"));
// 添加解析类型的地址
call.setEncodingStyle("webservice.service.exam.xm.cn"); // 给方法传递参数,并且调用方法
call.addParameter("arg0", XMLType.XSD_STRING, ParameterMode.IN);
call.setReturnType(XMLType.XSD_ENTITY);// 设置返回类型
return call.invoke(new Object[] { "140581197705070518" });
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}

  由于webservice采用SOAP协议,相当于http+xml,因此我们访问的时候可以获取到服务器的数据。

  而RPC相当于接口和实现分离,我们获取到接口,然后实现类可以从RPC的注册中心进行获取。当然RPC也可以获取远程的数据。其实webservice和RPC可以通过生成代理对象获取远程的数据。我们用RPC以本地方式调用服务,实则会向服务器的具体实现类发送请求并获取数据。(当然这中间有对方法、请求参数的包装以及解码等工作)

 

CXF访问参考:https://www.cnblogs.com/qlqwjy/p/9644078.html

webservice访问的几种方式的更多相关文章

  1. System.Web.Http.Cors配置跨域访问的两种方式

    System.Web.Http.Cors配置跨域访问的两种方式 使用System.Web.Http.Cors配置跨域访问,众多大神已经发布了很多文章,我就不在详细描述了,作为小白我只说一下自己的使用心 ...

  2. JavaScript对象属性访问的两种方式

    JavaScript对象属性访问的两种方式 object.attribute object["attribute"] 例如: var employees = [ { "f ...

  3. Oracle 执行计划(二)------表访问的几种方式

    表访问的几种方式:(非全部) 参照表 primary key is id 1.TABLE ACCESS FULL(全表扫描):查询出该表所有数据,获取的数据执行where语句. Don’t creat ...

  4. Axis2开发WebService客户端 的3种方式

    Axis2开发WebService客户端 的3种方式 在dos命令下   wsdl2java        -uri    wsdl的地址(网络上或者本地)   -p  com.whir.ezoffi ...

  5. 动态调用WebService接口的几种方式

    一.什么是WebService? 这里就不再赘述了,想要了解的====>传送门 二.为什么要动态调用WebService接口? 一般在C#开发中调用webService服务中的接口都是通过引用过 ...

  6. 【Java EE 学习 80 下】【调用WebService服务的四种方式】【WebService中的注解】

    不考虑第三方框架,如果只使用JDK提供的API,那么可以使用三种方式调用WebService服务:另外还可以使用Ajax调用WebService服务. 预备工作:开启WebService服务,使用jd ...

  7. webService调用的N种方式

    一.服务器端代码 新建一个web Service Project工程(貌似普通的java工程也可以,这里不太明白各种webService的框架有什么区别),建立如下的类: package com.bo ...

  8. 【js跨域】js实现跨域访问的几种方式

    这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据.只要协议.域名.端口有任何一个不同,都被 ...

  9. HTTP访问的两种方式(HttpClient+HttpURLConnection)整合汇总对比(转)

    在Android上http 操作类有两种,分别是HttpClient和HttpURLConnection,其中两个类的详细介绍可以问度娘. HttpClient: HttpClient是Apache ...

随机推荐

  1. 学习笔记《Mustache》模板

    Mustache 是一款经典的前端模板引擎,在前后端分离的技术架构下面,前端模板引擎是一种可以被考虑的技术选型,随着重型框架(AngularJS.ReactJS.Vue)的流行,前端的模板技术已经成为 ...

  2. C语言中可变参数的函数(三个点,“...”)

    C语言中可变参数的函数(三个点,“...”) 本文主要介绍va_start和va_end的使用及原理. 在以前的一篇帖子Format MessageBox 详解中曾使用到va_start和va_end ...

  3. 点击button自动刷新页面的奇葩错误

    以前在写练习的时候遇到过这样一个问题,自己在html中写了一个button <button>test1</button> 在没有给其附上onclick事件时是点击是不会有任何反 ...

  4. Android自动化测试手段之Monkey(adb shell monkey)

    一. 什么是Monkey Monkey是Android中的一个命令行工具,可以运行在模拟器里或实际设备中.它向系统发送伪随机的用户事件流(如按键输入.触摸屏输入.手势输入等),实现对正在开发的应用程序 ...

  5. 给hMailServer添加DKIM图文教程

    https://www.hmailserver.org/viewtopic.php?f=4&t=12

  6. SQL Server没有足够的内存继续执行程序 (mscorlib)的解决办法

    在Microsoft SQL Server Management Studio 中执行较大的sql脚本时,会报没有足够的内存继续执行程序(mscorlib)的错误.如下图所示 解决方法: 使用sqlc ...

  7. SpringCloud入门(一)

    一.微服务概述 1.什么是微服务 目前的微服务并没有一个统一的标准,一般是以业务来划分将传统的一站式应用,拆分成一个个的服务,彻底去耦合,一个微服务就是单功能业务,只做一件事. 与微服务相对的叫巨石 ...

  8. 其它综合-有关service、systemctl、chkconfig、init

    有关service.systemctl.chkconfig.init CentOS 7.x 开始,CentOS 开始使用 systemd 服务来代替 daemon,原来管理系统启动和管理系统服务的相关 ...

  9. 雷军微博拧螺丝,CFO为粉丝数发愁

    导读 小米集团联合创始人.品牌战略官黎万强4年前写的书<参与感>,估计又要热卖了. 3月24日,小米CFO周受资发微博,“我刚接受了同事的挑战,要在一定时间内在微博上有更多的粉丝”,并向粉 ...

  10. JS Array.reduce 对象属性累加

    Array reduce() 方法  ,无非就是 计算数组元素 相加后的总和 ,看网上给的Demo 全是  [1,2,3,4,6].reduce 这种基本用法, 本次我将使用 reduce 实现 数组 ...