当前位置: 首页 > news >正文

序列化方式二——JSON之Gson

Gson

1、什么是Gson?

Gson是Google提供的一个用于Java编程语言的JSON(JavaScript Object Notation)序列化和反序列化库。它允许开发者在Java对象和JSON数据之间进行高效的映射和转换。

官网地址:https://github.com/google/gson

官网文档:https://google.github.io/gson/UserGuide.html

2、为什么选择Gson?

  1. 快速、高效:Gson采用了一些优化策略,确保在处理大量数据时能够保持高效率。

  2. 代码量少、简洁:Gson的设计简洁,使用起来非常方便,开发者可以以较少的代码实现复杂的JSON处理功能。

  3. 面向对象:Gson支持Java对象的序列化,能够将复杂的Java对象(包括嵌套对象和集合)转换为JSON字符串,同时也支持将JSON字符串反序列化为Java对象。

  4. 数据传递和解析方便:Gson提供了灵活的数据传递和解析方式,使得在前后端之间传递数据时变得非常方便。

  5. 自定义序列化和反序列化:Gson允许开发者通过实现JsonSerializer和JsonDeserializer接口来自定义对象的序列化和反序列化过程,以满足特定需求。

  6. 支持复杂对象:Gson能够处理复杂的Java对象,包括嵌套对象和集合,它会自动处理对象之间的关系,将它们转换为相应的JSON格式。

  7. 与Android兼容:Gson在Android开发中也被广泛使用,因为它与Android平台兼容,能够方便地处理Android应用中的JSON数据。

  8. 性能优化:对于大型数据集,Gson提供了性能优化的选项,如使用JsonReader和JsonWriter进行流式处理,以减少内存占用并提高处理速度。

  9. 版本控制:Gson支持使用@Since和@Until注解来指定字段的版本信息,以便在对象模型发生变化时保持向后和向前兼容性。

  10. 处理空值和异常:Gson能够处理Java对象中的null值,并将它们序列化为JSON字符串中的null。同时,Gson也提供了异常处理机制,以便在反序列化过程中捕获和处理可能出现的异常。

3、Gson常用的API

3.1. Gson对象的创建

  • 直接创建:通过new Gson()直接创建一个Gson对象,使用默认配置。

  • GsonBuilder:使用GsonBuilder类可以构建自定义配置的Gson对象,如设置日期格式、排除空值、自定义序列化器等。

3.2. 序列化

  • toJson()方法:将Java对象序列化为JSON字符串。Gson提供了多个重载的toJson()方法,支持将对象、对象数组、集合等转换为JSON字符串。

3.3. 反序列化

  • fromJson()方法:将JSON字符串反序列化为Java对象。Gson同样提供了多个重载的fromJson()方法,支持将JSON字符串解析为指定的Java对象、对象数组、集合等。

3.4. JsonElement、JsonObject和JsonArray

  • JsonElement:表示JSON树中的一个节点,可以是JsonObject、JsonArray、JsonPrimitive或JsonNull。

  • JsonObject:表示JSON对象,即键值对集合。可以通过get()方法获取特定键对应的值,使用put()方法添加或修改键值对。

  • JsonArray:表示JSON数组,即值的有序列表。可以使用get()方法按索引访问数组中的元素,使用add()方法添加元素。

3.5. TypeToken

  • 当需要将JSON字符串反序列化为泛型集合时,由于类型擦除,直接使用fromJson()方法会丢失泛型信息。此时,可以使用TypeToken类来捕获泛型信息。

3.6. 自定义序列化器与反序列化器

  • JsonSerializer和JsonDeserializer:Gson 1.x版本中提供的自定义序列化器和反序列化器接口,基于树型结构进行解析。

  • TypeAdapter:Gson 2.0版本中新增的自定义序列化器和反序列化器接口,基于流式结构进行解析,相比树型结构更节省内存。

3.7. 注解

Gson提供了一系列注解来支持复杂的序列化和反序列化场景,如:

  • @SerializedName:用于指定JSON属性名与Java字段名之间的映射关系。

  • @Expose:用于控制字段是否参与序列化和反序列化。

  • @JsonAdapter:用于指定字段或类使用自定义的序列化器或反序列化器。

  • @Since和@Until:用于控制字段的序列化版本。

3.8. 流式API

