使用OpenFeign与DMM.com进行通信.

目录

    • 概要

 

    • 環境

 

    • 構成

 

    • 各種サービスの用意

 

    • 実装内容

 

    • 実行結果

 

    • 所感

 

    参考資料

简要概括

我在这里描述了使用OpenFeign来创建与DMM.com通信的应用程序的一系列过程。
关于页面部分,我们请ChatGPT为我们创建了一个基础,然后我们努力将其转换为Thymeleaf。
如果你只想查看源代码,请点击这里。

image.png

环境

    • Kotlin 1.8.22

 

    SpringBoot 3.1.5

组成

通过应用程序与关键字协作,获取并显示商品信息。
商品搜索功能使用了DMM.com提供的商品搜索API。
请查阅此处以了解API的规格。

提供多种服务提前准备

在使用API之前,需要进行DMM.com的会员注册、注册会员销售联盟以及申请API使用。请参考此处以获取更多详细信息。

实施内容

OpenFeign允许我们通过注解来描述通信方式,如下所示:
可以在Config类中进行各种设置,并通过指定该类来应用这些设置。
有关注解的详细规范,请参考此处。
※以下代码通过POJO方式传递查询参数。
可以使用@RequestParam注解将每个值作为参数单独传递。
个人认为使用DTO更容易管理,因此在这里我使用了DTO进行说明。

package com.example.openfeignexample.client

import com.example.openfeignexample.client.dto.GetItemsRequest
import com.example.openfeignexample.client.dto.GetItemsResponse
import com.example.openfeignexample.config.interceptor.DmmApiConfig
import org.springframework.cloud.openfeign.FeignClient
import org.springframework.cloud.openfeign.SpringQueryMap
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.GetMapping

@FeignClient(name = "DMMClient", url = "\${dmm-api.url}", configuration = [DmmApiConfig::class])
interface DmmClient {

	@GetMapping("/ItemList")
	fun getItems(@SpringQueryMap request: GetItemsRequest): ResponseEntity<GetItemsResponse>
}

以下为商品搜索API的请求内容。
虽然需要API密钥和联盟ID,但与其他通用要求无关。

package com.example.openfeignexample.client.dto

data class GetItemsRequest(
	val site: String = "DMM.com",
	val keyword: String,
	val hits: Int = 100,
	val sort: String = "date"
)

在Config类中进行了以下三个设置。虽然它们被注册为Bean,但日志级别等设置也可以通过配置文件进行设置。

    • APIキー等の付与。

 

    • リトライ設定。

 

    ログ出力設定。
package com.example.openfeignexample.config.interceptor

import com.example.openfeignexample.client.constant.DmmHeaders
import com.example.openfeignexample.constant.DmmApiConfigProperty
import com.example.openfeignexample.util.ConfigUtil
import feign.Logger
import feign.Request
import feign.RequestInterceptor
import feign.Response
import feign.RetryableException
import feign.Retryer
import feign.codec.ErrorDecoder
import org.apache.commons.io.IOUtils
import org.slf4j.LoggerFactory
import org.springframework.context.annotation.Bean
import org.springframework.http.HttpHeaders
import org.springframework.http.HttpStatus
import org.springframework.http.MediaType
import java.io.InputStream
import java.lang.Exception
import java.net.URLDecoder

