[Java] 40. Web Spring frameworkでControllerを扱う方法


Study / Java    作成日付 : 2019/10/03 20:02:06   修正日付 : 2021/06/03 17:09:28

こんにちは。明月です。


この投稿はWeb Spring frameworkでControllerを扱う方法に関する説明です。


以前の投稿でウェブサービスをSpring frameworkを利用して構築する方法に関して説明しました。

link - [Java] 39. Spring Web Frameworkを利用してウェブサービスプロジェクトを作成する方法


Controllerとはクライアント(Browser)から要請があればホストを取り除いたアドレス値をパーシングして当該なメソッドを呼び出す機能です。

このアドレス値でパーシングしてメソッドを呼び出す時に一番やりやすい方法は各のページで呼び出す方法をあり、よく使いますが、その以外には複数ページや正規表現の方法で呼び出す方法もあります。または呼び出すヘッダーの情報やパラメータの値によって呼び出す方法もあります。

@RequestMapping

@RequestMappingとはウェブから要請されたらアドレス値によって探索が可能にするアトリビュートです。このアトリビュートはクラスとメソッドに使えます。

package controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;

// コントロールを設定するアトリビュート
@Controller
// クラスにはRequestMappingを省略が可能だ。省略すればアドレスからホスト名を取り除いたルートを指す。
@RequestMapping(value = "/home")
public class Helloworld {
  // クラスから分けた下記のアドレスを探索する。
  // この例には/home/index.htmlを指す。
  @RequestMapping(value = "index.html")
  public String index(ModelMap modelmap, HttpSession session, HttpServletRequest req, HttpServletResponse res) {
    // viewに渡すデータ
    modelmap.addAttribute("Data", "Helloworld");
    // viewファイル指定
    return "index";
  }
}


上の例をみれば「/home/index.html」を呼び出したらindex関数が実行されたことを確認できます。


RequestMappingは一つのページをマッピングすることではなく、複数のアドレスを一つの関数に呼び出すことができます。

package controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;

// コントロールを設定するアトリビュート
@Controller
// クラスにはRequestMappingを省略が可能だ。省略すればアドレスからホスト名を取り除いたルートを指す。
@RequestMapping(value = "/home")
public class Helloworld {
  // クラスから分けた下記のアドレスを探索する。
  // この例には/home/index.htmlと/home/helloworld.htmlを指す。
  @RequestMapping(value = {"index.html", "helloworld.html"})
  public String index(ModelMap modelmap, HttpSession session, HttpServletRequest req, HttpServletResponse res) {
    // viewに渡すデータ
    modelmap.addAttribute("Data", "Helloworld");
    // viewファイル指定
    return "index";
  }
}


単純にアドレスを指定することより正規表現式によりマッピングすることも可能です。

package controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;

// コントロールを設定するアトリビュート
@Controller
// クラスにはRequestMappingを省略が可能だ。省略すればアドレスからホスト名を取り除いたルートを指す。
@RequestMapping(value = "/home")
public class Helloworld {
  // クラスから分けた下記のアドレスを探索する。
  // この例には/home/(iあるいはhに始まる単語).htmlを指す。
  @RequestMapping(value = {"i*.html", "h*.html"})
  public String index(ModelMap modelmap, HttpSession session, HttpServletRequest req, HttpServletResponse res) {
    // viewに渡すデータ
    modelmap.addAttribute("Data", "Helloworld");
    // viewファイル指定
    return "index";
  }
}


呼び出すメソッドタイプによりマッピングすることもできます。

package controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;

// コントロールを設定するアトリビュート
@Controller
// クラスにはRequestMappingを省略が可能だ。省略すればアドレスからホスト名を取り除いたルートを指す。
@RequestMapping(value = "/home")
public class Helloworld {
  // クラスから分けた下記のアドレスを探索する。
  // この例には/home/(iあるいはhに始まる単語).htmlを指す。
  // メソッドタイプがGET方式だけ呼び出す。もしPOST方式なら他の関数を呼び出す。(指定されてない場合はマッピング関数がないというエラーが発生)
  @RequestMapping(value = {"i*.html", "h*.html"}, method = RequestMethod.GET)
  public String index(ModelMap modelmap, HttpSession session, HttpServletRequest req, HttpServletResponse res) {
    // viewに渡すデータ
    modelmap.addAttribute("Data", "Helloworld");
    // viewファイル指定
    return "index";
  }
}


その以外にもパラメータ、ヘッダーの値により関数探索が可能です。


仕様により区分して細かく使うことができますが、普通はそんなに細かく分けて設定しないです。細かく使くなったら逆に可読性が悪くなるし、プログラムだけ複雑になります。

私もvalueとmethodの以外は使ったことがありません。

ModelMap

Springでマッピング関数を作成する時にパラメータがなくても構いません。マッピングは@RequestMappingで区分されるからです。

