To Do List νλ‘μ νΈ
βTodo List - ν μΌ λͺ©λ‘ UI λ§λ€κΈ°β
μ€ν μ’ λλ¬μ£ΌμΈμ
λ°±μλ (SpringBoot)
λ°μ΄ν°λ² μ΄μ€
todo ν
μ΄λΈ
CREATE TABLE `todo` (
`no` int NOT NULL AUTO_INCREMENT,
`name` text NOT NULL,
`status` int DEFAULT '0',
`reg_date` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`upd_date` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`no`)
) COMMENT='ν μΌ';
SQL
볡μ¬
νλ‘μ νΈ κ΅¬μ‘°
β’
π§ Server
β¦
βͺ
β’
βͺ
β’
βͺ
β’
β’
βͺ
β’
β¦
βͺ
β’
βͺ
βͺ
β¦
μ½λ μμ
1.
2.
3.
4.
β’
5.
β’
6.
β’
7.
β’
β’
8.
β’
build.gradle
plugins {
id 'java'
id 'war'
id 'org.springframework.boot' version '3.1.6'
id 'io.spring.dependency-management' version '1.1.4'
}
group = 'com.joeun'
version = '0.0.1-SNAPSHOT'
java {
sourceCompatibility = '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.3'
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.3'
}
tasks.named('bootBuildImage') {
builder = 'paketobuildpacks/builder-jammy-base:latest'
}
tasks.named('test') {
useJUnitPlatform()
}
Plain Text
볡μ¬
application.properties
# λ°μ΄ν° μμ€ - MySQL
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/joeun?serverTimezone=Asia/Seoul&allowPublicKeyRetrieval=true&useSSL=false&autoReconnection=true&autoReconnection=true
spring.datasource.username=joeun
spring.datasource.password=123456
# Mybatis μ€μ
# Mybatis μ€μ κ²½λ‘ : ~/resources/mybatis-config.xml
mybatis.config-location=classpath:mybatis-config.xml
# Mybatis λ§€νΌ νμΌ κ²½λ‘ : ~/λ©μΈν¨ν€μ§/mapper/**Mapper.xml
mybatis.mapper-locations=classpath:mybatis/mapper/**/**.xml
Plain Text
볡μ¬
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- μ€μ -->
<settings>
<!-- μΈλμ€μ½μ΄ μΌμ΄μ€μΈ 컬λΌμ μΉ΄λ© μΌμ΄μ€λ‘ λ³ννλ μ€μ -->
<!-- board_no - boardNo -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<!-- νμ
λ³μΉ μ€μ -->
<typeAliases>
<!-- ν
μ΄λΈκ³Ό λ§€νν DTOκ° μλ ν¨ν€μ§ κ²½λ‘ μ§μ -->
<package name="com.joeun.todo.dto"/>
</typeAliases>
</configuration>
XML
볡μ¬
main-package/mapper
β’
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace="λ§€νΌ μΈν°νμ΄μ€ κ²½λ‘" -->
<mapper namespace="com.joeun.todo.mapper.TodoMapper">
<!-- ν μΌ λͺ©λ‘ -->
<select id="list" resultType="Todo">
SELECT *
FROM todo
ORDER BY status ASC, no DESC
</select>
<!-- ν μΌ μ‘°ν -->
<select id="select" resultType="Todo">
SELECT *
FROM todo
WHERE no = #{no}
</select>
<!-- ν μΌ λ±λ‘ -->
<insert id="insert">
INSERT INTO todo( name )
VALUES ( #{name} )
</insert>
<!-- ν μΌ μμ -->
<update id="update">
UPDATE todo
SET name = #{name}
,status = #{status}
,upd_date = now()
WHERE no = #{no}
</update>
<!-- ν μΌ μμ -->
<delete id="delete">
DELETE FROM todo
WHERE no = #{no}
</delete>
<!-- last id -->
<select id="lastId" resultType="int">
select last_insert_id() id
</select>
<!-- μ 체 ν μΌ μλ£ -->
<update id="completeAll">
UPDATE todo
SET status = 1
,upd_date = now()
</update>
<!-- μ 체 ν μΌ μμ -->
<delete id="deleteAll">
DELETE FROM todo
</delete>
</mapper>
XML
볡μ¬
mapper
β’
package com.joeun.todo.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import com.joeun.todo.dto.Todo;
@Mapper
public interface TodoMapper {
public List<Todo> list() throws Exception;
public Todo select(int no) throws Exception;
public int insert(Todo todo) throws Exception;
public int update(Todo todo) throws Exception;
public int delete(int no) throws Exception;
public int lastId() throws Exception;
public int completeAll() throws Exception;
public int deleteAll() throws Exception;
}
Java
볡μ¬
dto
β’
package com.joeun.todo.service;
import java.util.List;
import com.joeun.todo.dto.Todo;
public interface TodoService {
public List<Todo> list() throws Exception;
public Todo select(int no) throws Exception;
public int insert(Todo todo) throws Exception;
public int update(Todo todo) throws Exception;
public int delete(int no) throws Exception;
public int lastId() throws Exception;
public int completeAll() throws Exception;
public int deleteAll() throws Exception;
}
Java
볡μ¬
service
β’
package com.joeun.todo.service;
import java.util.List;
import com.joeun.todo.dto.Todo;
public interface TodoService {
public List<Todo> list() throws Exception;
public Todo select(int no) throws Exception;
public int insert(Todo todo) throws Exception;
public int update(Todo todo) throws Exception;
public int delete(int no) throws Exception;
public int lastId() throws Exception;
public int completeAll() throws Exception;
public int deleteAll() throws Exception;
}
Java
볡μ¬
β’
package com.joeun.todo.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.joeun.todo.dto.Todo;
import com.joeun.todo.mapper.TodoMapper;
@Service
public class TodoServiceImpl implements TodoService {
@Autowired
private TodoMapper todoMapper;
@Override
public List<Todo> list() throws Exception {
return todoMapper.list();
}
@Override
public Todo select(int no) throws Exception {
return todoMapper.select(no);
}
@Override
public int insert(Todo todo) throws Exception {
int result = todoMapper.insert(todo);
if( result > 0 )
result = todoMapper.lastId();
return result;
}
@Override
public int update(Todo todo) throws Exception {
return todoMapper.update(todo);
}
@Override
public int delete(int no) throws Exception {
return todoMapper.delete(no);
}
@Override
public int lastId() throws Exception {
return todoMapper.lastId();
}
@Override
public int completeAll() throws Exception {
return todoMapper.completeAll();
}
@Override
public int deleteAll() throws Exception {
return todoMapper.deleteAll();
}
}
Java
볡μ¬
controller
β’
[Extension] Spring Code Generator
κΏν : sp-crud
package com.joeun.todo.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
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 com.joeun.todo.dto.Todo;
import com.joeun.todo.service.TodoService;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@RestController
@CrossOrigin(origins = "*") // cors νμ©
@RequestMapping("/todos")
public class TodoController {
@Autowired
private TodoService todoService;
@GetMapping()
public ResponseEntity<?> getAll() {
log.info("list...");
try {
List<Todo> todoList = todoService.list();
log.info("ν μΌ κ°μ : " + todoList.size());
return new ResponseEntity<>(todoList, HttpStatus.OK);
} catch (Exception e) {
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@GetMapping("/{id}")
public ResponseEntity<?> getOne(@PathVariable Integer id) {
log.info("select...");
log.info("id : " + id);
try {
Todo todo = todoService.select(id);
log.info("todo : " + todo);
return new ResponseEntity<>(todo, HttpStatus.OK);
} catch (Exception e) {
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@PostMapping()
public ResponseEntity<?> create(@RequestBody Todo todo) {
log.info("insert...");
try {
int result = todoService.insert(todo); // μλ‘ μμ±λ no λ₯Ό μλ΅
todo.setNo(result);
log.info("result : " + result);
if( result > 0 )
return new ResponseEntity<>(todo, HttpStatus.CREATED);
else
return new ResponseEntity<>(todo, HttpStatus.OK);
} catch (Exception e) {
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@PutMapping()
public ResponseEntity<?> update(@RequestBody Todo todo) {
log.info("update...");
log.info(todo.toString());
try {
int result = 0;
// μ 체 μλ£
if( todo.getNo() == -1 ) {
result = todoService.completeAll();
}
else {
result = todoService.update(todo);
}
if( result > 0 )
return new ResponseEntity<>("Update Result", HttpStatus.OK);
else
return new ResponseEntity<>("No Result", HttpStatus.OK);
} catch (Exception e) {
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@DeleteMapping("/{id}")
public ResponseEntity<?> destroy(@PathVariable Integer id) {
log.info("delete...");
log.info("id : " + id);
try {
int result = 0;
// μ 체 μμ
if( id == -1 ) {
result = todoService.deleteAll();
}
else {
result = todoService.delete(id);
}
if( result > 0 )
return new ResponseEntity<>("Destroy Result", HttpStatus.OK);
else
return new ResponseEntity<>("No Result", HttpStatus.OK);
} catch (Exception e) {
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
}
Java
볡μ¬
ν μ€νΈ
κ²μκΈ λͺ©λ‘ [GET]
http://localhost:8080/boards
Plain Text
볡μ¬
κ²μκΈ μ‘°ν [GET]
http://localhost:8080/boards/1
Plain Text
볡μ¬
κ²μκΈ λ±λ‘ [POST]
http://localhost:8080/boards
Plain Text
볡μ¬
κ²μκΈ μμ [PUT]
http://localhost:8080/boards
Plain Text
볡μ¬
κ²μκΈ μμ [DELETE]
http://localhost:8080/boards/1
Plain Text
볡μ¬