diff --git a/build.gradle.kts b/build.gradle.kts index b1e5524..9e98a10 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -28,9 +28,14 @@ dependencies { // implementation ("jakarta.servlet:jakarta.servlet-api") //스프링부트 3.0 이상 // implementation ("jakarta.servlet.jsp.jstl:jakarta.servlet.jsp.jstl-api") //스프링부트 3.0 이상 // implementation ("org.glassfish.web:jakarta.servlet.jsp.jstl") //스프링부트 3.0 이상 + implementation ("org.slf4j:jcl-over-slf4j") +// implementation ("org.springframework.boot:spring-boot-starter-batch") + implementation ("org.springframework.boot:spring-boot-starter-quartz") + implementation ("com.google.code.gson:gson:2.11.0") implementation ("org.apache.tomcat.embed:tomcat-embed-jasper") implementation("org.springframework.boot:spring-boot-starter-data-mongodb-reactive") implementation("org.springframework.boot:spring-boot-starter-web") + implementation("org.springframework.boot:spring-boot-starter-webflux") implementation("com.fasterxml.jackson.module:jackson-module-kotlin") implementation("io.projectreactor.kotlin:reactor-kotlin-extensions") implementation("org.jetbrains.kotlin:kotlin-reflect") diff --git a/src/main/kotlin/kr/lunaticbum/back/lun/LunApplication.kt b/src/main/kotlin/kr/lunaticbum/back/lun/LunApplication.kt index 3d7bbe4..fbd7c63 100644 --- a/src/main/kotlin/kr/lunaticbum/back/lun/LunApplication.kt +++ b/src/main/kotlin/kr/lunaticbum/back/lun/LunApplication.kt @@ -1,15 +1,42 @@ package kr.lunaticbum.back.lun +import com.google.gson.Gson +import kr.lunaticbum.back.lun.model.CurrentWeather import org.springframework.boot.CommandLineRunner import org.springframework.boot.SpringApplication import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication import org.springframework.context.annotation.Bean +import org.springframework.scheduling.annotation.EnableScheduling +import org.springframework.scheduling.annotation.Scheduled +import org.springframework.web.reactive.function.client.WebClient +import java.time.LocalDateTime import java.util.* - +@EnableScheduling // 추가 @SpringBootApplication -class LunApplication +class LunApplication { + @Scheduled(cron = "0 0 0/4 * * *") // + fun runJob() { + try { + val client0 = WebClient.create() + val result = client0.get() + .uri("http://api.weatherapi.com/v1/current.json?key=de574a260b1f474d99955729241909&q=seoul&aqi=no") + .retrieve() + .bodyToMono(String::class.java).block() ?: "FAIL" + var sss = Gson().fromJson(result,CurrentWeather::class.java) + + val client = WebClient.create() + client.get() + .uri("https://api.telegram.org/bot7934509464:AAE_xUbICxMdywLGnxo7BkeIqA1nVza4P9w/sendMessage?chat_id=71476436&text=온도${sss.current?.temp_c}") + .retrieve() + .bodyToMono(String::class.java).block() ?: "FAIL" + }catch (e : Exception) { + e.printStackTrace() + } + + } +} fun main(args: Array) { diff --git a/src/main/kotlin/kr/lunaticbum/back/lun/batch/BatchScheduler.kt b/src/main/kotlin/kr/lunaticbum/back/lun/batch/BatchScheduler.kt new file mode 100644 index 0000000..e941989 --- /dev/null +++ b/src/main/kotlin/kr/lunaticbum/back/lun/batch/BatchScheduler.kt @@ -0,0 +1,18 @@ +//package kr.lunaticbum.back.lun.batch +// +//import lombok.RequiredArgsConstructor +//import org.springframework.batch.core.Job +//import org.springframework.batch.core.JobParametersBuilder +//import org.springframework.batch.core.JobParametersInvalidException +//import org.springframework.batch.core.configuration.JobRegistry +//import org.springframework.batch.core.configuration.support.JobRegistryBeanPostProcessor +//import org.springframework.batch.core.launch.JobLauncher +//import org.springframework.batch.core.launch.NoSuchJobException +//import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException +//import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException +//import org.springframework.batch.core.repository.JobRestartException +//import org.springframework.context.annotation.Bean +//import org.springframework.scheduling.annotation.Scheduled +//import org.springframework.stereotype.Component +//import java.time.LocalDateTime +// diff --git a/src/main/kotlin/kr/lunaticbum/back/lun/configs/BatchConfig.kt b/src/main/kotlin/kr/lunaticbum/back/lun/configs/BatchConfig.kt new file mode 100644 index 0000000..6e27c5d --- /dev/null +++ b/src/main/kotlin/kr/lunaticbum/back/lun/configs/BatchConfig.kt @@ -0,0 +1,62 @@ +//package kr.lunaticbum.back.lun.configs +// +//import lombok.RequiredArgsConstructor +//import lombok.extern.slf4j.Slf4j +//import org.springframework.batch.core.Job +//import org.springframework.batch.core.Step +//import org.springframework.batch.core.StepContribution +//import org.springframework.batch.core.configuration.DuplicateJobException +//import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing +//import org.springframework.batch.core.configuration.support.DefaultBatchConfiguration +//import org.springframework.batch.core.job.builder.JobBuilder +//import org.springframework.batch.core.repository.JobRepository +//import org.springframework.batch.core.scope.context.ChunkContext +//import org.springframework.batch.core.step.builder.StepBuilder +//import org.springframework.batch.core.step.tasklet.Tasklet +//import org.springframework.batch.repeat.RepeatStatus +//import org.springframework.context.annotation.Bean +//import org.springframework.context.annotation.Configuration +//import org.springframework.transaction.PlatformTransactionManager +//import org.springframework.web.reactive.function.client.WebClient +// +// +//@Configuration +//@RequiredArgsConstructor +//class BatchConfig : DefaultBatchConfiguration() { +// +// @Bean +// @Throws(DuplicateJobException::class) +// fun testJob(jobRepository: JobRepository, transactionManager: PlatformTransactionManager?): Job { +// val job: Job = JobBuilder("testJob", jobRepository!!) +// .start(testStep(jobRepository, transactionManager)) +// .build() +// return job +// } +// +// fun testStep(jobRepository: JobRepository?, transactionManager: PlatformTransactionManager?): Step { +// val step: Step = StepBuilder("testStep", jobRepository!!) +// .tasklet(testTasklet(), transactionManager!!) +// .build() +// return step +// } +// +// fun testTasklet(): Tasklet { +// return (Tasklet { contribution: StepContribution?, chunkContext: ChunkContext? -> +// println("***** hello batch! *****") +// val client0 = WebClient.create() +// val result = client0.get() +// .uri("http://api.weatherapi.com/v1/current.json?key=de574a260b1f474d99955729241909&q=seoul&aqi=no") +// .retrieve() +// .bodyToMono(String::class.java).block() ?: "FAIL" +// +// +// val client = WebClient.create() +// client.get() +// .uri("https://api.telegram.org/bot7934509464:AAE_xUbICxMdywLGnxo7BkeIqA1nVza4P9w/sendMessage?chat_id=71476436&text=${result}") +// .retrieve() +// .bodyToMono(String::class.java).block() ?: "FAIL" +// +// RepeatStatus.FINISHED +// }) +// } +//} \ No newline at end of file diff --git a/src/main/kotlin/kr/lunaticbum/back/lun/configs/WebConfig.kt b/src/main/kotlin/kr/lunaticbum/back/lun/configs/WebConfig.kt index b366abf..9f4cd5f 100644 --- a/src/main/kotlin/kr/lunaticbum/back/lun/configs/WebConfig.kt +++ b/src/main/kotlin/kr/lunaticbum/back/lun/configs/WebConfig.kt @@ -1,14 +1,43 @@ package kr.lunaticbum.back.lun.configs +import io.netty.channel.ChannelOption +import io.netty.handler.timeout.ReadTimeoutHandler +import io.netty.handler.timeout.WriteTimeoutHandler import jakarta.servlet.ServletContext import jakarta.servlet.ServletException +import kr.lunaticbum.back.lun.utils.LogService +import kr.lunaticbum.back.lun.utils.Logger +import lombok.RequiredArgsConstructor +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.context.annotation.Bean +import org.springframework.http.client.reactive.ReactorClientHttpConnector import org.springframework.web.WebApplicationInitializer import org.springframework.web.context.ContextLoaderListener import org.springframework.web.context.support.AnnotationConfigWebApplicationContext +import org.springframework.web.reactive.function.client.ClientRequest +import org.springframework.web.reactive.function.client.ClientResponse +import org.springframework.web.reactive.function.client.ExchangeFilterFunction +import org.springframework.web.reactive.function.client.WebClient import org.springframework.web.servlet.DispatcherServlet +import org.springframework.web.util.DefaultUriBuilderFactory +import reactor.core.publisher.Mono +import reactor.netty.Connection +import reactor.netty.http.client.HttpClient +import java.time.Duration +import java.util.concurrent.TimeUnit +import java.util.function.Consumer - +@RequiredArgsConstructor class WebConfig : WebApplicationInitializer { + + lateinit var logService : LogService + + var factory: DefaultUriBuilderFactory = DefaultUriBuilderFactory() + + var httpClient: HttpClient = HttpClient.create() + .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000) // 10초 + + @Throws(ServletException::class) override fun onStartup(servletContext: ServletContext) { // Spring MVC 프로젝트 설정을 위해 작성하는 클래스의 객체를 생성한다. @@ -30,4 +59,62 @@ class WebConfig : WebApplicationInitializer { val listener = ContextLoaderListener(rootAppContext) servletContext.addListener(listener) } + + + + @Bean + fun webClient(): WebClient { + /** + * 통신시 timeout 세팅 + * - connect, read, write 를 모두 5000ms + */ + + val httpClient = HttpClient.create() + .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000) + .responseTimeout(Duration.ofMillis(5000)) + .doOnConnected { conn: Connection -> + conn.addHandlerLast(ReadTimeoutHandler(5000, TimeUnit.MILLISECONDS)) + .addHandlerLast(WriteTimeoutHandler(5000, TimeUnit.MILLISECONDS)) + } + + val webClient = WebClient.builder() + .baseUrl("https://api.telegram.org/bot7934509464:AAE_xUbICxMdywLGnxo7BkeIqA1nVza4P9w") + .clientConnector(ReactorClientHttpConnector(httpClient)) //생성한 HttpClient 연결 + //Request Header 로깅 필터 + .filter( + ExchangeFilterFunction.ofRequestProcessor { clientRequest: ClientRequest -> + logService.log(">>>>>>>>> REQUEST <<<<<<<<<<") + logService.log("Request: ${clientRequest.method()} ${clientRequest.url()}") + clientRequest.headers() + .forEach { (name: String?, values: MutableList?) -> + values.forEach( + Consumer { value: String? -> + logService.log( + "${name} : ${value}" + ) + }) + } + Mono.just(clientRequest) + } + ) //Response Header 로깅 필터 + .filter( + ExchangeFilterFunction.ofResponseProcessor { clientResponse: ClientResponse -> + logService.log(">>>>>>>>>> RESPONSE <<<<<<<<<<") + clientResponse.headers().asHttpHeaders() + .forEach { (name: String?, values: MutableList?) -> + values.forEach( + Consumer { value: String? -> + logService.log( + "${name} ${value}" + ) + }) + } + Mono.just(clientResponse) + } + ) + .defaultHeader("Content-type", "application/x-www-form-urlencoded;charset=utf-8") //기본 헤더설정 + .build() + + return webClient + } } \ No newline at end of file diff --git a/src/main/kotlin/kr/lunaticbum/back/lun/controllers/Telegram.kt b/src/main/kotlin/kr/lunaticbum/back/lun/controllers/Telegram.kt index e42637a..d539441 100644 --- a/src/main/kotlin/kr/lunaticbum/back/lun/controllers/Telegram.kt +++ b/src/main/kotlin/kr/lunaticbum/back/lun/controllers/Telegram.kt @@ -1,16 +1,39 @@ package kr.lunaticbum.back.lun.controllers -import org.springframework.web.bind.annotation.GetMapping -import org.springframework.web.bind.annotation.RequestMapping -import org.springframework.web.bind.annotation.ResponseBody -import org.springframework.web.bind.annotation.RestController +import org.springframework.web.bind.annotation.* +import org.springframework.web.reactive.function.client.WebClient @RestController -@RequestMapping("tlbt") +@RequestMapping("tlg") class Telegram { @ResponseBody @GetMapping("/hello") fun hello(): String { return "hello1212" } + + @ResponseBody + @GetMapping("webhook") + fun test(@PathVariable path : String) { + println("path >>> $path") + val client = WebClient.create() + client.get() + .uri("https://api.telegram.org/bot7934509464:AAE_xUbICxMdywLGnxo7BkeIqA1nVza4P9w/getUpdates") + .retrieve() + .bodyToMono(String::class.java).block() ?: "FAIL" + + } + +// @ResponseBody +// @GetMapping("webhook") +// fun test(@PathVariable path : String) { +// println("path >>> $path") +// val client = WebClient.create() +// client.get() +// .uri("https://api.telegram.org/bot7934509464:AAE_xUbICxMdywLGnxo7BkeIqA1nVza4P9w/getUpdates") +// .retrieve() +// .bodyToMono(String::class.java).block() ?: "FAIL" +// +// } + } \ No newline at end of file diff --git a/src/main/kotlin/kr/lunaticbum/back/lun/controllers/User.kt b/src/main/kotlin/kr/lunaticbum/back/lun/controllers/User.kt index 560aa51..f0a93fe 100644 --- a/src/main/kotlin/kr/lunaticbum/back/lun/controllers/User.kt +++ b/src/main/kotlin/kr/lunaticbum/back/lun/controllers/User.kt @@ -2,12 +2,14 @@ package kr.lunaticbum.back.lun.controllers import jakarta.servlet.http.HttpServletRequest import org.springframework.web.bind.annotation.* +import org.springframework.web.reactive.function.client.WebClient import org.springframework.web.servlet.ModelAndView import org.springframework.web.servlet.view.ContentNegotiatingViewResolver + @RestController @RequestMapping("/user") -class User(private val viewResolver: ContentNegotiatingViewResolver) { +class User { @GetMapping("join") fun hello(httpServletRequest: HttpServletRequest): ModelAndView { @@ -19,6 +21,8 @@ class User(private val viewResolver: ContentNegotiatingViewResolver) { } + + @ResponseBody @PostMapping("joinUser.api") fun joinUser(httpServletRequest: HttpServletRequest, @RequestBody jsonString: String) : String { @@ -32,6 +36,10 @@ class User(private val viewResolver: ContentNegotiatingViewResolver) { @GetMapping("test/{path}") fun test(@PathVariable path : String): String { println("path >>> $path") - return "ok" + val client = WebClient.create() + return client.get() + .uri("https://api.telegram.org/bot7934509464:AAE_xUbICxMdywLGnxo7BkeIqA1nVza4P9w/sendMessage?chat_id=71476436&text=${path}") + .retrieve() + .bodyToMono(String::class.java).block() ?: "FAIL" } } \ No newline at end of file diff --git a/src/main/kotlin/kr/lunaticbum/back/lun/model/Weather.kt b/src/main/kotlin/kr/lunaticbum/back/lun/model/Weather.kt new file mode 100644 index 0000000..2a1927b --- /dev/null +++ b/src/main/kotlin/kr/lunaticbum/back/lun/model/Weather.kt @@ -0,0 +1,55 @@ +package kr.lunaticbum.back.lun.model + +class Condition { + var text: String? = null + var icon: String? = null + var code: Int = 0 +} + +class Current { + var last_updated_epoch: Int = 0 + var last_updated: String? = null + var temp_c: Double = 0.0 + var temp_f: Double = 0.0 + var is_day: Int = 0 + var condition: Condition? = null + var wind_mph: Double = 0.0 + var wind_kph: Double = 0.0 + var wind_degree: Int = 0 + var wind_dir: String? = null + var pressure_mb: Double = 0.0 + var pressure_in: Double = 0.0 + var precip_mm: Double = 0.0 + var precip_in: Double = 0.0 + var humidity: Int = 0 + var cloud: Int = 0 + var feelslike_c: Double = 0.0 + var feelslike_f: Double = 0.0 + var windchill_c: Double = 0.0 + var windchill_f: Double = 0.0 + var heatindex_c: Double = 0.0 + var heatindex_f: Double = 0.0 + var dewpoint_c: Double = 0.0 + var dewpoint_f: Double = 0.0 + var vis_km: Double = 0.0 + var vis_miles: Double = 0.0 + var uv: Double = 0.0 + var gust_mph: Double = 0.0 + var gust_kph: Double = 0.0 +} + +class Location { + var name: String? = null + var region: String? = null + var country: String? = null + var lat: Double = 0.0 + var lon: Double = 0.0 + var tz_id: String? = null + var localtime_epoch: Int = 0 + var localtime: String? = null +} + +class CurrentWeather { + var location: Location? = null + var current: Current? = null +} \ No newline at end of file diff --git a/src/main/kotlin/kr/lunaticbum/back/lun/utils/Logger.kt b/src/main/kotlin/kr/lunaticbum/back/lun/utils/Logger.kt index 8dd0d80..06a9e13 100644 --- a/src/main/kotlin/kr/lunaticbum/back/lun/utils/Logger.kt +++ b/src/main/kotlin/kr/lunaticbum/back/lun/utils/Logger.kt @@ -27,6 +27,8 @@ class Logger { println("[$uuid] [$requestURL] $message") } + + @PostConstruct fun init() { uuid = UUID.randomUUID().toString() @@ -46,6 +48,9 @@ class LogService { fun logic(id: String) { myLogger?.log("service id = $id") } + fun log(id: String) { + myLogger?.log("log = $id") + } } @Controller diff --git a/src/main/kotlin/kr/lunaticbum/back/lun/utils/WebClientUtil.kt b/src/main/kotlin/kr/lunaticbum/back/lun/utils/WebClientUtil.kt new file mode 100644 index 0000000..0dca0f5 --- /dev/null +++ b/src/main/kotlin/kr/lunaticbum/back/lun/utils/WebClientUtil.kt @@ -0,0 +1,17 @@ +package kr.lunaticbum.back.lun.utils + +import kr.lunaticbum.back.lun.configs.WebConfig +import lombok.RequiredArgsConstructor +import org.apache.logging.log4j.util.InternalException +import org.springframework.http.HttpMethod +import org.springframework.http.HttpStatus +import org.springframework.stereotype.Component +import reactor.core.publisher.Mono + + +//@Component +//@RequiredArgsConstructor +//class WebClientUtil { +// private val webClientConfig: WebConfig? = null +// +//}