Dubbo——Dubbo协议整合Jackson序列化解决方案

Posted Starzkg

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Dubbo——Dubbo协议整合Jackson序列化解决方案相关的知识,希望对你有一定的参考价值。

环境配置

spring boot 2.6.3
spring cloud 2021.0.1
spring cloud alibaba 2021.0.1.0
nacos server 2.0.4
dubbo 2.7.15

官方文档

序列化扩展:SPI扩展实现-序列化扩展
多协议配置:配置多协议

已知扩展

解决方案

源代码:https://gitee.com/myzstu/auth/tree/master/auth-core/src/main/java/club/zstuca/myzstu/dubbo/serialize/jackson

Maven 项目结构:

src
 |-main
    |-java
        |-com
            |-xxx
                |-XxxSerialization.java (实现Serialization接口)
                |-XxxObjectInput.java (实现ObjectInput接口)
                |-XxxObjectOutput.java (实现ObjectOutput接口)
    |-resources
        |-META-INF
            |-dubbo
                |-org.apache.dubbo.common.serialize.Serialization (纯文本文件,内容为:xxx=com.xxx.XxxSerialization)

JacksonSerialization.java:

package club.zstuca.myzstu.dubbo.serialize.jackson;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.serialize.ObjectInput;
import org.apache.dubbo.common.serialize.ObjectOutput;
import org.apache.dubbo.common.serialize.Serialization;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

/**
 * Jackson serialization implementation
 *
 * <pre>
 *     e.g. &lt;dubbo:protocol serialization="jackson" /&gt;
 * </pre>
 *
 * @author shentuzhigang
 * @date 2022/3/19 15:00
 */
public class JacksonSerialization implements Serialization 
    private final byte JACKSON_SERIALIZATION_ID = 31;

    private static ObjectMapper objectMapper = new ObjectMapper();

    public static synchronized void setObjectMapper(ObjectMapper objectMapper) 
        JacksonSerialization.objectMapper = objectMapper;
    

    @Override
    public byte getContentTypeId() 
        return JACKSON_SERIALIZATION_ID;
    

    @Override
    public String getContentType() 
        return "text/json";
    

    @Override
    public ObjectOutput serialize(URL url, OutputStream output) throws IOException 
        return new JacksonObjectOutput(objectMapper, output);
    

    @Override
    public ObjectInput deserialize(URL url, InputStream input) throws IOException 
        return new JacksonObjectInput(objectMapper, input);
    


JacksonObjectInput.java:

package club.zstuca.myzstu.dubbo.serialize.jackson;

import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.TypeFactory;
import org.apache.dubbo.common.serialize.ObjectInput;

import java.io.*;
import java.lang.reflect.Type;

/**
 * Jackson object input implementation
 *
 * @author shentuzhigang
 * @date 2022/3/19 15:07
 */
public class JacksonObjectInput implements ObjectInput 

    private final ObjectMapper objectMapper;

    private final BufferedReader reader;

    public JacksonObjectInput(InputStream input) 
        this(new ObjectMapper(), input);
    

    public JacksonObjectInput(ObjectMapper objectMapper, InputStream input) 
        this(objectMapper, new InputStreamReader(input));
    

    public JacksonObjectInput(ObjectMapper objectMapper, Reader reader) 
        this.objectMapper = objectMapper;
        this.reader = new BufferedReader(reader);
    

    @Override
    public boolean readBool() throws IOException 
        return read(boolean.class);
    

    @Override
    public byte readByte() throws IOException 
        return read(byte.class);
    

    @Override
    public short readShort() throws IOException 
        return read(short.class);
    

    @Override
    public int readInt() throws IOException 
        return read(int.class);
    

    @Override
    public long readLong() throws IOException 
        return read(long.class);
    

    @Override
    public float readFloat() throws IOException 
        return read(float.class);
    

    @Override
    public double readDouble() throws IOException 
        return read(double.class);
    

    @Override
    public String readUTF() throws IOException 
        return read(String.class);
    

    @Override
    public byte[] readBytes() throws IOException 
        return readLine().getBytes();
    

    @Override
    public Object readObject() throws IOException, ClassNotFoundException 
        return objectMapper.readTree(readLine());
    

    @Override
    public <T> T readObject(Class<T> cls) throws IOException, ClassNotFoundException 
        return read(cls);
    

    @Override
    public <T> T readObject(Class<T> cls, Type type) throws IOException, ClassNotFoundException 
        JavaType javaType = TypeFactory.defaultInstance().constructType(type);
        return objectMapper.readValue(readLine(), javaType);
    

    private String readLine() throws IOException, EOFException 
        String line = reader.readLine();
        if (line == null || line.trim().length() == 0) 
            throw new EOFException();
        
        return line;
    

    private <T> T read(Class<T> cls) throws IOException 
        String json = readLine();
        return objectMapper.readValue(json, cls);
    


