今回は、@RestController
の戻り値を使ってフロントがJavaScriptで動的にHTMLを生成するAPI開発を作ります。
つまり、
「HTMLはそのまま表示するが、ユーザー一覧データ(List)はJSONで取得して、JavaScriptで動的にテーブルを生成する」という方針です。
✅ 全体構成のイメージ
■ pom.xml
にspring-boot-starter-thymeleaf
を追加する
■ Spring Boot側では@RestController
を使ってJSON API
を提供する(例: /api/users
)。
■ User.html
を返すだけのHTML表示用@Controller
を用意する。
■ HTML側で JavaScript(fetch)
を使ってJSON
を取得してテーブルを作る。
潤に説明していきます。
■pom.xml
にspring-boot-starter-thymeleaf
を追加する
これがなければ .html テンプレートを Spring Boot が処理できませんので、追加しましょう。
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
全体のpom.xml
はこちら⇩
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.5.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.packt.cardatabase</groupId>
<artifactId>SpringBootPostgresMybatis</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>SpringBootPostgresMybatis</name>
<description>Demo project for Spring Boot</description>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.thymeleaf/thymeleaf -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.4.1</version>
<configuration>
<configurationFile>${project.basedir}/src/main/resources/generatorConfig.xml</configurationFile>
<overwrite>true</overwrite>
<includeAllDependencies>true</includeAllDependencies>
</configuration>
</plugin>
</plugins>
</build>
</project>
■Spring Boot側では@RestControllerを使ってJSON APIを提供する(例: /api/users)。
UserController.java
package com.example.spring.mybatis.controller;
import java.util.List;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import com.example.spring.mybatis.model.Users;
import com.example.spring.mybatis.service.UserService;
@RestController
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@GetMapping("/api/users")
@ResponseBody
public List<Users> AllUser() {
List<Users> userList = userService.GetAllUsers();
System.out.println(userList);
// 拡張for文(for-each文)を使う方法
for(Users user : userList) {
System.out.println("=== 拡張for文(for-each文)を使う方法 ===" +
"User ID: " + user.getId() +
", Name: " + user.getName() +
", Email: " + user.getEmail() +
", Create_At: " + user.getCreatedAt()
);
}
return userList;
}
}
UserService.java
package com.example.spring.mybatis.service;
import java.util.List;
import org.springframework.stereotype.Service;
import com.example.spring.mybatis.mapper.UsersMapper;
import com.example.spring.mybatis.model.Users;
@Service
public class UserService {
private final UsersMapper userMapper;
// UsersMapperをコンストラクタインジェクションで注入
public UserService(UsersMapper userMapper) {
this.userMapper = userMapper;
}
public List<Users> GetAllUsers(){
List<Users> userList = userMapper.selectAll();
return userList;
}
}
■ User.html
を返すだけのHTML表示用@Controller
を用意する。
PageController.java
package com.example.spring.mybatis.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class PageController {
@GetMapping("/users")
public String showUserPage() {
return "User"; // resources/templates/User.html を返す
}
}
■ HTML側で JavaScript(fetch)
を使ってJSON
を取得してテーブルを作る。
User.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>ユーザー一覧(JSON版)</title>
<style>
table {
width: 100%;
border-collapse: collapse;
}
th, td {
border: 1px solid #ddd;
padding: 8px;
}
th {
background-color: #f2f2f2;
}
</style>
</head>
<body>
<h1>ユーザー一覧</h1>
<p id="countMsg">読み込み中...</p>
<table id="userTable">
<thead>
<tr>
<th>ID</th>
<th>名前</th>
<th>メールアドレス</th>
<th>作成日時</th>
</tr>
</thead>
<tbody>
<!-- JavaScriptで動的に行を挿入 -->
</tbody>
</table>
<script>
// JSON APIからデータを取得
fetch('/api/users')
.then(response => response.json())
.then(data => {
const tbody = document.querySelector('#userTable tbody');
const countMsg = document.getElementById('countMsg');
if (data.length === 0) {
countMsg.textContent = 'ユーザーは存在しません。';
return;
}
countMsg.textContent = `${data.length}件のユーザーが見つかりました。`;
data.forEach(user => {
const row = document.createElement('tr');
row.innerHTML = `
<td>${user.id}</td>
<td>${user.name}</td>
<td>${user.email}</td>
<td>${user.createdAt}</td>
`;
tbody.appendChild(row);
});
})
.catch(error => {
console.error('エラー:', error);
document.getElementById('countMsg').textContent = 'ユーザー取得に失敗しました。';
});
</script>
</body>
</html>