🧭 Vol.11.21 Struts2でJSONを返す！REST API連携と非同期通信の基本設計

### 🎯 本記事の目的

Struts2はサーバーサイドMVC型の代表的なJavaフレームワークですが、**HTML画面を返すだけでなく、JSON形式のレスポンスも扱えます**。本記事では以下の内容を解説します：

- JSONを返すためのStruts2の設定方法

- 実装例（ユーザー情報返却API）

- JSON出力のカスタマイズ方法

- セキュリティ面の注意点（CORS, CSRFなど）

---

### 🔸 1. なぜStruts2でJSON返却？
Struts2はもともとHTMLベースの画面遷移を前提としていますが、最近のアプリケーションでは以下のような**JSON連携のニーズ** があります。

- ✅ 画面の一部だけを非同期更新したい（AJAX）

- ✅ モバイルアプリからJSON APIを呼び出したい

- ✅ SPA（Single Page Application）でバックエンドAPIを分離したい

このような場面では、Struts2で**HTMLビューではなくJSONデータ**を返す仕組みを使うことで、柔軟な連携が可能になります。

---

### 🔧 2. Struts2でJSONレスポンスを返す構成
### 📌 必須ライブラリ（struts2-json-plugin）

Struts2でJSONを返すには、以下のjarをプロジェクトに追加します。

```xml
<!-- pom.xml (Mavenの場合) -->
<dependency>
  <groupId>org.apache.struts</groupId>
  <artifactId>struts2-json-plugin</artifactId>
  <version>2.5.31</version> <!-- プロジェクトに合わせて調整 -->
</dependency>
```

>補足：`struts2-json-plugin`が提供するResultタイプ "json" を利用することで、ActionクラスのプロパティをそのままJSONとして返せます

---


### 🛠 struts.xml の設定

```xml
<package name="json-api" namespace="/api" extends="json-default">
  <action name="getUserList" class="com.example.action.GetUserListAction">
    <result type="json" />
  </action>
</package>
```

ポイント：

- `extends="json-default"` にすることでJSON機能が有効化されます。

- `<result type="json" />` を設定すると、戻り値が JSON になります。

---

### 🧪 3. 実装例：ユーザー情報をJSONで返す
### 🎯 要件

以下のようなJSONを返すエンドポイント `/api/getUserList.action` を作成します。

```json
{
  "users": [
    { "id": 1, "username": "alice" },
    { "id": 2, "username": "bob" }
  ]
}
```

---

### 🧱 Actionクラスの実装

```java
package com.example.action;

import com.opensymphony.xwork2.ActionSupport;
import java.util.ArrayList;
import java.util.List;

public class GetUserListAction extends ActionSupport {
    private List<UserDto> users;

    @Override
    public String execute() {
        users = new ArrayList<>();
        users.add(new UserDto(1, "alice"));
        users.add(new UserDto(2, "bob"));
        return SUCCESS;
    }

    public List<UserDto> getUsers() {
        return users;
    }

    public static class UserDto {
        private int id;
        private String username;

        public UserDto(int id, String username) {
            this.id = id;
            this.username = username;
        }

        public int getId() { return id; }
        public String getUsername() { return username; }
    }
}
```

### 💡 解説
- `getUsers()` という`getter`を持つことで、自動的に `users` プロパティがJSONに変換されます。

- `UserDto` は内部クラスでもOKですが、実運用では独立したDTOクラスが望ましいです。

---

### 🔍 4. JSON出力のカスタマイズ方法
Struts2のJSON出力はかなり柔軟にカスタマイズできます。

### ✅ 除外プロパティを指定（例えばpasswordなど）
```xml
<result type="json">
  <param name="excludeProperties">users\[\d+\]\.password</param>
</result>
```

### ✅ ルートプロパティのみ返す（`root`指定）
```xml
<result type="json">
  <param name="root">users</param>
</result>
```

結果例（`users`の配列のみをルートとして返す）：

```json
[
  { "id": 1, "username": "alice" },
  { "id": 2, "username": "bob" }
]
```

---

### 🔐 5. セキュリティ上の注意点（REST連携）
**🔸 CORS（クロスオリジン）制御**
他ドメインからアクセスされる場合、レスポンスに以下のヘッダを設定する必要があります：

