48日目(Spring Framework6)
formタグ
使用時にJSPに以下を記述
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
★フォームのname属性=フィールドになるようにクラスを定義
アクセッサ、デフォルトコンストラクタも必要
(基本的にデフォルトコンストラクタは暗黙的に追加してくれるが、引数ありのコンストラクタを定義した場合は明示的に用意する必要がある。このformタグに限らず)
使ってみる
入力欄4つのcontact.jspを作成
- 氏名
- アドレス
- 年齢
- 問い合わせ内容(必須)
Controllerクラス
Controller①
Getリクエスト時(domainオブジェクト生成)
@GetMapping("/contact")
public String contactGet(Model model) {
model.addAttribute("contact", new Contact());
return "contact";
}
contact.jsp
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<form:form action="" method="post" modelAttribute="contact">
※modelAttribute属性の値と@ModelAttribute("contact") が対応
<p>氏名: <form:input path="name" /></p>
<p>メール: <form:input path="mail" /></p>
<p>年齢: <form:input path="age" /></p>
<p>お問い合わせ: <form:textarea path="message" /></p>
<input type="submit" />
</form:form>
この3つが初出
- <form:form>…<form>
- <form:input>…input type="text"
- <form:textarea>…input type="textarea"
Controller②
@PostMapping("/contact")
public String contactPost(
@ModelAttribute("contact") Contact contact,
Model model) {
// バリデーション
if(contact.getMessage().isEmpty()) {
// 入力に不備がある
model.addAttribute("error", "内容は必須です");
return "contact";
} else {
return "contactDone";
}
}
ほかのform部品
- <form:password />
- <form:textarea />
- <form:radiobutton />
- <form:checkbox />
- <form:select>
<form:password />、<form:textarea />はさらっと触れるだけ
<form:radiobutton />
<form:checkbox />
<form:select>
これらを実際に使って学習
アンケート調査
入力項目
※selectが少し難しいので一旦後回し
Survey.java
フィールド、アクセッサ用意
SurveyController.java
●@GetMappingでは、addAttribute()メソッド第一引数JSPに渡す値、第二引数で受渡用のドメインオブジェクトの生成を記述
●@PostMappingではSurveyオブジェクトを受け取る
(@ModelAttribute("survey") Survey survey)
個人情報に同意しているかどうかのみ入力チェックを行い、同意ありなら完了ページに遷移、なしならフォーム画面に戻す
survey.jsp
年代選択
<form:radiobutton value="20歳未満" path="ageGroup" />20歳未満
<form:radiobutton value="20歳以上" path="ageGroup" checked="checked" />20歳以上
興味の選択
<form:checkbox path="interest" value="文学"/>文学
個人情報の扱いの同意
<form:checkbox path="privacy" />同意する
※boolean型でパラメータを受け取るようにすればvalue属性は不要
surveyDone.jsp
完了画面
ここまでで一旦動作確認し、地域(Areaをselect)を記述
domain内にAreaクラスを定義
<form:select>では以下の属性がある
- itemValue="1"などの値が入る属性
- itemLavel="アジア"などの名前が入る属性
そのため今回はAreaクラスに以下を記述
Survey.java
以下のフィールドを追記し、アクセッサも用意
private Area area;
ServeyController.java
メソッドを一つ追加
private List<Area> getAreaList(){
List<Area> areaList = new ArrayList<>();
// ※ここで引数ありコンストラクタが役に立つ
areaList.add(new Area(1, "アジア"));
areaList.add(new Area(2, "アフリカ"));
areaList.add(new Area(3, "ヨーロッパ"));
return areaList;
}
@GetMappingのメソッド内に追記
// 選択肢リスト用
List<Area> areaList = getAreaList();
model.addAttribute("areaList", areaList);
Post時も利用可能にするため、↑の記述を@PostMappingにコピペ
※ただし、引数にModel型オブジェクトの記述の追記が必要
survey.jsp
<form:select path="area.id" items="${areaList}" itemLabel="name" itemValue="id" />
SurveyController内でareaListにaddした分が選択肢になっている
今日はここまで。
Springだと、入力不備で元の画面に戻す時に入力値の保持が簡単だったり、メリットが多いのがだんだんわかってきた。
ただまだまだ霧の中を進んでる感が半端ないので、できれば本とか買って授業外でも学習したいところだけどデザインパターンの話とかも普通に出てくるみたいな
なのでデザインパターンをつまみ食いしつつ、授業の内容の理解も深めたい所存
また来週
47日目(Spring Framework5)
SpringMVCの利用方法おさらい
Controllerのさらに深い内容
@RequestMapping()
- value
- method
- params
↑
※methodとparamsは現在あんまり使わないらしい
現在は@GetMapping、@PostMappingとかが使われるのが主流みたい
@RequestMappingはGET,POST両方に対応
分ける場合、
- @GetMapping
- @PostMapping
を使う
Controller用メソッドの引数
など
@GetMapping、@PostMappingを使ってみた例
@GetMapping("/addMember")
public String addMemberGet() {
return "addMember";
}
// method="post"
@PostMapping("/addMember")
public String addMemberPost(
@RequestParam("name") String name,
@RequestParam("age") Integer age,
Model model) {
if(name.isEmpty()) {
model.addAttribute("error","氏名は必須");
return "addMember";
} else {
return "addMemberDone";
}
※@RequestParamの引数("name")・String name(受取る変数名)が一致してたら、
@RequestParam String name
に省略可能(ageも同様)
このname,ageはEL式のparam(暗黙オブジェクト)で使用可能
URIテンプレート変数
※GETメソッドにちょっと似てる?URL末尾の値で表示ページを分ける
@PathVariableアノテーションで値を取得できる
@RequestMapping("/show/{id}")
public String show(
@PathVariable("id") Integer id,
Model model) {
if(id == 1) {
model.addAttribute("name", "りんご");
model.addAttribute("price", 150);
} else if(id == 2) {
model.addAttribute("name", "みかん");
model.addAttribute("price", 300);
} else if(id == 3) {
model.addAttribute("name", "バナナ");
model.addAttribute("price", 100);
} else {
return "redirect:/item/home";
}
return "item/show";
}
↑をJSPで記述して表示
<h1>選択した商品</h1>
<p>商品名:<c:out value="${name}" /></p>
<p>値段:<c:out value="${price}" /></p>
クッキー
- 色を設定するフォームのあるJSP(setColor)
- 設定した色を背景色として表示するJSP(getColor)
- フォームから受け取った色を受け取るController(ColorController)
setColor.jsp
<h1>色を設定する</h1>
<form action="" method="post">
<input type="color" name="color"/>
<input type="submit" value="設定" />
</form>
<p><a href="getColor">戻る</a></p>
getColor.jsp
<body style="background: <c:out value="${color}" />;">
<h1>Get Color</h1>
<p>設定した色:<c:out value="${color}" /></p>
<p><a href="setColor">色を設定する</a></p>
ColorController.java
@PostMapping("/setColor")
public String settingColorPost(
@RequestParam String color,
HttpServletResponse response) {
Cookie c = new Cookie("color", color);
c.setMaxAge(86400 * 3);
response.addCookie(c);
return "redirect:/getColor";
}
@RequestMapping("/getColor")
public String home(
@CookieValue(
value = "color",
defaultValue = "#ffffff") String color,
Model model) {
model.addAttribute("color", color);
return "getColor";
}
↑@CookieValue()の引数内で、色受け取ってればその色、そうじゃなければデフォルト色として白が入る
セッション
簡単なログイン機能を持ったアプリ
(IDのみ認証・taroなら会員ページ、それ以外弾く)
①loginPost()メソッドでsessionに値を格納し、
============================
@PostMapping("/login")
public String loginPost(
@RequestParam String loginId,
HttpSession session) {
if(loginId.equals("taro")) {
// ログインOK
session.setAttribute("loginOK", true);
return "redirect:/memberOnly";
} else {
// ログイン失敗
return "login";
}
}
②memberOnly()メソッドでその値で表示するか否かを判断する
============================
@RequestMapping("/memberOnly")
public String memberOnly(HttpSession session) {
if(session.getAttribute("loginOK") != null) {
//↓キャスト式がなんか注釈になるので[]を()で
if([boolean]session.getAttribute("loginOK")){
return "memberOnly";
}
}
return "redirect:/login";
}
③logout()メソッドでセッション内の値を削除する処理
============================
@RequestMapping("/logout")
public String logout(HttpSession session) {
// 実際にはログアウト処理を記述
session.removeAttribute("loginOK");
return "logout";
}
入力値をドメインオブジェクトで受け取る
①contact.jsp お問い合わせフォーム
②contactDone.jsp 入力内容の表示
③ContactController.java contactPostメソッドの引数にContact型オブジェクト、Model型オブジェクト
④domainパッケージ内にContact.java
①contact.jsp
<c:if test="${not empty error}">
<p style="color: red;"><c:out value="${error}" /></p>
</c:if>
<form action="" method="post">
<p>名前:
<input type="text" name="name" />
</p>
<p>メール:
<input type="text" name="mail" />
</p>
<p>年齢:
<input type="text" name="age" />
</p>
<p>メッセージ:
<textarea name="message" cols="30" rows="10"></textarea>
</p>
<input type="submit" />
</form>
②contactDone.jsp
<p>以下の内容で承りました。</p>
<p>氏名:<c:out value="${contact.name}" /></p>
<p>メール:<c:out value="${contact.mail}" /></p>
<p>年齢:<c:out value="${contact.age}" /></p>
<p>内容:</p>
<pre>
<c:out value="${contact.message}" />
</pre>
③ContactController.java
@PostMapping("/contact")
public String contactPost(
Contact contact,※ドメインオブジェクト
Model model) {
if(contact.getMessage().isEmpty()) {
model.addAttribute("error", "入力に不備があります");
return "contact";
} else {
return "contactDone";
}
}
④Contact.java
contact.jspのフォームのname属性と合わせたフィールド、
それぞれのアクセッサを持ったクラス
今日はここまで。
結構盛りだくさんだった
46日目(Spring Framework4)
午前中は自習
Spring MVC
今までのモデル、ビュー、コントローラの考え方と同じだが、若干作り方が変わる
・これまではスコープを通してJSP・Servlet間でデータのやり取りをしていたが、今後はModelオブジェクトがその役割を担う
・Servletではなく、Javaのファイルがコントローラの役を担う
1つのURLに対して1つのServletが対応していたが、今後はDispatcherServletがURLを受け取って、どのメソッドを実行するか振り分けてくれる
SpringMVCプロジェクトを使う
など、下準備が必要
Controllerクラスを作成
- クラス宣言の前に@Controllerを記述
- メソッド前に@RequestMapping("/sampleUrl")
※sampleUrlというURLリクエストがあったらこのメソッドが呼ばれる
- メソッドの戻り値はString(jspの名前)を指定
引数はいろいろ指定できるが今回はModel型オブジェクト。Modelオブジェクトは、スコープでデータをやり取りするような感覚のメソッドがある(addAttribute()メソッド)
今日進めた内容はここまで。
45日目(Spring Framework3)
Spring JDBC
DAOパターンでの煩雑な記述が簡略化できる
利用方法
Templateクラスを利用する
- JdbcTemplate
- NamedParameterJdbcTemplate
利用の準備
このうちConnector-JとTomcatの設定は以前設定したものを流用
pom.xml
spring-jdbc(JDBC用)
spring-context(BeanFactory用)
spring-web(サーブレット用)
Bean定義ファイル
アノテーションの利用宣言文
<context:annotation-config />
コンポーネントスキャン範囲
<context:component-scan base-package="dao" />
<context:component-scan base-package="controller" />
名前空間jee
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/mydb"/>
<bean class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg ref="dataSource" />
</bean>
<bean class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
<constructor-arg ref="dataSource" />
</bean>
ついでに、動的Webプロジェクトのweb.xmlにも追記(これも必要らしい)
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/beans.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener- class>
</listener>
※ただし動的Webプロジェクトで作業しない場合web.xmlの記述はいらないらしい
Templateクラスのメソッド
- queryForObject() 単体カラムデータの取得
- queryForMap() 1レコード(1行分)の取得
- queryForList() 複数レコード(複数行)の取得
※基本は共通
以降は、以前作成したDAOのパターンの書き換えを行う。
- BeanPropertyRowMapper
- BeanPropertySqlParameterSource
の自動変換が非常に楽…なので、データベースとデータのやり取りを行うクラスのフィールド名・データベースのカラム名を合わせることの重要性を再確認。
今日はここまで。
週明けということと、土曜日に高尾山に登ったり日曜にハイカーボデイを設けたりで疲れが出てた一日。
しっかり復習しないと。
44日目(Spring Framework2)
BeanFactoryの復習
昨日はlibフォルダ内にライブラリを追加したけど、今日はMavenを利用
Eclipseで新規>Springレガシープロジェクト>Simple Javaを選択して完了
(これは今だけで、今後はSpring MVC Projectとか選ぶことになるらしい)
プロジェクトフォルダができたらその上で右クリック>構成>Mavenプロジェクトに変換
MavenPOMウィンドウが開くが、特に変更しないで完了
pom.xmlが作成され、そこで読み込みたいライブラリを指定する
- グループid
- アーティファクトid
- バージョン
を、
依存関係タブで入れるか、
Mavenリポジトリのサイトで使いたいライブラリのコードをpom.xmlにコピペするか
↑のどっちかの方法でMaven管理が可能
Spring AOP
(言葉の意味はあんまり気にしない)
ある機能だけを分離して、つけ外ししやすくする技術らしい
(≠フィルター:フィルターはリクエストとレスポンスの際に間に入るだけ)
メリット
- メソッドから処理を分離できる
- 処理の後付けや取り外しができる
(クラスファイルを変更しなくていいので、必要な記述の削除などのミスを防ぎつつ機能追加ができるらしい)
- ログ処理
- トランザクション処理
- 認証チェック
- 例外処理
とかで使えるとのこと
がある
AOP用語
Advice:分離した共通の処理
Join Point:Adviceを入れるタイミング
参考:
ざっくりとSpringで使うAOPの解釈をする
https://qiita.com/ughirose/items/a7c66782f93cd1ae0d68
Spring AOP利用方法
Bean定義ファイルにAOP関係の記述を追加
Aspect用のクラスを作成
@Before("execution(* *(..))")とか@After("execution(void someMethod(..))")みたいな
※@Before()の()内のことをPointcutと呼ぶ
あんまり呑み込めなかった部分
・AdviceのメソッドにはJoinPoint型のオブジェクトを引数に指定できる
・Around AdviceではProceedingJoinPoint型のオブジェクトを引数に指定して、proceedメソッドを呼ばないといけない
※ここがFilterのchain.doFilterっぽい?と思った
今日はここまで。
フレームワークの恩恵はまだ先…
とりあえずつっかえた部分を噛み砕く
また来週
43日目(Spring Framework1)
ここまでの学習で簡単なプログラムは組めるような知識は入ってる
ただ、そのプログラム作成を簡略化できるのがフレームワーク
フレームワークを利用すると
- 共同で開発を行う場合などのルールが明確にしやすい
- 工数削減とかのメリット
※ただし習得コストはある
利用にはライブラリを取り込む必要がある
(EcripseではMavenで管理ができる)
BeanFactory
オブジェクト生成・初期化をSpring側で担当してくれる
メリット
- クラス間の依存関係を切る
- ソフトウェアの部品化
-部品単位の開発、テスト、変更がしやすい
※前にやったFactoryパターンでは、オブジェクト生成をFactoryクラスに依頼していたが、その依頼すら不要になる
BeanFactoryを使うためにはその定義をする必要がある
①XMLを用意
-beanタグ
-@Component
-@Autowired
③アノテーションのみ
※訓練では①、②の方法で定義を行う
XMLでオブジェクト生成を定義
<beans>タグ内で長い定型文
その中で<bean>タグを用意する
<bean id="sample" class="com.example.Sample"></bean>
※クラスの指定はパッケージまで含む
生成したオブジェクトをgetBean()メソッドで利用
(ここまでは全然便利ではない。かえって手間が…(笑))
・生成・初期化を同時に行う
<bean id="sample" class="com.example.Sample">
<property name="name" value="田中太郎" />
<property name="age" value="25" />
</bean>
name="name"はsetNameに相当。ageも同様
・引数付きコンストラクタの初期化
<bean id="sample" class="com.example.Sample">
<constructor-arg value="鈴木一郎" type="String" index="0" />
<constructor-arg value="27" type="int" index="1" />
</bean>
※type,indexは省略可能(indexは0が第一引数)
↓省略版
<bean id="sample" class="com.example.Sample">
<constructor-arg value="鈴木一郎" />
<constructor-arg value="27" />
</bean>
依存性を注入
DI:Dependency Injectionともいう
-あるオブジェクトのフィールドに、適切なオブジェクトを代入すること
ここでxmlのみをつかったやり方、アノテーションと組み合わせたやり方を実行
今日はここまで。
導入ですでにけっこう難しめなので復習必須