使用Spring框架自带对象,0入侵统一正常或异常接口对象返回

背景

公司的一个项目,没有统一接口返回值。前端对接接口时,由于不同接口返回对象的千差万别,导致抽象处理接口返回结果很复杂。
有的公司,会新增一个统一返回对象,每一个接口,都返回这个对象。这样是可以实现的,很多公司也是这么做的,但是对代码有一定的入侵性。
这里用另一个思路来实现:

  • 程序异常返回时,通过异常拦截,捕捉异常来构造统一返回对象
  • 程序正常返回时,自定义返回值处理器来实现统一处理返回值的功能。

对于一个新手来说,接口返回值很随意,下面这样写接口是很常见的:


    @RequestMapping("getAll")
    public List<GoodJobEveryDay> getAll() throws JsonProcessingException {
   
   

        List<GoodJobEveryDay> value = new ArrayList<>();
        // 判断文件是否存在
        if (FileHandling.isFileExists(FileHandling.FILE_NAME)) {
   
   
            // 如果文件存在,读取文件内容
            String fileContent = FileHandling.readFileContent(FileHandling.FILE_NAME);
            value = objectMapper.readValue(fileContent, new TypeReference<List<GoodJobEveryDay>>() {
   
   
            });
        }
        return value;
    }


    @GetMapping("getOne")
    public GoodJobEveryDay getOne(@RequestParam Integer id) throws JsonProcessingException {
   
   
        List<GoodJobEveryDay> value = getAll();
        if (!CollectionUtils.isEmpty(value)) {
   
   
            if (value.stream().filter(it -> id.equals(it.getId())).count() <= 0) {
   
   
                throw new BusinessException(ExceptionEnum.DATA_NOT_FOUND);
            }
            Optional<GoodJobEveryDay> first = value.stream().filter(it -> it.getId().equals(id)).findFirst();
            
<think> 我们正在讨论如何在Spring Cloud Feign调用前后添加日志。根据引用[4],我们可以通过配置Feign的日志级别来记录详细的调用信息。引用[4]展示了如何配置一个`Logger.Level` Bean来设置日志级别为`FULL`,这将记录请求和响应的所有细节。 但是,用户想要在“调用前后”添加日志,这可能意味着在业务逻辑层面记录自定义的日志(比如在调用前打印一行日志,调用后打印一行日志),而不仅仅是Feign自带的日志。另外,也可能是指配置Feign的日志级别以在调用前后记录详细信息。 因此,我们可以从两个方面回答: 1. 配置Feign的日志级别(记录Feign自身的详细日志,包括请求和响应信息) 2. 使用自定义拦截器(在Feign调用前后插入自定义的日志记录) 根据引用[4]: - Feign的日志级别有四种:NONE(默认,无日志)、BASIC(仅记录请求方法、URL、响应状态码、执行时间)、HEADERS(在BASIC基础上增加请求头)、FULL(记录所有,包括请求头和请求)。 配置Feign日志级别的方法有两种: - 第一种:通过配置文件配置(全局指定客户端)并配合Java配置类(定义日志级别Bean) - 第二种:纯配置方式(在配置文件中指定日志级别) 此外,我们还可以通过实现Feign的`RequestInterceptor`接口,在请求发送前和收到响应后(实际上,响应后需要用到`ResponseInterceptor`,但Feign本身没有直接的响应拦截器,我们可以通过包装Client的方式使用AOP)记录日志。不过,更常见的做法是使用日志级别配置,因为它已经提供了详细的信息。 但是,如果用户需要在业务代码中明确在调用前后打印日志,那么可以在调用Feign客户端接口的前后手动添加日志。但这样会侵入业务代码,因此可以考虑使用AOP切面来统一处理。 因此,回答将包括: 一、通过配置Feign日志级别(包括调用前后的详细日志) 二、通过自定义拦截器在请求发送前记录日志(注意:Feign没有直接的响应拦截器,但可以自定义Client包装响应) 三、使用AOP在Feign接口调用前后记录日志(业务层面) 下面组织回答: </think> ### Spring Cloud Feign 调用前后添加日志的方法 在 Spring Cloud 中使用 Feign 调用外部服务时,可通过以下三种方式在调用前后添加日志: --- #### 一、配置 Feign 日志级别(推荐) 通过调整日志级别记录完整的请求/响应信息,包括调用前后的详细数据: ```java @Configuration public class FeignConfig { @Bean Logger.Level feignLoggerLevel() { return Logger.Level.FULL; // 启用完整日志 } } ``` **日志级别说明**: - `NONE`:无日志(默认) - `BASIC`:仅记录请求方法、URL、状态码和时间 - `HEADERS`:记录基础信息+请求头 - `FULL`:记录完整请求/响应(含调用前后)[^4] **配置文件添加**(application.yml): ```yaml logging: level: com.example.YourFeignClient: DEBUG # 指定客户端包路径 ``` **日志输出示例**: ``` --> POST http://service-url/path HTTP/1.1 # 调用前日志 Content-Type: application/json Request Body: {"param":"value"} <-- HTTP/1.1 200 OK (123ms) # 调用后日志 Content-Length: 25 Response: {"result":"success"} ``` --- #### 二、自定义 RequestInterceptor 通过拦截器在调用前后插入自定义日志: ```java @Component public class FeignLogInterceptor implements RequestInterceptor { private static final Logger log = LoggerFactory.getLogger(FeignLogInterceptor.class); @Override public void apply(RequestTemplate template) { // 调用前日志 log.info("Feign调用开始 => URL: {}, Headers: {}", template.url(), template.headers()); // 可在此处添加请求日志(需额外处理) } } ``` **注册拦截器**: ```java @Configuration public class FeignConfig { @Bean public FeignLogInterceptor feignLogInterceptor() { return new FeignLogInterceptor(); } } ``` --- #### 三、自定义 Feign Client 包装器 通过包装 Client 实现获取响应后的日志记录: ```java public class LoggingFeignClient implements Client { private final Client delegate; private static final Logger log = LoggerFactory.getLogger(LoggingFeignClient.class); public LoggingFeignClient(Client delegate) { this.delegate = delegate; } @Override public Response execute(Request request, Request.Options options) throws IOException { // 调用前日志 log.info("Request: {} {}", request.httpMethod().name(), request.url()); Response response = delegate.execute(request, options); // 调用后日志 log.info("Response: {} - Payload: {}", response.status(), IOUtils.toString(response.body().asInputStream())); return response; } } ``` **注册自定义 Client**: ```java @Bean public Client feignClient() { return new LoggingFeignClient(new Default()); } ``` --- ### 方案对比 | **方式** | **优势** | **适用场景** | |------------------------|----------------------------------|--------------------------| | 日志级别配置 | 零代码入侵,支持完整调用链追踪 | 标准调试场景 | | RequestInterceptor | 灵活添加调用前日志 | 需要记录特定请求头的场景 | | 自定义 Client 包装器 | 可获取原始响应进行日志记录 | 需要精确分析响应的场景 | > **最佳实践**:生产环境建议使用`Logger.Level.BASIC`+日志框架过滤敏感信息,开发调试使用`FULL`级别[^4] ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值