对于大量数据,Gson提供了流式API,即JsonReaderJsonWriter,可以有效地读写JSON数据,减少内存占用。

4、使用

4.1、引入依赖

<dependency><groupId>com.google.code.gson</groupId><artifactId>gson</artifactId><version>2.10.1</version>
</dependency>

4.2、简单示例(json->对象,对象->json)

package com.zhz.test.entity;import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;import java.util.Date;@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class GsonStudent {private String name;private String sex;private Integer age;private Date birthday;
}
@Test
public void test() {// 创建Java对象GsonStudent gsonStudent = GsonStudent.builder().age(18).sex("男").birthday(new Date()).name("张三").build();// 创建Gson对象Gson gson = new Gson();// 序列化:将Java对象转换为JSON字符串(对象->json)String json = gson.toJson(gsonStudent);System.out.println(json); // 输出: {"name":"Alice","age":30}// 反序列化:将JSON字符串转换为Java对象(json->对象)GsonStudent newPerson = gson.fromJson(json, GsonStudent.class);System.out.println(newPerson.getName()); // 输出: AliceSystem.out.println(newPerson.getAge()); // 输出: 30
}

image.png

4.3、 自定义序列化器与反序列化器

通过实现JsonSerializer和JsonDeserializer接口来自定义序列化和反序列化过程。这在你需要处理复杂对象或特殊格式时非常有用。

package com.zhz.test.entity;import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;import java.util.Date;@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class GsonStudent {private String name;private String sex;private Integer age;private Date birthday;
}

序列化器

