• webservice访问的几种方式


      今天在对接的客户用到了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

  • 相关阅读:
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    Spring框架——AOP面向切面编程
    Spring学习
    面试题整理
    Java Web前端到后台常用框架介绍
    【Oracle】SQL/92 执行多个表的连接
    什么是持久化?
  • 原文地址:https://www.cnblogs.com/qlqwjy/p/10567378.html
Copyright © 2020-2023  润新知