トップ » 技術記事 » チャット作成で学ぶWebリモーティング(5) - DWRとSpringの連携

チャット作成で学ぶWebリモーティング(5) - DWRとSpringの連携

タグ: Ajax DWR Java javascript Spring

どうも皆さん、こんにちは。白石です。

今回はWebリモーティングに関する連載の第四回目です。前回までは、アノテーションやReverseAjaxと言ったDWR2の高度な機能を使用する方法を学んできました。
DWR2は、バージョン1に比べて機能が増えただけではなく、連携できるフレームワークの数や連携方法の改善、といった拡張も施されています。今回からは、Springフレームワークとの連携方法についてみていきたいと思います。

Springフレームワークと連携する方法

Springフレームワークと連携すると、DIやAOPなどの素晴らしい機能を用いてリモートサービスを作成することができます。連携させる方法の基本は、「CreatorをSpring用の物に差し替える」というものです。

Creatorについては連載の第一回でも少し触れましたが、要は「リモートサービスのインスタンス生成方法」を決めるものです。今まではdwr.xmlにおける以下のような設定により、NewCreatorというCreatorを使用していました。

<!-- creator="new"により、NewCreatorを使用するよう設定 -->
<create creator="new" javascript="ChatService" scope="application">

NewCreatorは、DWRがインスタンスのnewを行い管理すると言うものです。これを、「リモートサービスのインスタンスをSpringのコンテナから取得する」Creatorに差し替えれば連携は完了です。

<!-- creator="spring"により、NewCreatorを使用するよう設定 -->
<create creator="spring" javascript="ChatService" scope="application">

簡単ですね。
連携の設定方法は、これだけではありません。「Springのコンテキスト設定ファイル内で全て設定する」と言うさらに高度な方法もあります。これについては次回の記事で解説したいと思います。
では、これまでのサンプルをSpringと連携するよう改善していきたいと思います。

サンプルの修正方針

では、サンプルを修正していきたいと思います。上で説明したように、単にCreatorをspring用の物に差し替えるだけでも良いのですが、せっかくなのでDIをしっかり活用した、より本格的なソースコードにしていきたいと思います。

今までは、全ての処理をリモートサービスであるChatServiceRemote内で行っていました。しかし本来なら、このクラスは「サービスを外部に公開する」という役目だけを負うべきで、ビジネスロジックを含むべきではありません。そこで、以下のようにクラスを分けることを考えていきましょう。

ChatService
:チャットのビジネスロジックに関するインターフェース

ChatServiceImpl
:上のインターフェースを実装したクラス

ChatServiceRemote
:ChatServiceを使用したリモートAPIをクライアントに対して公開するクラス

また今までは、JavaScriptで処理しやすいよう、扱うデータをすべて文字列で取り扱っていました。チャットデータはChatMessageDTOというクラスに格納していました。

public class ChatMessageDTO implements Serializable {
    private static final long serialVersionUID = 1L;
    // 発言したユーザ
    private String user;
    // 投稿されたメッセージ
    private String text;
    // 投稿日時
    private String timestamp;
    …
}

これはこれで、クライアントとやり取りするデータとしては良いのですが、投稿日時などはjava.util.Dateで表現しておいた方が、Javaのロジック内ではあとあと都合がよさそうです。

ということで、データオブジェクトもビジネスロジック用の物を用意し、リモートサービス内で相互に変換するようにしましょう。

ChatMessage
:ビジネスロジック内で使用するチャットデータ

ChatMessageDTO
:Ajaxクライアント向けのデータ形式。

このように、「Javaのロジック内で使用するデータ」と「クライアントとやり取りするデータ」を分けておくことで、例えば画面に表示する日時の形式が変更になった場合、ビジネスロジック側に影響が及ぶことを避けられます。

これを踏まえて、パッケージもきれいに分割すると、以下のようなファイル構造になります。

remote/   … リモートAPIを格納するパッケージ
  ChatMessageDTO.java
  ChatServiceRemote.java
service/  … 業務ロジックAPIを格納するパッケージ
  ChatMessage.java
  ChatService.java
  impl/   … 業務ロジックAPIの実装クラス
    ChatServiceImpl.java

業務ロジックのソースコード

では、チャットアプリの業務ロジックがどのようなソースになったかを見ていきたいと思います。

まずは、業務ロジックで扱われるデータオブジェクトです。

ChatMessageクラス
package service;

import java.io.Serializable;
import java.util.Date;

public class ChatMessage implements Serializable {

  private String user;
  private String text;
  private Date timestamp;

  // 以下setter/getterは略
}

先ほど説明したように、更新日付をjava.util.Dateクラスで表現するようにしています。

ChatServiceクラス

業務ロジックのインターフェースは、以下のようになっています。

package service;

import java.util.List;

/**
 * チャットに関する業務ロジックAPI
 * @author Shumpei Shiraishi
 */
public interface ChatService {

  /**
   * メッセージを追加する
   * @param message
   */
  void addMessage(ChatMessage message);

  /**
   * 全てのメッセージを取得する
   * @return
   */
  List<ChatMessage> getAllMessages();
}

これでもか、というくらい簡単です。メッセージの追加と、メッセージの全件取得を行うメソッドを持ちます。

ChatServiceImplクラス

上のインターフェースを実装したクラスは、以下のようなソースコードになっています。

package service.impl;

import java.util.ArrayList;
import java.util.List;

import service.ChatMessage;
import service.ChatService;

public class ChatServiceImpl implements ChatService {
  private final List<ChatMessage> messages = new ArrayList<ChatMessage>();

  public synchronized void addMessage(ChatMessage message) {
    this.messages.add(message);
  }

  public synchronized List<ChatMessage> getAllMessages() {
    return messages;
  }
}

渡されたメッセージをListに格納するだけです。将来的にメッセージの保存先をDBに変えたいという要件が発生しても、このクラスを修正するだけでよく、リモートサービスには全く影響を与えません。

Series Navigation«DWRのReverse Ajaxで簡単Comet!Spring2の名前空間拡張機能を用いたDWRの設定»

1 2

執筆者紹介

shiraishi

shiraishi

最近書いてばっかりいます。 眠いとおんなじことばかり書きます。 そして、大概眠いです。

TrackBack URL :