前言
这一篇博客主要实现客户端和服务器端得数据通讯。在一开始学习的时候,发现实现通讯的方式真的是复杂多样。由于自己的项目中还需要实现文件类型相互传递(客户端往WebService服务器端发送数据)。因此本次在一个实例当中将同时介绍数据的通讯。
案例一:客户端获取WebService的数据(手机归属地查询实例)
1.1 简介
本案例主要是通过手机归属地的系统的接口地址。首先看一下手机归属地WebService的接口的地址。
http://www.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl
这个地址通过浏览器直接访问的效果如下:
我们将通过这个接口来获取天气情况的数据。
1.2 代码编写
1.2.1 新建一个工程,目录如下:
说明:1、 cn.com.webxml是自动生成的包。
2、lib是使用CXF框架的jar包
1.2.2 在CMD命令行下自动生成客户端代码
说明;1、打开自己的工程目录。在src目录下。输入wsimport http://www.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl
2、如果wsimport命令不能生效。解决方案在我的学习总结(2)里面。https://blog.csdn.net/sdddlll/article/details/81189111
生成的客户端代码如下(刷新自己的工程)结果如下:
1.2.3 编写Test类进行测试
package com.ws.test;
import cn.com.webxml.MobileCodeWS;
import cn.com.webxml.MobileCodeWSSoap;
/**
* 类描述:
*@author: 冯冬冬
*@date: 日期:2018-7-27 时间:下午8:31:12
*/
public class Test {
public static void main(String[] args) {
MobileCodeWS factory=new MobileCodeWS();
MobileCodeWSSoap mss=factory.getMobileCodeWSSoap();
String phoneInfo=mss.getMobileCodeInfo("15735171890", null);
System.out.print("我的手机信息是:"+phoneInfo);
}
}
说明:1、MobileCodeWS 相当于是一个在生成WSDL文档的根标签。用它可以拿到在里面实现的接口类。
2、MobileCodeWSSoap 相当于拿到了操作手机归属地的一个方法类。
3、mss.getMobileCodeInfo("15735171890", null);
括号里面的参数可以看到,第一个参数是自己的手机号。第二个参数是用户ID(UserID),这里不用管直接为空就可以。
运行一下看看效果:打开自己的控制台可以看到:
总结:这里的webService不是自己编写的代码。通过这个例子可以看到,使用WebService其实是非常简单的。但是当自己需要往外部提供服务时,这里的WebService服务器端就需要自己定义了。
案例二:客户端传递简单数据类型:
查看WebService学习总结(1)https://blog.csdn.net/sdddlll/article/details/81211172
案例三;客户端传递复杂数据
客户端:
3.1 传递复杂数据的原理:
我们都知道如何通过WebService把一个字符串形式的参数传递到服务器端的一个函数并取得返回的结果,而通过WebService上传文件的原理和上传一个字符串在根本上是一样的。
唯一不同的是,我们需要多做一点额外的工作,即先读取文件到一个字节数组中,再通过Base64将其转化为字符串。详情请看下面的代码:
// 客户端读取文件然后用Base64将其转化为字符串的函数
private static String getFileByteString(File file) throws Exception{
InputStream in = new FileInputStream(file);
// 取得文件大小
long length = file.length();
// 根据大小创建字节数组
byte[] bytes = new byte[(int) length];
// 读取文件内容到字节数组
int offset = 0;
int numRead = 0;
while (offset < bytes.length
&& (numRead = in.read(bytes, offset, bytes.length - offset)) >= 0) {
offset += numRead;
}
// 读取完毕的校验
if (offset < bytes.length) {
throw new IOException("不能完全讀取文件:"+ file.getName());
}
in.close();
String encodedFileString = Base64.encode(bytes);
return encodedFileString;
}
服务器端:
3.2 服务器去接受复杂数据
// uploadedFileString是传过来的包含你上传的文件内容的字符串
byte[] bytes = Base64.decode(uploadedFileString);
// 存储路径
String path=CommonUtil.getUploadPath();
// 存储的文件名
String localFileName=getLocalFileName(parser.getUserid(),parser.getFileName());
// 写入新文件
FileOutputStream out = new FileOutputStream(path+localFileName);
out.write(bytes);
out.flush();
out.close();
说明;首先你需要在自己的接口类里面去定义一个接口。这些代码在其实现类的方法中编写
3.3 详细的客户端代码:(我是在自己的Servlet中)
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
import com.ws.myinterface.AsAccess2;
import com.ws.myinterface.impl.AsAccessImpl2Service;
/**
* 类描述:
*@author: 冯冬冬
*@date: 日期:2018-7-27 时间:上午11:22:24
*/
public class UploadHandleFileServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//消息提示
String message = "";
boolean sss = false;
try{
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setHeaderEncoding("UTF-8");
if(!ServletFileUpload.isMultipartContent(request)){
return;
}
List<FileItem> list = upload.parseRequest(request);
for(FileItem item : list){
String name = item.getName();// 获取上传文件的名字
String fileExtName = name.substring(name.lastIndexOf(".") + 1);//获得文件的后缀名
InputStream input = item.getInputStream();// 获得上传文件字节流
byte[] bytes=new byte[1024];
int offset=0;
int numRead=0;
while (offset < bytes.length && (numRead = input.read(bytes, offset, bytes.length - offset)) >= 0) {
offset += numRead;
}
// 读取完毕的校验
if (offset < bytes.length) {
throw new IOException("不能完全读取文件:");
}
input.close();
String encodedFileString = Base64.encode(bytes);
AsAccessImpl2Service factoryservice=new AsAccessImpl2Service();
AsAccess2 hw=factoryservice.getAsAccessImpl2Port();
sss=hw.uploadFile(encodedFileString,fileExtName);
input.close();
// 删除处理文件上传时生成的临时文件
item.delete();
}
}catch (Exception e) {
e.printStackTrace();
}
request.setAttribute("message","上传结果是:"+sss);
request.getRequestDispatcher("/message.jsp").forward(request, response);
}
}
3.4 详细的服务器端代码
/**
*
*/
package com.ws.myinterface.impl;
import java.io.IOException;
import javax.jws.WebService;
import com.ws.myinterface.HelloWS;
import com.ws.util.InfoSave;
/**
* 类描述:
*@author: 冯冬冬
*@date: 日期:2018-7-27 时间:下午9:14:12
*/
@WebService
public class HelloWSImpl implements HelloWS {
public String sayHello(String name) {
//name是客户端传递过来的参数。
/*
* 这里写保存客户端传递过来的参数,或者是对参数进行一些其他的操作。
*/
System.out.println(name+"访问了WebService");
return "这里是WebService:欢迎 "+name+"访问";
}
//上传文件 fileExtName是上传文件的类型,比如doc或者是rar或者是pdf等等
public boolean uploadFile(String inputstream,String fileExtName) {
boolean result = false;
try {
result = InfoSave.saveFileInfo(inputstream,fileExtName);
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
}
在自己的公共类InfoSave中定义了如下的方法:
public static boolean saveFileInfo(String inputStream,String fileExtName) throws IOException {
// 写入新文件
FileOutputStream out;
try {
byte[] bytes = Base64.decode(inputStream);
// 存储路径
String path = "D:\\data\\";
out = new FileOutputStream(path+"Myfile."+fileExtName);
out.write(bytes);
out.flush();
out.close();
return true;
} catch (FileNotFoundException e) {
e.printStackTrace();
return false;
}
}
总结:通过以上案例可以知道整个WebService的参数传递过程了。在这里你不仅可以传递文件类型,也可以传递对象比如User类这些。具体代码自己动手既可以实现,和普通的String类型的参数传递相同。