Struts2 入門　フォームを使った足し算・引き算アプリの作り方

#前提
JSPの入門を勉強済み。
Struts2を動かす環境構築済み。
Struts2でHelloWorldレベルのコードを写生したことがある。
#プロジェクトツリー構造
この写真の通り
<img width="294" alt="スクリーンショット 2020-01-12 0.30.36.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201982/078472dc-ae42-e45a-838f-372e04291d3a.png">


#web.xml
丸ごとコピーでいい。
welcome-file-listタグの中はindexページの優先順位を書いているだけ
filterタグの中はどのページにstruts2フレームワークを適用するかを指定している。
この場合 /* だから全部のディレクトリ。

```java

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>Struts2Calc</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>

  <filter>
  	<filter-name>struts2</filter-name>
  	<filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class>
  </filter>

  <filter-mapping>
  	<filter-name>struts2</filter-name>
  	<url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>
```

#struts.xml
ルーティングを書くファイル。
packageタグはこのタグ自体の拡張に使用されるらしい。
この場合、struts-defaultというpackageタグが他に定義されていてそれを継承します。ということのようです。
今回はこれ以上継承しませんが、他のpackageタグから継承したくなった時にはこのname属性の値をキーにして継承するようです。
actionタグの中、
name=このactionの識別子になる。jsp内の\<s:form action="値">で指定した値と一致させることで呼べる。
class=起動するJavaのActionクラス。今回はcontrollerパッケージのCalcAction.javaを指定している。
method=上のJavaクラス内のどのメソッドを動かすかを指定。Actionクラス側でimplemetnsするクラスに
executeの関数名でのoverrideを求められる場合があるので、特に理由がなければexecuteを指定しておくと良さそう。

resultタグの中
name=上記のクラスのexecute関数（名前変えてたらそれ）で、returnされた名前
index.jsp=name属性に対応する結果がリターンされた時の遷移先を指定。今回はindex.jspだが実際に合わせて変える。

```java

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
	"-//Apache Software Foundation//DTD Struts Configration 2.0//EN"
	"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
	<package name="default" extends="struts-default">
		<action name="calc" class="controller.CalcAction" method="execute">
			<result name="success">/index.jsp</result>
		</action>
	</package>
</struts>
```

#CalcFormBean

jsp内のformタグ内で使用するtextboxの値を格納するためのモデルクラス。
この内容はActionクラスに直に書いても動きます。が、それだとこういう練習アプリならともかく、実戦で大きなアプリを書く時に
Actionクラスがとてつもなく肥大化するので切り離すべきでしょう。
POJOクラスだけど、Serializableをimplementsしておかないとsessionとかに保存できないので、
基本的につけといた方がいいでしょう。

```java
package bean;

import java.io.Serializable;

public class CalcFormBean implements Serializable {

	private String text1;
	private String text2;

	public String getText1() {
		return text1;
	}
	public void setText1(String text1) {
		this.text1 = text1;
	}
	public String getText2() {
		return text2;
	}
	public void setText2(String text2) {
		this.text2 = text2;
	}

	public String getSum() {
		int x = Integer.parseInt(this.text1);
		int y = Integer.parseInt(this.text2);
		Integer sum = x + y;
		return sum.toString();
	}
	public String getSubtract() {
		int x = Integer.parseInt(this.text1);
		int y = Integer.parseInt(this.text2);
		Integer sum = x - y;
		return sum.toString();
	}
}

```
#CalcAction

private CalcFormBean bean;
で上記のフォームビーンを定義しています。
newがどこにもありませんが、これだけでインスタンス化されています。
getter/setterの命名規則でインスタンスが生まれるので、カプセル化せずにpublic変数に
するとかではダメです。

String execute()は上記のstruts.xmlで指定したメソッド名。
今回ActionSupportというのをextendsしており、この場合execute()をoverrideすることになります。
実はこのアプリでは何もextendsしなくても動きます。
つけている入門ページが多いのでなんとなく習ってつけてみてるだけです。
まだよくわかっていないので。

```java

package controller;

import com.opensymphony.xwork2.ActionSupport;
import bean.CalcFormBean;
public class CalcAction extends ActionSupport{

	private CalcFormBean bean;

	public String execute() {
		return "success";
	}

	public CalcFormBean getBean() {
		return bean;
	}

	public void setBean(CalcFormBean bean) {
		this.bean = bean;
	}

}
```

#index.jsp

今回はこのページしか使いません。
submitした時の画面遷移先をこのページにしているため、サーバで計算した後ここに戻ってきます。
\<%@ taglib prefix="s" uri="/struts-tags"%>でstrutsタグをロード。
\<s:textfield name="bean.text1">でActionクラスに定義したsetterを呼び出しています。
setBean()で書き込む先のCalcFormBean.javaにはtext1とtext2が定義されているのでjavaSEのような書き方で
セットできます。

\<s:property value="bean.text1">はその逆でプロパティから値を取り出して表示します。

\<s:if test="bean.subtract<0">は条件がtrueの時だけifタグの中を表示します。
test=""の中が条件式になっていて、bean.subtract（ここでは引き算の結果が格納されている)
が0未満の場合に赤字で「マイナスです。」を表示させています。

```jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Struts入門</title>
</head>
<body>
	<h1>計算機</h1>
	<s:form action="calc">
		<s:textfield name="bean.text1" label="値1"/><br>
		<s:textfield name="bean.text2" label="値2"/>
		<s:submit value="計算実行"/>
	</s:form>
	<s:property value="bean.text1"/>+<s:property value="bean.text2"/>=<s:property value="bean.sum"/> <br>
	<s:property value="bean.text1"/>-<s:property value="bean.text2"/>=<s:property value="bean.subtract"/>
	<s:if test="bean.subtract<0">
		<p style="color:red">マイナスです。</p>
	</s:if>
</body>
</html>
```

#完成写真
Eclipseから起動して、値を入力して計算実行ボタンを押してこうなったら成功。
![スクリーンショット 2020-01-12 1.22.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201982/5ab4f4dd-5a66-d4a3-e7cb-522bee581222.png)