ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Java框架 SpringCloud 快速入门: Feign 的自定义配置与日志级别

Java框架 SpringCloud 快速入门: Feign 的自定义配置与日志级别 概述Feign 默认不打印任何远程调用日志所以接口能调通但控制台干干净净是正常行为。这篇把 Feign 的可配置项梳理一遍重点落在最常改、也最容易改错的日志级别上四档级别到底是什么、两种配置方式的完整写法、作用域优先级以及改了logging.level却依然没日志这类高频坑。纲要Feign 支持哪些自定义配置feign.Logger.Level日志级别feign.codec.Decoder/feign.codec.Encoder编解码器feign.Contract注解契约feign.Retryer失败重试自定义方式用Bean覆盖默认 Bean日志级别四档NONE/BASIC/HEADERS/FULL各自记录什么默认值是NONEFULL打印请求体的安全风险Feign 的Logger.Level与日志框架logging.level的区别方式一配置文件feign.client.config.服务名.loggerLevel用default做全局配套的logging.level.cn.itcast: debug方式二Java 代码Bean public Logger.Level feignLogLevel()全局EnableFeignClients(defaultConfiguration ...)局部FeignClient(configuration ...)作用域坑Bean放在启动类扫描范围内会全局生效优先级与验证方式实战坑清单API 速览 / 官方文档 / 总结Feign 支持哪些自定义配置SpringBoot 给 Feign 做了一套自动装配同时留了覆盖默认值的口子。常用的可配置项如下讲义 2.2 节给出的就是这张表类型作用说明feign.Logger.Level修改日志级别四档NONE、BASIC、HEADERS、FULLfeign.codec.Decoder响应结果解析器把远程返回的 JSON 字符串解析成 Java 对象feign.codec.Encoder请求参数编码把方法参数编码成 HTTP 请求体feign.Contract支持的注解格式默认是 SpringMVC 注解一般不动feign.Retryer失败重试机制Feign 自身默认不重试实际重试由底层 Ribbon 提供自定义的统一手法就是声明一个同类型的Bean覆盖默认实现。日常开发里前四类基本用不上——Decoder/Encoder默认的 Jackson 实现够用Contract默认就支持GetMapping这些熟悉注解。真正会动手调的九成场景是日志级别方法、URL、状态码、耗时、请求头、请求体这些信息只有把日志打开才看得见排查 401/404/序列化失败时非常关键。下面只讲日志级别其余配置项的写法可以照搬这个套路。日志级别四档feign.Logger.Level是个枚举四个取值记录的内容逐级递增级别记录内容适用场景NONE什么都不记这是默认值生产环境长期运行BASIC请求方法、URL、响应状态码、执行耗时日常开发、联调HEADERS在 BASIC 之上额外记录请求头与响应头排查鉴权头、Content-Type 问题FULL在 HEADERS 之上再记录请求体与响应体本地调试短时开启两个必须先说清楚的结论默认是NONE所以Feign 调用没有日志不是 bug。很多人第一次用 Feign看到控制台只有 MyBatis 的 SQL 日志就以为远程调用没走到或者依赖没生效。其实请求已经发出去了只是日志开关没打开——毕竟生产环境全量打请求体日志量和性能开销都不小。FULL会完整打印请求体和响应体里面可能带密码、手机号、身份证号、token。本地开发时开 FULL 看报文没问题但把loggerLevel: FULL提交到生产分支是很危险的事一方面敏感字段直接落到日志文件里另一方面单次调用四段文本、高 QPS 下磁盘很快会被刷满。生产建议保持NONE或者最多BASIC。别把 Feign 的 Level 和 logging.level 混为一谈这是最容易踩的坑两套东西名字里都有 “level”但管的是完全不同的层Feign 日志级别日志框架级别配置项feign.client.config.服务.loggerLevel或Bean Logger.Levellogging.level.包名取值NONE/BASIC/HEADERS/FULLTRACE/DEBUG/INFO/WARN/ERROR作用决定 Feign要不要生成这段日志内容决定日志框架要不要输出这段内容日志从上到下要过两道闸门是否否, 如 INFO是, 如 DEBUGFeign 发起远程调用Feign Level 是 NONE?不生成日志内容按 Level 生成日志内容接口所在包的 logger 级别够低?内容被框架拦掉, 看不到控制台输出日志两道闸门同时打开才看得到日志。Feign 生成的日志最终是交给该 Feign 接口所在包的 logger 去输出的所以配置文件里那句logging.level.cn.itcast: debug不是可选项——它决定了日志能不能落地。反过来只改logging.level而不配 Feign 的 Level一样什么都看不到因为 Feign 压根没生成内容框架自然没东西可打。方式一配置文件先给出工程结构本文涉及的文件都落在这几个模块里cloud-demo ├── order-service # 订单服务Feign 的调用方 │ ├── src/main/java/cn/itcast/order │ │ ├── OrderApplication.java # 启动类EnableFeignClients 在这里 │ │ └── service/OrderService.java # 通过 UserClient 发起远程调用 │ └── src/main/resources/application.yml # 方式一在这里配 loggerLevel ├── feign-api # 抽取出来的 Feign 客户端模块 │ └── src/main/java/cn/itcast/feign │ ├── clients/UserClient.java # FeignClient(userservice) │ ├── config/DefaultFeignConfiguration.java # 方式二Bean Logger.Level 在这里 │ └── pojo/User.java └── user-service # 用户服务8081配置前缀是feign.client.config再下一层写服务名或default# order-service/src/main/resources/application.ymlfeign:client:config:userservice:# 只对 userservice 这个服务生效loggerLevel:FULL# 日志级别, 取值 NONE/BASIC/HEADERS/FULLdefault:# 用 default 代替服务名, 就是全局默认loggerLevel:BASIClogging:level:cn.itcast:debug# Feign 的日志由 cn.itcast 包下的 logger 输出, 这里必须放开pattern:dateformat:MM-dd HH:mm:ss:SSS三点说明服务名就是FeignClient(value ...)里那个名字这里必须写userservice而不是user-service或某个地址——写错了不会报错静默不生效这是排查时的第一嫌疑对象。想让所有 Feign 客户端都按同一级别来把服务名换成default。上面同时写了两段userservice单独用 FULL、其余服务用 BASIC。只改 yml 里这段配置不够logging.level.cn.itcast: debug一定要有。工程本身的 yml 里本来就带了这一行所以视频里加完配置重启就能看到日志换个没配过的工程很容易在这里卡住。改完配置要重启order-service 才生效——它是启动时读取的不是热更新。方式二Java 代码Java 侧的写法是声明一个返回Logger.Level的Bean。类本身不加Component之类的注解靠EnableFeignClients或FeignClient显式引入packagecn.itcast.feign.config;importfeign.Logger;importorg.springframework.context.annotation.Bean;publicclassDefaultFeignConfiguration{BeanpublicLogger.LevelfeignLogLevel(){// 日志级别: NONE / BASIC / HEADERS / FULLreturnLogger.Level.BASIC;}}注意Logger是feign.Logger不是org.slf4j.Logger、也不是java.util.logging.Loggerimport 写错编译期就会报错。这个类放哪儿、怎么挂上去决定了它的作用域。全局生效——挂到启动类的EnableFeignClients上packagecn.itcast.order;importcn.itcast.feign.clients.UserClient;importcn.itcast.feign.config.DefaultFeignConfiguration;importorg.mybatis.spring.annotation.MapperScan;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;importorg.springframework.cloud.openfeign.EnableFeignClients;MapperScan(cn.itcast.order.mapper)SpringBootApplication// defaultConfiguration 指定的配置类, 对所有 Feign 客户端生效EnableFeignClients(clientsUserClient.class,defaultConfigurationDefaultFeignConfiguration.class)publicclassOrderApplication{publicstaticvoidmain(String[]args){SpringApplication.run(OrderApplication.class,args);}}局部生效——挂到具体的FeignClient上packagecn.itcast.feign.clients;importcn.itcast.feign.config.DefaultFeignConfiguration;importcn.itcast.feign.pojo.User;importorg.springframework.cloud.openfeign.FeignClient;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.PathVariable;// configuration 只对当前这一个 Feign 客户端生效FeignClient(valueuserservice,configurationDefaultFeignConfiguration.class)publicinterfaceUserClient{GetMapping(/user/{id})UserfindById(PathVariable(id)Longid);}作用域坑Bean放错包会变成全局这是和 Ribbon 自定义IRule同一类问题值得单独拎出来。DefaultFeignConfiguration位于cn.itcast.feign.config而启动类OrderApplication在cn.itcast.order。SpringBootApplication默认只扫描启动类所在包及其子包cn.itcast.feign.config不在扫描范围内所以这个类里的Bean不会被 Spring 当作普通配置加载只在被defaultConfiguration/configuration引用时才生效——现在的作用域是可控的。反过来的写法是这样的cn.itcast.order ├── OrderApplication.java # SpringBootApplication 扫描 cn.itcast.order 及子包 └── config └── FeignConfig.java # ❌ Bean Logger.Level 放在这里packagecn.itcast.order.config;importfeign.Logger;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;ConfigurationpublicclassFeignConfig{BeanpublicLogger.LevelfeignLogLevel(){returnLogger.Level.BASIC;}}启动类在cn.itcast.orderComponentScan覆盖了cn.itcast.order.config这个Bean会被当成全局 Bean 注册进容器于是所有 Feign 客户端都会用上它哪怕你原本只想给 userservice 开日志。想只对一个服务生效就得像上面那样把配置类挪出扫描范围、再用FeignClient(configuration ...)精确指定——讲义里 Feign 客户端被抽取到feign-api模块、配置类放在cn.itcast.feign.config这个包结构本身就规避了该问题。优先级两种方式同时存在时怎么取常见的理解口径是局部优先于全局从高到低FeignClient(configuration X.class) 指定的配置feign.client.config.服务名 的配置EnableFeignClients(defaultConfiguration ...)feign.client.config.default 的配置Feign 内置默认值 (Level 为 NONE)这个顺序是社区里常见的说法用来指导哪个会盖住哪个足够但具体行为随 Spring Cloud 版本有调整落地时以所用版本文档为准别当成铁律。验证日志长什么样以视频里的操作为例把 order-service 的loggerLevel配成FULL重启清空控制台浏览器访问一次http://localhost:8088/order/101再回来看 IDEA。除开 MyBatis 的 SQL 日志会多出下面这样一段不同 Feign 版本措辞和字段顺序略有差异2026-09-30 10:12:03:120 DEBUG 24680 --- [nio-8088-exec-3] c.i.f.clients.UserClient : [UserClient#findById] --- GET http://userservice/user/1 HTTP/1.1 2026-09-30 10:12:03:121 DEBUG 24680 --- [nio-8088-exec-3] c.i.f.clients.UserClient : [UserClient#findById] --- END HTTP (0-byte body) 2026-09-30 10:12:03:361 DEBUG 24680 --- [nio-8088-exec-3] c.i.f.clients.UserClient : [UserClient#findById] --- HTTP/1.1 200 (241ms) 2026-09-30 10:12:03:361 DEBUG 24680 --- [nio-8088-exec-3] c.i.f.clients.UserClient : [UserClient#findById] content-type: application/json 2026-09-30 10:12:03:361 DEBUG 24680 --- [nio-8088-exec-3] c.i.f.clients.UserClient : [UserClient#findById] date: Wed, 30 Sep 2026 02:12:03 GMT 2026-09-30 10:12:03:362 DEBUG 24680 --- [nio-8088-exec-3] c.i.f.clients.UserClient : [UserClient#findById] --- END HTTP (68-byte body)日志里能读出几件事---开头是请求段带方法、URL、协议---是响应段200 (241ms)说明状态码正常、耗时 241 毫秒头部字段逐行列出最后是响应体字节数。这段日志的 logger 名就是 Feign 接口的全限定名cn.itcast.feign.clients.UserClient再次印证了logging.level得按包名放开。换成BASIC上面只剩--- GET ...和--- HTTP/1.1 200 (241ms)两行头信息、Body 全部消失——这也是为什么建议日常开发用BASIC够定位问题又不至于把报文全刷出来。调用的代码本身不用动OrderService照常注入UserClient调用即可packagecn.itcast.order.service;importcn.itcast.feign.clients.UserClient;importcn.itcast.feign.pojo.User;importcn.itcast.order.mapper.OrderMapper;importcn.itcast.order.pojo.Order;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Service;ServicepublicclassOrderService{AutowiredprivateOrderMapperorderMapper;AutowiredprivateUserClientuserClient;publicOrderqueryOrderById(LongorderId){OrderorderorderMapper.findById(orderId);// Feign 远程调用, 这里的调用过程就是日志里记录的那次 HTTP 请求UseruseruserClient.findById(order.getUserId());order.setUser(user);returnorder;}}实战坑清单现象原因处理配了 Feign 的 Level还是没日志没配logging.level.cn.itcast: debug或包的 logger 级别是 INFO确认接口所在包被logging.level覆盖且为debug只改了logging.level依然没日志Feign 的 Level 还是默认NONE没有生成日志内容加上feign.client.config.服务名.loggerLevel配了服务名但完全不生效也不报错服务名写错如写成user-service、USER-SERVICE与FeignClient(value ...)逐字符核对只想给一个服务开日志结果全开了Bean Logger.Level所在包被ComponentScan扫到把配置类挪出启动类扫描范围改用configuration X.class生产环境日志文件暴涨、出现手机号 token生产开着FULL生产用NONE最多BASIC敏感报文只在本地短时开改了 yml 不生效Feign 配置在启动时读取重启服务以为 Feign 一定不重试Feign 自身默认不重试但底层 Ribbon 有重试机制需要精确控制时配置feign.RetryerAPI 速览配置项位置作用域说明feign.client.config.服务名.loggerLevelapplication.yml单个服务值是NONE/BASIC/HEADERS/FULLfeign.client.config.default.loggerLevelapplication.yml全局default即所有 Feign 客户端Bean Logger.LevelJava 配置类由挂载点决定feign.Logger.Level不是 slf4j 的 LoggerEnableFeignClients(defaultConfiguration X.class)启动类全局配置类需在扫描范围外才有意义FeignClient(configuration X.class)Feign 接口单个服务局部配置优先logging.level.包名application.yml日志框架Feign 日志的落地闸门必须为debug官方文档Spring Cloud OpenFeign — Feign loggingSpring Cloud OpenFeign — Overriding Feign DefaultsOpenFeign Logger.Level Javadoc总结Feign 可配置项有五类日常真正会调的是Logger.Level其余保持默认。日志四档里NONE是默认值所以没日志是正常现象FULL会打请求体生产慎用。Feign 的Logger.Level决定生成不生成日志logging.level决定输出不输出日志两道闸门要一起开。配置文件方式最省事feign.client.config.服务名.loggerLeveldefault即全局。Java 代码方式要盯住作用域Bean落在启动类扫描范围内就是全局要局部生效得把配置类放到扫描范围外再显式挂载。优先级上局部优先于全局但具体行为随版本变化以对应版本文档为准。
返回列表