加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

JAX-WS 文件传递

发布时间:2020-12-16 23:38:14 所属栏目:安全 来源:网络整理
导读:MTOM vs SwA WebService传递文件有两种标准,SwA(SOAP with Attachment)和MTOM(Message Transmission and Optimization Mechanism)。SwA正在被性能更好的MTOM with XOP(XML Binary Optimized Packaging)所代替。如果不开启MTOM的话,则使用SwA。 MTOM

MTOM vs SwA

WebService传递文件有两种标准,SwA(SOAP with Attachment)和MTOM(Message Transmission and Optimization Mechanism)。SwA正在被性能更好的MTOM with XOP(XML Binary Optimized Packaging)所代替。如果不开启MTOM的话,则使用SwA。

MTOM相比较SwA而言,具有下面的优势:

  1. SwA使用Base64binary传输,而MTOM使用ray binary传输。Base64binary比ray binary要多出33%的长度。

  2. MTOM在Base64binary与raw binary之间的转化是透明的,转化发生在临近wire两端,并不影响程序员的对SOAP消息的更改。程序员不需要关心。

  3. MTOM使用了现有的信息安全标准WS-Encryption和WS-Signatures,而SwA还需要自己照顾安全问题。

虽然MTOM具有传输优势,但对于小文件,过度的使用MTOM优化传输所带来的开销反而大于其传输所减少的时间。所以,对于MTOM可以设置一个值,当文件大小大于某值时,才开启MTOM。

借用下图,表示MTOM的工作方式。

MTOM开启方法

在服务器端,开启MTOM的方法有3

1, 在SEI实现类上使用@javax.xml.ws.soap.MTOM(threshold=1000). 此命令意思是对于1k以上的文件,开启MTOM。

2,在sun-jaxws.xml中声明<endpoint enable-mtom="true" .../>

3,在SEI实现类上使用@BindingType

  1. @BindingType(value=javax.xml.ws.soap.SOAPBinding.SOAP11HTTP_MTOM_BINDING) 为soap1.1开启MTOM

  2. @BindingType(value=javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_MTOM_BINDING)?为soap1.2开启MTOM

在客户端,开启MTOM的方法有2

1,在创建Port的时候,使用MTOMFeature()作为参数。?

2,像下面的代码一样,使用SOAPBinding

Hello?port?=?new?HelloService.getHelloPort();
//get?the?binding?and?enable?mtom
SOAPBinding?binding?=?(SOAPBinding)?((BindingProvider)?port).getBinding();
boolean?mtomEnabled?=?binding.isMTOMEnabled();
binding.setMTOMEnabled(true);

除了开启MTOM以外,还应该注意MIME数据与Java之间的转换。MTOM支持以下转换:

JAXB xmime:expectedContentType与java type之间的转换

在wsimport对wsdl转型的时候,若想将xml element转换成对应的java type,必须声明xmime:expectedContentType. 如:

<xs:complexType?name="downloadImgResponse">
????<xs:sequence>
??????<xs:element?name="return"?xmime:expectedContentTypes="image/jpeg"?type="xs:base64Binary"?minOccurs="0"/>
????</xs:sequence>
??</xs:complexType>

在wsgen对java想wsdl转型的时候,若想将operation的参数和返回值转为相应的mine type,则需要使用annotation @XmlMimeType,如:

public?boolean?uploadImg(String?name,?@XmlMimeType("image/jpeg")?Image?img);
????
@XmlMimeType("image/jpeg")
public?Image?downloadImg(String?name);

MTOM实例

本实例将实现一个文件上传与下载服务,为了展示不同MIME类型不同的处理方式,在服务中将提供两类文件的上传与下载,image/jpeg和application/octet-stream.

package?com.mycompany;

import?java.awt.Image;
import?javax.activation.DataHandler;
import?javax.jws.WebService;
import?javax.xml.bind.annotation.XmlMimeType;

@WebService
public?interface?AttachmentEngine?{
????//?上传图片
????public?boolean?uploadImg(String?name,?@XmlMimeType("image/jpeg")?Image?img);
????//?下载图片
????@XmlMimeType("image/jpeg")
????public?Image?downloadImg(String?name);
????//?上传二进制文件
????public?boolean?uploadBinary(String?name,?@XmlMimeType("application/octet-stream")?DataHandler?handler);
????//?下载二进制文件
????@XmlMimeType("application/octet-stream")
????public?DataHandler?downloadBinary(String?name);
}

SEI实现类

package?com.mycompany;

