什么是webservice?https://www.cnblogs.com/xdp-gacl/p/4048937.html
二、cxf框架实现REST风格http协议的WebService(JAX-RS标准):https://blog.csdn.net/IT_CREATE/article/details/86642980
下面我开始讲第一种WebService的客户端和服务器的创建,利用cxf框架和soap协议来实现。
1、首先需要导入相应的jar包:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.gezhi</groupId>
<artifactId>webservices</artifactId>
<packaging>war</packaging>
<version>1.0</version>
<name>webservices Maven Webapp</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<junit.version>4.12</junit.version>
<log4j.version>1.2.17</log4j.version>
<spring.version>4.3.14.RELEASE</spring.version>
<cxf.version>3.2.0</cxf.version>
<commons.httpclient.version>3.0.1</commons.httpclient.version>
</properties>
<dependencies>
<!-- 引入HttpClient 组件JAR包(完成:后台模拟浏览器向服务器发起HTTP请求) -->
<dependency>
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
<version>${commons.httpclient.version}</version>
</dependency>
<!-- 这下面2中JAR包,主要是引入SUN制定的JAX-WS标准的相关组件 -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>${cxf.version}</version>
</dependency>
<!-- 这下面2中JAR包,主要是引入SUN制定的JAX-RS标准的相关组件 -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-rs-service-description</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- 导入junit单元测试框架JAR包 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<!-- 导入LOG4J日志框架JAR包 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
</dependencies>
<build>
<finalName>webservices</finalName>
<pluginManagement>
<!-- 配置maven 在构建项目时,采用相关插件 -->
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
JAX-RS标准的相关组件不在这次soap的范围,soap使用的是JAX-WS的标准,也就是WSDL服务描述语言。
2、编写服务器
2.1 新建一个服务接口,这里我就新建了一个 ILoginWebService接口:(提供你想提供的服务)
package com.ge.webservices.soap;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
/**
* @WebService() 将该接口声明为一个WEB服务接口
*
* targetNamespace 给接口定义一个命名空间,写法是:该接口包名的反缀
*
* serviceName 暴露服务的名称
*
* portName 暴露服务所在的端口
*
* @author Administrator
*
*/
@WebService(targetNamespace="http://soap.webservices.ge.com",serviceName="LoginWebservice",portName="LoginWebservicePort")
public interface ILoginWebService {
/**
* 登录方法
* @param loginName
* @param pwd
* @return
*/
String login(@WebParam(name="arg0")String loginName,@WebParam(name="arg1")String pwd);
/**
* 欢迎方法
* @param userName
* @return
*/
@WebMethod(operationName="meth")
String welcome(@WebParam(name="arg0")String userName);
}
服务接口需要用到@WebService注解,有三个属性:
targetNamespace :给接口定义一个命名空间,写法是:http://该接口包名的反缀 ,就是将你定义的接口存在的包反着写
serviceName :暴露服务的名称,自己定义个名字
portName :暴露服务所在的端口,自己定义个名字
以后这些信息作为 wsdl 的访问路径
@WebMethod(operationName="meth")可以给这个方法起一个别名,向外暴露的名字就是你写的这个别名,如果没用这个注解,那么向外暴露的方法名也就是本身的方法名字
@WebParam(name="arg0")同样的,这个注解是给方法参数起别名,向外暴露的参数名字就是你起的这个别名,如果没用这个注解,那么向外暴露的方法参数名就是本身的方法参数名
2.2 实现这个服务接口,这里我就新建了一个LoginWebServiceImpl类继承 ILoginWebService接口:(对提供的服务进行实现)
package com.ge.webservices.soap.impl;
import javax.jws.WebService;
import com.ge.webservices.soap.ILoginWebService;
/**
* @WebService endpointInterface 描述该类是哪一个WEB接口的实现
* @author Administrator
*
*/
@WebService(endpointInterface="com.ge.webservices.soap.ILoginWebService")
public class LoginWebServiceImpl implements ILoginWebService {
@Override
public String login(String loginName, String pwd) {
// TODO Auto-generated method stub
return loginName + "登录成功!";
}
@Override
public String welcome(String userName) {
// TODO Auto-generated method stub
return userName + "你好!";
}
}
实现类中只有一个@WebService注解,它有一个属性:
endpointInterface 用来指定你实现的接口的名字
3、新建一个配置文件 cxf-servlet.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: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/schemas/jaxws.xsd">
<!-- 在spring容器中,声明WEB服务,id随便起一个名字,主要是作为被spring识别的id,
serviceClass表示你定义的服务接口,address表示起一个作为以后访问的路径-->
<jaxws:server id="loginWebService" serviceClass="com.ge.webservices.soap.ILoginWebService" address="/loginService">
<!-- 该接口的真实实现类 -->
<jaxws:serviceBean>
<bean class="com.ge.webservices.soap.impl.LoginWebServiceImpl"></bean>
</jaxws:serviceBean>
</jaxws:server>
<!-- 如果有多个服务,就继续按照上述方式,进行发布即可 -->
</beans>
4、在web.xml文件中进行一些配置(引入cxf-servlet.xml)
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<!-- 启动cxf框架的核心控制器,并启动spring容器,完成WEB服务的注册 -->
<servlet>
<servlet-name>cxf</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<init-param>
<param-name>config-location</param-name>
<param-value>classpath:cxf-servlet.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>cxf</servlet-name>
<!-- 需要区分:与SpringMVC框架的路径请求 -->
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
</web-app>
上面相当于服务端已经创建完毕了。
5、客户端的编写
开启服务器端tomcat容器,然后就可以通过http://localhost:8080/项目名/services/ 这个地址去访问 SOAP services页面:
就可以看见你提供的服务的一些方法,以及访问地址,蓝色线就是你以后客户端要访问的地址,
点击WSDL,进入描述文件:
从这个描述文件是我这叠起来了的,我们可以看到服务中有两个方法,一个叫做login,一个叫做meth,这是我们之前定义的;同时每个方法都有一个返回。同时这个接口的名字叫做 ILoginWebService,它的命名空间为http://soap.webservices.ge.com。
现在开始找我们能够获得的信息,点开<wsdl:types>标签:
从这里我们可以看到,
login方法有两个参数,arg0和arg1,并且是string类型,而他的响应也就是返回是string类型
meth方法有一个参数arg0,是string类型,并且它有一个返回是string类型
点开<wsdl:service name>标签:
可以看到该服务提供的服务名是:LoginWebservice,提供的端口名字是LoginWebservicePort,根据这些信息我们就可以写客户端了。
根据上面知道的接口名,方法名,参数名,参数类型,命名空间,服务名,端口名,来新建接口(其实说是通过这篇文档来看,但这些信息我们自己是知道的,只是在客户端这边重新写一份接口罢了):
package com.ge.webservices.soap.client;
import javax.jws.WebService;
/**
* 客户端,需要模拟服务器制定 WEB接口
* @author Administrator
*
*/
@WebService(targetNamespace="http://soap.webservices.ge.com",serviceName="LoginWebservice",portName="LoginWebservicePort")
public interface ILoginWebService {
String login(String arg0,String arg1);
String meth(String arg0);
}
客户端接口的写法和服务端基本一致,但客户端是根据阅读wsdl文档得出来的一些信息,模拟服务器指定web接口。我们在服务器端用了别名的,比如方法别名,参数别名,这里我们也用别名去写,虽然参数名对实际没影响。
然后写客户端测试:
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import javax.xml.ws.soap.SOAPBinding;
public class SOAPClient {
private static ILoginWebService loginWebServiceImpl;
private static final QName SERVICE_NAME = new QName("http://soap.webservices.ge.com", "LoginWebservice");
private static final QName PORT_NAME = new QName("http://soap.webservices.ge.com", "LoginWebservicePort");
public static void main(String[] args) {
//以下的这两句,使用地址、服务名称、端口名称 确认客户端需要访问哪个具体的WEB服务
Service service = Service.create(SERVICE_NAME);
//SOAPBinding.SOAP11HTTP_BINDING 为SOAP协议版本为 HTTP 1.1封装的版本
service.addPort(PORT_NAME, SOAPBinding.SOAP11HTTP_BINDING, "http://localhost/webservices/services/loginService");
loginWebServiceImpl = service.getPort(ILoginWebService.class);//获得客户端接口的代理实例
System.out.println(loginWebServiceImpl.login("张三", "123456"));
System.out.println(loginWebServiceImpl.meth("李四"));
}
}
通过上面模拟的服务器指定web接口,我们才能在客户端产生代理实例。