```java
HttpServletResponse response = ServletActionContext.getResponse();
response.setHeader("Access-Control-Allow-Origin", "*");
```

>※ 実運用では * は避けて、信頼ドメインだけ許可しましょう。

### 🔸 CSRF対策（JSONリクエストでも重要）
- JSON APIでも**CSRFトークン**の検証が必要です。

- POSTリクエストを扱う場合は、セッションやヘッダでトークンを送信・検証する実装が求められます。

- 参考：`TokenInterceptor` の利用や、`X-CSRF-TOKEN` ヘッダのチェックなど。


---

### 🔸 認証連携（APIへのログインチェック）
JSON返却Actionでも、通常の画面遷移と同様にログインセッションの検証が必要です。

Interceptor で `session.get("loginUser") == null` をチェックするなど。

---


### 🧾 おわりに：Struts2 × REST設計も十分可能！

Struts2は古典的なMVCフレームワークではありますが、`json-defaul`t パッケージと `Result設定`を使うことで、`REST風のJSON API`構築も可能です。

- フロントエンドとの非同期連携

- スマホアプリ向けのデータ提供

- JavaScriptによる動的UI制御（SPA）

といった現代のニーズにも柔軟に対応できます。


---

### ✅ まとめ：Struts2 JSON連携のチェックリスト

| 項目       | 内容                            |
| -------- | ----------------------------- |
| ライブラリ    | `struts2-json-plugin.jar` を追加 |
| パッケージ    | `extends="json-default"` にする  |
| Result設定 | `<result type="json" />`      |
| DTOクラス   | Getterを備えたプロパティ設計             |
| セキュリティ   | CORS, CSRF, 認証の確認             |




---