class DmmApiConfig(
	private val property: DmmApiConfigProperty,
	private val configUtil: ConfigUtil
) {

	private val log = LoggerFactory.getLogger(this::class.java)

	@Bean
	fun requestInterceptor(): RequestInterceptor {
		return RequestInterceptor { requestTemplate ->
			requestTemplate.query(DmmHeaders.DMM_API_ID, property.apiId)
			requestTemplate.query(DmmHeaders.AFFILIATE_ID, property.affiliateId)

			requestTemplate.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
			requestTemplate.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
		}
	}

	@Bean
	fun retry(): Retryer {
		return Retryer.Default(
			property.retryPeriod,
			property.retryDuration,
			property.retryMaxCount
		)
	}

	@Bean
	fun errorDecoder(): ErrorDecoder {
		return object : ErrorDecoder {

			override fun decode(methodKey: String?, response: Response?): Exception {
				val status = response?.status()
				if (status == HttpStatus.GATEWAY_TIMEOUT.value()) {
					val request = response.request()
					val method = request?.httpMethod()
					return RetryableException(status, "504: Gateway Timeout.", method, null, request)
				}

				return ErrorDecoder.Default().decode(methodKey, response)
			}
		}
	}

	@Bean
	fun logLevel(): Logger.Level {
		return Logger.Level.FULL
	}

	@Bean
	fun logger(): Logger {
		return object : Logger() {

			override fun log(configKey: String?, format: String?, vararg args: Any?) {
				// Not Used
			}

			override fun logRetry(configKey: String?, logLevel: Level?) {
				log.info(configKey, "RETRYING!!")
			}

			override fun logRequest(configKey: String?, logLevel: Level?, request: Request?) {
				if (logLevel != Level.FULL) {
					return
				}

				val url = request?.requestTemplate()?.path()
				val method = request?.httpMethod()
				val query = buildQuery(request?.requestTemplate()?.queries() ?: emptyMap())
				val body = buildBody(request?.body()?.inputStream())
				log.info(configUtil.getLogMessage("BE8001"), url, method, query, body)
			}

			override fun logAndRebufferResponse(configKey: String?, logLevel: Level?, response: Response?, elapsedTime: Long): Response {
				if (logLevel != Level.FULL) {
					return response!!
				}

				val request = response?.request()
				val url = request?.requestTemplate()?.path()
				val method = request?.httpMethod()
				val query = buildQuery(request?.requestTemplate()?.queries() ?: emptyMap())
				val body = buildBody(request?.body()?.inputStream())
				val status = response?.status()
				log.info(configUtil.getLogMessage("BE8002"), url, method, query, body, status, elapsedTime)
				return response!!
			}

			private fun buildQuery(queryMap: Map<String, Collection<String>>): Map<String, Collection<String>> {
				return queryMap.filterNot {
					it.key == DmmHeaders.DMM_API_ID ||
						it.key == DmmHeaders.AFFILIATE_ID
				}.mapValues {
					it.value.map { value ->
						URLDecoder.decode(value, Charsets.UTF_8)
					}
				}
			}

			private fun buildBody(body: InputStream?): String {
				if (body == null) {
					return "{}"
				}

				return IOUtils.toString(body, Charsets.UTF_8)
			}
		}
	}
}

连接信息和API密钥是通过环境变量进行管理的。

spring:
  application:
    name: OpenFeign-Example
  main:
    banner-mode: off
    log-startup-info: false
  messages:
    basename: messages
    encoding: UTF-8
    fallback-to-system-locale: false

server:
  tomcat:
    max-threads: ${TOMCAT_MAX_THREADS:200}
    min-spare-threads: ${TOMCAT_MIN_THREADS:20}
  shutdown: graceful
  port: ${PORT:5000}

dmm-api:
  url: https://api.dmm.com/affiliate/v3
  api-id: ${DMM_API_ID}
  affiliate-id: ${DMM_API_AFFILIATE_ID}
  retry-max-count: ${DMM_API_RETRY_MAX_COUNT:5}
  retry-period: ${DMM_API_RETRY_PERIOD:100}
  retry-duration: ${DMM_API_RETRY_DURATION:1000}

logging:
  level:
    root: ${LOG_LEVEL:INFO}
package com.example.openfeignexample.constant

import org.springframework.beans.factory.annotation.Value
import org.springframework.context.annotation.Configuration

@Configuration
class DmmApiConfigProperty {

	@Value("\${dmm-api.url}")
	val url: String = ""

	@Value("\${dmm-api.api-id}")
	val apiId: String = ""

	@Value("\${dmm-api.affiliate-id}")
	val affiliateId: String = ""

	@Value("\${dmm-api.retry-max-count}")
	val retryMaxCount: Int = 0

