의존성 추가
build.gradle dependencies 안에 아래 코드 추가
implementation("org.springframework.boot:spring-boot-starter-validation")
build.gradle.kt
plugins {
id("org.springframework.boot") version "3.4.2"
id("io.spring.dependency-management") version "1.1.7"
id("java")
id("org.jetbrains.kotlin.jvm") version "1.9.25"
id("org.jetbrains.kotlin.plugin.jpa") version "1.9.25"
id("org.jetbrains.kotlin.plugin.spring") version "1.9.25"
id("org.jetbrains.kotlin.kapt") version "1.9.25"
}
group = "com.contact"
version = "0.0.1-SNAPSHOT"
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(17))
}
}
repositories {
mavenCentral()
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("org.springframework.boot:spring-boot-starter-validation")
runtimeOnly("com.h2database:h2")
testImplementation("org.springframework.boot:spring-boot-starter-test")
}
tasks.withType<Test> {
useJUnitPlatform()
}
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
kotlinOptions {
jvmTarget = "17"
}
}
UserDto.kt
package com.contact.management.dto
import jakarta.validation.constraints.Email
import jakarta.validation.constraints.Size
data class UserDto(
val id: Long?= null,
@field:Size(min = 2, max = 50, message = "이름은 2~50자 사이여야 합니다.")
val name: String,
@field:Email(message = "올바른 이메일 형식을 입력하세요.")
val email: String
)
GlobalExceptionHandler.kt
package com.contact.management.exception
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.MethodArgumentNotValidException
import org.springframework.web.bind.annotation.ExceptionHandler
import org.springframework.web.bind.annotation.RestControllerAdvice
@RestControllerAdvice
class GlobalExceptionHandler {
@ExceptionHandler(CommonException::class)
fun handleCommonException(e: CommonException): ResponseEntity<ErrorResponse> {
val errorResponse = ErrorResponse(
status = e.exceptionCode.status.value(),
error = e.exceptionCode.message,
message = e.message ?: "예외 발생"
)
return ResponseEntity(errorResponse, e.exceptionCode.status)
}
@ExceptionHandler(MethodArgumentNotValidException::class)
fun handleValidationExceptions(ex: MethodArgumentNotValidException): ResponseEntity<ErrorResponse> {
val errors = ex.bindingResult.fieldErrors.associate { it.field to (it.defaultMessage ?: "잘못된 값") }
val errorResponse = ErrorResponse(
status = HttpStatus.BAD_REQUEST.value(),
error = "Validation Failed",
message = "입력값이 올바르지 않습니다.",
errors = errors
)
return ResponseEntity(errorResponse, HttpStatus.BAD_REQUEST)
}
}
-> handlerValdationExceptions를 추가함, vadliation에 걸렸을때 errorResponse에 400 BAD_REQUEST, 에러 내용을 return 하게 설정함
UserController.kt
package com.contact.management.controller
import com.contact.management.dto.UserDto
import com.contact.management.service.UserService
import jakarta.validation.Valid
import org.springframework.http.HttpHeaders
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.*
@RestController
@RequestMapping("/api/users")
class UserController(
private val userService: UserService
) {
@GetMapping
fun getUsers(): ResponseEntity<List<UserDto>> {
val users = userService.getAllUsers()
return ResponseEntity.ok(users)
}
@GetMapping("/{id}")
fun getUser(@PathVariable id: Long): ResponseEntity<UserDto> {
return ResponseEntity.ok(userService.getUserById(id))
}
@PostMapping
fun createUser(@Valid @RequestBody userDto: UserDto): ResponseEntity<UserDto> {
val createdUser = userService.createdUser(userDto)
return ResponseEntity
.status(HttpStatus.CREATED) // 201 Created
.header(HttpHeaders.LOCATION, "/api/users/${createdUser.id}") // 생성된 리소스의 URI 반환
.body(createdUser)
}
@PutMapping("/{id}")
fun updateUser(@PathVariable id: Long,@Valid @RequestBody userDto: UserDto): ResponseEntity<UserDto> {
val updatedUser = userService.updateUser(id, userDto)
return ResponseEntity.ok(updatedUser)
}
@DeleteMapping("/{id}")
fun deleteUser(@PathVariable id: Long): ResponseEntity<Void> {
userService.deleteUser(id)
return ResponseEntity.noContent().build() // 204 No Content
}
}
-> createUser, updateUser api에 @Valid를 추가
이름 길이가 2~50자가 아닌경우
이메일 형식을 벗어난 경우
만약 GlobalException에 handleValidationExceptions를 적용하지않았다면
-> GlobalExcpetionHandler에 등록했을때와 비교했을때 에러 메시지가 부족