アラカン"BOKU"のITな日常

文系システムエンジニアの”BOKU”が勉強したこと、経験したこと、日々思うことを書いてます。

AMP対応ページと非AMPページとを行き来する。URLパラメータの受け取り方も含めて。 SpringBoot/thymeleaf/STS

前回、Formを使う画面をAMP対応するのは、当面、面倒だな・・と考えて、非AMPページとAMPページが混在する形にならざるをえないと書きました。

(個人的見解ですけどね)

arakan-pgm-ai.hatenablog.com

 

で・・まあ、できて当たり前ではありますけど、念の為に、非AMPページと、AMPページの混在での動きを確認しようと思います。

 

まあ、凝ったことをするのは・・アレ・・なので、以下のようなことをします。

  • ① 非AMPページ:SELECTで曲名を選んで、実行ボタンを押す。
  • ② AMPページ:選択されたVideo-idの動画を表示する。
  • ③ AMPページ:リンクをクリックして、非AMPページへ遷移する。
  • ④ 非AMPページ:表示していた曲をSELECTEDとして表示する

 

こういうのは、よくありがちな行き来の例になると思いますので。

 

非AMPページ(曲を選択する画面)を用意します

 

こんな感じの画面です。

f:id:arakan_no_boku:20180312213916j:plain

 

「Qkr60BoW4q0」と表示しているのは、選択中の曲のVIDEO-IDです。

 

最初にソースを表示して、後で解説します。

 

最初にコントローラクラスのこの画面を表示させる部分です。

	@RequestMapping(value = "/inpg01", method = RequestMethod.GET)
	public String index(SongInputForm form, Model model,@RequestParam(name ="videoid", required = false) String videoid) {
		model.addAttribute("songInputForm", form);
	    model.addAttribute("selectItems",getSelectedItems());
	    if(form.getSelectedItem()== null){
		    form.setSelectedItem("Qkr60BoW4q0");
	    }
	    if(videoid != null){
	    	form.setSelectedItem(videoid);
	    }
	    return "inpg01";
	}
	
	private Map<String,String> getSelectedItems(){
	     Map<String, String> selectMap = new LinkedHashMap<String, String>();
	     selectMap.put("Qkr60BoW4q0", "TaRo&JiRo /silent siren");
	     selectMap.put("HIEdkeWZwQM", "superfly / ビリリエモーション");
	     selectMap.put("uM_z5PXRE3E", "ローリング・ストーンズ/ジャンピンジャックフラッシュ");
	     selectMap.put("WK0z87WrhGo", "ニュース/パワー・オブ・ラブ");
	     return selectMap;
	 }   

 

上記の「 getSelectedItems()」メソッドで今回は、簡易にSELECTの選択肢をセットしています。

 

KEYがVIDEOーID、VALUEが曲名になるMapを生成して、Modelにセットすることで、HTML側から参照できるようにしてます。

 

あと、ポイントになるのが、index()メソッドの引数に追加している「@RequestParam(name ="videoid", required = false) String videoid」です。

 

こうすることで、URLパラメータで「?videoid=XXXXXXXX」のようにして値を受け取ることができます。

 

required=falseとしているのは、URLパラメータを必須にしないという意味です。

 

こうしておかないと、渡すべき値がない時でも、URLパラメータをつけないとエラーになるので、必ずつけるようにしてます。

 

続けて、HTMLです。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Sample App</title>
  <link href="../static/css/styles.csss" th:href="@{/css/styles.css}" rel="stylesheet"/>
</head>
<body>
<div class="box">
    <h1>Video-id</h1>
   <form role="form" id="SongInputForm" action="/outpg01" th:action="@{/outpg01}" th:object="${songInputForm}" method="post">
        <p>Please select Video-Id</p>
        <p th:text="*{selectedItem}"></p>
        <select id="singleSelect" name="selectedItem">
            <option value="">---</option>
            <option th:each="item : ${selectItems}" th:value="${item.key}" th:text="${item.value}" th:selected="${item.key} == *{selectedItem}">singleSelect</option>
        </select>
        <button type="submit">実行</button>
   </form>
</div>
</body>
</html>

 

まあ、普通のthymeleafのHTMLです。

 

さきほど、SELECTの選択肢をセットした SelectedItemの値を「th:each="item : ${selectItems}"」でループして表示しています。

 

CSSは、staticフォルダのcssフォルダにおいて参照してます。

 

こんな程度しか書いてませんが。

@CHARSET "UTF-8";

html {
    font-size:16px
}

body {
    font-family: 'メイリオ','Hiragino Kaku Gothic Pro',sans-serif;
    background-color:white;
}

.box{
    wide:100%;
    text-align:center;
}    

p{
	margin-left:1em;
	margin-right:auto;
	margin-top:0.5em;
	margin-bottom:0.5em;
}

 

そしてFormクラスです。

 

画面で選択された値(KEYの方)を保持して、画面間で引き継ぐ変数を定義します。

