Board App REST API ์๋ฒ ๊ตฌํ
1.
Board ํ
์ด๋ธ ์ ์
2.
Spring Boot REST API ๊ตฌํ
3.
API ๋ช
์ธ์ ์๋ ์์ฑ - OpenAPI(Swagger)
4.
API ํ
์คํธ
Board ํ ์ด๋ธ ์ ์
boards.sql
DROP TABLE IF EXISTS `boards`;
CREATE TABLE `boards` (
`no` BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT 'PK',
`id` VARCHAR(64) NOT NULL COMMENT 'UK',
`title` VARCHAR(100) NOT NULL COMMENT '์ ๋ชฉ',
`writer` VARCHAR(100) NOT NULL COMMENT '์์ฑ์',
`content` TEXT NULL COMMENT '๋ด์ฉ',
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '๋ฑ๋ก์ผ์',
`updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '์์ ์ผ์'
) COMMENT '๊ฒ์ํ';
SQL
๋ณต์ฌ
Spring Boot REST API ๊ตฌํ
์์ฒญ ๋ฉ์๋ | ์์ฒญ ๊ฒฝ๋ก | ํญ๋ชฉ | Response | ๋น๊ณ |
GET | /boards | ๊ฒ์ํ ๋ชฉ๋ก | {
โlistโ : [],
โpaginationโ :
} | |
GET | /boards?page= | ๊ฒ์ํ ๋ชฉ๋ก ํ์ด์ง | {
โlistโ : [],
โpaginationโ :
} | |
GET | /boards/{id} | ๊ฒ์ํ ์กฐํ | { } | |
POST | /boards | ๊ฒ์ํ ๋ฑ๋ก | โSUCCESSโ 201
โFAILโ 400 | |
PUT | /boards | ๊ฒ์ํ ์์ | โSUCCESSโ 200
โFAILโ 400 | |
DELETE | /boards/{id} | ๊ฒ์ํ ์ญ์ | โSUCCESSโ 200
โFAILโ 400 |
โข
application.properties
โข
domain
โฆ
Boards.java
โข
Mapper
โฆ
BoardMapper.xml
โฆ
BaseMapper.java
โฆ
BoardMapper.java
โข
Service
โฆ
BaseService.java
โฆ
boardservice.java
โฆ
boardserviceImpl.java
โข
Controller
โฆ
BoardController.java
โฆ
@CrossOrigin("*")
โฆ
@RestController
โช
application.properties
# ๋ฐ์ดํฐ ์์ค - MySQL
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/aloha?serverTimezone=Asia/Seoul&allowPublicKeyRetrieval=true&useSSL=false&autoReconnection=true&autoReconnection=true
spring.datasource.username=aloha
spring.datasource.password=123456
# Mybatis ์ค์
mybatis.configuration.map-underscore-to-camel-case=true
mybatis.type-aliases-package=com.aloha.boards.domain
mybatis.mapper-locations=classpath:mybatis/mapper/**/**.xml
Java
๋ณต์ฌ
API ๋ช ์ธ์ ์๋ ์์ฑ - OpenAPI(Swagger)
// Springdoc openapi
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.7.0'
SQL
๋ณต์ฌ
build.gradle
plugins {
id 'java'
id 'war'
id 'org.springframework.boot' version '3.4.1'
id 'io.spring.dependency-management' version '1.1.6'
}
group = 'com.aloha'
version = '0.0.1-SNAPSHOT'
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:3.0.4'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
runtimeOnly 'com.mysql:mysql-connector-j'
annotationProcessor 'org.projectlombok:lombok'
providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter-test:3.0.4'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
// Springdoc openapi
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.7.0'
}
tasks.named('test') {
useJUnitPlatform()
}
SQL
๋ณต์ฌ
SwaggerConfig.java
import org.springdoc.core.models.GroupedOpenApi;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
@Configuration
public class SwaggerConfig {
@Bean
public GroupedOpenApi publicApi() {
return GroupedOpenApi.builder()
.group("aloha") // ๊ทธ๋ฃน๋ช
์ค์
.pathsToMatch("/**") // ๊ฒฝ๋ก ์ค์
.build();
}
@Bean
public OpenAPI springShopOpenAPI() {
return new OpenAPI()
.info(new Info().title("๊ฒ์ํ Proejct API")
.description("๊ฒ์ํ ํ๋ก์ ํธ API ์
๋๋ค.")
.version("v0.0.1"));
}
}
Java
๋ณต์ฌ
๊ธฐ๋ณธ ๊ฒฝ๋ก
PageHelper ๋ฅผ ์ด์ฉํ ํ์ด์ง ์ฒ๋ฆฌ
builde.gradle
// pagehelper
implementation 'com.github.pagehelper:pagehelper-spring-boot-starter:2.1.0'
Java
๋ณต์ฌ
application.properites
# PageHelper ์ค์
pagehelper.helperDialect=mysql
pagehelper.reasonable=true
pagehelper.supportMethodsArguments=true
pagehelper.params=count=countSql
Java
๋ณต์ฌ
Pagination.java
import lombok.Data;
/**
* [ํ์ด์ง]
* โ
ํ์ด์ง ํ์ ์ ๋ณด
* - ํ์ด์ง ๋ฒํธ : page
* - ํ์ด์ง๋น ๊ฒ์๊ธ ์ : size
* - ๋
ธ์ถ ํ์ด์ง ๊ฐ์ : count
* - ์ ์ฒด ๋ฐ์ดํฐ ๊ฐ์ : total
*
* โญ ํ์ด์ง ์์ ์ ๋ณด
* - ์์ ๋ฒํธ : start
* - ๋ ๋ฒํธ : end
* - ์ฒซ ๋ฒํธ : first
* - ๋ง์ง๋ง ๋ฒํธ : last
* - ์ด์ ๋ฒํธ : prev
* - ๋ค์ ๋ฒํธ : next
* - ๋ฐ์ดํฐ ์์ ๋ฒํธ : index
*/
@Data
public class Pagination {
// ํ์ด์ง ๊ธฐ๋ณธ๊ฐ
private static final long PAGE_NUM = 1; // ํ์ฌ ํ์ด์ง ๋ฒํธ ๊ธฐ๋ณธ๊ฐ
private static final long SIZES = 10; // ํ์ด์ง๋น ๊ฒ์๊ธ ์ ๊ธฐ๋ณธ๊ฐ
private static final long COUNT = 10; // ๋
ธ์ถ ํ์ด์ง ๊ฐ์ ๊ธฐ๋ณธ๊ฐ
// โ
ํ์ ์ ๋ณด
private long page;
private long size;
private long count;
private long total;
// โญ ์์ ์ ๋ณด
private long start;
private long end;
private long first;
private long last;
private long prev;
private long next;
private long index;
// ์์ฑ์
public Pagination() {
this(0);
}
// ๋ฐ์ดํฐ ๊ฐ์
public Pagination(long total) {
this(PAGE_NUM, total);
}
// ํ์ฌ ๋ฒํธ, ๋ฐ์ดํฐ ๊ฐ์
public Pagination(long page, long total) {
this(page, SIZES, COUNT, total);
}
// ํ์ ์ ๋ณด
public Pagination(long page, long size, long count, long total) {
this.page = page;
this.size = size;
this.count = count;
this.total = total;
calc();
}
// setter
// * ๋ฐ์ดํฐ ๊ฐ์ ์ง์ ํ, ํ์ด์ง ์์ ์ฌ๊ณ์ฐ
public void setTotal(long total) {
this.total = total;
calc();
}
// ํ์ด์ง ์ฒ๋ฆฌ ์์
public void calc() {
// ์ฒซ ๋ฒํธ
this.first = 1;
// ๋ง์ง๋ง ๋ฒํธ
this.last = (this.total - 1) / size + 1;
// ์์ ๋ฒํธ
this.start = ( (page-1) / count ) * count + 1;
// ๋ ๋ฒํธ
this.end = ( (page-1) / count + 1 ) * count;
if( this.end > this.last ) this.end = this.last;
// ์ด์ ๋ฒํธ
this.prev = this.page - 1;
// ๋ค์ ๋ฒํธ
this.next = this.page + 1;
// ๋ฐ์ดํฐ ์์ ๋ฒํธ
this.index = (this.page - 1) * this.size;
}
}
Java
๋ณต์ฌ