プロジェクトを作成する
-
Project: Maven
-
Language: Java
-
SpringBoot: 3.0.12
-
Group: simple_spring_restapi
-
Artifact: simple_spring_restapi
-
Name : simple_spring_restapi
-
Description: Demo project for Spring Boot
-
Package name: simple_spring_restapi
Dependencies
- Spring Boot DevTools
- Spring Web
Dockerを作成する
① .devcontainerフォルダとdevcontainer.jsonとdocker-compose.ymlを作成する
{
"name": "workspace",
"dockerComposeFile": "docker-compose.yml",
"service": "workspace",
"workspaceFolder": "/home/vscode/workspace",
"remoteUser": "vscode",
"shutdownAction": "stopCompose",
"customizations": {
"vscode": {
"extensions": [
"vscjava.vscode-java-pack",
"vscjava.vscode-spring-initializr",
"vscjava.vscode-gradle"
]
}
}
}
② docker/workspaceファイルとDockerfileを作成する
# イメージのベースとなるイメージを指定
FROM ubuntu:22.04
# イメージのベースとなるイメージを指定(Mac用)
# FROM arm64v8/alpine:latest
# イメージに追加するファイルを指定
ARG USERNAME=vscode
ARG USER_GROUP_NAME=workspace
ARG USER_UID=1000
ARG USER_GID=1000
ARG PKG="git vim curl unzip zip"
# イメージの起動時に実行するコマンドを指定
SHELL [ "/bin/bash","-c" ]
RUN apt-get update \
&& apt-get install -y ${PKG} \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* \
&& grouapp --gid ${USER_GID} ${USER_GROUP_NAME} \
&& useradd --uid ${USER_UID} --shell /bin/bash --gid ${USER_GID} -m{USERNAME} \
&& echo %${USER_GROUP_NAME} ALL=\(ALL\) NOPASSWORD:ALL > /etc/sudoers.d/${USER_GROUP_NAME} \
&& chmod 0440 /etc/sudoers.d/${USER_GROUP_NAME}
## JAVAの環境構築
ARG JAVA _VARSION=18.0.2-amzn
ARG GRADLE_VARSION=7.5
RUN su ${USERNAME} --command \
'curl -s "https//get.sdkman.io" | bash \
&& source "${HOME}/.sdkman/bin/sdkman-init.sh" \
&& sdk install java "${JAVA_VARSION}" \
&& sdk install gradle "${GRADLE_VARSION}"'
③ docker-compose.ymlを編集する
version: '3.9'
services:
workspace:
container_name: ${PROJECT_NAME:default}-workspace
build:
context: ./docker/workspace
args:
USERNAME: ${USERNAME:-vscode}
USER_GROUP_NAME: ${USER_GROUP_NAME:-workspace}
USER_UID: ${USER_UID:-1000}
USER_GID: ${USER_GID:-1000}
tty: true
volumes:
- ../:/home/${USERNAME:-vscode}/workspace:cached
ports:
- '8080:8080'
④ .devcontainerに.envを作成する
PROJECT_NAME=simple-spring-restapi
USERNAME=vscode
USER_GROUP_NAME=workspace
USER_UID=1000
USER_UID=1000
⑤ docker compose.yml buildを行う
docker compose.yml build
コントローラーを作成する
① src/main/java/simple_spring_restapiにcontrollersフォルダとTodoController.javaファイルを作成する
package simple_spring_restapi.controller;
import java.net.URI;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
import jakarta.validation.Valid;
import simple_spring_restapi.models.TodoItem;
import simple_spring_restapi.services.TodoService;
@RequestMapping(path = TodoController.BASE_URL)
@RestController
public class TodoController {
public static final String BASE_URL = "/api/v1/todos";
@Autowired
private TodoService _todoService;
@GetMapping(path = "")
public ResponseEntity<List<TodoItem>> getTodoItems() {
List<TodoItem> todoItems = _todoService.getTodoItems();
return ResponseEntity.ok(todoItems);
}
@GetMapping(path = "/{id}")
public ResponseEntity<TodoItem> getTodoItems(@PathVariable int id) {
TodoItem found = _todoService.getTodoItemById(id);
return ResponseEntity.ok(found);
}
@PostMapping(path="")
public ResponseEntity<todoItem> creteTodoItems(@Valid @RequestBody TodoItem newTodoItem) {
TodoItem saveTodoItem = _todoService.saveTodoItem(newTodoItem);
URI location = ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}");
.bulidAndExpand(saveTodoItem.getId()).toUri();
return ResponseEntity.created(location).body(newTodoItem);
}
@PutMapping(path = "/{id}")
public ResponseEntity<?> updateTodoItems(@RequestBody TodoItem newTodoItem, @PathVariable int id) {
_todoService.updateTodoItems(id, newTodoItem);
return ResponseEntity.noContent().build();
}
@DeleteMapping(path = "/{id}")
public ResponseEntity<?> removeTodoItems(@PathVariable int id) {
_todoService.deleteTodoItem(id);
return ResponseEntity.noContent().build();
}
}
② build.grandleファイルにimplementation 'org.springdoc:springdoc-openapi-ui:1.6.9'を加えて、
swagger-uiが使用できるようにする
//省略
dependencies {
//省略
implementation 'org.springdoc:springdoc-openapi-ui:1.6.9'
}
③ src/main/java/simple_spring_restapiにmodelsフォルダとTodoItem.javaファイルを作成する
package simple_spring_restapi.models;
import jakarta.persistence.Column;
import jakarta.annotation.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.validation.constraints.NotBlank;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "todos", schema = "business")
public class TodoItem {
@Id
@GeneratedValue(strategy = GenerationType.Auto)
@Column(name = "id", nullable = false)
private int id;
@NotBlank(message = "Title must not be blank.")
@Column(name = "id", nullable = false)
private String title;
}
④ resouces/application.propertiesをapplication.yamlに変更する
spring:
jpa:
database: POSTGRESQL
hibernate:
ddl-auto: update
show-sql: true
properties:
hibernate:
hbm2dll: create_namespaces:true
datasource:
url: jdbc:postgresql://${POSTGRES_HOST:-postgres}:${POSTGRES_PORT:5432}/ ${POSTGRES_DB:-dev}
username: ${POSTGRES_USER:-postgres}
password: ${POSTGRES_PASSWORD:-postgres}
driver-class-name: org.postgresql.Driver
⑤ src/main/java/javnautas.fakeapiusにbusinessフォルダとserviceフォルダとFakeApiService.javaファイルを作成する
⑥ src/main/java/javnautas.fakeapius/appv1.dtoにFakeApi Controller.javaファイルを作成する
⑦ SpringDoc OpenAPI Starter WebMVC UI で、Spring Boot アプリケーションの RESTful API の OpenAPI ドキュメントを生成する
// 省略
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0'
// 省略
⑧ Swagger UIを開き、fake-apiの定義を読み込み、HTML 形式で API のドキュメントを生成する
⑨ instructureにentitiesフォルダとProductoEntity.javaを作成する
SpringDoc OpenAPI Starter WebMVC UI
※ SpringDoc OpenAPI Starter WebMVC UI は、Spring Boot アプリケーションの RESTful API の OpenAPI ドキュメントを生成するための Spring Boot Starter
servicesを作成する
① src/main/java/simple_spring_restapiにservicesフォルダとTodoServices.javaファイルを作成する
② src/main/java/simple_spring_restapi/servicesに
TodoServiceImplWithoutRepo.javaファイルを作成する
エラーハンドラーの追加する
① src/main/java/simple_spring_restapiにerrorsフォルダとNotFoundException.javaファイルを作成する
② src/main/java/simple_spring_restapi/errorsにBadRequestException.javaファイルを作成する
③ src/main/java/simple_spring_restapi/errorsにRestResponseEntityExceptionHandler.javaファイルを作成する
④ src/main/java/simple_spring_restapi/errorsにErrorResponse.javaファイルを作成する
⑤ src/main/java/simple_spring_restapi/errorsにHttpException.javaファイルを作成する
モデルバリデーションの追加
① build.grandleファイルに
implementation 'org.springframework.boot:spring-boot-starter-validation:2.7.3'
compileOnlyorg.projectlombok:lombok:1.18.24'を加えて、modelヴァリデーションが使用できるようにする
//省略
dependencies {
//省略
implementation 'org.springframework.boot:spring-boot-starter-validation:2.7.3'
compileOnly 'org.projectlombok:lombok:1.18.24'
}
データアクセスレイヤーの追加
① .devcontainerフォルダとdevcontainer.jsonとdocker-compose.ymlに追加する
version: '3.9'
services:
workspace:
container_name: ${PROJECT_NAME:default}-workspace
build:
context: ./docker/workspace
args:
USERNAME: ${USERNAME:-vscode}
USER_GROUP_NAME: ${USER_GROUP_NAME:-workspace}
USER_UID: ${USER_UID:-1000}
USER_GID: ${USER_GID:-1000}
tty: true
volumes:
- ../:/home/${USERNAME:-vscode}/workspace:cached
ports:
- '8080:8080'
postgres:
container_name: ${PROJECT_NAME:default}-postgres
image: postgres:14.2
environment:
POSTGRES_USER: ${POSTGRES_USER:-postgres}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-postgres}
POSTGRES_DB: ${POSTGRES_DB:-dev}
volumes:
- ./data/db:/var/lib/postgresql/data
ports:
- ${POSTGRES_PORT:-5432}:5432
restart: always
pgadmin4:
container_name: ${PROJECT_NAME:default}-pgadmin4
restart: always
image: dpage/pgadmin4
environment:
PGADMIN_DEFAULT_EMAIL: ${PGADMIN_DEFAULT_EMAIL:-pgadmin4@pgadmin.com}
PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_DEFAULT_PASSWORD:-password}
volumes:
- ./pgadmin:/var/lib/pgadmin
ports:
- 8080:80
depends_on:
- postgres
② .envを編集する
PROJECT_NAME=simple-spring-restapi
# workspace
USERNAME=vscode
USER_GROUP_NAME=workspace
USER_UID=1000
USER_UID=1000
# postgres
POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres
POSTGRES_DB=dev
# pgadmin4
PGADMIN_DEFAULT_EMAIL=pgadmin4@pgadmin.com
PGADMIN_DEFAULT_PASSWORD=password
③ resources/application.propertiesを編集する
application.properties ⇨ application.ymlに変更する
spring:
jpa:
database: POSTGRESQL
hibernate:
ddl-auto: update
show-sql: true
properties:
hibernate:
hbm2dll: create_namespaces:true
datasource:
url: jdbc:postgresql://${POSTGRES_HOST:-postgres}:${POSTGRES_PORT:5432}/ ${POSTGRES_DB:-dev}
username: ${POSTGRES_USER:-postgres}
password: ${POSTGRES_PASSWORD:-postgres}
driver-class-name: org.postgresql.Driver
④ build.grandleファイルにコードを加える
//省略
dependencies {
//省略
implementation 'org.springframework.boot:spring-boot-starter-data-jpa:2.7.3'
implementation 'org.postgresql:postgresql:42.5.0'
}
⑤ TodoItem.javaを編集する
package simple_spring_restapi.models;
import jakarta.persistence.Column;
import jakarta.annotation.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.validation.constraints.NotBlank;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "todos", schema = "business")
public class TodoItem {
@Id
@GeneratedValue(strategy = GenerationType.Auto)
@Column(name = "id", nullable = false)
private int id;
@NotBlank(message = "Title must not be blank.")
@Column(name = "id", nullable = false)
private String title;
}
⑥ repositoriesフォルダとTodoRepositories.java を作成する
package simple_spring_restapi.repositories;
import org.springframework.stereotype.Repository;
import com.juniordevmind.simplespringrestapi.models.TodoItem;
@Repository
public interface TodoRepositories extends JpaRepository<TodoItem, Integer> {
}
⑦ src/main/java/simple_spring_restapi/services/TodoServiceImpl.javaファイルを作成する
package simple_spring_restapi.services;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.webjars.NotFoundException;
import com.juniordevmind.simplespringrestapi.models.TodoItem;
import simple_spring_restapi.repositories.TodoRepositories;
@Service
public class TodoServiceImpl implements TodoService {
@Autowired
private TodoRepository _todoRepository;
@Override
public TodoItem getTodoItemsById(int id) {
return _findTodoItemById(id);
}
@Override
public List<TodoItem> getTodoItems() {
return _todoRepository.findAll();
}
@Override
public Todo removeTodoItemById(int id) {
_todoRepository.deleteById(id);
}
@Override
public TodoItem saveTodoItem(TodoItem todoItem) {
return _todoRepository.save(todoItem);
}
@Override
public TodoItem updateTodoItem(int id, TodoItem todoItem) {
return _todoRepository.save(todoItem);
}
private TodoItem _findTodoItemById(int id) throws NotFoundException {
Optional<TodoItem> found = _todoRepository.findById(id);
if (!found.isPresent()) {
throw new NotFoundException("The todo item is not available");
}
return found.get();
}
}
参考サイト
【Spring Boot】REST API 開発 - Dockerとvscodeを使った、Javaの開発環境構築 #1
【Spring Boot】REST API 開発 - Spring Boot プロジェクトの生成 #2
【Spring Boot】REST API 開発 - コントローラーの立ち上げ #2.5
【Spring Boot】REST API 開発 - モデルバリデーションの追加 #6
【Spring Boot】REST API 開発 - データアクセスレイヤーの追加 #7