首頁 >Java >java教程 >教你用applet創建一個系統從而使瀏覽器可以存取web服務

教你用applet創建一個系統從而使瀏覽器可以存取web服務

Y2J
Y2J原創
2017-05-18 10:57:402526瀏覽

本文將介紹如何建立一個系統,從而可以使用瀏覽器請求和互動任意來源的 Web 服務資料。首先建立一個基本的 applet,然後再建立從 Web 頁面中提取資料的 JavaScript 程式碼,最後建立一個 servlet 作為非本機請求的代理程式。

本文假設您熟悉 Java 技術和(初步了解)XML。除了 J2SE 1.4 或更高版本這樣的 Java 開發環境之外,本文還需要使用幾個軟體。為了傳送和接收SOAP 訊息,您需要SOAP with Attachments Application Program Interface (API) for Java(SAAJ,關於如何設定它,請參閱「 Send and receive SOAP messages with SAAJ」),以及servlet 引擎,如IBM? WebSphere? Application Server 或Apache Tomcat 來執行servlet。

一個簡單的請求

先看一看最終由 applet 發出的請求。雖然這項技術適用於任何能夠透過 URL 傳遞的數據,但本文主要討論 Web 服務,因此我們從一個簡單的 SOAP 訊息開始,如清單 1 所示。

清單 1. 一個簡單的 SOAP 訊息

<SOAP-ENV:Envelope 
               SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
    xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:ns1="urn:chaosmagnet-quote"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">
  <SOAP-ENV:Body>
      <ns1:getQuoteResponse>
         <return xsi:type="xsd:string">The early bird gets the worm, but it&#39;s the 
second mouse that gets the cheese...</return>
      </ns1:getQuoteResponse>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

該訊息允許您建立一個簡單的 Java 應用程式(清單 2)來檢索和解析 URL。

清單 2. 透過 Java 應用程式存取 URL

import java.net.URLConnection;
import java.net.URL;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
public class SendRequest {
  public static void main(String args[]){
     try{
        URL url = new URL("http://www.nicholaschase.com/testsoap.php");
        URLConnection urlconn = url.openConnection();
        Document doc = null;
        try {
           DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
           DocumentBuilder db = dbf.newDocumentBuilder();
           doc = db.parse(urlconn.getInputStream());
           System.out.println(doc.getDocumentElement()
                .getFirstChild().getNextSibling()
                .getFirstChild().getNextSibling()
                .getFirstChild().getNextSibling().getFirstChild().getNodeValue());
        } catch (IOException e) {
           System.out.println("can&#39;t find the file:"+e.getMessage());
        } catch (Exception e) {
           System.out.print("Problem parsing the XML.");
        }
     } catch (Exception e){
        e.printStackTrace();
     }
  }
}

#首先,建立真正的 URLConnection 。在此,需要將 InputStream 提供給DocumentBuilder ,作為

建構 Document 物件的來源。我發現輸出語句不是很好,但本文主要討論如何存取資料而不是分析資料教你用applet創建一個系統從而使瀏覽器可以存取web服務

,所以我就採用了直接引用的方法。

編譯程式然後在命令列中運行就可以得到預期的結果:

The early bird gets the worm, but it&#39;s the second mouse that gets the cheese...

您可能奇怪我為何寧願這麼麻煩地直接處理XML,而不去使用(比方說) SAAJ。這是因為最終要把這些程式碼打包成一個 applet,它要在我無法控制的電腦上運行,因此希望堅持使用作為 Java 技術本身一部分的類別。

建立applet

applet 本身很簡單,如清單3 所示:

清單3. 一個簡單的applet

import java.applet.*;
import java.awt.*;
public class SendRequest extends Applet {
  public void paint(Graphics g) {
      g.drawRect(0, 0, 499, 149);
      g.drawString("Printing...", 5, 70);
  }
}

每次打開這個applet 時,applet 都僅僅繪製一個矩形,並在其中顯示「Printing...」。儲存並編譯這個類,然後開啟第二個文字檔案建立來顯示這個 applet 的 HTML 頁面,如清單 4 所示。

清單 4. 顯示 applet 的 HTML 頁面

<HTML>
<HEAD>
   <TITLE>A Simple Program</TITLE>
</HEAD>
<BODY>
   <CENTER>      
        
        <APPLET CODE="SendRequest.class" WIDTH="500" HEIGHT="150">
      </APPLET>
   </CENTER>
</BODY>
</HTML>

注意,通常 HTML 頁面都包含用來呼叫 applet 程式碼的 APPLET 標籤。將該 HTML 頁面儲存到 SendRequest.class 檔案所在的目錄中,然後在瀏覽器中開啟它。您應該會看到與圖 1 類似的結果。

