Spring整合CXF 发布webservice接口服务器和客户端,WSDL简单解析
ccwgpt 2024-10-28 14:58 125 浏览 0 评论
在垮平台通讯中有很多的接口方式,这里做个简单的webservice接口。发布webservice接口的方式也多种多样,这里做个基于CXF的webservice接口。首先做点知识储备,javax.jws包中常用的注解,参考链接:http://blog.csdn.net/w410589502/article/details/51742004
下面开始,这里Spring用的4.2的,CXF用的3.2的,JDK是1.8的,这里只要是1.6及以后的就没问题了,主要是要用javax.jws的包
服务端webservice接口
package com.lovo.webservice;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;
/**
* SOAP协议的webservice接口
* @author WZH
*服务器端,服务提供者
*/
/*
* @WebService 标记为一个webservice接口
* 1.targetNamespace:指定你想要的名称空间,默认认是使用接口实现类的包名的反缀,
* 但是在实际测试中发现cxf+spring编写webservice的时候,targetNamespace要指向
* 服务类的接口所在的包名而不是实现类的包名,否则,在客户端将不能识别可用的服务
* 2.serviceName: 对外发布的服务名,指定 Web Service 的服务名称:wsdl:service。
* 缺省值为 Java 类的简单名称 + Service。(字符串)
* 3.portName: wsdl:portName。缺省值为 WebService.name+Port。
*
* @SOAPBinding 消息绑定, 这个标记怎么说,我这里测试的时候加不加都无所谓,但是有同仁说过
* 不加这个有时候会出现客户端无法识别,有的人又报错,所以还是加上吧
* Exception in thread "main" com.sun.xml.internal.ws.model.RuntimeModelerException:
* runtime modeler error: Wrapper class org.soap.service.jaxws.Add is not found. Have you run APT to generate them?
*/
@WebService(targetNamespace ="http://webservice.lovo.com/",serviceName="HelloService",portName="HellowServicePort")
@SOAPBinding(style=Style.RPC)
public interface IHelloService {
/*
* @WebResult 注释用于定制从返回值至 WSDL 部件或 XML 元素的映射。将此注释应用于客户机或服务器服务端点接口(SEI)上的方法,
* 或者应用于 JavaBeans 端点的服务器端点实现类
* 1.name:当返回值列示在 WSDL 文件中并且在连接上的消息中找到该返回值时,指定该返回值的名称。对于 RPC 绑定,这是用于表示返回值的
* 2.targetNamespace:指定返回值的 XML 名称空间。仅当操作类型为 RPC 或者操作是文档类型并且参数类型为 BARE 时才使用此参数。(字符串)
*
* @WebMethod 注释表示作为一项 Web Service 操作的方法,将此注释应用于客户机或服务器服务端点接口(SEI)上的方法,
* 或者应用于 JavaBeans 端点的服务器端点实现类。
* 1.operationName:指定与此方法相匹配的wsdl:operation 的名称。缺省值为 Java 方法的名称。(字符串)
*
* @WebParam 注释用于定制从单个参数至 Web Service 消息部件和 XML 元素的映射
* 1.name :参数的名称。如果操作是远程过程调用(RPC)类型并且未指定partName 属性,
* 那么这是用于表示参数的 wsdl:part 属性的名称。如果操作是文档类型或者参数映射至某个头,那么 -name 是用于表示该参数的 XML 元素的局部名称。
* 如果操作是文档类型、参数类型为 BARE 并且方式为 OUT 或 INOUT,那么必须指定此属性。(字符串)
*/
@WebResult(name="helloRequest",targetNamespace="http://webservice.lovo.com/")
@WebMethod(operationName="sayHello1")
public String hello(@WebParam(name="msg")String message);
}
服务端接口实现类
package com.lovo.webservice.impl;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;
import org.springframework.stereotype.Service;
import com.lovo.webservice.IHelloService;
/*
* endpointInterface: 服务接口全路径, 指定做SEI(Service EndPoint Interface)服务端点接口,简单的说就写接口的全路径
*/
@WebService(endpointInterface="com.lovo.webservice.IHelloService")
@SOAPBinding(style=Style.RPC)
public class HelloServiceImpl implements IHelloService {
@Override
public String hello(String message) {
return "你好" + message;
}
}
前面的两段代码只是简单的java加上一些注解,下面把代码整合入Spring的web工程
web.xml 配置
需在web.xml中配置CXF
<!-- 启动CXF框架 web service-->
<servlet>
<servlet-name>cxf</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>cxf</servlet-name>
<url-pattern>/webservice/*</url-pattern>
</servlet-mapping>
完整的xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>Spring</display-name>
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>Spring.root</param-value>
</context-param>
<!-- spring容器启动 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/classes/applicationContext.xml</param-value>
</context-param>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/log4j.xml</param-value>
</context-param>
<!-- 指定日志刷新的时间,单位毫秒 -->
<context-param>
<param-name>log4jRefreshInterval</param-name>
<param-value>60000</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 配置欢迎页面 -->
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!-- 字符过滤器 -->
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- <filter>
<filter-name>encoding</filter-name>
<filter-class>com.lovo.filter.EncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping> -->
<!-- 启动CXF框架 web service-->
<servlet>
<servlet-name>cxf</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>cxf</servlet-name>
<url-pattern>/webservice/*</url-pattern>
</servlet-mapping>
<!-- 配置核心控制器 -->
<servlet>
<servlet-name>Spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
配置cxf的配置文件,这个也可以直接配置在Spring的配置文件中,看项目风格吧
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd">
<!--CXF配置 这里因为是3.x的CXF 只需要引用一个文件就好-->
<import resource="classpath:META-INF/cxf/cxf.xml" />
<!-- id是接口名,不重复就好,serviceClass 是接口的路径,address是对外暴露的地址名,bean classs是引用的接口的实现类 -->
<jaxws:server id="helloService" serviceClass="com.lovo.webservice.IHelloService" address="/HelloService">
<jaxws:serviceBean>
<bean class="com.lovo.webservice.impl.HelloServiceImpl"></bean>
</jaxws:serviceBean>
</jaxws:server>
</beans>
在application.xml中引入cxf.xml
<!--CXF配置 -->
<import resource="classpath:META-INF/cxf/cxf.xml"/>
<import resource="classpath:/cxf-beans.xml"/>
完整的application.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:task="http://www.springframework.org/schema/task"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-3.0.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
<!-- 开启自动扫描机制 -->
<context:component-scan base-package="com"></context:component-scan>
<!-- <context:property-placeholder location="classpath:mysql.properties"/> -->
<!-- 配置数据库连接池 -->
<!-- 商业数据源 c3p0, apache提供的DBCP -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="oracle.jdbc.driver.OracleDriver"></property>
<property name="jdbcUrl" value="jdbc:oracle:thin:@localhost:1521:oracle"></property>
<property name="user" value="system"></property>
<property name="password" value="Password01"></property>
<property name="initialPoolSize" value="15"></property><!-- 初始化连接数的数量 -->
<property name="minPoolSize" value="15"></property>
<property name="maxPoolSize" value="100"></property>
<property name="acquireIncrement" value="5"></property>
<property name="maxStatements" value="200"></property>
<property name="maxIdleTime" value="200"></property><!-- 超时时间 -->
<property name="checkoutTimeout" value="2000"></property><!-- 多长时间回收一次超时连接 -->
</bean>
<!-- SessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<!-- 如果有多包需要取类别名的话,使用,或;分割 -->
<property name="typeAliasesPackage" value="com.lovo.beans"></property>
</bean>
<!-- 将Session与Mapper直接进行关联 -->
<bean id="mapperScanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.lovo.mapper"></property>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
</bean>
<!-- 配置事务管理器 -->
<bean id="txManage"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- session实例化 -->
<!-- 声明事物 -->
<tx:advice id="txAdvice" transaction-manager="txManage">
<tx:attributes>
<tx:method name="*" read-only="true"></tx:method>
<tx:method name="add*" read-only="false" propagation="REQUIRED"
isolation="REPEATABLE_READ" rollback-for="java.lang.Exception"></tx:method>
<tx:method name="save*" read-only="false" propagation="REQUIRED"
isolation="REPEATABLE_READ" rollback-for="java.lang.Exception"></tx:method>
<tx:method name="insert*" read-only="false" propagation="REQUIRED"
isolation="REPEATABLE_READ" rollback-for="java.lang.Exception"></tx:method>
<tx:method name="update*" read-only="false" propagation="REQUIRED"
isolation="REPEATABLE_READ" rollback-for="java.lang.Exception"></tx:method>
<tx:method name="modify*" read-only="false" propagation="REQUIRED"
isolation="REPEATABLE_READ" rollback-for="java.lang.Exception"></tx:method>
<tx:method name="change*" propagation="REQUIRED" read-only="false"
rollback-for="java.lang.Exception" isolation="REPEATABLE_READ"></tx:method>
<tx:method name="delete*" read-only="false" propagation="REQUIRED"
isolation="REPEATABLE_READ" rollback-for="java.lang.Exception"></tx:method>
<tx:method name="remove*" read-only="false" propagation="REQUIRED"
isolation="REPEATABLE_READ" rollback-for="java.lang.Exception"></tx:method>
<!-- 添加了一个删除方法的命名 -->
<tx:method name="del*" read-only="false" propagation="REQUIRED"
isolation="REPEATABLE_READ" rollback-for="java.lang.Exception"></tx:method>
<tx:method name="select*" read-only="true" propagation="SUPPORTS"></tx:method>
<tx:method name="find*" read-only="true" propagation="SUPPORTS"></tx:method>
<tx:method name="get*" read-only="true" propagation="SUPPORTS"></tx:method>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="serviceMethods"
expression="execution(* com.lovo.service.impl.*.*(..))"></aop:pointcut>
<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethods"></aop:advisor>
</aop:config>
<!-- 开启切面功能 -->
<aop:aspectj-autoproxy />
<!--CXF配置 -->
<import resource="classpath:META-INF/cxf/cxf.xml"/>
<import resource="classpath:/cxf-beans.xml"/>
</beans>
下面来测试下发布是否成功,我这里是tomcat 工程名是Spring,拦截的是webservice,所以访问的地址是:http://localhost:8080/Spring/webservice?wsdl
出现界面
右键连接地址可以下载wsdl
这样就发布了一个简单的webservice接口,下面在发布一个接口以便wsdl的时候做对比,然后再发布一个rest风格的接口
package com.lovo.webservice;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;
/**
* SOAP协议的webservice接口
* @author WZH
*服务器端,服务提供者
*/
/*
* @WebService 标记为一个webservice接口
* 1.targetNamespace:指定你想要的名称空间,默认认是使用接口实现类的包名的反缀,
* 但是在实际测试中发现cxf+spring编写webservice的时候,targetNamespace要指向
* 服务类的接口所在的包名而不是实现类的包名,否则,在客户端将不能识别可用的服务
* 2.serviceName: 对外发布的服务名,指定 Web Service 的服务名称:wsdl:service。
* 缺省值为 Java 类的简单名称 + Service。(字符串)
* 3.portName: wsdl:portName。缺省值为 WebService.name+Port。
*
* @SOAPBinding 消息绑定, 这个标记怎么说,我这里测试的时候加不加都无所谓,但是有同仁说过
* 不加这个有时候会出现客户端无法识别,有的人又报错,所以还是加上吧
* Exception in thread "main" com.sun.xml.internal.ws.model.RuntimeModelerException:
* runtime modeler error: Wrapper class org.soap.service.jaxws.Add is not found. Have you run APT to generate them?
*/
@WebService(targetNamespace ="http://webservice.lovo.com/",serviceName="HelloService",portName="HellowServicePort")
@SOAPBinding(style=Style.RPC)
public interface IHelloService {
/*
* @WebResult 注释用于定制从返回值至 WSDL 部件或 XML 元素的映射。将此注释应用于客户机或服务器服务端点接口(SEI)上的方法,
* 或者应用于 JavaBeans 端点的服务器端点实现类
* 1.name:当返回值列示在 WSDL 文件中并且在连接上的消息中找到该返回值时,指定该返回值的名称。对于 RPC 绑定,这是用于表示返回值的
* 2.targetNamespace:指定返回值的 XML 名称空间。仅当操作类型为 RPC 或者操作是文档类型并且参数类型为 BARE 时才使用此参数。(字符串)
*
* @WebMethod 注释表示作为一项 Web Service 操作的方法,将此注释应用于客户机或服务器服务端点接口(SEI)上的方法,
* 或者应用于 JavaBeans 端点的服务器端点实现类。
* 1.operationName:指定与此方法相匹配的wsdl:operation 的名称。缺省值为 Java 方法的名称。(字符串)
*
* @WebParam 注释用于定制从单个参数至 Web Service 消息部件和 XML 元素的映射
* 1.name :参数的名称。如果操作是远程过程调用(RPC)类型并且未指定partName 属性,
* 那么这是用于表示参数的 wsdl:part 属性的名称。如果操作是文档类型或者参数映射至某个头,那么 -name 是用于表示该参数的 XML 元素的局部名称。
* 如果操作是文档类型、参数类型为 BARE 并且方式为 OUT 或 INOUT,那么必须指定此属性。(字符串)
*/
@WebResult(name="helloRequest",targetNamespace="http://webservice.lovo.com/")
@WebMethod(operationName="sayHello1")
public String hello(@WebParam(name="msg")String message);
@WebResult(name="loginRequest",targetNamespace="http://webservice.lovo.com/")
@WebMethod(operationName="login")
public String login(@WebParam(name="userName")String userName,@WebParam(name="password")String password);
}
这里需要特别注意,targetNamespace中路径结尾需写反斜杠/不然会出现问题
package com.lovo.webservice.impl;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;
import org.springframework.stereotype.Service;
import com.lovo.webservice.IHelloService;
/*
* endpointInterface: 服务接口全路径, 指定做SEI(Service EndPoint Interface)服务端点接口,简单的说就写接口的全路径
*/
@WebService(endpointInterface="com.lovo.webservice.IHelloService")
@SOAPBinding(style=Style.RPC)
public class HelloServiceImpl implements IHelloService {
@Override
public String hello(String message) {
return "你好" + message;
}
@Override
public String login(String userName, String password) {
String req = null;
//这里做个假的登录验证
if("小明".equals(userName)&&"123456".equals(password))
{
req = "登录成功";
}else
{
req = "登录失败";
}
return req;
}
}
这个时候再访问wsdl的网址就看见有两个方法了
下载wsdl
<?xml version='1.0' encoding='UTF-8'?>
<wsdl:definitions xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="http://webservice.lovo.com"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:ns1="http://schemas.xmlsoap.org/soap/http"
name="HelloService"
targetNamespace="http://webservice.lovo.com/">
<wsdl:message name="loginResponse">
<wsdl:part name="loginRequest" type="xsd:string">
</wsdl:part>
</wsdl:message>
<wsdl:message name="sayHello1Response">
<wsdl:part name="helloRequest" type="xsd:string">
</wsdl:part>
</wsdl:message>
<wsdl:message name="sayHello1">
<wsdl:part name="msg" type="xsd:string">
</wsdl:part>
</wsdl:message>
<wsdl:message name="login">
<wsdl:part name="userName" type="xsd:string">
</wsdl:part>
<wsdl:part name="password" type="xsd:string">
</wsdl:part>
</wsdl:message>
<wsdl:portType name="IHelloService">
<wsdl:operation name="sayHello1">
<wsdl:input message="tns:sayHello1" name="sayHello1">
</wsdl:input>
<wsdl:output message="tns:sayHello1Response" name="sayHello1Response">
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="login">
<wsdl:input message="tns:login" name="login">
</wsdl:input>
<wsdl:output message="tns:loginResponse" name="loginResponse">
</wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="HelloServiceSoapBinding" type="tns:IHelloService">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="sayHello1">
<soap:operation soapAction="" style="rpc"/>
<wsdl:input name="sayHello1">
<soap:body namespace="http://webservice.lovo.com/" use="literal"/>
</wsdl:input>
<wsdl:output name="sayHello1Response">
<soap:body namespace="http://webservice.lovo.com/" use="literal"/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="login">
<soap:operation soapAction="" style="rpc"/>
<wsdl:input name="login">
<soap:body namespace="http://webservice.lovo.com/" use="literal"/>
</wsdl:input>
<wsdl:output name="loginResponse">
<soap:body namespace="http://webservice.lovo.com/" use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="HelloService">
<wsdl:port binding="tns:HelloServiceSoapBinding" name="HellowServicePort">
<soap:address location="http://localhost:8080/Spring/webservice/HelloService"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
阅读wsdl的方法详细的阅读方式方式可以看这篇文章:http://blog.csdn.net/liuchunming033/article/details/41210151
拿到一个wsdl,个人一般是先看最后,也就是wsdl:service部分。wsdl:service:存放接口名和接口地址
<!--多个接口放在一起为一个service name为视图服务名-->
<wsdl:service name="HelloService">
<!-- 一个port表示一个接口 name表示刚刚绑定的name,就是portName这个参数 -->
<wsdl:port binding="tns:HelloServiceSoapBinding" name="HellowServicePort">
<!-- address表示接口对象的地址 -->
<soap:address location="http://localhost:8080/Spring/webservice/HelloService"/>
</wsdl:port>
</wsdl:service>
然后再看binding部分,也就是wsdl:binding
wsdl:binding:每个端口定义消息格式和协议细节
<!-- 把接口进行soap绑定 type为接口名 name对应 service中的binding参数-->
<wsdl:binding name="HelloServiceSoapBinding" type="tns:IHelloService">
<!--指明绑定的协议为http soap协议,类型为rpc 这里就是@SOAPBinding那个注解指定了为rpc ,如果不指定默认为document-->
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<!--具体方法的bnding类型,接口中有多少个方法就有多少个operation 其中name表示方法名 literal文本-->
<wsdl:operation name="sayHello1">
<soap:operation soapAction="" style="rpc"/>
<wsdl:input name="sayHello1">
<!--方法的命名空间namespace 就是方法@WebResult注解中指定的targetNamespace-->
<soap:body namespace="http://webservice.lovo.com/" use="literal"/>
</wsdl:input>
<wsdl:output name="sayHello1Response">
<soap:body namespace="http://webservice.lovo.com/" use="literal"/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="login">
<soap:operation soapAction="" style="rpc"/>
<wsdl:input name="login">
<soap:body namespace="http://webservice.lovo.com/" use="literal"/>
</wsdl:input>
<wsdl:output name="loginResponse">
<soap:body namespace="http://webservice.lovo.com/" use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
再看portType部分,wsdl:portType
wsdl:portType:描述webservice可被执行的操作,以及相关的消息,通过binding指向portType
<!--name表示接口名-->
<wsdl:portType name="IHelloService">
<!--接口中有很多方法,没个opertion就表示一个方法名,name为方法名,为代码中@WebMethod中定义的operationName-->
<wsdl:operation name="sayHello1">
<!--通过message可以查看方法中对应的参数,input表示传入,output表示返回-->
<wsdl:input message="tns:sayHello1" name="sayHello1">
</wsdl:input>
<wsdl:output message="tns:sayHello1Response" name="sayHello1Response">
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="login">
<wsdl:input message="tns:login" name="login">
</wsdl:input>
<wsdl:output message="tns:loginResponse" name="loginResponse">
</wsdl:output>
</wsdl:operation>
</wsdl:portType>
在看message,wsdl:message
wsdl:message:定义一个操作(方法)的数据参数(可有多个参数)
<!--login方法的返回值定义,一般为方法名+response 这里方法只有一个简单的返回值,类型为String-->
<wsdl:message name="loginResponse">
<wsdl:part name="loginRequest" type="xsd:string">
</wsdl:part>
</wsdl:message>
<wsdl:message name="sayHello1Response">
<wsdl:part name="helloRequest" type="xsd:string">
</wsdl:part>
</wsdl:message>
<wsdl:message name="sayHello1">
<wsdl:part name="msg" type="xsd:string">
</wsdl:part>
</wsdl:message>
<!--name对应portType中的operation name属性对应的值。login方法好传入的参数,有几个参数就有几个part-->
<wsdl:message name="login">
<!--参数名为userName,参数类型为String-->
<wsdl:part name="userName" type="xsd:string">
</wsdl:part>
<wsdl:part name="password" type="xsd:string">
</wsdl:part>
</wsdl:message>
最后还是需要看看开始部分
<!--name 表示接口名,targetNamespace表示接口的命名空间-->
<?xml version='1.0' encoding='UTF-8'?>
<wsdl:definitions xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="http://webservice.lovo.com"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:ns1="http://schemas.xmlsoap.org/soap/http"
name="HelloService"
targetNamespace="http://webservice.lovo.com/">
这么一个简单的xml就解析完了
完整的xml文档
<!--name 表示接口名,targetNamespace表示接口的命名空间-->
<?xml version='1.0' encoding='UTF-8'?>
<wsdl:definitions xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="http://webservice.lovo.com"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:ns1="http://schemas.xmlsoap.org/soap/http"
name="HelloService"
targetNamespace="http://webservice.lovo.com/">
<!--login方法的返回值定义,一般为方法名+response 这里方法只有一个简单的返回值,类型为String-->
<wsdl:message name="loginResponse">
<wsdl:part name="loginRequest" type="xsd:string">
</wsdl:part>
</wsdl:message>
<wsdl:message name="sayHello1Response">
<wsdl:part name="helloRequest" type="xsd:string">
</wsdl:part>
</wsdl:message>
<wsdl:message name="sayHello1">
<wsdl:part name="msg" type="xsd:string">
</wsdl:part>
</wsdl:message>
<!--name对应portType中的operation name属性对应的值。login方法好传入的参数,有几个参数就有几个part-->
<wsdl:message name="login">
<!--参数名为userName,参数类型为String-->
<wsdl:part name="userName" type="xsd:string">
</wsdl:part>
<wsdl:part name="password" type="xsd:string">
</wsdl:part>
</wsdl:message>
<!--name表示接口名-->
<wsdl:portType name="IHelloService">
<!--接口中有很多方法,没个opertion就表示一个方法名,name为方法名,为代码中@WebMethod中定义的operationName-->
<wsdl:operation name="sayHello1">
<!--通过message可以查看方法中对应的参数,input表示传入,output表示返回-->
<wsdl:input message="tns:sayHello1" name="sayHello1">
</wsdl:input>
<wsdl:output message="tns:sayHello1Response" name="sayHello1Response">
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="login">
<wsdl:input message="tns:login" name="login">
</wsdl:input>
<wsdl:output message="tns:loginResponse" name="loginResponse">
</wsdl:output>
</wsdl:operation>
</wsdl:portType>
<!-- 把接口进行soap绑定 type为接口名 name对应 service中的binding参数-->
<wsdl:binding name="HelloServiceSoapBinding" type="tns:IHelloService">
<!--指明绑定的协议为http soap协议,类型为rpc 这里就是@SOAPBinding那个注解指定了为rpc ,如果不指定默认为document-->
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<!--具体方法的bnding类型,接口中有多少个方法就有多少个operation 其中name表示方法名 literal文本-->
<wsdl:operation name="sayHello1">
<soap:operation soapAction="" style="rpc"/>
<wsdl:input name="sayHello1">
<!--方法的命名空间namespace 就是方法@WebResult注解中指定的targetNamespace-->
<soap:body namespace="http://webservice.lovo.com/" use="literal"/>
</wsdl:input>
<wsdl:output name="sayHello1Response">
<soap:body namespace="http://webservice.lovo.com/" use="literal"/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="login">
<soap:operation soapAction="" style="rpc"/>
<wsdl:input name="login">
<soap:body namespace="http://webservice.lovo.com/" use="literal"/>
</wsdl:input>
<wsdl:output name="loginResponse">
<soap:body namespace="http://webservice.lovo.com/" use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<!--多个接口放在一起为一个service name为视图服务名-->
<wsdl:service name="HelloService">
<!-- 一个port表示一个接口 name表示刚刚绑定的name,就是portName这个参数 -->
<wsdl:port binding="tns:HelloServiceSoapBinding" name="HellowServicePort">
<!-- address表示接口对象的地址 -->
<soap:address location="http://localhost:8080/Spring/webservice/HelloService"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
wsdl阅读完成了,需要的参数都明白了,下面就可以做个简单的客户端进行调用,webService客户端调用的方法有很多,我们这里简单的做几个。
一:Service编程方式
特点:可以自定义关键元素,方便以后维护,是一种标准的开发方式
首先写一个客户端调用对象
package com.lovo.client;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;
/**
* 客户端调用者,根据wsdl初始化接口对象
* @author WZH
*
*targetNamespace 对应wsdl抬头 targetNamespace,serviceName和portName分别对应wsdl结尾的wsdl:service name="HelloService"
*和wsdl:port binding="tns:HelloServiceSoapBinding" name="HellowServicePort">
*因为wsdl文档中有指定SOAP类型,所以需书写类型 <soap:operation soapAction="" style="rpc"/>
*/
@WebService(targetNamespace="http://webservice.lovo.com/",serviceName="HelloService",portName="HellowServicePort")
@SOAPBinding(style=Style.RPC)
public interface HellowService {
/**
* 方法名对应wsdl wsdl:operation name="login"
* @param username 参数名对应 wsdl:part name="userName" type="xsd:string"
* @param password
* @return
*
* 方法名映射 <wsdl:operation name="login">
* 地址映射<soap:body namespace="http://webservice.lovo.com" use="literal"/>
* 参数映射:<wsdl:part name="userName" type="xsd:string"> <wsdl:part name="password" type="xsd:string">
*/
@WebResult(name="login",targetNamespace="http://webservice.lovo.com/")
@WebMethod(operationName = "login")
public String login(@WebParam(name = "userName")String username , @WebParam(name = "password")String password);
@WebResult(name="helloRequest",targetNamespace="http://webservice.lovo.com/")
@WebMethod(operationName="sayHello1")
public String hello(@WebParam(name="msg")String msg);
}
这里需要特别注意,targetNamespace中路径结尾需写反斜杠/不然会出现问题
准备工作做好了,可以做个客户端的调用了
package com.lovo.client;
import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import javax.xml.ws.soap.SOAPBinding;
public class wsClient {
/**
* XML 类 第一个参数表示地址,第二个参数表示端口名
* 这里第一个参数是wsdl 表头targetNamespace
* 第二个参数是service name
*/
private static final QName SERVICE_NAME = new QName("http://webservice.lovo.com/", "HelloService");
private static final QName PORT_NAME = new QName("http://webservice.lovo.com/", "HellowServicePort");
//编程方式一 begin -----------------------
public static void testSayHello()
{
try {
//创建Serivce业务类
Service service = Service.create(SERVICE_NAME);
//连接地址 <soap:address location="http://localhost:8080/Spring/webservice/HelloService"/>
String endPointAddress = "http://localhost:8080/Spring/webservice/HelloService";
//配置业务访问参数 portName, bindingId, endpointAddress,
//这里因为是SOPA11的所有配置11,SOAP现在有11和12两种 可通过xmlns:ns1="http://schemas.xmlsoap.org/soap/http" 判断
service.addPort(PORT_NAME, SOAPBinding.SOAP11HTTP_BINDING, endPointAddress);
//把本地客户端的接口与网络上的WSDL连接起来
HellowService hs = service.getPort(HellowService.class);
System.out.println(hs.hello("小明"));
} catch (Exception e) {
e.printStackTrace();
}
}
//end-------------------------------------
//编程方式二 begin 不知道为什么 Service.create报错,可能是jar原因-----------------------
public static void testSayHello2()
{
try
{
//创建WSDL的URL,注意不是服务地址
URL url = new URL("http://localhost:8080/Spring/webservice?wsdl");
//创建服务名,代码有写成了静态常量,这里直接引用
//创建服务视图
javax.xml.ws.Service service = Service.create(url, SERVICE_NAME);
//获取服务实例
HellowService hs = service.getPort(new QName("http://webservice.lovo.com/", "HellowServicePort"), HellowService.class);
System.out.println(hs.hello("小明"));
} catch (Exception e)
{
e.printStackTrace();
}
}
//end-------------------------------------
public static void main(String[] args) {
//testSayHello();
testSayHello2();
}
}
剩下的等有空的再完善
相关推荐
- 用Steam启动Epic游戏会更快吗?(epic怎么用steam启动)
-
Epic商店很香,但也有不少抱怨,其中一条是启动游戏太慢。那么,如果让Steam启动Epic游戏,会不会速度更快?众所周知,Steam可以启动非Steam游戏,方法是在客户端左下方点击“添加游戏”,然...
- Docker看这一篇入门就够了(dockerl)
-
安装DockerLinux:$curl-fsSLhttps://get.docker.com-oget-docker.sh$sudoshget-docker.sh注意:如果安装了旧版...
- AYUI 炫丽PC开发UI框架2016年6月15日对外免费开发使用 [1]
-
2016年6月15日,我AY对外发布AYUI(WPF4.0开发)的UI框架,开发时候,你可以无任何影响的去开发PC电脑上的软件exe程序。AYUI兼容XP操作系统,在Win7/8/8.1/10上都顺利...
- 别再说C#/C++套壳方案多了!Tauri这“借壳生蛋”你可能没看懂!
-
浏览器套壳方案,C#和C++有更多,你说的没错,从数量和历史积淀来看,C#和C++确实有不少方式来套壳浏览器,让Web内容在桌面应用里跑起来。但咱们得把这套壳二字掰扯清楚,因为这里面学问可大了!不同的...
- OneCode 核心概念解析——Page(页面)
-
在接触到OneCode最先接触到的就是,Page页面,在低代码引擎中,页面(Page)设计的灵活性是平衡“快速开发”与“复杂需求适配”的关键。以下从架构设计、组件系统、配置能力等维度,解析确...
- React是最后的前端框架吗,为什么这么说的?
-
油管上有一位叫Theo的博主说,React是终极前端框架,为什么这么说呢?让我们来看看其逻辑:这个标题看起来像假的,对吧?React之后明明有无数新框架诞生,凭什么说它是最后一个?我说的“最后一个”不...
- 面试辅导(二):2025前端面试密码:用3个底层逻辑征服技术官
-
面试官放下简历,手指在桌上敲了三下:"你上次解决的技术难题,现在回头看有什么不足?"眼前的候选人瞬间僵住——这是上周真实发生在蚂蚁金服终面的场景。2025年的前端战场早已不是框架熟练...
- 前端新星崛起!Astro框架能否终结React的霸主地位?
-
引言:当"背着背包的全能选手"遇上"轻装上阵的短跑冠军"如果你是一名前端开发者,2024年的框架之争绝对让你眼花缭乱——一边是React这位"背着全家桶的全能选...
- 基于函数计算的 BFF 架构(基于函数计算的 bff 架构是什么)
-
什么是BFFBFF全称是BackendsForFrontends(服务于前端的后端),起源于2015年SamNewman一篇博客文章《Pattern:BackendsFor...
- 谷歌 Prompt Engineering 白皮书:2025年 AI 提示词工程的 10 个技巧
-
在AI技术飞速发展的当下,如何更高效地与大语言模型(LLM)沟通,以获取更准确、更有价值的输出,成为了一个备受关注的问题。谷歌最新发布的《PromptEngineering》白皮书,为这一问题提供了...
- 光的艺术:灯具创意设计(灯光艺术作品展示)
-
本文转自|艺术与设计微信号|artdesign_org_cn“光”是文明的起源,是思维的开端,同样也是人类睁眼的开始。每个人在出生一刻,便接受了光的照耀和洗礼。远古时候,人们将光奉为神明,用火来...
- MoE模型已成新风口,AI基础设施竞速升级
-
机器之心报道编辑:Panda因为基准测试成绩与实际表现相差较大,近期开源的Llama4系列模型正陷入争议的漩涡之中,但有一点却毫无疑问:MoE(混合专家)定然是未来AI大模型的主流范式之一。...
- Meta Spatial SDK重大改进:重塑Horizon OS应用开发格局
-
由文心大模型生成的文章摘要Meta持续深耕SpatialSDK技术生态,提供开自去年9月正式推出以来,Meta持续深耕其SpatialSDK技术生态,通过一系列重大迭代与功能增强,不断革新H...
- "上云"到底是个啥?用"租房"给你讲明白IaaS/PaaS/SaaS的区别
-
半夜三点被机房报警电话惊醒,顶着黑眼圈排查服务器故障——这是十年前互联网公司运维的日常。而现在,程序员小王正敷着面膜刷剧,因为公司的系统全"搬"到了云上。"部署到云上"...
- php宝塔搭建部署thinkphp机械设备响应式企业网站php源码
-
大家好啊,欢迎来到web测评。本期给大家带来一套php开发的机械设备响应式企业网站php源码,上次是谁要的系统项目啊,帮你找到了,还说不会搭建,让我帮忙录制一期教程,趁着今天有空,简单的录制测试了一下...
你 发表评论:
欢迎- 一周热门
- 最近发表
-
- 用Steam启动Epic游戏会更快吗?(epic怎么用steam启动)
- Docker看这一篇入门就够了(dockerl)
- AYUI 炫丽PC开发UI框架2016年6月15日对外免费开发使用 [1]
- 别再说C#/C++套壳方案多了!Tauri这“借壳生蛋”你可能没看懂!
- OneCode 核心概念解析——Page(页面)
- React是最后的前端框架吗,为什么这么说的?
- 面试辅导(二):2025前端面试密码:用3个底层逻辑征服技术官
- 前端新星崛起!Astro框架能否终结React的霸主地位?
- 基于函数计算的 BFF 架构(基于函数计算的 bff 架构是什么)
- 谷歌 Prompt Engineering 白皮书:2025年 AI 提示词工程的 10 个技巧
- 标签列表
-
- 框架图 (58)
- flask框架 (53)
- quartz框架 (51)
- abp框架 (47)
- jpa框架 (47)
- springmvc框架 (49)
- 分布式事务框架 (65)
- scrapy框架 (56)
- shiro框架 (61)
- 定时任务框架 (56)
- java日志框架 (61)
- JAVA集合框架 (47)
- mfc框架 (52)
- abb框架断路器 (48)
- ui自动化框架 (47)
- beego框架 (52)
- java框架spring (58)
- grpc框架 (55)
- ppt框架 (48)
- 内联框架 (52)
- cad怎么画框架 (58)
- ps怎么画框架 (47)
- ssm框架实现登录注册 (49)
- oracle字符串长度 (48)
- oracle提交事务 (47)