この記事は1年以上編集されていないため、情報が古い可能性がございます。
ご注意ください。

このWordPress pluginを配布しています

2014年にはStrutsの脆弱性が見つかり、Java界隈に激震が走った様子を、私はWebの端っこから見て感じていました。

そんな折にSpring Frameworkと出会い、実際に1案件で使ってみて「使えるフレームワーク」という結論に至りました。

サンプルを交え、Spring Frameworkの特徴をご紹介いたします。

バージョンはSpring 4.0です。
Webアプリケーションの開発のため、Spring Web、Spring Web MVC、Spring ORMあたりを使用しました。

Spring BootやSpring Rooといったプロジェクト生成の補助ツールやSpring Securityは未使用です。
Spring AndroidもNo Checkです。

オフィシャル

spring-hp
http://spring.io/

オシャレですね。
そして、しっかりレスポンシブします。

Spring Frameworkはフルスタックなフレームワークではなく、コンポーネントの集合体から成っています。
そのためプロジェクトの数が多く、「あれをやるのに何が必要か」を把握するまでのとっつきにくさは否めません。

そんな時は公式のガイドページからサンプルをチェックしてみましょう。

Guides
http://spring.io/guides

ガイドの点数が豊富で、例えば以下のようなトピックがあります。

  • Building a RESTful Web Service
  • Accessing Relational Data using JDBC with Spring
  • Registering an Application with Twitter
  • Validating Form Input
  • Spring Boot with Docker

ガイドの詳細ページでは所要時間、環境、Maveのpom.xmlなど記載があり、使いやすいですね。
ただし、英語ですけれど。

STS

Spring FrameworkにはSpring Tool Suite、略してSTSというIDEが用意されています。

Spring Tool Suite
https://spring.io/tools/sts

STSはEclipseをSpring開発向けにカスタマイズしたものです。
お手元のEclipseにSpring用の機能を追加するSTS Pluginもありますが、STSと完全に同じではなく、STSの方が高機能なようです。

STSですと、Eclipseが1つ前のバージョンでしたため、私はEclipseにPluginをインストールする形をとりました。
そこまで大きな差はないし、あったところで使いこなしませんので、、、

Spring Frameworkの特徴

  • コンポーネントの集合体
  • アノテーション・ドリブン
  • DI
  • AOP
  • REST

アノテーション・ドリブン

Javaといえばアノテーションです。

Web開発では、spring-webmvcに@Controller@RequestMappingなど必須アノテーションが提供されています。

一口にクラスといっても、Controller、Model、Viewと様々な役割がありますが、アノテーションによって役割を明示し、ふるまいを定義することができ、プログラムの構成単位が分かりやすくなります。

また、アノテーションの自作も可能です。
例として、こんなことをしていました。

  • APIは@isApiというアノテーションで装飾する
  • ログイン不要なページには@NoLoginをつけておく

DI

DIとは依存性の注入といわれるもので、SpringといえばDIというくらいDIする場面が多かったです。
それは各コンポーネント間を疎結合にし「外部の設定ファイルなどを用いてコンポーネントを注入する仕組み」です。

Springで提供されるDIコンテナが、インスタンスの生成、初期化、破棄などを管理します。
DIコンテナにクラスのインスタンスを要求すれば使えるようになるのです。
理解が進むと、大変便利な機能です。

求めよさらば与えられん。

例:クラスをDIする

  • servlet-context.xml
<context:annotation-config />
<context:component-scan base-package="com.example.controller" />

準備として、com.example.controller以下のクラスをすべてDIできるように設定を行います。

  • ExampleServoceImpl.java
@Controller
public class ExampleController {

    @Autowired
    private ExampleService exampleService ;

