Home 成长之路 Leetcode题解 Dubbo服务调用下划线出参拿不到的问题

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,这样就可以正常拿到了~

SIMILAR ARTICLES

0 120

0 112

发表评论

发表评论