でも、ブラウザにパラメータ値を受け取る時や様々なセッション情報、要請値(Request)、応答値(Response)を使う時があります。

そのため、基本的にModelMap modelmap, HttpSession session, HttpServletRequest req, HttpServletResponse resを使います。

HttpSessionはセッション情報、HttpServletRequestは要請値、HttpServletResponseは応答値があります。この部分はServletと同じです。


ここでModelMapの場合はviewにデータを渡す時に使います。リターンのStringタイプのデータはviewのファイル名をマッピングするしreqやresの値では値を渡すことができないからです。

package controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;

// コントロールを設定するアトリビュート
@Controller
// クラスにはRequestMappingを省略が可能だ。省略すればアドレスからホスト名を取り除いたルートを指す。
@RequestMapping(value = "/home")
public class Helloworld {
  // クラスから分けた下記のアドレスを探索する。
  // この例には/home/index.htmlを指す。
  @RequestMapping(value = "index.html")
  public String index(ModelMap modelmap, HttpSession session, HttpServletRequest req, HttpServletResponse res) {
    // viewに渡すデータ
    modelmap.addAttribute("Data", "Helloworld");
    // viewファイル指定
    return "index";
  }
}
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
  </head>
  <body>
    <!-- ModelMapから受け取ったデータをJSTL言語で表示する。 -->
    ${Data}
  </body>
</html>


上の例はindex関数でリターンの値をindexに設定したのでview/index.jspをマッピングします。

index.jspファイルの中でJSTL言語にData値を表示することになっています。index関数の中でModelMapを利用してData値を設定します。

@RequestParam

我々がクライアント(Browser)からデータを受け取る時があります。

GET方式ならurlアドレスから?マークに区分して設定するQueryString値により伝えるし、POST方式はform値をsubmitしてプロトコールヘッダーに値を渡す方法があります。

Springでデータを受け取る方法ではパラメータに@RequestParamを利用してパラメータを取得することができます。

package controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

// コントロールを設定するアトリビュート
@Controller
public class Helloworld {
  // この例には/home/index.htmlを指す。
  @RequestMapping(value = "index.html")
  // パラメータでdataの値を取得する。
  public String index(@RequestParam String data, ModelMap modelmap, HttpSession session, HttpServletRequest req, HttpServletResponse res) {
    // パラメータより受け取ったデータをModelMapに設定する。
    modelmap.addAttribute("Data", data);
    // viewファイル指定
    return "index";
  }
}


でも、私はこの方法をお勧めしていません。なぜならdataの値がnullになるとエラーになるからです。


Servletに使うHttpServletRequest変数を通ってgetParameter関数を利用したらパラメータがnullでも関数が呼び出せます。その後で別に関数の中でnull処理したら良いです。

でも、クライアント(Browser)から渡すデータ値が多い場合、getParameter関数ですべて処理することはソースのステップが多くなると思います。

それで私の場合はModelAttributeのアトリビュートを利用してクラスタイプでデータを受け取ります。

package controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

// コントロールを設定するアトリビュート
@Controller
public class Helloworld {
  // この例には/home/index.htmlを指す。
  @RequestMapping(value = "index.html")
  // Nodeクラスにパラメータがdataの場合はdata変数に格納、data1の場合はdata1変数に格納する。
  public String index(@ModelAttribute Node node, ModelMap modelmap, HttpSession session, HttpServletRequest req, HttpServletResponse res) {
    // パラメータより受け取ったデータをModelMapに設定する。
    modelmap.addAttribute("Data", data);
    // viewファイル指定
    return "index";
  }
}
// パラメータを受け取るためのBeanクラス
class Node {
  // パラメータのdataを受け取る。
  private String data;
  // パラメータのdata1を受け取る。
  private String data1;
  // data変数のgetter
  public String getData() {
    return data;
  }
  // data変数のsetter
  public void setData(String data) {
    this.data = data;
  }
  // data1変数のgetter
  public String getData1() {
    return data1;
  }
  // data1変数のsetter
  public void setData1(String data1) {
    this.data1 = data1;
  }
}


上の処理はdataのパラメータの場合はデータ値があるのでそのまま表示されましたが、data1のパラメータの場合は設定してないのでnullが表示されますね。

ここまでクライアント(Browser)から呼び出したらControllerから処理してviewをパーシングして最終結果を応答します。

でも、ウェブサービスの中でウェブページを要請すると当然ページをリターンするが、ajaxの場合はどのように処理するでしょう?

ajaxはウェブページが必要なことではなく、Controllerで処理した値をjsonやデータ構造に変換しなければならないです。

次の投稿ではSpring frameworkでajaxを処理する方法に関して説明します。


ここまでWeb Spring frameworkでControllerを扱う方法に関する説明でした。


ご不明なところや間違いところがあればコメントしてください。

Study / Java」の他投稿
最新投稿