圖 1. 簡單的 applet

教你用applet創建一個系統從而使瀏覽器可以存取web服務

#現在加入檢索 URL 的程式碼。

从 applet 中访问响应

在 applet 中添加检索 URL 的代码很简单,如清单 5 所示。

清单 5. 在 applet 中添加检索 URL 的代码

import java.applet.*;
import java.awt.*;
import java.net.URLConnection;
import java.net.URL;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
public class SendRequest extends Applet {
  public void paint(Graphics g) {
     g.drawRect(0, 0, 499, 149);
     g.drawString(        
        getResponseText(), 5, 70);
  }  
        
        public String getResponseText(){
    try{
      URL url = new URL("http://www.nicholaschase.com/testsoap.php");
      URLConnection urlconn = url.openConnection();
      Document doc = null;
      try {
       DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
       DocumentBuilder db = dbf.newDocumentBuilder();
       doc = db.parse(urlconn.getInputStream());
       return (doc.getDocumentElement()
            .getFirstChild().getNextSibling()
            .getFirstChild().getNextSibling()
            .getFirstChild().getNextSibling()
               .getFirstChild().getNodeValue());
      } catch (Exception e) {
       return "Can&#39;t get the string.";
      }
    } catch (Exception e){
      return "Problem accessing the response text.";
    }
  }}

这里包含了大量原来应用程序中的代码,只是将 main() 方法改成了 getResponseText() 方法,并在浏览器显示 applet 时输出到页面中。

一切都准备就绪,但在刷新页面时,会看到情况并非如此,如图 2 所示。(要看到变化,必须在刷新页面时按下 Ctrl键)。

图 2. 从本地文件系统中调用 applet

教你用applet創建一個系統從而使瀏覽器可以存取web服務

那么,问题出在哪儿呢?前面已经提到,applet 在设计时有一些安全性限制,其中之一就是不能访问服务器,但是不包括最初下载 applet 的服务器。因此,为了从 www.nicholaschase.com 上请求 URL,只需要把 applet 和 HTML 文件上传到那台服务器上。然后再调用 applet,就能得到预期的结果,如图 3 所示。

图 3. 从适当的服务器上访问 applet

教你用applet創建一個系統從而使瀏覽器可以存取web服務

现在已经获得了数据,可以从 HTML 页面中访问了。

通过 JavaScript 访问 applet 数据

这个过程的最终目标是使用 JavaScript 代码分析检索的数据。其中的关键是将 applet 看作一个对象,事实上, APPLET 标签最后将被替换为object 标签。为了替换标签,必须为其指定 id 属性,如清单 6 所示。

清单 6. 作为对象访问 applet

<HTML>
<HEAD>
   <TITLE>A Simple Program</TITLE>
</HEAD>
<BODY>
   <CENTER>
      <APPLET CODE="SendRequest.class" WIDTH="500" HEIGHT="150" id="TheApplet">
      </APPLET>
   </CENTER>        
           <b>The returned data is:</b><br />
   <script type="text/javascript">
      document.write(TheApplet.getResponseText());
   </script></BODY>
</HTML>

为 applet 指定一个 id 属性,从而能够将其作为简单的对象处理,并且可以直接调用 applet 的方法。如果保存该页面并刷新它,就会看到从页面中提取的信息(参见图 4)。

图 4: 通过 JavaScript 访问 applet 数据

教你用applet創建一個系統從而使瀏覽器可以存取web服務

现在就只剩下能够访问任意 URL 的问题了。

创建代理

现在万事俱备,但是因为安全性要求,您只能访问下载 applet 的服务器。如何才能访问不同的服务器呢?

比方说,假设要从 Quote of the Day service 获得实时报价。由于 applet 只能连接到自己的服务器,所以您就不能直接连接到 applet。但是服务器可以连接任何事物,就是说除了直接连接到数据,您还可以连接到检索数据的 servlet。

清单 7 中的代码创建了一个从 Quote of the Day service 中检索响应的 servlet。

清单 7. 检索远程信息的 servlet

import javax.servlet.http.*;
import javax.servlet.*;
 
