LoginSignup
1
0

More than 1 year has passed since last update.

Spring bootで簡単なWebアプリを作ってみる(ロジック作成1)

Posted at

こんにちは。船井総研デジタルのいっちーです。
前回の記事では、画面遷移を作成しました。

今回は、ロジックを組み込んで、画面(フロントサイド)とサーバ(バックサイド)でデータの授受ができるようにしていきます。長くなると思いますので、何回かに分けて投稿したいと思います。

データのやり取りを考える

画面遷移の際に、どのようなデータがやり取りされるかを考えます。

メイン画面

メイン画面とサーバの間でやり取りされるデータを洗い出していきます。

mainscreen.png

サーバーから画面に送られるデータ

No データ 繰り返し 備考
1 つぶやき あり -
2 エラーメッセージ あり 処理時にエラーが発生した場合のみ。エラーメッセージがなければ表示エリアそのものを出力しない。
3 ページ情報 なし -

画面からサーバーに送られるデータ

No データ 繰り返し 備考
4 つぶやき なし 処理時にエラーが発生した場合、表示中のページに戻すため、自ページ番号を一緒に送る。

ねぎ登録画面

ねぎ登録画面とサーバの間でやり取りされるデータを洗い出していきます。

registerscreen.png

ねぎマスタの主キーであるIDを非表示項目として画面に渡すことで、対応する「修正」「削除」のボタンを押したときに、対応するねぎ情報のIDをサーバーに返せるようにします。

サーバーから画面に送られるデータ

No データ 繰り返し 備考
1 ねぎ情報 あり -
2 エラーメッセージ あり 処理時にエラーが発生した場合のみ。エラーメッセージがなければ表示エリアそのものを出力しない。

画面からサーバーに送られるデータ

No データ 繰り返し 備考
3 登録情報 なし -
4 更新情報 なし ボタンの種類で修正/削除を区別し、ねぎマスタのIDを送ることで修正/削除対象のレコードを特定する。

データ受け渡しのためのクラスを作成する。

画面とサーバーの間でデータを受け渡すためのクラスを実装していきます。

画面からサーバーに送られるデータ

画面からサーバーに送られるデータは、画面のformに対応したFormクラスで表現します。前準備として、データのバリデーションを自動的に組み込めるように、pom.xmlのdependenciesに下記の2つを追加します。

pom.xml

(略)

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-validation</artifactId>
	<version>3.0.4</version>
</dependency>
<dependency>
	<groupId>org.springframework.data</groupId>
	<artifactId>spring-data-commons</artifactId>
	<version>3.0.3</version>
</dependency>

(略)

つぶやきForm
src/main/java/com/example/negitter/form/NegiitForm.java
@Data
@AllArgsConstructor
public class NegiitForm {

    @NotBlank(message="お名前は必須項目です。")
    @Size(max=128, message="お名前は128文字以下で入力してください。")
    private String name;
    @NotBlank(message="つぶやきは必須項目です。")
    @Size(max=128, message="つぶやきは128文字以下で入力してください。")
    private String negiit;
    private Integer pageNum;

}
ねぎ登録Form
src/main/java/com/example/negitter/form/RegisterNegiForm.java
@Data
@AllArgsConstructor
public class RegisterNegiForm {

    @NotBlank(message="ねぎ名称は必須項目です。")
    @Size(max=128, message="ねぎ名称は128文字以下で入力してください。")
    private String negiName;

}
ねぎ更新Form
src/main/java/com/example/negitter/form/UpdateNegiForm.java
@Data
@AllArgsConstructor
public class UpdateNegiForm {

    @NotBlank(message="処理区分が設定されていません。")
    private String process;
    @NotNull(message="処理対象が設定されていません。")
    private Integer id;
    @NotBlank(message="ねぎ名称が入力されていません。")
    @Size(max=128, message="ねぎ名称は128文字以下で入力してください。")
    private String negiName;

}

各フィールドに@NotNull等のアノテーションをつけることによって、項目チェックを組み込むことができます。バリデーション結果は、ControllerクラスのメソッドにBindingResult型の引数を定義することで受け取ることができます。

サーバーから画面に送られるデータ

サーバーから画面に送られるデータのうち、つぶやきとねぎ情報の2つは、DBテーブルレコードのListとなります。今回MyBatisを使ってO/Rマッピングを行いますので、MyBatis Generatorで必要なソースを自動作成します。

pom.xmlの修正

pom.xmlのpluginsに下記の設定を追加します。

pom.xml

(略)