JacksonObjectOutput.java:

package club.zstuca.myzstu.dubbo.serialize.jackson;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.dubbo.common.serialize.ObjectOutput;

import java.io.*;

/**
 * Jackson object output implementation
 *
 * @author shentuzhigang
 * @date 2022/3/19 15:06
 */
public class JacksonObjectOutput implements ObjectOutput 

    private final ObjectMapper objectMapper;

    private final PrintWriter writer;

    public JacksonObjectOutput(OutputStream output) 
        this(new ObjectMapper(), output);
    

    public JacksonObjectOutput(ObjectMapper objectMapper, OutputStream out) 
        this(objectMapper, new OutputStreamWriter(out));
    

    public JacksonObjectOutput(ObjectMapper objectMapper, Writer writer) 
        this.objectMapper = objectMapper;
        this.writer = new PrintWriter(writer);
    

    @Override
    public void writeBool(boolean v) throws IOException 
        writeObject(v);
    

    @Override
    public void writeByte(byte v) throws IOException 
        writeObject(v);
    

    @Override
    public void writeShort(short v) throws IOException 
        writeObject(v);
    

    @Override
    public void writeInt(int v) throws IOException 
        writeObject(v);
    

    @Override
    public void writeLong(long v) throws IOException 
        writeObject(v);
    

    @Override
    public void writeFloat(float v) throws IOException 
        writeObject(v);
    

    @Override
    public void writeDouble(double v) throws IOException 
        writeObject(v);
    

    @Override
    public void writeUTF(String v) throws IOException 
        writeObject(v);
    

    @Override
    public void writeBytes(byte[] v) throws IOException 
        writer.println(new String(v));
    

    @Override
    public void writeBytes(byte[] v, int off, int len) throws IOException 
        writer.println(new String(v));
    

    @Override
    public void writeObject(Object obj) throws IOException 
        writer.write(objectMapper.writeValueAsString(obj));
        writer.println();
        writer.flush();
    

    @Override
    public void flushBuffer() throws IOException 
        writer.flush();
    


META-INF/dubbo/org.apache.dubbo.common.serialize.Serialization:

jackson=club.zstuca.myzstu.dubbo.serialize.jackson.JacksonSerialization

ObjectMapper:
默认情况下,Jackson序列化和反序列化时所使用的ObjectMapper定义如下:

  @Override
    public ObjectMapper getObjectMapper() 
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
//            objectMapper.disable(SerializationFeature.FLUSH_AFTER_WRITE_VALUE);
        objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        objectMapper.setTimeZone(TimeZone.getDefault());
        return objectMapper;

使用

provider

XML

<dubbo:protocol name="dubbo" port="20880" serialization="jackson" />

配置文件

Properties
dubbo.protocols.id=jackson
dubbo.protocols.name=dubbo
dubbo.protocols.port=20880
dubbo.protocols.serialization=jackson
YAML
dubbo:
  config:
    multiple: true
  protocols:
    dubbo:
      id: dubbo
      name: dubbo
      port: -1
    jackson:
      id: jackson
      name: dubbo
      port: 20880
      serialization: jackson

consumer

无需其他配置

常见问题

  1. 不支持泛型对象的序列化, 如 List,Map类型的序列化和反序列化

参考文章

以上是关于Dubbo——Dubbo协议整合Jackson序列化解决方案的主要内容,如果未能解决你的问题,请参考以下文章

Dubbo——Dubbo协议整合Jackson序列化解决方案

Dubbo Jackson序列化使用说明

Dubbo Jackson序列化使用说明

dubbo内部通信用的啥协议

Dubbo源码学习系列 整合Netty

dubbo协议