	@Value("\${dmm-api.retry-period}")
	val retryPeriod: Long = 0

	@Value("\${dmm-api.retry-duration}")
	val retryDuration: Long = 0
}

设定日志消息

# 8XXX: 外部通信関連
BE8001=SEND: URL={}, Method={}, Query={}, Body={}
BE8002=RECV: URL={}, Method={}, Query={}, Body={}, Status={}, Time={}ms

执行结果

image.png
"C:\Program Files\Java\jdk-17\bin\java.exe" "-javaagent:C:\Users\golde\AppData\Local\Programs\IntelliJ IDEA Community Edition\lib\idea_rt.jar=61403:C:\Users\golde\AppData\Local\Programs\IntelliJ IDEA Community Edition\bin" -Dfile.encoding=UTF-8 -classpath C:\Projects\IdeaProjects\openfeign-example\build\classes\kotlin\main;C:\Projects\IdeaProjects\openfeign-example\build\resources\main;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib-jdk8\1.8.22\b25c86d47d6b962b9cf0f8c3f320c8a10eea3dd1\kotlin-stdlib-jdk8-1.8.22.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-web\3.1.5\3674e5603cc25bc4dccf73b97d50234332fc3d72\spring-boot-starter-web-3.1.5.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.core\jackson-databind\2.11.0\8f5aaf3878b0647ff3a16610af53b1a5c05d9f15\jackson-databind-2.11.0.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.module\jackson-module-kotlin\2.15.3\36ea7813ada694e67f562ff1dc6f3b47883e373\jackson-module-kotlin-2.15.3.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-reflect\1.8.22\b52be44bc57cb6fd2169a29aefa4507c4e49c858\kotlin-reflect-1.8.22.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.springframework.cloud\spring-cloud-starter-openfeign\4.0.4\51d8b8ea8698bce969dd3afad8420f04a7251dde\spring-cloud-starter-openfeign-4.0.4.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-aop\3.1.5\2ac1f8bf4c2bce13b46d04abafc69a4f1523a08\spring-boot-starter-aop-3.1.5.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-thymeleaf\3.1.5\3d5f1bff03e5e58b065ca230b7ee24b84bf7fe75\spring-boot-starter-thymeleaf-3.1.5.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-validation\3.1.5\f653e6661ec3da08003789f4a6583d1674e333b1\spring-boot-starter-validation-3.1.5.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\nz.net.ultraq.thymeleaf\thymeleaf-layout-dialect\3.2.1\526f2e950a4d67ea49198f9ea5b4ec303ed002c2\thymeleaf-layout-dialect-3.2.1.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib-jdk7\1.8.22\4dabb8248310d833bb6a8b516024a91fd3d275c\kotlin-stdlib-jdk7-1.8.22.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib\1.8.22\636bf8b320e7627482771bbac9ed7246773c02bd\kotlin-stdlib-1.8.22.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-json\3.1.5\36ce79c1a5c63ffd72b092eb312cb35ac6edb128\spring-boot-starter-json-3.1.5.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter\3.1.5\a14cd17b86261933929566775d80c65b9f7440fc\spring-boot-starter-3.1.5.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-tomcat\3.1.5\4b362b923ec1ca080556c4e55fe4ae73cf5a84d7\spring-boot-starter-tomcat-3.1.5.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.springframework\spring-webmvc\6.0.13\df1230a7dde55b9ce9d72670b42d621dc2e481df\spring-webmvc-6.0.13.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.springframework\spring-web\6.0.13\c374fcaf34d82d735a1dcf2c496f064488aa2b20\spring-web-6.0.13.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.core\jackson-annotations\2.15.3\79baf4e605eb3bbb60b1c475d44a7aecceea1d60\jackson-annotations-2.15.3.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.core\jackson-core\2.15.3\60d600567c1862840397bf9ff5a92398edc5797b\jackson-core-2.15.3.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.springframework.cloud\spring-cloud-openfeign-core\4.0.4\30883d013fe1586e06e9f995020124ba6202a317\spring-cloud-openfeign-core-4.0.4.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.springframework.cloud\spring-cloud-starter\4.0.4\7a90112c371183668b51e657a1f9113ed38f126f\spring-cloud-starter-4.0.4.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.springframework.cloud\spring-cloud-commons\4.0.4\b8fd08d1066deb7dd7e924d913b21f8c2ff44e70\spring-cloud-commons-4.0.4.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\io.github.openfeign\feign-slf4j\12.4\25a7a8249a2b9cb9ae3ca4eeba9a57050551913b\feign-slf4j-12.4.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\io.github.openfeign\feign-core\12.4\7acf105cbe60a58af10fcaa610a41ceec9a4fa9d\feign-core-12.4.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.springframework\spring-aop\6.0.13\aae1a18033787c9d324322f4470b12264e773e83\spring-aop-6.0.13.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.aspectj\aspectjweaver\1.9.20\da562407e43f74c0f8f5f5df4065d85ec1736d01\aspectjweaver-1.9.20.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.thymeleaf\thymeleaf-spring6\3.1.2.RELEASE\6030c7b4e260c41336f378e53da6e8531263f24b\thymeleaf-spring6-3.1.2.RELEASE.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.apache.tomcat.embed\tomcat-embed-el\10.1.15\49e784ef48d5fc7bc48d7e2a7ceb57e88b4d58b7\tomcat-embed-el-10.1.15.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.hibernate.validator\hibernate-validator\8.0.1.Final\e49e116b3d3928060599b176b3538bb848718e95\hibernate-validator-8.0.1.Final.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.apache.groovy\groovy\4.0.15\1fa486007f31bd7f245ba4674fb8afb173bea745\groovy-4.0.15.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib-common\1.8.22\1a8e3601703ae14bb58757ea6b2d8e8e5935a586\kotlin-stdlib-common-1.8.22.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.jetbrains\annotations\13.0\919f0dfe192fb4e063e7dacadee7f8bb9a2672a9\annotations-13.0.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.datatype\jackson-datatype-jdk8\2.15.3\80158cb020c7bd4e4ba94d8d752a65729dc943b2\jackson-datatype-jdk8-2.15.3.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.datatype\jackson-datatype-jsr310\2.15.3\4a20a0e104931bfa72f24ef358c2eb63f1ef2aaf\jackson-datatype-jsr310-2.15.3.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.module\jackson-module-parameter-names\2.15.3\8d251b90c5358677e7d8161e0c2488e6f84f49da\jackson-module-parameter-names-2.15.3.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-autoconfigure\3.1.5\42a5b2ee98f700fba8d8c88d4af7b23266f1de0f\spring-boot-autoconfigure-3.1.5.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot\3.1.5\c188015a5a79f5df65e876dcfdef16148c45fe2c\spring-boot-3.1.5.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-logging\3.1.5\8d8a91061baa4347d97a8fe15f3337d943badab\spring-boot-starter-logging-3.1.5.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\jakarta.annotation\jakarta.annotation-api\2.1.1\48b9bda22b091b1f48b13af03fe36db3be6e1ae3\jakarta.annotation-api-2.1.1.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.springframework\spring-core\6.0.13\cd565c2408e37d2026822b871cd43e69da8ec40e\spring-core-6.0.13.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.yaml\snakeyaml\1.33\2cd0a87ff7df953f810c344bdf2fe3340b954c69\snakeyaml-1.33.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.apache.tomcat.embed\tomcat-embed-websocket\10.1.15\14cc0999d4a5128dc9bb8862487aa8ed4cd7fcd8\tomcat-embed-websocket-10.1.15.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.apache.tomcat.embed\tomcat-embed-core\10.1.15\e3a725405f494abc0fd4f30263c2e6ad87052de1\tomcat-embed-core-10.1.15.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.springframework\spring-context\6.0.13\4c49af6dde7fce9602049f952b45ca29f30e2a37\spring-context-6.0.13.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.springframework\spring-beans\6.0.13\5b205c9f2fb07c1367db144ce7ab305f94300604\spring-beans-6.0.13.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.springframework\spring-expression\6.0.13\2bedffa4a3850bbbb652a31c47671824b17fbe01\spring-expression-6.0.13.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\io.micrometer\micrometer-observation\1.11.5\803f341121416365d1c438fe2a7290b146fadc92\micrometer-observation-1.11.5.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\io.github.openfeign.form\feign-form-spring\3.8.0\71059f6e16ddbaf0e42f1b1aa0bb60cc2f823e4d\feign-form-spring-3.8.0.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\commons-fileupload\commons-fileupload\1.5\ad4ad2ab2961b4e1891472bd1a33fabefb0385f3\commons-fileupload-1.5.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.springframework.cloud\spring-cloud-context\4.0.4\6962fd8ddc995cea96b2499cfbc44df181c41b47\spring-cloud-context-4.0.4.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.springframework.security\spring-security-rsa\1.0.12.RELEASE\2c6aca9e7eee11aee196a29eeea35d7aa8692398\spring-security-rsa-1.0.12.RELEASE.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.springframework.security\spring-security-crypto\6.1.5\971a767ef1ef6bea94486ac944f0e17b143dc680\spring-security-crypto-6.1.5.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.slf4j\slf4j-api\2.0.9\7cf2726fdcfbc8610f9a71fb3ed639871f315340\slf4j-api-2.0.9.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.thymeleaf\thymeleaf\3.1.2.RELEASE\273997509a4c7aef86cee0521750140c587d9be2\thymeleaf-3.1.2.RELEASE.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\jakarta.validation\jakarta.validation-api\3.0.2\92b6631659ba35ca09e44874d3eb936edfeee532\jakarta.validation-api-3.0.2.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.jboss.logging\jboss-logging\3.5.3.Final\c88fc1d8a96d4c3491f55d4317458ccad53ca663\jboss-logging-3.5.3.Final.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\com.fasterxml\classmate\1.5.1\3fe0bed568c62df5e89f4f174c101eab25345b6c\classmate-1.5.1.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\ch.qos.logback\logback-classic\1.4.11\54450c0c783e896a1a6d88c043bd2f1daba1c382\logback-classic-1.4.11.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.apache.logging.log4j\log4j-to-slf4j\2.20.0\d37f81f8978e2672bc32c82712ab4b3f66624adc\log4j-to-slf4j-2.20.0.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.slf4j\jul-to-slf4j\2.0.9\9ef7c70b248185845f013f49a33ff9ca65b7975\jul-to-slf4j-2.0.9.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.springframework\spring-jcl\6.0.13\91ea90f2de4c71dac3cff04882156b00cdca3e0d\spring-jcl-6.0.13.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\io.micrometer\micrometer-commons\1.11.5\3e708f737ba2674823201a836b5858482b183902\micrometer-commons-1.11.5.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\io.github.openfeign.form\feign-form\3.8.0\3083889996b18443c275a352d3ab4bc6c8321598\feign-form-3.8.0.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\commons-io\commons-io\2.11.0\a2503f302b11ebde7ebc3df41daebe0e4eea3689\commons-io-2.11.0.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.bouncycastle\bcpkix-jdk18on\1.73\fd41dae0f564a93888ed5ade426281de94824717\bcpkix-jdk18on-1.73.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.attoparser\attoparser\2.0.7.RELEASE\e5d0e988d9124139d645bb5872b24dfa23e283cc\attoparser-2.0.7.RELEASE.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.unbescape\unbescape\1.1.6.RELEASE\7b90360afb2b860e09e8347112800d12c12b2a13\unbescape-1.1.6.RELEASE.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\ch.qos.logback\logback-core\1.4.11\2f9f280219a9922a74200eaf7138c4c17fb87c0f\logback-core-1.4.11.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.apache.logging.log4j\log4j-api\2.20.0\1fe6082e660daf07c689a89c94dc0f49c26b44bb\log4j-api-2.20.0.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.bouncycastle\bcutil-jdk18on\1.73\73a680acd04b249a6773f49200092cadb670bf0\bcutil-jdk18on-1.73.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.bouncycastle\bcprov-jdk18on\1.73\4bd3de48e5153059fe3f80cbcf86ea221795ee55\bcprov-jdk18on-1.73.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-devtools\3.1.5\e7725476fbcd154d7ee5d85446cac2e16db1d818\spring-boot-devtools-3.1.5.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\nz.net.ultraq.groovy\groovy-extensions\2.1.0\c869dc033867e8861957ff3ff4e1ce0a00260e3a\groovy-extensions-2.1.0.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\nz.net.ultraq.thymeleaf\thymeleaf-expression-processor\3.1.1\81360e5289e8b4551733708c0ef11799d2716e54\thymeleaf-expression-processor-3.1.1.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\ognl\ognl\3.3.4\1904789bdd96f226ad252a02f230be1015f4462b\ognl-3.3.4.jar;C:\Users\golde\.gradle\caches\modules-2\files-2.1\org.javassist\javassist\3.29.0-GA\d3959fa7e00bf04dbe519228a23213d2afb625d8\javassist-3.29.0-GA.jar com.example.openfeignexample.OpenfeignExampleApplicationKt
2023-11-03T23:57:03.569+09:00  INFO 10908 --- [  restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable
2023-11-03T23:57:03.573+09:00  INFO 10908 --- [  restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG'
2023-11-03T23:57:04.978+09:00  INFO 10908 --- [  restartedMain] o.s.cloud.context.scope.GenericScope     : BeanFactory id=750cf38b-3d33-3f45-a8b2-68bc6615318c
2023-11-03T23:57:05.017+09:00  INFO 10908 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'com.example.openfeignexample.client.DmmClient' of type [org.springframework.cloud.openfeign.FeignClientFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2023-11-03T23:57:05.900+09:00  INFO 10908 --- [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 5000 (http)
2023-11-03T23:57:05.919+09:00  INFO 10908 --- [  restartedMain] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2023-11-03T23:57:05.919+09:00  INFO 10908 --- [  restartedMain] o.apache.catalina.core.StandardEngine    : Starting Servlet engine: [Apache Tomcat/10.1.15]
2023-11-03T23:57:06.025+09:00  INFO 10908 --- [  restartedMain] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2023-11-03T23:57:06.027+09:00  INFO 10908 --- [  restartedMain] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 2451 ms
2023-11-03T23:57:06.509+09:00  INFO 10908 --- [  restartedMain] o.s.b.d.a.OptionalLiveReloadServer       : LiveReload server is running on port 35729
2023-11-03T23:57:07.581+09:00  INFO 10908 --- [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 5000 (http) with context path ''
2023-11-03T23:57:10.266+09:00  INFO 10908 --- [nio-5000-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2023-11-03T23:57:10.267+09:00  INFO 10908 --- [nio-5000-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2023-11-03T23:57:10.268+09:00  INFO 10908 --- [nio-5000-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 1 ms
2023-11-03T23:57:23.035+09:00  INFO 10908 --- [nio-5000-exec-4] c.e.o.config.interceptor.DmmApiConfig    : SEND: URL=https://api.dmm.com/affiliate/v3/ItemList, Method=GET, Query={hits=[100], site=[DMM.com], sort=[date], keyword=[バビル二世]}, Body={}
2023-11-03T23:57:23.609+09:00  INFO 10908 --- [nio-5000-exec-4] c.e.o.config.interceptor.DmmApiConfig    : RECV: URL=https://api.dmm.com/affiliate/v3/ItemList, Method=GET, Query={hits=[100], site=[DMM.com], sort=[date], keyword=[バビル二世]}, Body={}, Status=200, Time=568ms

我对此有所感触。

上一次我们使用了 RestTemplate 进行通信,但是我觉得 OpenFeign 更直观。
在工作中,绝大多数人都使用 RestTemplate,但如果有机会进行技术选择,我想试试推荐 OpenFeign。

请看相关资料

 

bannerAds