<plugin>
	<groupId>org.mybatis.generator</groupId>
	<artifactId>mybatis-generator-maven-plugin</artifactId>
	<version>1.4.1</version>
	<configuration>
		<configurationFile>
			${project.basedir}/src/resources/dev/generatorConfig.xml</configurationFile>
		<overwrite>
			true</overwrite>
		<includeAllDependencies>true</includeAllDependencies>
	</configuration>
	<dependencies>
		<dependency>
			<groupId>com.softwareloop</groupId>
			<artifactId>mybatis-generator-lombok-plugin</artifactId>
			<version>1.0</version>
		</dependency>
	</dependencies>
</plugin>

(略)

configurationFileは、MyBatis Generatorの設定ファイルを格納するパスを指定します。続いて、MyBatis Generatorの設定ファイルを作ります。

MyBatis Generatorの設定

generatorConfig.xml
src/resources/dev/generatorConfig.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
    <context id="tables" targetRuntime="MyBatis3">
        <!-- <plugin type="org.mybatis.generator.plugins.EqualsHashCodePlugin"/> -->
        <plugin type="org.mybatis.generator.plugins.MapperAnnotationPlugin" />
        <plugin type="com.softwareloop.mybatis.generator.plugins.LombokPlugin" />
        <jdbcConnection
            driverClass="com.mysql.cj.jdbc.Driver"
            connectionURL="jdbc:mysql://localhost/negitter"
            userId="user"
            password="pass" />

        <javaModelGenerator
            targetPackage="com.example.negitter.entity"
            targetProject="MAVEN" />
        <sqlMapGenerator
            targetPackage="com.example.negitter.mapper"
            targetProject="MAVEN" />
        <javaClientGenerator
            type="XMLMAPPER"
            targetPackage="com.example.negitter.mapper"
            targetProject="MAVEN" />

        <table tableName="negi_mst" enableInsert="true" enableSelectByPrimaryKey="true"
            enableSelectByExample="false" enableUpdateByPrimaryKey="true"
            enableDeleteByPrimaryKey="true" enableDeleteByExample="false"
            enableCountByExample="false" enableUpdateByExample="false"
            selectByPrimaryKeyQueryId="false" selectByExampleQueryId="false">
            <generatedKey column="id" sqlStatement="JDBC" />
        </table>
        <table tableName="message_tbl" enableInsert="true"
            enableSelectByPrimaryKey="true"
            enableSelectByExample="false" enableUpdateByPrimaryKey="true"
            enableDeleteByPrimaryKey="true" enableDeleteByExample="false"
            enableCountByExample="false" enableUpdateByExample="false"
            selectByPrimaryKeyQueryId="false" selectByExampleQueryId="false">
            <generatedKey column="id" sqlStatement="JDBC" />
        </table>
    </context>
</generatorConfiguration>

ソース生成

VSCodeのMAVENタブを開いていくとmybatis-generatorという項目が追加されていると思いますので、「generate」を実行します。

mybatisgenerate.png

実行が終わると、targetフォルダ配下に自動生成されたentitiyクラス、mapperクラス、mapper.xmlが格納されますので、これをsrcフォルダ内のしかるべきパスに配置します。

image.png

後の工程でこれらのソースを手書きで修正していきますが、手書き修正したソースと自動生成したソースが混在すると、デグレしたりして管理が面倒なことになるので、十分お気をつけください。

受け渡しデータの定義をControllerクラスに追加する

設計したデータ定義に基づいて、Controllerクラスを修正します。

画面からサーバーに送られるデータ

ControllerクラスのPost/GetMappingしているメソッドに引数を追加します。それぞれ以下のような意味合いがあります。

アノテーション 役割 備考
Model - サーバーから画面へ引き渡すデータを格納する -
T @RequestParam リクエストパラメータを格納する -
T @ModelAttribute 画面のFormデータを格納する -
T @Valid 自動的にバリデーションされるデータであることを示す BindingResultでバリデーション結果を受け取る前提
BindingResult - バリデーション結果を格納する 対象のFormクラスが@Validで修飾されている前提
Controllerクラス
src/main/java/com/example/negitter/controller/NegitterController.java

()