import javax.xml.soap.SOAPConnectionFactory;
import javax.xml.soap.SOAPConnection;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPElement;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamResult;
public class SendingServlet extends HttpServlet {
    public void doGet(HttpServletRequest req, HttpServletResponse resp)
                                         throws ServletException {
    try {
     
       //First create the connection
       SOAPConnectionFactory soapConnFactory = 
                      SOAPConnectionFactory.newInstance();
       SOAPConnection connection = 
                        soapConnFactory.createConnection();
         
       //Next, create the actual message
       MessageFactory messageFactory = MessageFactory.newInstance();
       SOAPMessage message = messageFactory.createMessage();
         
       //Create objects for the message parts            
       SOAPPart soapPart =     message.getSOAPPart();
       SOAPEnvelope envelope = soapPart.getEnvelope();
       SOAPBody body =         envelope.getBody();
       //Populate the body
       //Create the main element and namespace
       SOAPElement bodyElement = 
           body.addChildElement(envelope.createName("getQuote" , 
                                     "ns1", 
                                     "urn:xmethods-qotd"));
       //Save the message
       message.saveChanges();
       //Send the message and get a reply   
            
       //Set the destination
       String destination = 
              "http://webservices.codingtheweb.com/bin/qotd";
       //Send the message
       SOAPMessage reply = connection.call(message, destination);
       //Check the output
       //Create the transformer
       TransformerFactory transformerFactory = 
                         TransformerFactory.newInstance();
       Transformer transformer = 
                       transformerFactory.newTransformer();
       //Extract the content of the reply
       Source sourceContent = reply.getSOAPPart().getContent();
       resp.setHeader("Content-Type", "text/plain");
       //Set the output for the transformation
       StreamResult result = new StreamResult(resp.getWriter());
       transformer.transform(sourceContent, result);
       //Close the connection            
       connection.close();
            
     } catch(Exception e) {
      System.out.println(e.getMessage());
     }
  }
}

这段脚本看起来又长又复杂,但实际上非常简单。它首先创建 SOAPConnection 和消息对象,然后根据 Quote of the Day service 的要求使用getQuote 元素填充该对象。

创建完成请求消息之后,将其发送到服务并检索答复。将答复作为 SOAPMessage 对象返回,但是您需要把消息的实际文本传递给 servlet 的Response 对象。为此,只需要使用以响应为目标的 XSLT 恒等转换。

编译上述 servlet,并按照一般的 servlet 方式安装它,然后就可以直接从浏览器中调用它,并看到图 5 所示的结果。

图 5: 本地 servlet 检索得到的远程响应

教你用applet創建一個系統從而使瀏覽器可以存取web服務

现在,把远程信息放到 applet 中就与调用 servlet 一样简单了,如清单 8 所示:

清单 8. 从 applet 中调用远程数据

...
  public void paint(Graphics g) {
      g.drawRect(0, 0, 499, 149);
      g.drawString(getResponseText(), 5, 70);
  }
  public String getResponseText(){
     try{
        URL url = new URL("        
        http://localhost:8080/servlet/SendingServlet");
        URLConnection urlconn = url.openConnection();
        Document doc = null;
        try {
           DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
           DocumentBuilder db = dbf.newDocumentBuilder();
           doc = db.parse(urlconn.getInputStream());
  
           return (doc.getDocumentElement() 
        
                          .getFirstChild().getFirstChild().getFirstChild()
                   .getFirstChild().getNodeValue()); 
        } catch (Exception e) {
           return "Can&#39;t get the string:"+e.toString();
        }
     } catch (Exception e){
        return "Problem accessing the response text."+e.toString();
     }
  }
}

注意,这里的代码基本上是相同的,只有两个地方不一样。首先,这里没有直接调用数据,而是调用检索数据的 servlet。其次,因为服务返回的消息没有断行,所以在这里稍微整理了一下。

如需查看结果,可以将 applet 和 HTML 页面复制到安装 serlevt 的服务器上,然后就可以访问 applet 并察看结果了,如图 6 所示。

图 6: 查看结果

教你用applet創建一個系統從而使瀏覽器可以存取web服務

结束语

本文介绍了如何创建一个系统,可以使浏览器访问任意的 Web 服务。JavaScript 代码在 applet 中调用了一个方法,而 applet 又调用了检索远程信息的 servlet,这样就避开了 applet 访问能力的限制。

现在,您可以从几个方面来理清整个过程或者增强其功能。因为数据是被拖放入 JavaScript 代码中的,所以您不需要在页面上显示真正的 applet。您还可以修改 applet,从服务中检索多条信息,或者在单个请求中传回信息,而不必在每次用户更改窗口时发送新的请求。

如果想更进一步,还可以修改 servlet 的选项,使它从 applet 中获取参数。这些参数可以决定 servlet 调用什么服务,或者传递给服务什么参数。使用这些方法(如本文中的 getResponseText() ),您甚至可以编写 JavaScript 代码,将这些参数导入 applet,让用户决定最终显示什么信息。

【相关推荐】

1. 特别推荐“php程序员工具箱”V0.1版本下载

2. Java免费视频教程

3. 详解一个嵌入java的html标签:applet

4. 教你如何去設定Applet的環境

#5. 詳解Application和Applet的不同之處

以上是教你用applet創建一個系統從而使瀏覽器可以存取web服務的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn