| // |
| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, |
| // software distributed under the License is distributed on an |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| // KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations |
| // under the License. |
| // |
| |
| = 端到端二进制 SOAP 附件第 3 部分:对 Web 服务进行编码和测试 |
| :jbake-type: tutorial |
| :jbake-tags: tutorials |
| :jbake-status: published |
| :icons: font |
| :syntax: true |
| :source-highlighter: pygments |
| :toc: left |
| :toc-title: |
| :description: 端到端二进制 SOAP 附件第 3 部分:对 Web 服务进行编码和测试 - Apache NetBeans |
| :keywords: Apache NetBeans, Tutorials, 端到端二进制 SOAP 附件第 3 部分:对 Web 服务进行编码和测试 |
| |
| 在本课中,将学习如何向 Web 服务/会话 Bean 类中添加代码,以将 JPEG 文件转换为字节数组以及将字节数组转换为 ``java.awt.Image`` 对象。您还将向公共 Web 服务操作中添加代码以便操作可返回这些 ``Image`` 对象。最后,将使用 NetBeans IDE 的 "Test Web Service"(测试 Web 服务)实用程序来在浏览器中对 Web 服务进行测试。 |
| |
| |
| *本教程中的课程* |
| |
| image::images/netbeans-stamp-80-74-73.png[title="此页上的内容适用于 NetBeans IDE 7.2、7.3、7.4 和 8.0"] |
| |
| 1. link:./flower_overview.html[+概述+] |
| 2. link:flower_ws.html[+创建 Web 服务+] |
| 3. => 对 Web 服务进行编码和测试 |
| 4. link:./flower_wsdl_schema.html[+修改方案文件和 WSDL 文件以传递二进制数据+] |
| 5. link:./flower_swing.html[+创建 Swing 客户端+] |
| |
| *本课内容* |
| 6. <<coding-ws,对 Web 服务进行编码>> |
| |
| . <<retrieve-jpeg-as-bytes,以字节数组形式获取 JPEG 文件>> |
| . <<read-bytes-as-image,读取字节数组作为图像>> |
| . <<implement-getflower,实现 getFlower>> |
| . <<create-byte-array-list,为所有 JPEG 文件创建字节数组列表>> |
| . <<implement-getthumbnails,实现 getThumbnails>> |
| |
| [start=2] |
| . <<test-ws,测试 Web 服务>> |
| |
| |
| [[coding-ws]] |
| == 对 Web 服务进行编码 |
| |
| 现在得到了包含一组 JPEG 文件和一个 Web 服务的 Web 应用程序。Web 服务被实现为一个无状态会话 Bean。Web 服务包含两个空 Web 操作。在本课中,您将向 Web 服务中添加代码,以将 JPEG 文件转换为字节数组以及将字节数组转换为 ``java.awt.Image`` 对象。您还将向公共 Web 服务操作中添加代码以便操作可返回这些 ``Image`` 对象。 |
| |
| |
| [[retrieve-jpeg-as-bytes]] |
| === 以字节数组形式获取 JPEG 文件 |
| |
| 在此部分,将向 ``FlowerService`` 类主体中添加一对私有方法。这些方法采用鲜花的名称,创建到鲜花的 JPEG 文件的路径,并返回 JPEG 文件的二进制表示(字节数组)。在后续部分中,将向公共 Web 服务操作中添加代码以使操作调用这些私有方法。 |
| |
| 1. 打开项目的 "Source"(源)视图。需要添加代码,该代码采用图像的名称,基于该名称创建到图像的路径,以及检索图像以作为字节数组。将以下代码键入或粘贴到 ``FlowerService`` 类主体中: |
| |
| [source,java] |
| ---- |
| |
| private byte[] getFlowerBytes(String name) throws IOException { |
| URL resource = this.getClass().getResource("/org/flower/resources/"+name+".jpg"); |
| return getBytes(resource); |
| } |
| ---- |
| |
| [start=2] |
| . 随即出现 IDE 无法找到类 ``URL`` 的警告。通过手动方式或者按 Ctrl-Shift-I 组合键(在 Mac 上为 ⌘-Shift-I 组合键)为 ``link:http://download.oracle.com/javase/6/docs/api/java/net/URL.html[+java.net.URL+]`` 添加一条导入语句。 |
| |
| [start=3] |
| . 随即出现新的警告。警告表明 IDE 无法找到 ``getBytes`` 方法。左键单击警告图标然后单击提示以创建 ``getBytes`` 方法。 |
| |
| image::images/create-method-tip.png[] |
| |
| [start=4] |
| . 编辑器会将焦点置于刚刚创建的 ``getBytes`` 方法上。将以下代码添加到方法中。此代码link:http://download.oracle.com/javase/6/docs/api/java/net/URL.html#openStream%28%29[+打开到 URL 的连接+],通过 ``getFlowerBytes`` 方法传递该 URL 并返回一个 ``link:http://download.oracle.com/javase/6/docs/api/java/io/InputStream.html[+InputStream+]`` 。然后此代码读取输入流(一次 1024 个字节),将字节存储在字节数组缓冲区中,接着再从缓冲区写入 ``link:http://download.oracle.com/javase/6/docs/api/java/io/ByteArrayOutputStream.html[+ByteArrayOutputStream+]`` 。 |
| |
| [source,java] |
| ---- |
| |
| private byte[] getBytes(URL resource) throws IOException { |
| InputStream in = resource.openStream(); |
| ByteArrayOutputStream bos = new ByteArrayOutputStream(); |
| byte[] buf = new byte[1024]; |
| for(int read; (read = in.read(buf)) != -1;) { |
| bos.write(buf, 0, read); |
| } |
| return bos.toByteArray(); |
| } |
| ---- |
| |
| [start=5] |
| . 为 ``java.io.InputStream`` 和 ``java.io.ByteArrayOutputStream`` 添加导入语句。 |
| |
| |
| [[read-bytes-as-image]] |
| === 读取字节数组作为图像 |
| |
| 在此部分,将向 ``FlowerService`` 类主体中添加一个私有方法。该方法传入一个代表 JPEG 文件的字节数组,并返回 ``java.awt.Image`` 对象。请注意,字节数组是由 ``getBytes(URL)`` 方法所创建的,该方法在<<retrieve-jpeg-as-bytes,以字节数组形式获取 JPEG 文件>>部分中创建。 |
| |
| 1. 在 ``FlowerService`` 类主体中,添加以下名为 ``getImage`` 的私有方法。 ``getImage`` 方法的返回类型为 ``Image`` 。该方法采用两个参数。第一个参数是由 ``getBytes`` 方法创建的字节数组。第二个参数是一个布尔值,用于表示该图像是否为缩略图。 ``getImage`` 方法抛出一个 ``IOException`` 。 |
| |
| [source,java] |
| ---- |
| |
| private Image getImage(byte[] bytes, boolean isThumbnail) throws IOException { |
| } |
| ---- |
| |
| [start=2] |
| . 在 ``getImage`` 方法主体中,添加一行代码,以通过该方法作为参数传入的字节数组来创建 ``link:http://download.oracle.com/javase/6/docs/api/java/io/ByteArrayInputStream.html[+ByteArrayInputStream+]`` 。 |
| |
| [source,java] |
| ---- |
| |
| ByteArrayInputStream bis = new ByteArrayInputStream(bytes); |
| ---- |
| |
| [start=3] |
| . 添加一行代码,以通过 ``ByteArrayInputStream`` 创建一个 ``Object`` 。 |
| |
| [source,java] |
| ---- |
| |
| Object source = bis; |
| ---- |
| |
| [start=4] |
| . 添加一行代码,以通过通用 ``Object`` 创建一个 ``link:http://download.oracle.com/javase/6/docs/api/javax/imageio/stream/ImageInputStream.html[+ImageInputStream+]`` 。 |
| |
| [source,java] |
| ---- |
| |
| ImageInputStream iis = ImageIO.createImageInputStream(source); |
| ---- |
| |
| [start=5] |
| . 添加一行代码来为所有当前注册的可以解码 JPEG 文件的 ``link:http://download.oracle.com/javase/6/docs/api/javax/imageio/ImageReader.html[+ImageReader+]`` 创建一个 ``link:http://download.oracle.com/javase/6/docs/api/java/util/Iterator.html[+Iterator+]`` 。 |
| |
| [source,java] |
| ---- |
| |
| Iterator readers = ImageIO.getImageReadersByFormatName("jpeg"); |
| ---- |
| |
| [start=6] |
| . 添加一行代码,用于通过 ``Iterator`` 中的下一个元素创建 ``ImageReader`` 。 |
| |
| [source,java] |
| ---- |
| |
| ImageReader reader = (ImageReader) readers.next(); |
| ---- |
| |
| [start=7] |
| . 添加代码行以创建默认的link:http://download.oracle.com/javase/6/docs/api/javax/imageio/IIOParam.html[+图像读取参数+],但是如果 ``Image`` 代表缩略图,请将四种link:http://download.oracle.com/javase/6/docs/api/javax/imageio/IIOParam.html#setSourceSubsampling%28int,%20int,%20int,%20int%29[+二次采样+]中的一种添加到图像读取参数中。 |
| |
| [source,java] |
| ---- |
| |
| ImageReadParam param = reader.getDefaultReadParam(); |
| if (isThumbnail) { |
| param.setSourceSubsampling(4, 4, 0, 0); |
| } |
| ---- |
| |
| [start=8] |
| . 最后,添加代码以使用 ``ImageReader`` 对象来读取 ``ImageInputStream`` 对象,并基于该对象和图像读取参数来返回 ``Image`` 。 |
| |
| [source,java] |
| ---- |
| |
| reader.setInput(iis, true); |
| return reader.read(0, param); |
| ---- |
| |
| [start=9] |
| . 按 Ctrl-Shift-I 组合键(在 MacOS 上按 ⌘-Shift-I 组合键)。"Fix All Imports"(修复所有导入)对话框即打开。接受 "Fix All Imports"(修复所有导入)对话框的默认建议,然后单击 "OK"(确定)。 |
| |
| image::images/fix-getimage-imports.png[] |
| |
| ``getImage`` 方法现在已完成。 |
| |
| |
| [source,java] |
| ---- |
| |
| private Image getImage(byte[] bytes, boolean isThumbnail) throws IOException { |
| ByteArrayInputStream bis = new ByteArrayInputStream(bytes); |
| Object source = bis; // File or InputStream |
| ImageInputStream iis = ImageIO.createImageInputStream(source); |
| Iterator readers = ImageIO.getImageReadersByFormatName("jpeg"); |
| ImageReader reader = (ImageReader) readers.next(); |
| ImageReadParam param = reader.getDefaultReadParam(); |
| if (isThumbnail) { |
| param.setSourceSubsampling(4, 4, 0, 0); |
| } |
| reader.setInput(iis, true); |
| return reader.read(0, param); |
| } |
| ---- |
| |
| |
| [[implement-getflower]] |
| === 实现 getFlower |
| |
| 将以下实现代码添加到 ``getFlower()`` 方法中以通过花的名称来获取鲜花并返回该花的图像,如下所示。请注意,此代码调用私有的 ``getFlowerBytes(name)`` 方法来以字节数组形式获取 JPEG 文件。然后该代码调用私有的 ``getImage`` 方法来返回字节数组以作为 ``Image`` 对象。 |
| |
| |
| [source,java] |
| ---- |
| |
| @WebMethod(operationName = "getFlower") |
| public Image getFlower(@WebParam(name = "name") String name) throws IOException { |
| byte[] bytes = getFlowerBytes(name); |
| return getImage(bytes, false); |
| } |
| ---- |
| |
| |
| [[create-byte-array-list]] |
| === 为所有 JPEG 文件创建字节数组列表 |
| |
| 1. 在 ``FlowerService`` 类主体的顶部,创建一个用于表示每朵花名称的 String 数组。 |
| |
| [source,java] |
| ---- |
| |
| private static final String[] FLOWERS = {"aster", "honeysuckle", "rose", "sunflower"}; |
| ---- |
| |
| [start=2] |
| . 添加一个方法,该方法创建一个 ``link:http://download.oracle.com/javase/6/docs/api/java/util/ArrayList.html[+ArrayList+]`` ,并将每朵花的字节数组添加到 ``List`` 中。 |
| |
| [source,java] |
| ---- |
| |
| private List allFlowers() throws IOException { |
| List flowers = new ArrayList(); |
| for (String flower:FLOWERS) { |
| URL resource = this.getClass().getResource("/org/flower/resources/"+flower+".jpg"); |
| flowers.add(getBytes(resource)); |
| } |
| return flowers; |
| } |
| ---- |
| |
| [start=3] |
| . 为 ``java.util.ArrayList`` 和 ``java.util.List`` 添加导入语句。 |
| |
| |
| [[implement-getthumbnails]] |
| === 实现 getThumbnails |
| |
| 按照如下所示更改 ``getThumbnails()`` 方法。请注意,添加实现代码并将返回类型从 ``List`` 更改为 ``List<Image>`` 。还请注意,将布尔型 ``isThumbnail`` 的值 ``true`` 传递到 ``getImage`` 方法。 ``getThumbnails`` 的实现代码调用 ``allFlowers`` 方法来<<create-byte-array-list,为所有 JPEG 文件创建字节数组列表>>。然后 ``getThumbnails`` 方法创建一个 ``Image`` 的 ``List`` 并为每朵花调用 ``getImage`` 方法,从而将该花的字节数组作为 ``Image`` 对象返回,并将该 ``Image`` 添加到 ``List`` 中。 |
| |
| |
| [source,java] |
| ---- |
| |
| @WebMethod(operationName = "getThumbnails") |
| public List<Image> getThumbnails() throws IOException { |
| List<byte[]> flowers = allFlowers(); |
| List<Image> flowerList = new ArrayList<Image>(flowers.size()); |
| for (byte[] flower : flowers) { |
| flowerList.add(getImage(flower, true)); |
| } |
| return flowerList; |
| } |
| ---- |
| |
| 结合的 Web 服务/会话 Bean 现在已完成。Web 服务类的最终窗体如下: |
| |
| |
| [source,java] |
| ---- |
| |
| package org.flower.service;import java.awt.Image; |
| import java.io.ByteArrayInputStream; |
| import java.io.ByteArrayOutputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.net.URL; |
| import java.util.ArrayList; |
| import java.util.Iterator; |
| import java.util.List; |
| import javax.jws.WebMethod; |
| import javax.jws.WebParam; |
| import javax.jws.WebService; |
| import javax.ejb.Stateless; |
| import javax.imageio.ImageIO; |
| import javax.imageio.ImageReadParam; |
| import javax.imageio.ImageReader; |
| import javax.imageio.stream.ImageInputStream;@WebService(serviceName = "FlowerService") |
| @Stateless() |
| public class FlowerService {private static final String[] FLOWERS = {"aster", "honeysuckle", "rose", "sunflower"};@WebMethod(operationName = "getFlower") |
| public Image getFlower(@WebParam(name = "name") String name) throws IOException { |
| byte[] bytes = getFlowerBytes(name); |
| return getImage(bytes, false); |
| }@WebMethod(operationName = "getThumbnails") |
| public List<Image> getThumbnails() throws IOException { |
| List flowers = allFlowers(); |
| List<Image> flowerList = new ArrayList<Image>(flowers.size()); |
| for (byte[] flower : flowers) { |
| flowerList.add(getImage(flower, true)); |
| } |
| return flowerList; |
| }private byte[] getFlowerBytes(String name) throws IOException { |
| URL resource = this.getClass().getResource("/org/flower/resources/" + name + ".jpg"); |
| return getBytes(resource); |
| }private byte[] getBytes(URL resource) throws IOException { |
| InputStream in = resource.openStream(); |
| ByteArrayOutputStream bos = new ByteArrayOutputStream(); |
| byte[] buf = new byte[1024]; |
| for (int read; (read = in.read(buf)) != -1;) { |
| bos.write(buf, 0, read); |
| } |
| return bos.toByteArray(); |
| }private Image getImage(byte[] bytes, boolean isThumbnail) throws IOException { |
| ByteArrayInputStream bis = new ByteArrayInputStream(bytes); |
| Iterator readers = ImageIO.getImageReadersByFormatName("jpeg"); |
| ImageReader reader = (ImageReader) readers.next(); |
| Object source = bis; // File or InputStream |
| ImageInputStream iis = ImageIO.createImageInputStream(source); |
| reader.setInput(iis, true); |
| ImageReadParam param = reader.getDefaultReadParam(); |
| if (isThumbnail) { |
| param.setSourceSubsampling(4, 4, 0, 0); |
| } |
| return reader.read(0, param); |
| }private List allFlowers() throws IOException { |
| List flowers = new ArrayList(); |
| for (String flower : FLOWERS) { |
| URL resource = this.getClass().getResource("/flower/album/resources/" + flower + ".jpg"); |
| flowers.add(getBytes(resource)); |
| } |
| return flowers; |
| } |
| } |
| ---- |
| |
| |
| [[test-ws]] |
| == 测试 Web 服务 |
| |
| 既然 Web 服务已完成,您可以对其进行部署和测试。 |
| |
| *测试 Web 服务:* |
| |
| 1. 右键单击 "FlowerAlbumService" 节点,然后选择 "Deploy"(部署)。IDE 编译源代码,启动 GlassFish Server,并将项目的 WAR 文件部署到服务器。如果打开 "Services"(服务)窗口,将在服务器的 "Applications"(应用程序)节点中看到已部署的 ``FlowerService`` 。 |
| |
| *重要说明:*GlassFish Server Open Source Edition 的版本必须是 3.1 或更高版本。 |
| |
| image::images/deployed-service.png[] |
| |
| [start=2] |
| . 展开项目的 "Web Services"(Web 服务)节点。右键单击 "FlowerService" 然后选择 "Test Web Service"(测试 Web 服务)。 |
| |
| image::images/test-ws-node.png[] |
| |
| [start=3] |
| . Web 服务测试器在浏览器中打开。在 ``getFlower`` 参数字段中键入 "rose"。 |
| |
| image::images/ws-tester.png[] |
| |
| [start=4] |
| . 按 ``getFlower`` 按钮。IDE 在浏览器中显示有关调用的信息。查看“Method Returned”时,会看到乱码。您想要看到一幅图像,而不是一系列的符号。但是,由于 ``java.awt.Image`` 不是有效的方案类型,需要手动配置方案文件以返回二进制 image/jpeg 数据。这将在下一个教程中完成。 |
| |
| image::images/ws-tester-badschema.png[] |
| |
| [start=5] |
| . |
| |
| == 后续步骤: |
| |
| link:./flower_wsdl_schema.html[+修改方案文件和 WSDL 文件以传递二进制数据+] |
| |
| link:/about/contact_form.html?to=3&subject=Feedback:%20Flower%20Coding%20WS%20EE6[+发送有关此教程的反馈意见+] |
| |
| 要发送意见和建议、获得支持以及随时了解 NetBeans IDE Java EE 开发功能的最新开发情况,请link:../../../community/lists/top.html[+加入 nbj2ee@netbeans.org 邮件列表+]。 |
| |