2014 年にはStrutsの脆弱性が見つかり、Java 界隈に大きな衝撃を与えました。

私はそんなタイミングで 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 Framework Official
Spring Framework Official
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

ガイドの詳細ページでは所要時間、環境、Maven の 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
1<context:annotation-config />
2<context:component-scan base-package="com.example.controller" />

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

  • ExampleServoceImpl.java
 1@Controller
 2public class ExampleController {
 3
 4    @Autowired
 5    private ExampleService exampleService ;
 6
 7    @RequestMapping('/')
 8    @ResponseBody
 9    public String find() {
10        List<ItemEntity> items = exampleService.findAllItems();
11        
12    }
13}

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

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

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

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

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

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

[Java][Spring]Propertiesクラスの使い方
SpringFrameworkでPropertiesクラスの使い方を勉強してみました。
atuweb 開発ブログ

AOP

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

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

実装例

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

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

  • MaintenanceAspect.java
 1@Aspect
 2public class LoginAspect implements Ordered {
 3
 4    // 指定のアノテーションに対してcheckLogin()実行する
 5    @Pointcut(
 6        "!@annotation(com.example.game.annotation.NoLogin) && "+
 7        " @annotation(org.springframework.web.bind.annotation.RequestMapping)"
 8    )
 9    public void checkLogin() {
10    }
11
12    // checkLogin()の前後に処理を挟む
13    @Around("checkLogin()")
14    public Object execCheckLogin(ProceedingJoinPoint pjp) throws Throwable {
15        // ログイン処理
16        return pjp.proceed();
17    }
18
19    @Override
20    public int getOrder() {
21        return AspectOrder.LOGIN.ordinal();
22    }
23}

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

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

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

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

REST

REpresentational State Transfer

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

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

 1import static org.springframework.web.bind.annotation.RequestMethod.GET;
 2import static org.springframework.web.bind.annotation.RequestMethod.POST;
 3
 4@Controller
 5public class WebViewController {
 6
 7    @RequestMapping(value = "/serial", method = GET);
 8    public String showSerialForm (Model model) {
 9    	return "/serial/index"
10    }
11
12    @RequestMapping(value = "/serial", method = POST);
13    public String inputSerial (
14        Model model,
15        @RequestParam(required = true) String code
16    ) {
17        // シリアルコードの検証処理
18    	return "redirect:/serial"
19    }
20}

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

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

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

まとめ

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

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

[Java]PHPオンリーでJava初心者だった私がSpring Webの開発でつまづいた点を振り返る
Javaの経験が浅い私が、SpringFrameworkを使った開発で困ったことなどをまとめました。
atuweb 開発ブログ

関連書籍

Spring3入門 ――Javaフレームワーク・より良い設計とアーキテクチャ

長谷川 裕一,大野 渉,土岐 孝平
出版社:技術評論社  発売日:2012-11-02

Amazonで詳細を見る

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

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


その他、比較的ああらしい書籍としては次のものがあるようです。

Spring徹底入門 Spring FrameworkによるJavaアプリケーション開発

株式会社NTTデータ
出版社:翔泳社  発売日:2016-07-21

Amazonで詳細を見る

[改訂新版]Spring入門 ――Javaフレームワーク・より良い設計とアーキテクチャ

長谷川 裕一,大野 渉,土岐 孝平
出版社:技術評論社  発売日:2016-06-14

Amazonで詳細を見る