本文将使用代码和文字说明简单讲解web service在java端的开发使用。
写本章的目的:
- 一方面是通过写博客的方式能对所学习的东西进一步加深印象,能掌握的更牢固。
- 另一方面也是想借此锻炼一下自己原创写博客的能力,写的不好望谅解,谢谢!
- 不用多说,自然是希望能帮到学习此技术的童鞋们。废话不多说,进入正题。
关于web service的答疑:
- web service是什么
答:面向服务架构(SOA),指在将一个系统中的每个模块拆分为一个个服务组件,以解耦的方式在各个服务组件之间进行远程调用。
- 它的特性
答:跨系统(跨操作系统,如windows和linux之间),跨语言(跨编程语言,如java和c++)
- web service如何使用
答:它并非一个具体的框架,而是java EE规范,实现它的现在一般是apache的CXF框架。
下载安装CXF框架
- 下载地址:http://cxf.apache.org/download.html
- 下载自己所要的版本之后解压如下,把该bin目录添加到环境变量
服务端开发
- 新建一个maven项目作为服务端,添加CXF依赖
<dependencies>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-core</artifactId>
<version>3.3.1</version>
</dependency>
</dependencies>
- 新增接口添加@WebService注解,添加业务功能
- CXF框架所支持的传输数据类型有:8中基本数据类型、包装类、String、数组、一系列集合(Map集合需jdk1.8才支持)、java bean类型,以上这些类型可以直接请求传输。
- 那其它类型怎么办,比如File文件,这里就涉及到“类型适配器”。
- 如一下接口代码中,在入参或出参前面(不支持的参数类型时)添加@XmlJavaTypeAdapter(XXX.class)适配器注解,将不支持的参数类型转换为当前系统语言所支持的类型,括号中属性为继承适配器的自定义类。
@WebService
public interface EmployeService {
/**
* --员工注册
* @param employe
* @return
*/
public String register(Employe employe);
/**
* --传输文件
* @param file
* @return
*/
public String transferFile(@XmlJavaTypeAdapter(FileConvertAdapter.class) File file);
}
- 创建一个类继承XmlAdapter适配器抽象类,实现它的方法来做自己的数据类型转换
public class FileConvertAdapter extends XmlAdapter<FileConvertBean, File> {
/**
* --接口方法入参时会调用此方法进行转换
*/
@Override
public File unmarshal(FileConvertBean fcb) throws Exception {
String projectPath = System.getProperty("user.dir");
File file = new File(projectPath +"/"+ fcb.getName());
FileOutputStream fos = new FileOutputStream(file);
fos.write(fcb.getData());
fos.flush();
fos.close();
return file;
}
/**
* --接口方法出参时会调用此方法转换
*/
@Override
public FileConvertBean marshal(File file) throws Exception {
FileConvertBean fcb = new FileConvertBean();
fcb.setName(file.getName());
FileInputStream fis = new FileInputStream(file);
byte[] data = new byte[fis.available()];
fis.read(data);
fcb.setData(data);
fis.close();
return fcb;
}
}
- 新增一个实现类来实现上面这个接口,并添加带有属性的接口,serviceName属性随便填,endpointInterface属性就是当前这个实现类的接口包名+类名
//此处的注解和接口的相比,多了这两个属性
@WebService(serviceName = "accountService", endpointInterface = "com.ws.service.EmployeService")
public class EmployeServiceImpl implements EmployeService {
public String register(Employe employe) {
System.out.println(employe.getName() + "==" + employe.getPwd());
return "用户" + employe.getName() + "注册成功";
}
public String transferFile(File file) {
System.out.println("服务端保存文件地址==="+file.getAbsolutePath());
return "服务端文件传输成功";
}
}
- 再添加一个main方法启动类来暴露服务(把当前服务的功能接口暴露给客户端)
public class Server {
public static void main(String[] args) {
EmployeService es = new EmployeServiceImpl();
//http://localhost:8080/test为向外暴露服务的地址
Endpoint.publish("http://localhost:8080/test", es);
System.out.println("成功暴露服务");
}
}
- 启动main方法后通过以上的地址+?wsdl进行访问http://localhost:8080/test?wsd
- 服务端最终工程目录结构
客户端开发
- 新建一个空的客户端maven工程,然后通过服务端暴露地址“http://localhost:8080/test?wsdl”来生成客户端部分代码
- 生成客户端代码两种方式
1、通过jdk中的java命令"wsimport http://localhost:8080/test?wsdl -keep",然后刷新客户端工程查看
2、通过CXF框架bin目录中的wsdl2java命令“wsdl2java http://localhost:8080/test?wsdl”生成,然后刷新客户端工程查看
- 编写客户端的启动类
public class Client {
public static void main(String[] args) throws IOException {
// 通过代理获取员工接口
EmployeService es = new AccountService().getEmployeServiceImplPort();
// 调用员工注册接口功能
Employe employe = new Employe();
employe.setName("test2117");
employe.setPwd("0604");
String register = es.register(employe);
System.out.println(register);
// 调用文件传输接口功能
File file = new File("bg.jpg");
FileInputStream fis = new FileInputStream(file);
byte[] data = new byte[fis.available()];
fis.read(data);
fis.close();
FileConvertBean fcb = new FileConvertBean();
fcb.setName(file.getName());
fcb.setData(data);
String transferFile = es.transferFile(fcb);
System.out.println("客户端传输文件结果=====" + transferFile);
}
}
- 客户端最终工程目录结构
- 最后咱们试一下,先启动服务端,再启动客户端
客户端打印
服务端打印
至此,搭建结束。谢谢,不喜勿喷。