import?java.awt.Image;
import?java.awt.image.RenderedImage;
import?java.io.File;
import?java.io.FileNotFoundException;
import?java.io.FileOutputStream;
import?java.io.IOException;

import?javax.activation.DataHandler;
import?javax.activation.FileDataSource;
import?javax.imageio.ImageIO;
import?javax.jws.WebService;
import?javax.xml.bind.annotation.XmlMimeType;
import?javax.xml.ws.WebServiceException;
import?javax.xml.ws.soap.MTOM;

@MTOM
@WebService(endpointInterface="com.mycompany.AttachmentEngine")
public?class?AttachmentEngineImpl?implements?AttachmentEngine?{
????private?final?File?saveDir?=?new?File("d:/share/server");
????//?将上传的图片以参数name命名,并存储到d:/share/server目录下。
????@Override
????public?boolean?uploadImg(String?name,?@XmlMimeType("image/jpeg")?Image?img)?{
????????try?{
????????????ImageIO.write((RenderedImage)?img,?"jpg",?new?File(saveDir,?name));
????????}?catch?(IOException?e)?{
????????????throw?new?WebServiceException("Fail?to?upload.");
????????}
????????return?true;
????}
????//?获取d:/share/server下名为name的图片
????@Override
????@XmlMimeType("image/jpeg")
????public?Image?downloadImg(String?name)?{
????????File?image?=?new?File(saveDir,?name);
????????try?{
????????????return?ImageIO.read(image);
????????}?catch?(IOException?e)?{
????????????throw?new?WebServiceException("Fail?to?download.",e);
????????}
????}
????//?将上传的文件以参数name命名,并存储到d:/share/server目录下。
????@Override
????public?boolean?uploadBinary(String?name,????????????@XmlMimeType("application/octet-stream")?DataHandler?handler)?{
????????try?{
????????????handler.writeTo(new?FileOutputStream(new?File(saveDir,?name)));
????????????return?true;
????????}?catch?(FileNotFoundException?e)?{
????????????throw?new?WebServiceException("Fail?to?upload.",e);
????????}?catch?(IOException?e)?{
????????????throw?new?WebServiceException("Fail?to?upload.",e);
????????}
????}
????//?获取d:/share/server下名为name的文件
????@Override
????@XmlMimeType("application/octet-stream")
????public?DataHandler?downloadBinary(String?name)?{
????????return?new?DataHandler(new?FileDataSource(new?File(saveDir,?name)));
????}
}

打包部署

创建sun-jaxws.xml

<?xml?version="1.0"?encoding="UTF-8"?>
<endpoints?xmlns='http://java.sun.com/xml/ns/jax-ws/ri/runtime'?version='2.0'>
????<endpoint
????????name='attachment'
????????implementation='com.mycompany.AttachmentEngineImpl'
????????url-pattern='/service'/>
</endpoints>

然后打包成file.war,最后部署到tomcat。

访问http://localhost:8080/file/service?

生成客户端

首先使用wsimport生成客户端。最后写一个类来检验webservice是否工作。

public?class?App?{
????private?static?final?File?uploadDir?=?new?File("d:/share/client/upload");
????private?static?final?File?downloadDir?=?new?File("d:/share/client/download");
????
????public?static?void?main(?String[]?args?)?throws?IOException??{
????????//?生成一个开启MTOM的port
????????AttachmentEngine?engine?=?new?AttachmentEngineImplService().getAttachmentEngineImplPort(new?MTOMFeature());
????????//?将upload目录下的a.JPG以另一个名字photo.jpg上传
????????engine.uploadImg("photo.jpg",?ImageIO.read(new?File(uploadDir,?"a.JPG")));
????????//?从服务器端重新获取photo.jpg
????????Image?img?=?engine.downloadImg("photo.jpg");
????????//?将服务器端获取的photo.jpg以download.jpg的名字存到download目录中。
????????ImageIO.write((RenderedImage)?img,?new?File(downloadDir,?"download.jpg"));
????????//?上传b.pdf,改名为test.pdf
????????engine.uploadBinary("test.pdf",?new?DataHandler(new?FileDataSource(new?File(uploadDir,?"b.pdf"))));
????????//?下载test.pdf
????????DataHandler?handler?=?engine.downloadBinary("test.pdf");
????????//?将下载的test.pdf存入download目录
????????handler.writeTo(new?FileOutputStream(new?File(downloadDir,?"download.pdf")));
????}
}

在运行程序前,请先将a.JPG和b.pdf复制到upload目录下。

在运行完程序以后,可以查看服务器目录和下载目录,文件应该已经在那里了。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读