Dubbo服务调用下划线出参拿不到的问题
起因:有一个功能,需要调用pop-order的PRC接口,我在Dubbo中进行了声明
<!-- pop订单 --> <dubbo:reference id="popOrderService" interface="com.fenqile.pop.order.service.PopOrderService" timeout="3000" protocol="fsof" group="default" version="1.0.0" check="false"/> 一般的接口都是这样声明就可以了 出参定义如下: @Setter @Getter @NoArgsConstructor @ToString public class PopOrderDetailResp { private Integer uid; @JSONField(name = "order_id") private String orderId; @JSONField(name = "create_time") private String createTime; @JSONField(name = "modify_time") private Date modifyTime; @JSONField(name = "merch_sale_state") private Integer merchSaleState; @JSONField(name = "merch_sale_state_desc") private String merchSaleStateDesc; @JSONField(name = "sale_type") private Integer saleType; @JSONField(name = "sale_type_desc") private String saleTypeDesc; @JSONField(name = "sku_id") private String skuId; @JSONField(name = "product_name") private String productName; @JSONField(name = "sku_key_1") private String skuKey1; @JSONField(name = "sku_key_2") private String skuKey2; @JSONField(name = "sku_key_3") private String skuKey3; @JSONField(name = "delivery_mode") private Integer deliveryMode; @JSONField(name = "delivery_mode_desc") private String deliveryModeDesc; @JSONField(name = "spec") private String spec; @JSONField(name = "pic") private String pic; @JSONField(name = "quantity") private Integer quantity = 1; @JSONField(name = "amount") private String amount; @JSONField(name = "used_discount") private Integer usedDiscount; @JSONField(name = "price") private String price; @JSONField(name = "discount_info") private List<String> discountInfo; @JSONField(name = "memo_flag") private Integer memoFlag; @JSONField(name = "channel_desc") private String channelDesc; @JSONField(name = "company_name") private String companyName = ""; @JSONField(name = "express_id") private String expressId = ""; @JSONField(name = "express_flag") private Integer expressFlag = 0; @JSONField(name = "invoice_id") private String invoiceId = ""; @JSONField(name = "receipt_mobile") private String receiptMobile = ""; @JSONField(name = "receiver_credit_id") private String receiverCreditId = ""; @JSONField(name = "group_flag") private Integer groupFlag = 0; @JSONField(name = "apply_flag") private Integer applyFlag = 0; @JSONField(name = "pre_sell_flag") private Integer preSellFlag = 0; @JSONField(name = "pre_sell_desc") private String preSellDesc; @JSONField(name = "pre_sell_amount") private String preSellAmount; @JSONField(name = "pre_sell_state_desc") private String preSellStateDesc; @JSONField(name = "final_pay_desc") private String finalPayDesc; @JSONField(name = "final_pay_amount") private String finalPayAmount; @JSONField(name = "final_pay_state_desc") private String finalPayStateDesc; @JSONField(name = "imei") private String imei; @JSONField(name = "port") private String port; @JSONField(name = "port_name") private String portName; @JSONField(name = "taxes") private String taxes; @JSONField(name = "refund_taxes_flag") private Integer refundTaxesFlag = 0; @JSONField(name = "shop_coupon") private String shopCoupon; @JSONField(name = "plat_coupon") private String platCoupon; @JSONField(name = "refund_flag") private List<Integer> refundFlag = new ArrayList<>(); @JSONField(name = "freight") private String freight; @JSONField(name = "lease_term") private String leaseTerm = ""; @JSONField(name = "lease_period") private String leasePeriod = ""; @JSONField(name = "lease_price") private String leasePrice = ""; @JSONField(name = "guarantee_service") private String guaranteeService = ""; @JSONField(name = "associated_order") private String associatedOrder = ""; @JSONField(name = "deposit_turnover") private List<DeposoitTurnOver> depositTurnover = new ArrayList<>(); @JSONField(name = "pay_back_amount") private String payBackAmount = ""; @JSONField(name = "deduction_amount") private String deductionAmount = ""; @JSONField(name = "deduction_reason") private String deductionReason = ""; @JSONField(name = "pay_time") private String payTime; @JSONField(name = "associated_amount") private String associatedAmount; @JSONField(name = "check_flag") private Integer checkFlag = 0; @JSONField(name = "checkPassFlag") private Integer checkPassFlag = 0; //买断金额 @JSONField(name = "buy_out_amout") private String buyOutAmount; //押金 @JSONField(name = "deposite_amount") private String depositeAmount; //用户授信免押额度 @JSONField(name = "shop_credit_amount") private String shopCreditAmout; //首付金额 @JSONField(name = "after_pay_flag") private Integer afterPayFlag = 0; @JSONField(name = "first_pay") private String firstPay = ""; @JSONField(name = "first_pay_way") private String firstPayWay = ""; @JSONField(name = "pay_way") private String payWay = ""; @JSONField(name = "month_pay") private String monthPay = ""; @JSONField(name = "goods_business_type") private Integer goodsBusinessType; @JSONField(name = "goods_business_type_desc") private String goodsBusinessTypeDesc; @Setter @Getter @ToString public static class DeposoitTurnOver { private String time; private String remark; private String amount; @JSONField(name = "associated_amount") private String associatedAmount; } } 然后我调用RPC接口拿到的参数为: [{"after_pay_flag":0,"amount":"0.90","apply_flag":0,"associated_order":"","checkPassFlag":0,"check_flag":0,"company_name":"","deduction_amount":"","deduction_reason":"","deposit_turnover":[],"express_flag":0,"express_id":"","first_pay":"","first_pay_way":"","freight":"0","group_flag":0,"guarantee_service":"","invoice_id":"","lease_period":"","lease_price":"","lease_term":"","month_pay":"","pay_back_amount":"","pay_way":"","pic":"https://coss-ec.fenqile.com/ecproduct201/M00/ex/20231030142247-ee1e3b73-100f-483a-ba7b-2c14b6d7fedb.png","pre_sell_flag":0,"price":"0.99","quantity":1,"receipt_mobile":"","receiver_credit_id":"","refund_flag":[],"refund_taxes_flag":0,"spec":"满折互斥平台券","taxes":"0","uid":4063946} 仔细观察可以发现,除了有默认值的参数,和无需下划线的参数都能拿到,其他的参数都拿不到! 刚开始定位方向错了,以为是包版本没有对应上,更新包版本后还是不行(耽误了大半天) 后面,我注意到关键信息【除了有默认值的参数,和无需下划线的参数都能拿到,其他的参数都拿不到!】 于是我重新看了下dubbo的RPC接口配置 在提供方是这样写的 <!--提供的service--> <dubbo:service interface="com.fenqile.pop.order.service.PopOrderService" ref="popOrderService" protocol="fsof" group="default" version="1.0.0" timeout="8000" openfastjsonsupport="true"> <dubbo:method name="shipX" timeout="8000"/> </dubbo:service> 注意,这里提供方用了openfastjsonsupport="true"! 然后我问了下Ai,这个参数是干什么的 得到如下回复: 在Apache Dubbo中,OpenFastJsonSupport并非Dubbo官方提供的组件,但在实际开发中,有可能是指开发者基于开源JSON处理库Fastjson定制的一个适配器或扩展,用于整合Dubbo与Fastjson。 Fastjson是由阿里巴巴公司开发的一款高性能的JSON处理器,用于Java对象与JSON之间的转换。在Dubbo框架中,序列化和反序列化是通信过程中的重要环节,一般会使用某种序列化工具将Java对象转换成可在网络上传输的格式,如JSON格式。 OpenFastJsonSupport可能是一个扩展点,它使Dubbo能够使用Fastjson作为其默认的序列化方案,替代或补充Dubbo自带的序列化方式(如Hessian2、Java原生序列化等)。通过集成Fastjson,Dubbo服务之间交互的数据可以高效地进行JSON格式的序列化和反序列化,从而提升服务调用的性能。具体实现上,它可能提供了一些注册Fastjson为Dubbo的序列化器和反序列化器的配置方法或类。 就是这里,使用OpenFastJsonSupport 指定了该接口的出参使用Fastjson作为其默认的序列化方案,和出参里面使用 @JSONField注解呼应上了,到这里 答案呼之欲出了! 解密:由于服务提供方指定了该接口的出参序列化方式为Fastjson,而我在配置调用方的RPC时,没有使用openfastjsonsupport="true",导致调用方拿到出参后,使用dubbo默认的序列化方式进行反序列化,而Dubbo默认的序列化方式是Hessian2,Hessian2本身并不直接支持Fastjson的@JSONField注解,因为这两个是不同的序列化框架。 Hessian2有自己的序列化规则,并且不会解析或识别Fastjson的注解。 然而,在Dubbo中,可以通过配置将序列化方式改为Fastjson,这样在序列化和反序列化时,Fastjson就会生效,并且支持@JSONField注解。当你将Dubbo的序列化方式配置为fastjson时,Fastjson将会被用来处理对象与JSON之间的转换,此时@JSONField注解的功能才会得到体现。 默认的Hessian2不能处理@JSONField注解,所以拿不到参数信息!那怎样才能拿到呢?很简单,调用方和提供方保持一致的序列化框架就可以了 于是在dubbo配置中写上: <!-- pop订单 --> <dubbo:reference id="popOrderService" interface="com.fenqile.pop.order.service.PopOrderService" timeout="3000" protocol="fsof" group="default" version="1.0.0" check="false" openfastjsonsupport="true"/> OK,这样就可以正常拿到了~