-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- webflux 설정 - openfeign 설정
- Loading branch information
Showing
13 changed files
with
345 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
51 changes: 51 additions & 0 deletions
51
api/src/main/kotlin/com/john/lotto/common/dto/BaseResponse.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package com.john.lotto.common.dto | ||
|
||
import org.springframework.http.HttpStatus | ||
import org.springframework.web.reactive.function.BodyInserters | ||
import org.springframework.web.reactive.function.server.ServerResponse | ||
import java.io.Serializable | ||
|
||
/** | ||
* @author yoonho | ||
* @since 2023.06.22 | ||
*/ | ||
data class BaseResponse ( | ||
val message: String?, | ||
val status: HttpStatus, | ||
val data: Any? | ||
): Serializable { | ||
constructor(): this(message = "Success", status = HttpStatus.OK, null) | ||
constructor(message: String?, status: HttpStatus): this(message = message, status = status, null) | ||
|
||
fun error(status: HttpStatus, message: String) = | ||
ServerResponse.status(status) | ||
.bodyValue( | ||
BaseResponse( | ||
message = message, | ||
status = status, | ||
null | ||
) | ||
) | ||
|
||
fun success(data: Any?) = | ||
ServerResponse.ok().body( | ||
BodyInserters.fromValue( | ||
BaseResponse( | ||
message = "Success", | ||
status = HttpStatus.OK, | ||
data | ||
) | ||
) | ||
) | ||
|
||
fun successNoContent() = | ||
ServerResponse.ok().body( | ||
BodyInserters.fromValue( | ||
BaseResponse( | ||
message = "Success", | ||
status = HttpStatus.OK, | ||
null | ||
) | ||
) | ||
) | ||
} |
10 changes: 10 additions & 0 deletions
10
api/src/main/kotlin/com/john/lotto/common/exception/BadRequestException.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package com.john.lotto.common.exception | ||
|
||
/** | ||
* @author yoonho | ||
* @since 2023.06.22 | ||
*/ | ||
class BadRequestException: RuntimeException { | ||
constructor(msg: String?): super(msg) | ||
constructor(): super() | ||
} |
10 changes: 10 additions & 0 deletions
10
api/src/main/kotlin/com/john/lotto/common/exception/InternalServerException.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package com.john.lotto.common.exception | ||
|
||
/** | ||
* @author yoonho | ||
* @since 2023.06.22 | ||
*/ | ||
class InternalServerException: RuntimeException { | ||
constructor(msg: String?): super(msg) | ||
constructor(): super() | ||
} |
43 changes: 43 additions & 0 deletions
43
api/src/main/kotlin/com/john/lotto/common/handler/FeignErrorDecoder.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package com.john.lotto.common.handler | ||
|
||
import com.john.lotto.common.exception.BadRequestException | ||
import com.john.lotto.common.exception.InternalServerException | ||
import feign.Response | ||
import feign.codec.ErrorDecoder | ||
import org.slf4j.LoggerFactory | ||
import org.springframework.http.HttpStatus | ||
import java.io.BufferedReader | ||
import java.io.InputStream | ||
import java.lang.Exception | ||
|
||
/** | ||
* @author yoonho | ||
* @since 2023.06.22 | ||
*/ | ||
class FeignErrorDecoder: ErrorDecoder { | ||
private val log = LoggerFactory.getLogger(this::class.java) | ||
|
||
override fun decode(methodKey: String?, response: Response): Exception { | ||
val status = HttpStatus.resolve(response.status()) ?: HttpStatus.BAD_REQUEST | ||
val body = this.getInputStreamText(input = response.body().asInputStream()) | ||
|
||
if(status.is4xxClientError) { | ||
log.warn(" >>> [decode] 4xx Client Error - methodKey: $methodKey, status: ${response.status()}, body: $body") | ||
throw BadRequestException() | ||
}else if(status.is5xxServerError) { | ||
log.warn(" >>> [decode] 5xx Server Error - methodKey: $methodKey, status: ${response.status()}, body: $body") | ||
throw InternalServerException() | ||
} | ||
|
||
return ErrorDecoder.Default().decode(methodKey, response) | ||
} | ||
|
||
private fun getInputStreamText(input: InputStream): String { | ||
val reader = BufferedReader(input.reader()) | ||
lateinit var content: String | ||
reader.use { | ||
content = it.readText() | ||
} | ||
return content | ||
} | ||
} |
52 changes: 52 additions & 0 deletions
52
api/src/main/kotlin/com/john/lotto/common/handler/WebFluxExceptionHandler.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package com.john.lotto.common.handler | ||
|
||
import com.fasterxml.jackson.databind.ObjectMapper | ||
import com.john.lotto.common.dto.BaseResponse | ||
import org.slf4j.LoggerFactory | ||
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler | ||
import org.springframework.core.annotation.Order | ||
import org.springframework.http.HttpStatus | ||
import org.springframework.http.MediaType | ||
import org.springframework.stereotype.Component | ||
import org.springframework.web.server.ServerWebExchange | ||
import reactor.core.publisher.Mono | ||
|
||
/** | ||
* @author yoonho | ||
* @since 2023.06.22 | ||
*/ | ||
@Component | ||
@Order(-2) | ||
class WebFluxExceptionHandler: ErrorWebExceptionHandler { | ||
|
||
companion object { | ||
private val log = LoggerFactory.getLogger(this::class.java) | ||
private val objectMapper = ObjectMapper() | ||
} | ||
|
||
override fun handle(exchange: ServerWebExchange, ex: Throwable): Mono<Void> { | ||
when(ex) { | ||
is IllegalArgumentException -> { | ||
log.warn(" >>> [handle] IllegalArgumentException occurs - message: {}", ex.message) | ||
return exchange.response.writeWith(Mono.fromSupplier { | ||
val bufferFactory = exchange.response.bufferFactory() | ||
exchange.response.statusCode = HttpStatus.BAD_REQUEST | ||
exchange.response.headers.contentType = MediaType.APPLICATION_JSON | ||
return@fromSupplier bufferFactory.wrap( | ||
objectMapper.writeValueAsBytes(BaseResponse(ex.message, HttpStatus.BAD_REQUEST, null)) | ||
) | ||
}) | ||
} | ||
else -> { | ||
return exchange.response.writeWith(Mono.fromSupplier { | ||
val bufferFactory = exchange.response.bufferFactory() | ||
exchange.response.statusCode = HttpStatus.BAD_REQUEST | ||
exchange.response.headers.contentType = MediaType.APPLICATION_JSON | ||
return@fromSupplier bufferFactory.wrap( | ||
objectMapper.writeValueAsBytes(BaseResponse(ex.message, HttpStatus.BAD_REQUEST, null)) | ||
) | ||
}) | ||
} | ||
} | ||
} | ||
} |
63 changes: 63 additions & 0 deletions
63
api/src/main/kotlin/com/john/lotto/config/OpenFeignConfig.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package com.john.lotto.config | ||
|
||
import com.john.lotto.common.handler.FeignErrorDecoder | ||
import feign.RequestInterceptor | ||
import feign.codec.ErrorDecoder | ||
import org.slf4j.LoggerFactory | ||
import org.springframework.cloud.openfeign.EnableFeignClients | ||
import org.springframework.cloud.openfeign.FeignFormatterRegistrar | ||
import org.springframework.context.annotation.Bean | ||
import org.springframework.context.annotation.Configuration | ||
import org.springframework.format.datetime.standard.DateTimeFormatterRegistrar | ||
import org.springframework.http.MediaType | ||
|
||
/** | ||
* @author yoonho | ||
* @since 2023.06.22 | ||
*/ | ||
@Configuration | ||
@EnableFeignClients(basePackages = ["com.john.lotto"]) | ||
class OpenFeignConfig { | ||
private val log = LoggerFactory.getLogger(this::class.java) | ||
|
||
/** | ||
* LocalDateTime Format 설정 | ||
* | ||
* @see <a href="https://techblog.woowahan.com/2630/">Feign</a> | ||
* @return [FeignFormatterRegistrar] | ||
* @author yoonho | ||
* @since 2023.06.22 | ||
*/ | ||
@Bean | ||
fun localDateFeignFormatterRegister(): FeignFormatterRegistrar = | ||
FeignFormatterRegistrar { registry -> | ||
val registrar = DateTimeFormatterRegistrar() | ||
registrar.setUseIsoFormat(true) | ||
registrar.registerFormatters(registry) | ||
} | ||
|
||
/** | ||
* Request Interceptor | ||
* | ||
* @return [RequestInterceptor] | ||
* @author yoonho | ||
* @since 2023.06.22 | ||
*/ | ||
@Bean | ||
fun requestInterceptor(): RequestInterceptor = | ||
RequestInterceptor { interceptor -> | ||
log.info(" >>> [requestInterceptor] path: ${interceptor.path()}, method: ${interceptor.method()}, body: ${interceptor.body()}, queries: ${interceptor.queries()}") | ||
interceptor.header("Content-Type", MediaType.APPLICATION_JSON_VALUE) | ||
} | ||
|
||
/** | ||
* Error 핸들러 등록 | ||
* | ||
* @return [ErrorDecoder] | ||
* @author yoonho | ||
* @since 2023.06.22 | ||
*/ | ||
@Bean | ||
fun errorDecoder(): ErrorDecoder = | ||
FeignErrorDecoder() | ||
} |
21 changes: 21 additions & 0 deletions
21
api/src/main/kotlin/com/john/lotto/config/WebFluxConfig.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package com.john.lotto.config | ||
|
||
import org.springframework.context.annotation.Configuration | ||
import org.springframework.web.reactive.config.CorsRegistry | ||
import org.springframework.web.reactive.config.EnableWebFlux | ||
import org.springframework.web.reactive.config.WebFluxConfigurer | ||
|
||
/** | ||
* @author yoonho | ||
* @since 2023.06.22 | ||
*/ | ||
@Configuration | ||
@EnableWebFlux | ||
class WebFluxConfig: WebFluxConfigurer { | ||
|
||
override fun addCorsMappings(registry: CorsRegistry) { | ||
registry.addMapping("/webjars/**") | ||
.allowedOrigins("http://localhost:8080") | ||
.allowedMethods("GET", "POST") | ||
} | ||
} |
31 changes: 31 additions & 0 deletions
31
api/src/main/kotlin/com/john/lotto/number/adapter/in/web/NumberHandler.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package com.john.lotto.number.adapter.`in`.web | ||
|
||
import com.john.lotto.common.dto.BaseResponse | ||
import com.john.lotto.common.exception.BadRequestException | ||
import com.john.lotto.number.application.port.`in`.FindLottoNumberUseCase | ||
import feign.FeignException.BadRequest | ||
import org.slf4j.LoggerFactory | ||
import org.springframework.stereotype.Component | ||
import org.springframework.web.reactive.function.server.ServerRequest | ||
import org.springframework.web.reactive.function.server.ServerResponse | ||
import reactor.core.publisher.Mono | ||
|
||
|
||
/** | ||
* @author yoonho | ||
* @since 2023.06.22 | ||
*/ | ||
@Component | ||
class NumberHandler( | ||
private val lottoNumberUseCase: FindLottoNumberUseCase | ||
) { | ||
private val log = LoggerFactory.getLogger(this::class.java) | ||
|
||
fun findLottoNumber(request: ServerRequest): Mono<ServerResponse> = | ||
lottoNumberUseCase.findLottoNumber( | ||
request.queryParam("drwtNo").orElseThrow { BadRequestException("필수 입력값 누락") } | ||
.toLong() | ||
) | ||
.flatMap { BaseResponse().success(it) } | ||
|
||
} |
25 changes: 25 additions & 0 deletions
25
api/src/main/kotlin/com/john/lotto/number/adapter/in/web/NumberRouter.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package com.john.lotto.number.adapter.`in`.web | ||
|
||
import org.springframework.context.annotation.Bean | ||
import org.springframework.context.annotation.Configuration | ||
import org.springframework.http.MediaType | ||
import org.springframework.web.reactive.function.server.RouterFunction | ||
import org.springframework.web.reactive.function.server.ServerResponse | ||
import org.springframework.web.reactive.function.server.router | ||
|
||
/** | ||
* @author yoonho | ||
* @since 2023.06.22 | ||
*/ | ||
@Configuration | ||
class NumberRouter( | ||
private val numberHandler: NumberHandler | ||
) { | ||
|
||
@Bean | ||
fun numberRouterFunction(): RouterFunction<ServerResponse> = router { | ||
accept(MediaType.APPLICATION_JSON).nest { | ||
GET("/api/number", numberHandler::findLottoNumber) | ||
} | ||
} | ||
} |
21 changes: 21 additions & 0 deletions
21
api/src/main/kotlin/com/john/lotto/number/application/NumberService.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package com.john.lotto.number.application | ||
|
||
import com.john.lotto.common.exception.BadRequestException | ||
import com.john.lotto.number.NumberRepository | ||
import com.john.lotto.number.application.port.`in`.FindLottoNumberUseCase | ||
import com.john.lotto.number.dto.LottoNumberDto | ||
import org.springframework.stereotype.Service | ||
import reactor.core.publisher.Mono | ||
|
||
/** | ||
* @author yoonho | ||
* @since 2023.06.22 | ||
*/ | ||
@Service | ||
class NumberService( | ||
private val numberRepository: NumberRepository | ||
): FindLottoNumberUseCase { | ||
|
||
override fun findLottoNumber(drwtNo: Long): Mono<LottoNumberDto> = | ||
Mono.just(numberRepository.findLottoNumber(drwtNo = drwtNo) ?: throw BadRequestException("로또번호가 존재하지 않습니다.")) | ||
} |
12 changes: 12 additions & 0 deletions
12
api/src/main/kotlin/com/john/lotto/number/application/port/in/FindLottoNumberUseCase.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package com.john.lotto.number.application.port.`in` | ||
|
||
import com.john.lotto.number.dto.LottoNumberDto | ||
import reactor.core.publisher.Mono | ||
|
||
/** | ||
* @author yoonho | ||
* @since 2023.06.22 | ||
*/ | ||
interface FindLottoNumberUseCase { | ||
fun findLottoNumber(drwtNo: Long): Mono<LottoNumberDto> | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters