Spring Boot プロジェクトセットアップ
Spring Boot で実装する REST API のプロジェクトの初期セットアップ方法について記載します。
プロジェクト作成
cf. https://docs.spring.io/initializr/docs/0.9.1/reference/html/#command-line
- Spring initializer を使ってプロジェクトを新規作成します。
curl https://start.spring.io/starter.zip \
-d javaVersion=21 \
-d dependencies=web,lombok,data-jpa,mariadb \
-d type=maven-project \
-d language=java \
-d name=easyapp \
-d groupId=nob.example \
-d artifactId=easyapp \
-o easyapp.zip
- zip を解凍します。
unzip easyapp.zip && rm -rf easyapp.zip
実装
サンプルコードを掲載します。ここでは擬似的なログイン API を実装します。
事前準備
データベースを docker で構築し、Java プロジェクト側に接続情報を記載します。
docker-compose.yaml
services:
eadb:
image: mariadb:latest
container_name: eadb
ports:
- 3306:3306
volumes:
- ./volumes/initdb.d:/docker-entrypoint-initdb.d
environment:
- MYSQL_ROOT_PASSWORD=password
volumes/initdb.d/create-database.sql
CREATE DATABASE eadb;
USE eadb;
CREATE TABLE users (
name VARCHAR(8) PRIMARY KEY
, password VARCHAR(32)
, age INT
);
INSERT INTO users (
name
, password
, age
) VALUES (
'nob'
, 'passwd'
, 13
);
src/main/resources/application.properties
#MariaDBのドライバ設定
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
#接続用URL
spring.datasource.url=jdbc:mariadb://localhost/eadb
#ユーザ名
spring.datasource.username=root
#パスワード
spring.datasource.password=password
ディレクトリ構成
作成が必要なもののみ記載しています。
.
├── controller # APIとしてのインターフェース
│ ├── AuthController.java
│ ├── impl # APIの実装
│ │ └── AuthControllerImpl.java
│ └── model # APIのリクエスト・レスポンスモデル
│ ├── LoginRequest.java
│ ├── LoginResponse.java
│ ├── MeRequest.java
│ └── MeResponse.java
├── repository # データベース操作のインターフェース
│ ├── entity # データベースのテーブル定義に対応するエンティティ
│ │ └── Users.java
│ └── UsersRepository.java
└── service # 業務処理のインターフェース
├── AuthService.java
├── impl # 業務処理の実装
│ └── AuthServiceImpl.java
└── model # 業務処理の入力・出力モデル
├── LoginInModel.java
├── LoginOutModel.java
├── MeInModel.java
└── MeOutModel.java
クラス一覧
repository/UsersRepository.java
データベースにアクセスする repository インターフェースを定義します。JpaRepository によって実装が自動生成されます。
package nob.example.easyapp.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import nob.example.easyapp.repository.entity.Users;
/**
* usersテーブル向けrepositoryのインターフェースです。
*
* @author nob
*/
@Repository
public interface UsersRepository extends JpaRepository<Users, String> {
/**
* ユーザ情報を取得します。
*
* @param name 検索キーのユーザ名
* @return ユーザ情報
*/
Users findByName(String name);
}
repository/entity/Users.java
データベースのテーブル定義に対応するエンティティを定義します。
package nob.example.easyapp.repository.entity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
/**
* usersテーブルのエンティティクラスです。
*
* @author nob
*/
@Table(name = "users")
@Entity
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class Users {
/** ユーザ名 */
@Id
@Column(name = "name", length = 8, nullable = false)
private String name;
/** パスワード */
@Column(name = "password", length = 32, nullable = false)
private String password;
/** 年齢 */
@Column(name = "age", nullable = false)
private Integer age;
}
service/AuthService.java
業務処理を担うクラスのインターフェースを定義します。
package nob.example.easyapp.service;
import org.springframework.stereotype.Service;
import nob.example.easyapp.service.model.LoginInModel;
import nob.example.easyapp.service.model.LoginOutModel;
import nob.example.easyapp.service.model.MeInModel;
import nob.example.easyapp.service.model.MeOutModel;
/**
* 認証サービスのインターフェースです。
*
* @author nob
*/
@Service
public interface AuthService {
/**
* 認証処理を行います。
*
* @param inModel 認証情報
* @return 認証結果
*/
LoginOutModel login(LoginInModel inModel);
/**
* ユーザ情報を取得します。
*
* @param inModel ユーザ情報検索条件
* @return ユーザ情報
*/
MeOutModel me(MeInModel inModel);
}
service/impl/AuthServiceImpl.java
サービスを実装します。アプリの業務処理はこのクラスで行います。
package nob.example.easyapp.service.impl;
import org.springframework.stereotype.Service;
import lombok.NonNull;
import nob.example.easyapp.repository.UsersRepository;
import nob.example.easyapp.repository.entity.Users;
import nob.example.easyapp.service.AuthService;
import nob.example.easyapp.service.model.LoginInModel;
import nob.example.easyapp.service.model.LoginOutModel;
import nob.example.easyapp.service.model.MeInModel;
import nob.example.easyapp.service.model.MeOutModel;
/**
* AuthServiceの実装クラスです。
*
* @author nob
*/
@Service
public class AuthServiceImpl implements AuthService {
@NonNull
private UsersRepository usersRepository;
public AuthServiceImpl(UsersRepository usersRepository) {
this.usersRepository = usersRepository;
}
@Override
public LoginOutModel login(LoginInModel inModel) {
return new LoginOutModel(
usersRepository.findByName(inModel.getName()).getPassword().equals(inModel.getPassword()));
}
@Override
public MeOutModel me(MeInModel inModel) {
Users users = usersRepository.findByName("nob");
return new MeOutModel(users.getName(), users.getAge());
}
}
service/model/LoginInModel.java
業務処理を担うクラスの入力モデルを定義します。
package nob.example.easyapp.service.model;
import lombok.Value;
/**
* 認証向けの入力モデルです。
*
* @author nob
*/
@Value
public class LoginInModel {
/** ユーザ名 */
private String name;
/** パスワード */
private String password;
}
service/model/LoginOutModel.java
業務処理を担うクラスの出力モデルを定義します。
package nob.example.easyapp.service.model;
import lombok.Value;
/**
* 認証向けの出力モデルです。
*
* @author nob
*/
@Value
public class LoginOutModel {
/** 認証可否 */
private boolean valid;
}
service/model/MeInModel.java
package nob.example.easyapp.service.model;
import lombok.Value;
/**
* ユーザ情報取得向けの入力モデルです。
*
* @author nob
*/
@Value
public class MeInModel {
/** ユーザ名 */
private String name;
}
service/model/MeOutModel.java
package nob.example.easyapp.service.model;
import lombok.Value;
/**
* ユーザ情報取得向けの出力モデルです。
*
* @author nob
*/
@Value
public class MeOutModel {
/** ユーザ名 */
private String name;
/** 年齢 */
private Integer age;
}
controller/AuthController.java
API のインターフェースを定義します。
package nob.example.easyapp.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import nob.example.easyapp.controller.model.LoginRequest;
import nob.example.easyapp.controller.model.LoginResponse;
import nob.example.easyapp.controller.model.MeRequest;
import nob.example.easyapp.controller.model.MeResponse;
/**
* 認証コントローラーのインターフェースです。
*
* @author nob
*/
@RestController
@RequestMapping(value = "/api/v1")
public interface AuthController {
/**
* 認証処理を呼び出します。
*
* @param request 認証リクエスト
* @return 認証結果
*/
@PostMapping(value = "/login")
LoginResponse login(@RequestBody LoginRequest request);
/**
* ユーザ情報取得処理を呼び出します。
*
* @param request ユーザ情報取得リクエスト
* @return ユーザ情報
*/
@GetMapping(value = "/me")
MeResponse me(MeRequest request);
}
controller/impl/AuthControllerImpl.java
コントローラーを実装します。ここでは業務処理を実装せず、サービスを呼び出すことに専念します。
package nob.example.easyapp.controller.impl;
import org.springframework.web.bind.annotation.RestController;
import lombok.NonNull;
import nob.example.easyapp.controller.AuthController;
import nob.example.easyapp.controller.model.LoginRequest;
import nob.example.easyapp.controller.model.LoginResponse;
import nob.example.easyapp.controller.model.MeRequest;
import nob.example.easyapp.controller.model.MeResponse;
import nob.example.easyapp.service.AuthService;
import nob.example.easyapp.service.model.LoginInModel;
import nob.example.easyapp.service.model.MeInModel;
import nob.example.easyapp.service.model.MeOutModel;
/**
* AuthControllerの実装クラスです。
*
* @author nob
*/
@RestController
public class AuthControllerImpl implements AuthController {
@NonNull
private AuthService authService;
public AuthControllerImpl(AuthService authService) {
this.authService = authService;
}
@Override
public LoginResponse login(LoginRequest request) {
return new LoginResponse(
authService.login(new LoginInModel(request.getName(), request.getPassword())).isValid());
}
@Override
public MeResponse me(MeRequest request) {
MeOutModel meOutModel = authService.me(new MeInModel(request.getName()));
return new MeResponse(meOutModel.getName(), meOutModel.getAge());
}
}
controller/model/LoginRequest.java
コントローラーのリクエストモデルを定義します。
package nob.example.easyapp.controller.model;
import lombok.Value;
/**
* 認証向けのリクエストモデルです。
*
* @author nob
*/
@Value
public class LoginRequest {
/** ユーザ名 */
private String name;
/** パスワード */
private String password;
}
controller/model/LoginResponse.java
コントローラーのレスポンスモデルを定義します。
package nob.example.easyapp.controller.model;
import lombok.Value;
/**
* 認証向けのレスポンスモデルです。
*
* @author nob
*/
@Value
public class LoginResponse {
/** 認証可否 */
private boolean valid;
}
controller/model/MeRequest.java
package nob.example.easyapp.controller.model;
import lombok.Value;
/**
* ユーザ情報取得向けのリクエストモデルです。
*
* @author nob
*/
@Value
public class MeRequest {
/** ユーザ名 */
private String name;
}
controller/model/MeResponse.java
package nob.example.easyapp.controller.model;
import lombok.Value;
/**
* ユーザ情報取得向けのレスポンスモデルです。
*
* @author nob
*/
@Value
public class MeResponse {
/** ユーザ名 */
private String name;
/** 年齢 */
private Integer age;
}
起動
下記コマンドでアプリを起動します。
./mvnw spring-boot:run
下記コマンドで API を打鍵できます。
# /login
curl -X POST -H 'Content-Type: application/json' -d '{"name": "nob", "password": "passwd"}' localhost:8080/api/v1/login
# /me
curl -X GET localhost:8080/api/v1/me?name=nob