サーブレットの準備
続いて、サーブレット側の準備をしましょう。ここでは、アプレットから送信されたイメージを受け取ったり、要求に応じてイメージをアプレットに送信するサーブレット「Applet2Servlet」を作成します。
package jp.tuyano.codezine; import java.awt.image.BufferedImage; import java.io.*; import javax.imageio.*; import javax.imageio.stream.ImageOutputStream; import javax.servlet.*; import javax.servlet.http.*; public class Applet2Servlet extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet { private static final long serialVersionUID = 1L; private String imgpath = "lastSavedImage.jpg"; public Applet2Servlet() { super(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("EUC-JP"); loadImageFromFile(response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { saveImageToFile(request); } // イメージを読み込んでアプレットに送る public void loadImageFromFile(HttpServletResponse response){} // イメージをアプレットから受け取り保存する private void saveImageToFile(HttpServletRequest request) {} }
<servlet>
<display-name>Applet2Servlet</display-name>
<servlet-name>Applet2Servlet</servlet-name>
<servlet-class>
jp.tuyano.codezine.Applet2Servlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Applet2Servlet</servlet-name>
<url-pattern>/app2serv</url-pattern>
</servlet-mapping>
サーブレットは、GET時にはloadImageFromFileを呼び出し、POST時にはsaveImageToFileを呼び出すように設計してあります。アプレットからイメージを送信するときにはPOSTで受け取り、アプレットからイメージを要求されたときにはGETで受け取る、という形で設計するわけです。
アプレットからサーブレットへの送信
では、プログラムの基本部分ができあがったところで、具体的な処理をメソッドとして実装していきましょう。まずは「アプレットからサーブレットにイメージを送信する」という処理です。
これは、アプレット側のsaveImageでサーブレットに送信をし、サーブレット側ではsaveImageToFileで送られてきたイメージを受け取って保存する、という形になります。では、それぞれのメソッドを実装しましょう。まずはアプレットの処理からです。
private void saveImage(ActionEvent ev){ InputStreamReader inreader = null; ImageOutputStream imgout = null; OutputStream out = null; HttpURLConnection connect = null; try { URL url = new URL(servpath); connect = (HttpURLConnection) url.openConnection(); connect.setDoInput(true); connect.setDoOutput(true); connect.setRequestMethod("POST"); connect.setRequestProperty("Content-Type", "application/octed-stream"); out = connect.getOutputStream(); imgout = ImageIO.createImageOutputStream(out); ImageIO.write(panel.getDrawImage(),"JPEG" ,imgout); inreader = new InputStreamReader(connect.getInputStream()); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { imgout.close(); inreader.close(); connect.disconnect(); } catch (Exception ex2) { ex2.printStackTrace(); } } }
まず、アプレット側からの処理について説明しましょう。イメージのサーブレットへの送信は、基本的にHttpURLConnectionを使って行います。送信するデータを扱うためにOutputStreamとImageWriterを用意し、これを利用してHttpURLConnectionから取得したOutputStreamに対してイメージを出力するのです。
URL url = new URL(servpath);
HttpURLConnection connect = (HttpURLConnection)url.openConnection();
まずは、HttpURLConnectionを作成します。これは、送信するサーブレットのURLを用意し、openConnectionを呼び出して作成をします。アプレットから特定のURLにHTTPで接続をする場合に使われる最も基本となるクラスです。
HTTPプロトコルに限らず接続するための専用クラスとして、これのスーパークラスとなるURLConnectionというクラスも用意されていますが、今回はHTTP用に多用されるHttpURLConnectionを使ってみることにしました。
さて、HttpURLConnectionインスタンスを取得したら、これを利用するための下準備を行います。
connect.setDoInput(true); connect.setDoOutput(true); connect.setRequestMethod("POST");
setDoInputとsetDoOutputは、それぞれ入力・出力を行うかどうかを設定するものです。ここでは両方を利用できる状態にしておきます。
setRequestMethodは使用するリクエストメソッドを設定するものです。これでPOSTを使ってリクエストを受け付けるようになります。非常に簡単です。
後は、データを送信すればよいわけですが、その前に一つやっておくことがあります。それはリクエストに送信するデータ形式に関する情報を付加することです。
connect.setRequestProperty("Content-Type", "application/octed-stream");
ここでは、BufferedImageインスタンスをそのまま送信します。Javaのオブジェクトをそのまま送る場合、HTTPでのContent-Typeは"application/octed-stream"を使うことになります。その設定をこれで行っています。
これで下準備は終わりました。続いて、データを送信するためのOutputStreamと、イメージを書き出すためのImageWriterを用意します。
out = connect.getOutputStream();
ImageWriter iw = (ImageWriter)ImageIO.
getImageWritersByFormatName("jpeg").next();
接続先へ送信するためのOutputStreamは、HttpURLConnectionのgetOutputStreamで取得することができます。また、JPEGフォーマットのデータとしてデータを書き出すためのImageWriterは、getImageWritersByFormatNameを使って得ることができます。
両者がそろったら、これらを元にImageOutputStreamを作成します。
imgout = ImageIO.createImageOutputStream(out);
ImageIO.createImageOutputStreamにOutputStreamを引数として渡してImageOutputStreamが作成できます。これが、最終的にイメージを出力するために使われるストリームとなります。
後は、先にImageWriterでイメージをファイルに出力したのと同じです。ImageWriterに送信するOutputStream(ここではImageOutputStream)を設定し、BufferedImageをwriteして書き出します。
ImageIO.write(panel.getDrawImage(),"JPEG" ,imgout);
書き出しは、ImageIO.writeが利用できます。これは引数にImageOutputStreamを指定できますので、これを使ってイメージをファイルに出力します。既にファイルへの保存で使っていますから簡単です。
これで送信の作業は終わりです。が、実はもう一つだけやることがあります。
inreader = new InputStreamReader(connect.getInputStream());
入力ストリームをHttpURLConnectionから作成をします。これは実際に使うものではありません。送信後にサーバ側からの返事を受け取るものです。ただ「受け取れる体制になっていればOK」なので、特に利用はしていません。
後は、finallyで不要になったストリームや接続を開放して終わりです。なお、本来なら開放処理は1つずつ例外処理すべきでしょうが、サンプルということでここでは少々簡潔化させてもらいました。
イメージの送信ということで少々面倒くさいことをしていますが、単純に「アプレットからサーブレットへの送信」という点だけを考えれば、それほど複雑ではないことが分かるでしょう。
