Spring5中HttpInvokerServiceExporter废弃,替代方案与Spring6支持情况咨询
HttpInvokerServiceExporter 以及同模块下的传统RMI远程调用组件已在Spring 6中被完全移除。Spring 5.3版本标记该类废弃的核心原因是这类组件基于Java原生序列化实现远程调用,存在天然的反序列化RCE安全漏洞,官方无后续维护计划,也不建议在任何生产环境继续使用。
以下方案均基于HTTP协议实现,默认不使用Java原生序列化,从根源规避RCE风险,同时可以实现和原有RMI/HttpInvoker接近的透明远程Bean调用体验:
Spring HTTP Interface(Spring 6+ 官方首选方案)
这是Spring 6原生提供的声明式HTTP远程调用组件,使用体验和原有
RmiProxyFactoryBean几乎一致,只需要定义接口即可生成可直接注入的代理Bean,不需要手动封装HTTP请求逻辑。
服务端不需要引入特殊导出组件,直接提供标准Spring MVC REST接口即可:@RestController public class BookingServiceController { @Autowired private DTBookingService bookingService; @PostMapping("/remote/bookingService") public BookingResp createBooking(@RequestBody BookingReq req) { return bookingService.createBooking(req); } }客户端配置示例:
// 声明远程调用接口 public interface DTBookingRemoteService { @PostExchange("/remote/bookingService") BookingResp createBooking(@RequestBody BookingReq req); } @Configuration public class RemoteCallConfig { @Bean public WebClient webClient() { return WebClient.builder() .baseUrl("http://服务端域名/IP") .build(); } @Bean public DTBookingRemoteService bookingRemoteService(WebClient webClient) { HttpServiceProxyFactory proxyFactory = HttpServiceProxyFactory .builder(WebClientAdapter.forClient(webClient)) .build(); return proxyFactory.createClient(DTBookingRemoteService.class); } }配置完成后直接在业务代码中注入
DTBookingRemoteService即可像调用本地Bean一样发起远程调用。Spring Cloud OpenFeign(微服务场景适用)
如果你的服务运行在微服务架构下,需要对接服务发现、负载均衡、熔断降级等能力,可以选择OpenFeign组件,同样采用声明式接口定义的方式实现透明HTTP远程调用,和Spring生态组件无缝兼容。
客户端配置示例:// 启动类添加Feign客户端开启注解 @SpringBootApplication @EnableFeignClients public class ClientApp { public static void main(String[] args) { SpringApplication.run(ClientApp.class, args); } } // 定义远程服务客户端 @FeignClient(name = "booking-service", url = "http://服务端域名/IP") public interface BookingFeignClient { @PostMapping("/remote/bookingService") BookingResp createBooking(@RequestBody BookingReq req); }服务端同样只需要提供标准Spring MVC REST接口,不需要额外的导出配置。
轻量自定义RPC封装
如果业务场景强依赖原有HttpInvoker"服务端直接导出Spring Bean、客户端无感知调用"的模型,不需要REST风格的接口拆分,可以基于JSON等安全序列化器+Spring内置HTTP能力做轻量封装:服务端提供统一入口接收远程调用请求,通过反射调用对应Spring Bean的指定方法,将结果序列化后返回;客户端通过JDK动态代理生成接口实现类,自动封装HTTP请求完成调用,全程不使用Java原生序列化,彻底规避反序列化漏洞风险。
安全提示:不要尝试通过引入旧版本Spring组件的方式在Spring 6中兼容使用HttpInvokerServiceExporter或RmiServiceExporter,这类基于Java原生序列化的远程调用组件不存在可靠的安全加固方案,只要暴露在网络中就存在被RCE攻击的可能。
内容的提问来源于stack exchange,提问作者Kablu Mandal

