springboot2.x集成webservice服务(二)(文件传输)

背景

前几天我不是在鼓捣webservice嘛,鼓捣了半天,终于被我搞出点东西来了。
(感兴趣的同学可以去看下之前的文章,因为这个文章的代码都是基于前一篇的代码。
附上地址:springboot2.x集成webservice服务(一)
但随着webservice的继续使用,会产生一些实际的问题。举个例子,很简单的问题:我们可以类比下http,比如文件传输?
我觉得这个算是一个很常见的问题吧。在webservice当中该如何进行文件传输呢?

思考

在接口参数中定义byte[]类型,文件在xml中以base64编码传输(未实际证明)

首先我们想一下,http中的文件传输的本质是什么?
文件的传输就是字节流的传输。
文件转化成流,流再转化成文件
类比到java中,无非就是byte[]。
但是http在传输字节数组的时候,都会通过Base64做一层转化(图片就是base64转string传输)
webservice同样也是。

总结:

客户端:先读取文件到一个字节数组中,再通过Base64将其转化为字符串
服务单:字符串Base64转为字节数组,然后将字节数组写入到文件(或者图片、或者其他)。

参数定义DataHandler类型,然后使用MTOM形式来进行传输(实际证明可行)

这是我项目中使用的方法,参数类型是DataHandler,然后通过DataHandler这个类获取上传的附件信息。

直接附件(这种方式不清楚,网上都是这么说。没研究)

服务端

跟之前相比,没什么,新增了一个文件bean对象,用来保存上传的文件内容、文件名以及其他参数:

FileUploadRequestBean .java

package com.cj.webservice.bean;
import javax.activation.DataHandler;
import java.util.Date;
/**
 * 描述:
 *
 * @author caojing
 * @create 2020-02-12-21:07
 */
public class FileUploadRequestBean {
    private String requestId;
    private DataHandler file;
    private String fileName;
    public String getRequestId() {
        return requestId;
    }
    public void setRequestId(String requestId) {
        this.requestId = requestId;
    }
    public DataHandler getFile() {
        return file;
    }
    public void setFile(DataHandler file) {
        this.file = file;
    }
    public String getFileName() {
        return fileName;
    }
    public void setFileName(String fileName) {
        this.fileName = fileName;
    }
}

接口中新增方法

package com.cj.webservice.service;
import com.cj.webservice.bean.FileUploadRequestBean;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.ws.RequestWrapper;
import javax.xml.ws.ResponseWrapper;
@WebService
public interface WebServiceDemoService {
    @WebMethod
    public String hello(@WebParam(name = "name") String name);
	/**
	新增的方法
	**/
    @WebMethod
    public String upoload(@WebParam(name = "requestBean") FileUploadRequestBean requestBean);
}

接口实现类

package com.cj.webservice.service;

import com.cj.webservice.bean.FileUploadRequestBean;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
/**
 * 描述:
 *
 * @author caojing
 * @create 2020-02-14-14:56
 */
@WebService(serviceName = "fileDeviceService",//对外发布的服务名
        targetNamespace = "http://service.webservice.cj.com",//指定你想要的名称空间,通常使用使用包名反转
        endpointInterface = "com.cj.webservice.service.WebServiceDemoService")
@Service
public class WebServiceDemoServiceImpl implements WebServiceDemoService {
    @Override
    public String hello(String name) {
        return "hello" + name;
    }
    @Override
    public String upoload(FileUploadRequestBean requestBean) {
        String requestId = requestBean.getRequestId();
        try {
            String path = "/opt/file/"+requestBean.getFileName();
            InputStream inputStream = requestBean.getFile().getInputStream();
            File targetFile = new File(path);
            FileUtils.copyInputStreamToFile(inputStream, targetFile);
            return "保存地址" + path;
        } catch (Exception e) {
            return "错误";
        }
    }
}

注意:这里我转文件存储,用的是一个commom-io 工具类,很方便。附上maven

 <dependency>
     <groupId>commons-io</groupId>
     <artifactId>commons-io</artifactId>
     <version>2.4</version>
 </dependency>

工具测试

上篇文章中推荐使用的 soapUI又派上用场了。

  1. 第一步还是刷新下之前的wsdl地址,能够找到新部署的方法
    在这里插入图片描述
    具体的步骤我都在上图标记出来了。参考一下。
    然后可以去 项目的所在盘符 的根目录 /opt/file 查看刚才上传的文件:
    在这里插入图片描述

客户端

其实我觉得难的还是在客户端去调用,因为你最终的目的还是给别人调用对吧。如果说你自己都不会的话,那别人来问你的时候,你总不能说你也不会吧,这如果不会就很尴尬了。

注意:记得jar包重新生成下,把bean放到需要打包的文件中,打包class文件(先编译,在打包)


    public static void main(String[] args) {
        JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
        factory.setServiceClass(WebServiceDemoService.class);
        factory.setAddress("http://localhost:8080/webservice/webservice");
        webServiceDemoService = (WebServiceDemoService) factory.create();
        FileUploadRequestBean fileUploadRequestBean = new FileUploadRequestBean();
        File file = new File("D:\\opt\\file\\error.log");
        DataSource dataSource = new FileDataSource(file);
        DataHandler dataHandler = new DataHandler(dataSource);
        fileUploadRequestBean.setFile(dataHandler);
        fileUploadRequestBean.setRequestId("123132");
        fileUploadRequestBean.setFileName("error.log");
        webServiceDemoService.upoload(fileUploadRequestBean);
    }

DataHandler类

说到底,最重要的还是DataHandler类,所以,给大家重点介绍下这个类:

The DataHandler class provides a consistent interface to data available in many different sources and formats. It manages simple stream to string conversions and related operations using DataContentHandlers. It provides access to commands that can operate on the data.

java传送门:DataHandler类
以我四级的水平给大家翻译一下:

DataHandler提供一个一致性的接口:这个接口可以从不用的源和格式中获取数据。DataHandler使用DataContentHandlers可以简单的将流转化到字符串和相关的操作。它提供对操作数据的命令的访问。

大概意思就是讲原始数据转为统一的数据格式。
看下构造方法吧:
在这里插入图片描述
三种构造方法。常用的也就是DataSource第一种。
第二种我不明白是什么意思?所以我也不用,希望有了解的能帮忙解释下。
第三种其实说白了就是能够访问网络的文件。不需要下载下来在从本地读取流,直接一个url地址。
那我重点给大家讲下这个DataSource。
在这里插入图片描述
啥都别说,看图。
很明显,通过这个DataSource的构造方法,我们可以看出来,DataSource可以通过不同的文件构造一个数据源(文件、(网络Url-这个和第三种方法有点像,只不过第三种是在内部创建,这个是在外部)、字节)
如果只是需要怎么去用,其实到这里也就可以了。那正好,我也只需要会用,所以到这里结束啦

总结

  1. webservice中上传文件主要有三种方式:byte[]字节数组,base64编码、附件形式、dataHandler。
  2. dataHandler主要是客户端如何去调用,最重要的类DataHandler
  3. 遇到问题,不着急百度,先自己思考一下,类比一下如果去做,带着思考去找答案总比伸手党要好得多。

附加题

我项目中比较过分的是逻辑:
三个项目 A、B、C.
A调用B,B调用C
A调用B采用Http方式。
B调用C采用webservice方式。
比较饶人的是文件在之间传输的过程中,采用何种形式来流转?(本质上就是使用Http方式和webservice的方式传输文件,两者结合起来)
附上B段的代码:

 public String upload(MultipartHttpServletRequest request, HttpServletResponse response) {
            String accessToken = request.getParameter("accessToken");
            MultipartFile dataFile = request.getFile("file");
            //这是最主要的
            DataSource dataSource = new DataSource() {
                @Override
                public InputStream getInputStream() throws IOException {
                    return dataFile.getInputStream();
                }

                @Override
                public OutputStream getOutputStream() throws IOException {
                    return null;
                }

                @Override
                public String getContentType() {
                    return dataFile.getContentType();
                }

                @Override
                public String getName() {
                    return dataFile.getOriginalFilename();
                }
            };

            DataHandler dataHandler = new DataHandler(dataSource);
    }

附上A段的代码:

  /**
     * post请求带文件附件内容(文件key是file)
     *
     * @param url      请求地址
     * @param file     文件二进制内容
     * @param map      其余参数
     * @param fileName 文件名称
     * @return
     */
    public static String postFileFromData(String url, byte[] file, Map<String, Object> map, String fileName) {
        MultipartBody.Builder builder = new MultipartBody.Builder();
        builder.setType(MultipartBody.FORM)
                .addFormDataPart("file", fileName,
                        RequestBody.create(MediaType.parse("application/octet-stream"), file));
        for (Map.Entry<String, Object> item : map.entrySet()) {
            builder.addFormDataPart(item.getKey(), item.getValue().toString());
        }
        MultipartBody body = builder.build();
        Request request = new Request.Builder()
                .url(url)
                .method("POST", body)
                .addHeader("Content-Type", "multipart/form-data")
                .build();
        try {
            Response response = getInstance().newCall(request).execute();
            return response.body().string();
        } catch (Exception e) {
            log.error("postFileFromData error", e);
            return null;
        }

    }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值