public class SongInputForm implements Serializable {
	
	private static final long serialVersionUID = 109099L;
	
	private String selectedItem;

	public String getSelectedItem() {
		return selectedItem;
	}

	public void setSelectedItem(String selectedItem) {
		this.selectedItem = selectedItem;
	}
	
}

 

 出力側(AMP対応ページ)を用意する。

 

まず、実行ボタンが押された時に、処理を行うメソッドをコントローラクラスに追加します。

	@RequestMapping(value = "/outpg01", method = RequestMethod.POST)
	public String confirm(@Validated @ModelAttribute SongInputForm form, BindingResult result, Model model) {
	if (result.hasErrors()) {
	        return index(form, model,null);
	} 
        String vid = form.getSelectedItem();
        model.addAttribute("returnUrl","http://localhost:8080/inpg01?videoid=" + vid);
        model.addAttribute("amp1","<amp-youtube width=\"480\" height=\"270\" layout=\"responsive\"  data-videoid=\"" + vid + "\"  autoplay>  </amp-youtube>");
        return "outpg01";
	} 

 

入力画面の<form>のactionで「/outpg01」と指定されているのを受けて、「confirm」メソッドが実行されるというお約束にそってます。

 

選択されたVIDEO-IDは、Formクラスを経由して、「 String vid = form.getSelectedItem();」でうけとって、セットします。

 

あとはそれを使って表示するだけなので、前々回と変わりません。

arakan-pgm-ai.hatenablog.com

 

注意が必要なのは、入力画面に戻るためのリンクを組み立てている以下の部分です。

model.addAttribute("returnUrl","http://localhost:8080/inpg01?videoid=" + vid);

 

URLパラメータで選択されたVIDEO-IDを渡す形にURLを作ってます。

 

単純にリンクで画面遷移しても、Formの内容は引き継がれませんので、こうしないと情報を渡せないからです。

 

<form>を使って引き継ぐ方法は、AMP対応ページでは使えるけど使わない・・と前回決めたのでね。

 

最後に、これをうけるHTMLです。

<!doctype html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title>Sample App</title>
  <script async src="https://cdn.ampproject.org/v0.js"></script>
  <script async custom-element="amp-youtube" src="https://cdn.ampproject.org/v0/amp-youtube-0.1.js"></script>
  <link rel="canonical" href="http://localhost:8080/amp01">
  <meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
  <style amp-custom>
    .content{
        wide:100%;
        text-align:center;
    }    
    .content_fix{
        margin-left:2em;
        margin-right:2em;
     }
    
   h1 {
        text-align:center;
        color: red;
    }
    
    p{
        margin-left:2em;
        margin-right:2em;
        margin-top:0.5em;
        margin-bottom:0.5em;
    }
    img{
        width:auto;
        height:auto;
    }

  </style>
  <style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style><noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript>
</head>
<body>  
    <div class="content" th:object="${songInputForm}">
        <h1>AMPで動画を表示してみる</h1>
        <a th:href="${returnUrl}" target="_blank">動画選択画面へ</a>
        <div class="content_fix" th:utext="${amp1}"></div>
    </div>
</body>
</html>

 

ほぼ、前々回のAMPページサンプルと変わりません。

 

注意が必要なのは、以下の部分です。

<a th:href="${returnUrl}" target="_blank">動画選択画面へ</a>

 

returnUrlで組み立てたURLを表示するわけですが、「target="_blank"」を指定しています。

 

実は、AMP対応ページでの「a」タグのtarget属性は_blank以外は駄目・・らしいので、注意が必要です。

 

さて実行してみよう。

 

tomcatを8080ポートで動かしているので、「http:localhost:8080/inpg01」でアクセス。

 

それで、「ビリリエモーション」を選択して、実行ボタンを押します。

f:id:arakan_no_boku:20180312225637j:plain

 

そしたら、AMPページでビリリエモーションが再生。

f:id:arakan_no_boku:20180312225738j:plain

 

その状態で、動画選択画面へをクリックして画面遷移します。

f:id:arakan_no_boku:20180312225834j:plain

 

いちおう、ビリリエモーションのIDが引き継がれて、初期選択状態になってます。

 

まあ、こんなもんでしょうね。

 

まとめ

 

4回ほど、AMP対応ページで遊んでみました。

 

確かに表示の速さは体感できるほど改善されるので、非常によいなと思う半面、速度を実現するための様々な制限があることもわかりました。

 

まあ、万能な技術なんてありませんから・・当然なんですけど。

 

でも、Springbootとthymeleafの組み合わせなら、そのへんのメリット・デメリットを意識して設計すれば、非AMPとAMPのページを適材適所配置することも可能かもしれないな・・というのが、現時点での個人的見解です。

 

また、ちょこちょこ勉強していきたいですね。

 

どんどん、進化している感もあるので。 

 

f:id:arakan_no_boku:20170725215801j:plain