package com.zhz.test.json.gson;import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.zhz.test.entity.GsonStudent;import java.lang.reflect.Type;public class GsonStudentSerializer implements JsonSerializer<GsonStudent> {@Overridepublic JsonElement serialize(GsonStudent src, Type typeOfSrc, JsonSerializationContext context) {JsonObject jsonObject = new JsonObject();jsonObject.addProperty("name", src.getName());// 假设我们对年龄进行特殊处理,比如加10jsonObject.addProperty("age", src.getAge() + 10);// 可以添加更多自定义逻辑return jsonObject;}
}

反序列化器

package com.zhz.test.json.gson;import com.google.gson.*;
import com.zhz.test.entity.GsonStudent;import java.lang.reflect.Type;public class GsonStudentDeserializer implements JsonDeserializer<GsonStudent> {@Overridepublic GsonStudent deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {JsonObject jsonObject = json.getAsJsonObject();String name = jsonObject.get("name").getAsString();// 假设我们从JSON中读取的年龄需要减10以还原原始值int age = jsonObject.get("age").getAsInt() - 10;// 创建并返回Person对象return GsonStudent.builder().name(name).age(age).build();}
}

测试代码

@Testpublic void testSerializable() {// 创建并注册自定义序列化器和反序列化器Gson gson = new GsonBuilder().registerTypeAdapter(GsonStudent.class, new GsonStudentSerializer()).registerTypeAdapter(GsonStudent.class, new GsonStudentDeserializer()).create();// 序列化GsonStudent gsonStudent = GsonStudent.builder().age(18).sex("男").birthday(new Date()).name("张三").build();String json = gson.toJson(gsonStudent);System.out.println(json); // 输出: {"name":"John","age":40}// 反序列化GsonStudent deserializedPerson = gson.fromJson(json, GsonStudent.class);System.out.println(deserializedPerson); // 输出: Person{name='John', age=20}}

image.png

4.4、排除字段

  • 使用@Expose注解来标记哪些字段应该被序列化或反序列化。未标记的字段将默认被排除。

  • 在Gson中,如果你想要排除某些字段,在序列化过程中不被包含到JSON字符串中,有几种方法可以实现这一点。然而,Gson本身并没有直接提供一个简单的注解来标记一个字段应该被排除。不过,你可以使用@Expose注解(虽然它主要用于Gson 2.x之前的版本,并且在新版本中可能不再推荐使用),或者更常见的是,使用GsonBuilder的excludeFieldsWithoutExposeAnnotation()方法结合@Expose注解(尽管这是标记哪些字段应该被包含,而不是排除),或者使用@SerializedName注解的变体(实际上不是用于排除,但可以用来避免生成JSON中的某些字段),或者通过自定义序列化器来完全控制序列化过程。

  • 不过,对于Gson 2.8及以上版本,简单地通过自定义序列化器来排除字段。以下是一个使用自定义序列化器来排除字段的示例:

package com.zhz.test.entity;import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;import java.util.Date;@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class GsonStudent {private String name;private String sex;private Integer age;private Date birthday;
}
/*** 排除字段*/
@Test
public void testExclusion(){// 创建一个Gson实例,使用自定义的排除策略Gson gson = new GsonBuilder().setExclusionStrategies(new ExclusionStrategy() {@Overridepublic boolean shouldSkipField(FieldAttributes f) {// 这里可以根据字段名、类型等条件来排除字段// 例如,排除所有名为"age"的字段return "age".equals(f.getName());}@Overridepublic boolean shouldSkipClass(Class<?> clazz) {// 这里可以根据类来排除整个类的序列化,但通常不需要return false;}}).create();// 序列化GsonStudent gsonStudent = GsonStudent.builder().age(18).sex("男").birthday(new Date()).name("张三").build();// 序列化Person对象,注意"age"字段被排除了String json = gson.toJson(gsonStudent);System.out.println(json); // 输出可能类似于: {"name":"John"}
}

image.png

4.5、格式化输出

使用GsonBuilder的setPrettyPrinting()方法可以使Gson以更易读的格式输出JSON字符串。

package com.zhz.test.entity;import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;import java.util.Date;@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class GsonStudent {private String name;private String sex;private Integer age;private Date birthday;
}
@Test
public void testPrettyPrinting(){// 使用GsonBuilder设置格式化输出并创建Gson对象Gson gson = new GsonBuilder().setPrettyPrinting().create();GsonStudent gsonStudent = GsonStudent.builder().age(18).sex("男").birthday(new Date()).name("张三").build();// 将Person对象序列化为格式化的JSON字符串String jsonString = gson.toJson(gsonStudent);// 输出结果System.out.println(jsonString);
}

image.png

4.6、处理泛型

对于泛型集合,Gson提供了TypeToken来捕获泛型信息,以便正确地进行反序列化。

基本对象

package com.zhz.test.entity;import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;import java.util.Date;@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class GsonStudent {private String name;private String sex;private Integer age;private Date birthday;
}

处理List集合

   /*** 测试泛型*/@Testpublic void testPansexual(){// 序列化GsonStudent gsonStudent = GsonStudent.builder().age(18).sex("男").birthday(new Date()).name("张三").build();// 创建一个包含Person对象的ListList<GsonStudent> gsonStudents = new ArrayList<>();gsonStudents.add(gsonStudent);// 创建Gson实例Gson gson = new Gson();// 序列化List<Person>为JSON字符串String json = gson.toJson(gsonStudents);System.out.println(json);// 反序列化JSON字符串回List<Person>// 注意:由于类型擦除,我们需要使用TypeToken来捕获List<Person>的类型信息Type listType = new TypeToken<List<GsonStudent>>(){}.getType();List<GsonStudent> deserializedPersons = gson.fromJson(json, listType);// 输出反序列化后的List内容for (GsonStudent gsonStudent1 : deserializedPersons) {System.out.println(gsonStudent1);}}

image.png

处理Set

/*** 测试Set泛型*/@Testpublic void testPansexualSet(){// 序列化GsonStudent gsonStudent = GsonStudent.builder().age(18).sex("男").birthday(new Date()).name("张三").build();// 创建一个包含Person对象的ListSet<GsonStudent> gsonStudents = new HashSet<>();gsonStudents.add(gsonStudent);// 创建Gson实例Gson gson = new Gson();// 序列化List<Person>为JSON字符串String json = gson.toJson(gsonStudents);System.out.println(json);// 反序列化JSON字符串回List<Person>// 注意:由于类型擦除,我们需要使用TypeToken来捕获List<Person>的类型信息Type setType = new TypeToken<Set<GsonStudent>>(){}.getType();Set<GsonStudent> deserializedPersons = gson.fromJson(json, setType);// 输出反序列化后的List内容for (GsonStudent gsonStudent1 : deserializedPersons) {System.out.println(gsonStudent1);}}

image.png

处理Map

/*** 测试Map泛型*/@Testpublic void testPansexualMap(){// 序列化GsonStudent gsonStudent = GsonStudent.builder().age(18).sex("男").birthday(new Date()).name("张三").build();// 创建一个包含Person对象的ListMap<String,GsonStudent> gsonStudents = new HashMap<>();gsonStudents.put("111",gsonStudent);// 创建Gson实例Gson gson = new Gson();// 序列化List<Person>为JSON字符串String json = gson.toJson(gsonStudents);System.out.println(json);// 反序列化JSON字符串回List<Person>// 注意:由于类型擦除,我们需要使用TypeToken来捕获List<Person>的类型信息Type mapType = new TypeToken<Map<String,GsonStudent>>(){}.getType();Map<String,GsonStudent> deserializedPersons = gson.fromJson(json, mapType);// 输出反序列化后的Map内容for (Map.Entry<String, GsonStudent> entry : deserializedPersons.entrySet()) {System.out.println(entry.getKey()+"\t"+entry.getValue());}}

image.png

4.7、处理日期格式

Gson本身并不直接提供注解来指定日期格式,但你可以通过自定义序列化器(JsonSerializer)和反序列化器(JsonDeserializer)来解决这个问题。

以下是一个处理日期格式的示例,展示了如何为java.util.Date类型自定义序列化器和反序列化器,并设置特定的日期格式(例如,yyyy-MM-dd)。代码如下:

package com.zhz.test.entity;import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;import java.util.Date;@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class GsonStudent {private String name;private String sex;private Integer age;private Date birthday;
}

自定义Date序列化

package com.zhz.test.json.gson;import com.google.gson.JsonElement;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;import java.lang.reflect.Type;
import java.text.SimpleDateFormat;
import java.util.Date;public class DateSerializer implements JsonSerializer<Date> {private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");@Overridepublic JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext context) {return new JsonPrimitive(dateFormat.format(src));}
}

自定义Date反序列化器

package com.zhz.test.json.gson;import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;import java.lang.reflect.Type;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;public class DateDeserializer implements JsonDeserializer<Date> {private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");@Overridepublic Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {try {return dateFormat.parse(json.getAsString());} catch (ParseException e) {throw new JsonParseException(e);}}
}

测试demo

@Test
public void testDate(){Gson gson = new GsonBuilder().registerTypeAdapter(Date.class, new DateSerializer()).registerTypeAdapter(Date.class, new DateDeserializer()).create();// 序列化GsonStudent gsonStudent = GsonStudent.builder().age(18).sex("男").birthday(new Date()).name("张三").build();// 序列化对象String json = gson.toJson(gsonStudent);System.out.println(json); // 输出类似:{"date":"2023-04-01"}// 反序列化JSON字符串GsonStudent deserializedObj = gson.fromJson(json, GsonStudent.class);System.out.println(deserializedObj.getBirthday()); // 输出:对应的Date对象,但注意它只包含日期部分
}

image.png

4.8、处理异常

在使用Gson库处理JSON数据时,可能会遇到各种异常情况,例如解析错误、类型转换错误等。Gson通过抛出异常来指示这些错误情况,因此你需要适当地捕获和处理这些异常。Gson主要会抛出以下几种类型的异常:

  1. JsonSyntaxException:当输入的JSON字符串不符合JSON规范时,Gson会抛出此异常。这通常发生在解析JSON数据时。

  2. JsonParseException:Gson在解析JSON时,如果遇到无法理解的格式或结构,也会抛出此异常。虽然Gson主要使用JsonSyntaxException,但在某些情况下(或旧版本中),你可能会遇到JsonParseException

  3. JsonIOException:当Gson在读取或写入JSON数据时遇到I/O错误时,会抛出此异常。这通常与文件或网络I/O操作相关。

  4. IllegalStateException:虽然这不是Gson特有的异常,但在Gson的使用中,如果Gson的状态不正确(比如,在反序列化过程中尝试修改JsonReader的状态),则可能会抛出此异常。

  5. TypeMismatchException(Gson 2.8.6及以后版本):这是一个自定义的异常,用于指示在反序列化过程中类型不匹配的情况。它可以帮助你更容易地识别和处理类型错误。

  6. IllegalArgumentException 和 NullPointerException:这些Java标准异常也可能在Gson的使用中出现,尤其是在处理无效输入或配置错误时。

解决方案,只需要在fromJson ,toJson的时候加个try/catch就好了

@Test
public void testTryCatch() {// 创建Java对象GsonStudent gsonStudent = GsonStudent.builder().age(18).sex("男").birthday(new Date()).name("张三").build();// 创建Gson对象Gson gson = new Gson();// 序列化:将Java对象转换为JSON字符串String json = gson.toJson(gsonStudent);System.out.println(json); // 输出: {"name":"Alice","age":30}try {// 反序列化:将JSON字符串转换为Java对象GsonStudent newPerson = gson.fromJson(json, GsonStudent.class);System.out.println(newPerson.getName()); // 输出: AliceSystem.out.println(newPerson.getAge()); // 输出: 30}catch (Exception e) {throw new RuntimeException(e);}
}

4.9、字段访问权限

Gson默认只能访问类中的公共字段(public fields)和方法。如果类变量的访问权限不是公共的(如private、protected或默认包级私有),Gson就无法直接访问到这些变量。为了解决这个问题,Gson提供了几种方法:

  • 使用@Expose注解:通过@Expose注解,可以将非公共字段标记为可序列化和反序列化的字段。但请注意,要使用这个注解,必须在创建Gson对象时通过GsonBuilder配置Gson实例,以包含@Expose注解的字段。

  • 自定义序列化器和反序列化器:通过实现JsonSerializer和JsonDeserializer接口,可以自定义序列化和反序列化的逻辑,从而控制对字段的访问。

  • 修改字段访问权限:虽然这不是最佳实践,但在某些情况下,将字段的访问权限修改为public可能是一个简单的解决方案。

4.10、循环引用

循环引用是指两个或多个对象之间相互引用的现象。在Java中,循环引用可能导致内存泄漏和程序崩溃等问题。Gson提供了处理循环引用的方法:

  • 自动处理:在大多数情况下,Gson能够自动处理循环引用,确保数据结构的稳定性。这通常是通过在序列化过程中检测并处理循环引用来实现的。

  • 自定义序列化器和反序列化器:对于复杂的循环引用情况,可以通过自定义序列化器和反序列化器来特别处理循环引用,如跳过循环引用对象的某些属性等。

  • 使用GsonBuilder的setExclusionStrategies:通过实现ExclusionStrategy接口,可以定义排除策略,从而在序列化或反序列化过程中排除特定的字段或类。

4.11、性能优化&TypeAdapter测试用例

Gson的性能优化可以从多个方面入手:

  • 全局Gson对象:在项目中提供一个全局的Gson对象,以避免频繁创建Gson实例带来的性能开销。

  • 避免不必要的序列化:只序列化需要的数据,避免序列化整个对象图,特别是包含大量不必要数据或复杂对象图的情况。

  • 自定义序列化器和反序列化器:通过自定义序列化器和反序列化器,可以优化序列化和反序列化的过程,减少不必要的计算或内存使用。

  • 使用流式API(TypeAdapter):Gson 2.0引入了TypeAdapter,这是一个基于流式结构的API,相比基于树型结构的JsonSerializer和JsonDeserializer,TypeAdapter更节省内存。\

下面给一个TypeAdapter的测试用例

package com.zhz.test.entity;import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;import java.util.Date;@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class GsonStudent {private String name;private String sex;private Integer age;private Date birthday;
}
package com.zhz.test.json.gson;import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;
import com.zhz.test.entity.GsonStudent;import java.io.IOException;public class GsonStudentTypeAdapter extends TypeAdapter<GsonStudent> {@Overridepublic void write(JsonWriter out, GsonStudent value) throws IOException {if (value == null) {out.nullValue();return;}out.beginObject();out.name("name").value(value.getName());out.name("age").value(value.getAge());out.endObject();}@Overridepublic GsonStudent read(JsonReader in) throws IOException {if (in.peek() == JsonToken.NULL) {in.nextNull();return null;}in.beginObject();String name = null;int age = 0;while (in.hasNext()) {switch (in.nextName()) {case "name":name = in.nextString();break;case "age":age = in.nextInt();break;default:in.skipValue(); // 忽略未知字段}}in.endObject();return GsonStudent.builder().age(age).name(name).build();}
}
@Test
public void testSerializationAndDeserialization() {// 序列化GsonStudent gsonStudent = GsonStudent.builder().age(18).sex("男").birthday(new Date()).name("张三").build();Gson gson = new GsonBuilder().registerTypeAdapter(GsonStudent.class, new GsonStudentTypeAdapter()).create();// 序列化String json = gson.toJson(gsonStudent);System.out.println(json);// 反序列化GsonStudent deserializedUser = gson.fromJson(json, GsonStudent.class);System.out.println(deserializedUser);
}

4.12、版本控制

Gson的版本控制主要涉及到两个方面:

  • Gson库的版本:在使用Gson时,应关注Gson库的最新版本,以便利用新功能和性能改进。同时,也需要注意版本兼容性,避免升级后引入不兼容的变更。

  • 序列化数据的版本:在序列化数据时,有时需要控制数据的版本,以便在反序列化时能够处理不同版本的数据。Gson提供了@Since和@Until注解,用于声明字段的起始和终止序列化版本。这样,在反序列化时,只有满足版本条件的字段才会被包含在内。

5、注意事项

  1. 版本兼容性:Gson的不同版本之间可能存在一些差异,特别是API的变化。因此,在升级Gson版本时,请务必参考官方文档或更新日志。

  2. 性能优化:对于大型数据集,Gson提供了流式API(JsonReaderJsonWriter)来减少内存占用并提高性能。

  3. 安全性:在处理不受信任的JSON数据时,请确保你的应用程序能够正确处理潜在的安全问题,如JSON注入攻击。

打个广告

本人新搞的个人项目,有意者可到 DDD用户中台 这里购买

可以学习到的体系

  • 项目完全从0到1开始架构,包含前端,后端,架构,服务器,技术管理相关运维知识!

    • 最佳包名设计,项目分层
  • 破冰CRUD,手撕中间件!

    • 基于MybatisPlus封装属于自己的DDD ORM框架

    • 基于Easyexcel封装属于自己的导入导出组件

    • oss对象存储脚手架(阿里云,minio,腾讯云,七牛云等)

    • 邮件脚手架

    • completefuture脚手架

    • redis脚手架

    • xxl-job脚手架

    • 短信脚手架

    • 常用工具类等

  • 传统MVC代码架构弊端的解决方案

    • DDD+CQRS+ES最难架构
  • 结合实际代码的业务场景

    • 多租户单点登录中心

    • 用户中台

    • 消息中心

    • 配置中心

    • 监控设计

  • 程序员的职业规划,人生规划

    • 打工永远没有出路!

    • 打破程序员的35岁魔咒

    • 技术带给你的优势和竞争力【启发】

    • 万物互联网的淘金之路!

技术以外的赚钱路子

可以一起沟通

具体的文章目录

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

购买链接

DDD用户中台


http://www.mrgr.cn/news/33561.html

相关文章:

  • 华为大咖说 | 浅谈智能运维技术
  • WSL 2 中 FastReport 与 FastCube 的设置方法与优化策略
  • 机器人 正向运动学(Forward Kinematics) 关节空间转换为笛卡尔空间
  • 2024年11月10日系统架构设计师考试题目回顾
  • 【OpenEuler】配置虚拟ip
  • 贪心算法-汽车加油
  • CCC SPAKE2+流程解析
  • 【数据结构-栈】力扣1441. 用栈操作构建数组
  • 图书管理系统
  • 什么是数据库视图(View)?视图和表有何区别?
  • 程序员软硬通吃的核心竞争力修炼指南
  • 如何在堆和栈上分别创建一个`QObject`子类对象
  • 用OPenCV分割视频
  • 【米哈游AI大模型“Glossa”正式完成备案,AI加持游戏行业开拓新赛道】
  • typedef的用法
  • 对网页聊天项目进行性能测试, 使用JMeter对于基于WebSocket开发的webChat项目的聊天功能进行测试
  • 机器学习算法那些事 | TPAMI 2024.9 | FeatAug-DETR:通过特征增强丰富DETRs的一对多匹配
  • 【人工智能】在大型活动中的应用案例
  • 带你0到1之QT编程:十七、Http协议实战,实现一个简单服务器和一个客户端进行http协议通信
  • Python 虚拟环境安装使用(Anaconda 完整实操版)
  • stable diffusion 神经网络插件 controlnet 的安装,很详细
  • 自学笔记之TVM编译器框架 ,核心特性,模型优化概述,AI应用落地
  • 【C++初阶】模版进阶
  • 6、论文阅读:水下图像增强基准数据集及其他数据集
  • go语言 swagger 查询 json 字段注释
  • REST-系统架构师(六十九)