@GetMapping("/")
-public String index() {
+public String index(@RequestParam(name = "page", required = false, defaultValue = "1") int pageNum, Model model) {
	return "negitter";
}

()

@GetMapping("/register")
-public String register() {
+public String register(Model model) {
	return "register";
}

()

@GetMapping("/negitter")
-public String negitter() {
+public String negitter(@RequestParam(name = "page", required = false, defaultValue = "1") int pageNum, Model model) {
	return "negitter";
}

()

@PostMapping("/negiit")
-public String negiit() {
+public String negiit(@ModelAttribute @Valid NegiitForm negiitForm, BindingResult bindingResult, Model model) {
	return "negitter";
}

()

@PostMapping("/registerNegi")
-public String registerNegi() {
+public String registerNegi(@ModelAttribute @Valid RegisterNegiForm negiForm, BindingResult bindingResult, Model model) {
	return "register";
}

()

@PostMapping("/updateNegi")
-public String updateNegi() {
+public String updateNegi(@ModelAttribute @Valid UpdateNegiForm updateNegiForm, BindingResult bindingResult, Model model) {
	return "register";
}

()

サーバーから画面に送られるデータ

Post/GetMappingメソッドに追加したModel型の引数に画面に引き渡すデータを格納します。
データの中身は次回以降作成していきますので、バリデーション結果以外は仮の値をとりあえず詰めておくことにします。

Controllerクラス
src/main/java/com/example/negitter/controller/NegitterController.java
()

@GetMapping("/")
public String index(@RequestParam(name = "page", required = false, defaultValue = "1") int pageNum, Model model) {
+    // TODO つぶやきとページ情報を取得
+    model.addAttribute("negiits", new ArrayList<MessageTbl>());
+    model.addAttribute("pageNum", pageNum);
+    model.addAttribute("totalPages", 1);
+    model.addAttribute("prevPage", 1);
+    model.addAttribute("nextPage", 1);
+    model.addAttribute("errorMessages", new ArrayList<String>());
	return "negitter";
}

()

@GetMapping("/register")
public String register(Model model) {
+    // TODO ねぎマスタのデータを取得
+    model.addAttribute("negiList", new ArrayList<NegiMst>());
+    model.addAttribute("errorMessages", new ArrayList<String>());
	return "register";
}

()

@GetMapping("/negitter")
public String negitter(@RequestParam(name = "page", required = false, defaultValue = "1") int pageNum, Model model) {
+    // TODO つぶやきとページ情報を取得
+    model.addAttribute("negiits", new ArrayList<MessageTbl>());
+    model.addAttribute("pageNum", pageNum);
+    model.addAttribute("totalPages", 1);
+    model.addAttribute("prevPage", 1);
+    model.addAttribute("nextPage", 1);
+    model.addAttribute("errorMessages", new ArrayList<String>());
	return "negitter";
}

()

@PostMapping("/negiit")
public String negiit(@ModelAttribute @Valid NegiitForm negiitForm, BindingResult bindingResult, Model model) {
+    List<String> errorMessages = bindingResult.getAllErrors().stream().map(e -> e.getDefaultMessage()).toList();    
+    // TODO つぶやき登録処理結果によってページ情報を設定
+    model.addAttribute("negiits", new ArrayList<MessageTbl>());
+    model.addAttribute("pageNum", pageNum);
+    model.addAttribute("totalPages", 1);
+    model.addAttribute("prevPage", 1);
+    model.addAttribute("nextPage", 1);
+    model.addAttribute("errorMessages", errorMessages);	
+    return "negitter";
}

()

@PostMapping("/registerNegi")
public String registerNegi(@ModelAttribute @Valid RegisterNegiForm negiForm, BindingResult bindingResult, Model model) {
+    List<String> errorMessages = bindingResult.getAllErrors().stream().map(e -> e.getDefaultMessage()).toList();
+    // TODO ねぎ情報登録結果を設定
+    // TODO ねぎ情報を検索し直す
+    model.addAttribute("negiList", negiList);
+    model.addAttribute("errorMessages", errorMessages);
	return "register";
}

()

@PostMapping("/updateNegi")
public String updateNegi(@ModelAttribute @Valid UpdateNegiForm updateNegiForm, BindingResult bindingResult, Model model) {
+    List<String> errorMessages = bindingResult.getAllErrors().stream().map(e -> e.getDefaultMessage()).toList();
+    // TODO ねぎ情報更新結果を設定
+    // TODO ねぎ情報を検索し直す
+    model.addAttribute("negiList", negiList);
+    model.addAttribute("errorMessages", errorMessages);
	return "register";
}

+ // TODO ページ情報を管理するprivate methodを作る

()

まとめ

今回は、サーバーと画面の間でやり取りされるデータの設計と、必要なクラス等の実装を行いました。
次回は、受け取ったデータを画面側で表示できるように、テンプレートを修正していきます。

それではまた。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0