### 🧭 関連記事（Vol.11.xxxシリーズ）
| 連番           | タイトル                                                  | 内容分類              |
| ------------ | ----------------------------------------------------- | ----------------- |
| [Vol.11.0](https://qiita.com/juehara-crypto/items/a0cc66893cb499a6e23a)     | Struts2が提供してくれる便利機能まとめ9選                              | 導入＆概要             |
| [Vol.11.1](https://qiita.com/juehara-crypto/items/0a584da537059dd43a7c)     | 自動注入とステートレスActionの仕組み                                 | フレームワーク内部理解       |
| [Vol.11.2](https://qiita.com/juehara-crypto/items/c69962826bb29639c351) | **UX改善に効く！アクション層設計と入力制御の極意（プロローグ）**                   | UX設計・アクション層総論     |
| [Vol.11.2.1](https://qiita.com/juehara-crypto/items/9ca115073e6f928c7f71)   | 【実践編】Struts2アクション層の役割と設計パターン（Command型 / UIアクション分離など）  | アクション設計パターン       |
| [Vol.11.2.2](https://qiita.com/juehara-crypto/items/88b7634a64b1ad564668)   | 【UX重視】戻るボタン・キャンセル処理の設計手法と「戻り先管理」のスマート実装               | 戻り先制御とUX設計        |
| [Vol.11.2.3](https://qiita.com/juehara-crypto/items/c5165c92a4366fd1962b)   | 【設計ノウハウ】多画面遷移時のパラメータ受け渡し・保持戦略（セッション vs hidden vs URL） | パラメータ多重管理         |
| [Vol.11.2.4](https://qiita.com/juehara-crypto/items/06162659215cca86de28)   | 【実践ガイド】ユーザー操作を考慮したアクション遷移設計（リダイレクト vs フォワードの使い分け）     | UX遷移設計／Result制御   |
| [Vol.11.2.5](https://qiita.com/juehara-crypto/items/b538b50eaa9c263a31bb)   | 【トラブル防止】アクション層の共通処理とメンテナブルなBaseAction設計               | アクション共通化／保守性      |
| [Vol.11.3](https://qiita.com/juehara-crypto/items/913de7c942a9242201e8)     | Struts2の defaultStack とは？Interceptorの中身を詳しく追ってみる      | Interceptor       |
| [Vol.11.3.2](https://qiita.com/juehara-crypto/items/ede8d3c2a9b147f6161e)     | 🔧 Vol.11.3.2 独自Interceptorの作り方と使い所 _Struts2のカスタマイズを“実践で使えるレベル”に一歩進めよう_     | Interceptor       |
| [Vol.11.4](https://qiita.com/juehara-crypto/items/253142d13fe5f604610f)     | 入門者のための「パラメータ自動バインディング」完全理解ガイド                        | 自動バインディング         |
| [Vol.Vol.11.4.1](https://qiita.com/juehara-crypto/items/4fd8ed2a8be317f6e1bd)     | 入門者のための自動バインディング実践パターン集                        | 自動バインディング         |
| [Vol.11.5](https://qiita.com/juehara-crypto/items/6ef7a87a54163d81a9ba)     | Struts2の構成理解が“実務レベル”へと進化する決定版         | 設定ファイル構造          |
| [Vol.11.5.1](https://qiita.com/juehara-crypto/items/df407b24101e92a02eab)     | Struts2の“画面遷移の全体像”を理解するためのマイルストーン記事         | 設定ファイル構造          |
| [Vol.11.6](https://qiita.com/juehara-crypto/items/bfbdc2203acac7ba3f19)     | ActionSupport の便利メソッドと国際化対応                           | ユーティリティ / i18n    |
| [Vol.11.7](https://qiita.com/juehara-crypto/items/ed8f0977c23ee8c8b959)     | validate() / input 戦略とUX設計                            | 開発スタイルの違い    
| [Vol.11.8](https://qiita.com/juehara-crypto/items/bb2b23612c22fa9bf50b)     | アノテーションベースの設定 vs XML定義の比較                             | 開発スタイルの違い         |
| [Vol.11.9](https://qiita.com/juehara-crypto/items/6163ad6c9308cc8dda6d)     | バリデーション完全解説（XML / アノテーション）                            | バリデーション（※Vol.8補完） |
| [Vol.11.10](https://qiita.com/juehara-crypto/items/207cb3d7f0a889c54df9)     | Struts2の「OGNL」ってなに？しくみと使い方をやさしく解説                     | 式言語OGNL解説         |
| [Vol.11.11](https://qiita.com/juehara-crypto/items/c313ea56f97984756c05)    | ModelDriven インターフェースの使いどころと注意点                        | Model駆動開発         |
| [Vol.11.12](https://qiita.com/juehara-crypto/items/de7a17d53e53d6466f17)    | SessionAware と RequestAware でセッション/リクエスト管理            | セッション管理           |
| [Vol.11.13](https://qiita.com/juehara-crypto/items/539bd5bae75a8e154753)    | Resultタイプ完全解説（dispatcher / redirect / stream など）      | 遷移パターン理解          |
| [Vol.11.14](https://qiita.com/juehara-crypto/items/142d9aa2c623c5eb70bc)    | Vol.11.14 ValueStackの中身を理解する – 画面とActionの橋渡し役                 | Action            |
| [Vol.11.15](https://qiita.com/juehara-crypto/items/84f024816d0cf2212cb6)    | Interceptorチェーンを自作してみよう（ログ / 認証フィルタ）                 | Interceptor            |
| [Vol.11.16](https://qiita.com/juehara-crypto/items/ff3ad75f9ee45fcd0f8f)    | エラー処理と例外ハンドリングの実践パターン                                 | ハンドリング設計          |
| [Vol.11.17](https://qiita.com/juehara-crypto/items/0d8d5101ff39b34b4704)    | Struts2でファイルアップロード機能を実装する方法                           | 実装系Tips           |
| [Vol.11.18](https://qiita.com/juehara-crypto/items/d93c8d9cee719997c068)    | 非同期通信（AJAX）とStruts2の連携方法                              | フロント連携編           |
| [Vol.11.19](https://qiita.com/juehara-crypto/items/dd6cf06d3100c9204d1f)    | セキュリティ対策（CSRF, XSS, パラメータ偽装）                              | セキュリティ対策           |
| [Vol.11.20](https://qiita.com/juehara-crypto/items/9442d9f4705f1c6c4da1)    | 複数フォームを安全に扱う！セッション管理と動的フォームの考え方                              | セッション管理           |
| [Vol.11.22](https://qiita.com/juehara-crypto/items/424155ee0e567a36b9a1)    | 本番環境構成とセキュリティ設計（Apache+Tomcat+Struts2連携）                             | 外部公開           |

---