    @RequestMapping('/')
    @ResponseBody
    public String find() {
        List<ItemEntity> items = exampleService.findAllItems();
        :

ExampleServiceに@AutowiredアノテーションをつけDIします。
こうするだけでnewせずに、オブジェクトを操作することができるんですね。

Autowiredは便利ですが、クラスの冒頭で100もAutowiredしているようなものはやりすぎですね。

また、サンプルではControllerを起点にしています。
こうした場合、ControllerでNewしたインスタンスの中にAutowiredが宣言されていたとしても、DIされずにNULLだったということがありました。

例:プロパティファイルをDIする

PropertiesFactoryBeanを使い、propertiesのDIを行うことが可能です。

詳しくは以下をご覧ください。

[Java][Spring]Propertiesクラスの使い方
Springの便利な機能を知らず、メッセージ管理クラスで都度テキストファイルを読み込む実装をしていたため、Propertie...

AOP

「横断的関心事の分離(Separation Of Cross-Cutting Concerns)」といいます。

後から機能や処理を差し込む、フィルターのようなものという解釈でOKでしょう。

実装例

  • servret-context.xml
    <aop:aspectj-autoproxy proxy-target-class="true" />
    <context:component-scan base-package="com.example.game.web.annotation" />
    <beans:bean id="MaintenanceAspect" class="com.example.game.aspect.MaintenanceAspect" />
    <beans:bean id="LoginAspect"       class="com.example.game.aspect.LoginAspect" />

aspectj-autoproxyを宣言し、AOPを有効にします。
また、AspectのクラスをXML内に定義します。

  • MaintenanceAspect.java
@Aspect
public class LoginAspect implements Ordered {

    // 指定のアノテーションに対してcheckLogin()実行する
    @Pointcut(
        "!@annotation(com.example.game.annotation.NoLogin) && "+
        " @annotation(org.springframework.web.bind.annotation.RequestMapping)"
    )
    public void checkLogin() {
    }

    // checkLogin()の前後に処理を挟む
    @Around("checkLogin()")
    public Object execCheckLogin(ProceedingJoinPoint pjp) throws Throwable {
        // ログイン処理
        return pjp.proceed();
    }

    @Override
    public int getOrder() {
        return AspectOrder.LOGIN.ordinal();
    }
}

こうすること「@RequestMappingが付加され、かつ@NoLoginが付加されていない」メソッドを実行するときポイントカットが働きます。

処理順序を制御するためにはgetOrder()をオーバーライドしてください。
AspectOrderは処理順を保証するための次のEnumを用意し、 getOrder()内から呼び出します。

  • AspectOrder.java
public enum AspectOrder {
    MAINTENANCE,
    LOGIN;
}

サーブレットフィルタですと、処理順序を制御するのが難しい印象があるのですが、こちらはシンプルです。

REST

REpresentational State Transfer

これは「HTTP メソッド (GET、POST、PUT、DELETE など) でリソースを操作する」ものと認識しています。

最近のWebフレームワークはRESTfulなものが多いですね。
Springを採用した案件がAPIベースのため、あまり意識する場面はありませんでした。

import static org.springframework.web.bind.annotation.RequestMethod.GET;
import static org.springframework.web.bind.annotation.RequestMethod.POST;

@Controller
public class WebViewController {

    @RequestMapping(value = "/serial", method = GET);
    public String showSerialForm (Model model) {
        return "/serial/index"
    }

    @RequestMapping(value = "/serial", method = POST);
    public String inputSerial (
        Model model,
        @RequestParam(required = true) String code
    ) {
        // シリアルコードの検証処理
        return "redirect:/serial"
    }
}

どちらも/serialにマッピングしていますが、GET/POSTごとに受け取るメソッドがことなることが、おわかりになると思います。

APIの実装ではメソッドを「POSTのみ」に制限していましたが、method = POSTするだけでしたので非常に簡単でした。

ちなみに、POSTのみに制限されたURLへ、GETでアクセスした場合はHTTP status 405 method not allowedがかえります。

まとめ

Javaにはディファクトスタンダードがないと言われますが、Spring Frameworkはその候補と言えるフレームワークではないでしょうか。

pom.xmlやweb.xmlを設定することは正直大変でしたが、慣れると各コンポーネントの結合度が浅く使いやすいと感じる場面が多かったですね。
そして、JavaVM上で動作しますので、一定のメモリ消費はありますが、高速に動作します。

この記事を書いた人はtomita@atuwebでした。

[Java]PHPオンリーでJava初心者だった私がSpring Webの開発でつまづいた点を振り返る
この記事はtomita@atuwebがお届けします。 開発経験はほとんどPHPのみ という状態の私がJava + Spring...

関連書籍

ざっくり読みました。
Springの時代背景、AOPやDIについて詳しめに説明しており、Springを少し触った後に読むと理解が進むという印象を受けました。

Javaを理解していることが前提であり、プログラミング初心者向けではありません。

その他Spring4を扱っている書籍としては次のものがあるようです。


2016年02月03日:関連書籍を追加
2015年12月29日:補足説明など追記、タイトルを修正
2015年12月01日:Springのバージョンを追記

スポンサーリンク
ad_336
ad_336
  • このエントリーをはてなブックマークに追加
  • Evernoteに保存Evernoteに保存