如何获取Feign客户端无返回体方法的HTTP响应状态码?
问题原因
Feign默认的JacksonDecoder在处理204(NO_CONTENT)响应时,由于没有响应体可解析,会直接返回null,导致调用getDepartment()时拿到null触发空指针异常,无法获取响应状态码。
解决方案
方法一:直接返回Feign原生Response类型
使用Feign自带的feign.Response作为返回值,它能完整保留响应状态码、请求头等所有响应元数据,无需依赖解码器处理空响应体。
修改Feign接口:
import feign.Response; public interface DepartmentApi { @RequestLine("GET /department/nocontent") @Headers("Content-Type: application/json") Response getDepartment(); }
调用时获取状态码示例:
Response response = departmentApi.getDepartment(); int statusCode = response.status(); // 直接拿到204状态码 // 还可通过response.headers()获取响应头信息
方法二:自定义解码器处理204响应
如果希望继续使用ResponseEntity<Void>作为返回值,可以自定义解码器,针对204状态码返回空的ResponseEntity而非null。
自定义解码器实现:
import feign.FeignException; import feign.Response; import feign.codec.Decoder; import org.springframework.http.ResponseEntity; import java.io.IOException; import java.lang.reflect.Type; public class CustomDecoder implements Decoder { private final Decoder delegate; public CustomDecoder(Decoder delegate) { this.delegate = delegate; } @Override public Object decode(Response response, Type type) throws IOException, FeignException { // 针对204状态码且返回类型为ResponseEntity<Void>的情况处理 if (response.status() == 204 && type.getTypeName().equals(ResponseEntity.class.getTypeName() + "<java.lang.Void>")) { return ResponseEntity.noContent().build(); } // 其他情况交给原解码器处理 return delegate.decode(response, type); } }
修改客户端工厂的解码器配置:
@Component public class ClientApiFactory { @Bean @RequestScope public DepartmentApi getDepartmentApi() { return HystrixFeign.builder() .logLevel(Logger.Level.BASIC) .decoder(new CustomDecoder(new JacksonDecoder())) // 用自定义解码器包装JacksonDecoder .encoder(new JacksonEncoder()) .target(DepartmentApi.class, "http://localhost:8080"); } }
修改后调用getDepartment()会返回正常的ResponseEntity<Void>对象,可通过getStatusCode()获取204状态码。
方法三:改用Spring Cloud OpenFeign(Spring环境推荐)
如果你的项目基于Spring Cloud,建议直接使用Spring Cloud OpenFeign,它对Spring的ResponseEntity有原生友好支持,无需额外配置即可处理204无响应体的场景。
- 引入Maven依赖:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
- 定义Feign接口:
import org.springframework.cloud.openfeign.FeignClient; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; @FeignClient(name = "department-service", url = "http://localhost:8080") public interface DepartmentApi { @GetMapping("/department/nocontent") ResponseEntity<Void> getDepartment(); }
直接注入该接口调用即可,返回的ResponseEntity不会为null,可正常获取状态码。
内容的提问来源于stack exchange,提问作者Anandharaj Anandharaj
相关产品推荐
相关产品推荐

