Jackson无缝替换Fastjson

目录

文章目录

  • 一,Fastjson到Jackson的替换方案
    • 方案代码
    • 序列化
    • 反序列化
    • 通过key获取某种类型的值
    • 类型替换
  • 二,Springboot工程中序列化的使用场景
  • 三,SpringMVC框架中的Http消息转换器
    • 1,原理:
    • 2,自定义消息转换器
      • Fastjson序列化消息转换器定义:
      • Jackson序列化消息转换器定义:
    • 3,Jackson常用注解自定义序列化规则

一,Fastjson到Jackson的替换方案

方案代码

package main.java.solutions;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * json工具类
 * @Date: 2023/7/4 14:38
 */
@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class JsonUtil {

    /**
     * 这个是提供给http接口使用的对象
     */
    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

    static {
        // 通过该方法对mapper对象进行设置,所有序列化的对象都将按改规则进行系列化
        // Include.Include.ALWAYS 默认
        // Include.NON_DEFAULT 属性为默认值不序列化
        // Include.NON_EMPTY 属性为 空("") 或者为 NULL 都不序列化,则返回的json是没有这个字段的。这样对移动端会更省流量
        // Include.NON_NULL 属性为NULL 不序列化
        OBJECT_MAPPER.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        OBJECT_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        OBJECT_MAPPER.configure(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS, true);
        OBJECT_MAPPER.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        OBJECT_MAPPER.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
        OBJECT_MAPPER.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);

        SimpleModule module = new SimpleModule();
        module.addSerializer(BigDecimal.class, ToStringSerializer.instance);
        module.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer());
        module.addSerializer(LocalDate.class, new LocalDateSerializer());
        module.addDeserializer(LocalDateTime.class, new LocalDateTimeDeSerializer());
        module.addDeserializer(LocalDate.class, new LocalDateDeSerializer());
        OBJECT_MAPPER.registerModule(module);
    }

    /**
     * 直接获取ObjectMapper对象
     */
    public static ObjectMapper getObjectMapper() {
        return OBJECT_MAPPER;
    }

    /**
     * 序列化一个对象,序列化失败时仅仅打印日志并且返回null。
     *
     * @param object 对象
     * @return String
     */
    public static String toJsonOrNull(Object object) {
        if (object == null) {
            return null;
        }
        try {
            return OBJECT_MAPPER.writeValueAsString(object);
        } catch (JsonProcessingException e) {
            log.error("Json serialize error :", e);
        }
        return null;
    }

    /**
     * 序列化一个对象,序列化失败则抛异常
     *
     * @param object 对象
     * @return String
     */
    public static String toJsonString(Object object) throws Exception {
        if (object == null) {
            return null;
        }
        try {
            return OBJECT_MAPPER.writeValueAsString(object);
        } catch (JsonProcessingException e) {
            log.error("Json serialize error :", e);
            throw new Exception("Json serialize error");
        }
    }

    /**
     * 反序列化,失败则抛异常
     */
    public static <T> T parseObject(String json, Class<T> classType) throws Exception {
        if (StringUtils.isEmpty(json)) {
            return null;
        }
        try {
            return OBJECT_MAPPER.readValue(json, classType);
        } catch (Exception e) {
            log.error("Json de-serialize error :", e);
            throw new Exception("Json de-serialize error");
        }
    }

    /**
     * 自定义复杂的泛型对象,反序列化,失败则抛异常
     */
    public static <T> T parseObject(String json, TypeReference<T> typeReference) throws Exception{
        if (StringUtils.isEmpty(json)) {
            return null;
        }
        try {
            return OBJECT_MAPPER.readValue(json, typeReference);
        } catch (Exception e) {
            log.error("Json de-serialize error :", e);
            throw new Exception("Json de-serialize error");
        }

    }

    /**
     * 反序列化为Map
     */
    public static Map<String, Object> parseMap(String json) throws Exception{
        return parseObject(json, new TypeReference<Map<String, Object>>() {});
    }

    /**
     * 自定义 List 类型的反序列化
     *
     * @param json      JSON 字符串
     * @param classType List 中元素的类类型
     * @param <T>       List 中元素的泛型类型
     * @return 反序列化后的 List 对象
     */
    @SuppressWarnings("unchecked")
    public static <T> List<T> parseArray(String json, Class<T> classType) throws Exception {
        if (StringUtils.isEmpty(json)) {
            return null;
        }
        try {
            return parseCollection(json, ArrayList.class, classType);
        } catch (Exception e) {
            log.error("Error occurred during json deserialization for List: ", e);
            throw new Exception("Error occurred during json deserialization");
        }
    }

    /**
     * 通用的集合类型反序列化
     *
     * @param jsonStr     JSON 字符串
     * @param resultClass 结果集合的类类型
     * @param classType   集合元素的类类型
     * @param <C>         返回结果的泛型类型,必须是 Collection 的子类
     * @param <T>         集合元素的泛型类型
     * @return 反序列化后的集合对象
     * @throws IOException 如果反序列化过程中出现 I/O 错误
     */
    public static <C extends Collection<T>, T> C parseCollection(String jsonStr, Class<C> resultClass, Class<T> classType) throws IOException {
        return OBJECT_MAPPER.readValue(jsonStr, OBJECT_MAPPER.getTypeFactory().constructCollectionType(resultClass, classType));
    }

    public static Long getLong(Map<String, Object> map, String key) throws Exception {
        return TypeUtils.castToLong(map.get(key));
    }

    public static Integer getInteger(Map<String, Object> map, String key) throws Exception{
        return TypeUtils.castToInt(map.get(key));
    }

    public static String getString(Map<String, Object> map, String key) {
        return TypeUtils.castToString(map.get(key));
    }

}
package main.java.solutions;

import java.math.BigDecimal;
import java.util.Iterator;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 类型转换类
 * @Date: 2023/7/4 14:38
 */
public class TypeUtils {
    private static final Pattern NUMBER_WITH_TRAILING_ZEROS_PATTERN = Pattern.compile("\\.0*$");

    public static String castToString(Object value) {
        if (value == null) {
            return null;
        }
        return value.toString();
    }

    public static Integer castToInt(Object value) throws Exception{
        if (value == null) {
            return null;
        }
        if (value instanceof Integer) {
            return (Integer)value;
        }
        if (value instanceof BigDecimal) {
            return intValue((BigDecimal)value);
        }
        if (value instanceof Number) {
            return ((Number)value).intValue();
        }
        if (value instanceof String) {
            String strVal = (String)value;
            if (strVal.length() == 0 //
                || "null".equals(strVal) //
                || "NULL".equals(strVal)) {
                return null;
            }
            if (strVal.indexOf(',') != -1) {
                strVal = strVal.replaceAll(",", "");
            }
            Matcher matcher = NUMBER_WITH_TRAILING_ZEROS_PATTERN.matcher(strVal);
            if (matcher.find()) {
                strVal = matcher.replaceAll("");
            }
            return Integer.parseInt(strVal);
        }
        if (value instanceof Boolean) {
            return (Boolean)value ? 1 : 0;
        }
        if (value instanceof Map) {
            Map map = (Map)value;
            if (map.size() == 2
                && map.containsKey("andIncrement")
                && map.containsKey("andDecrement")) {
                Iterator iter = map.values().iterator();
                iter.next();
                Object value2 = iter.next();
                return castToInt(value2);
            }
        }
        throw new Exception("Cast type error: "+value);
    }

    public static Long castToLong(Object value) throws Exception {
        if (value == null) {
            return null;
        }
        if (value instanceof BigDecimal) {
            return longValue((BigDecimal)value);
        }
        if (value instanceof Number) {
            return ((Number)value).longValue();
        }
        if (value instanceof String) {
            String strVal = (String)value;
            if (strVal.length() == 0 //
                || "null".equals(strVal) //
                || "NULL".equals(strVal)) {
                return null;
            }
            if (strVal.indexOf(',') != -1) {
                strVal = strVal.replaceAll(",", "");
            }
            try {
                return Long.parseLong(strVal);
            } catch (NumberFormatException ex) {
                //
            }
        }
        if (value instanceof Map) {
            Map map = (Map)value;
            if (map.size() == 2
                && map.containsKey("andIncrement")
                && map.containsKey("andDecrement")) {
                Iterator iter = map.values().iterator();
                iter.next();
                Object value2 = iter.next();
                return castToLong(value2);
            }
        }
        if (value instanceof Boolean) {
            return (Boolean)value ? 1L : 0L;
        }
        throw new Exception("Cast type error: "+value);
    }

    public static int intValue(BigDecimal decimal) {
        if (decimal == null) {
            return 0;
        }
        int scale = decimal.scale();
        if (scale >= -100 && scale <= 100) {
            return decimal.intValue();
        }
        return decimal.intValueExact();
    }

    public static long longValue(BigDecimal decimal) {
        if (decimal == null) {
            return 0;
        }
        int scale = decimal.scale();
        if (scale >= -100 && scale <= 100) {
            return decimal.longValue();
        }
        return decimal.longValueExact();
    }
}

序列化

1,JSON.toJSONString(this)JSON.toJSON(this); if为null,则返回null,如果转换异常,就抛异常。

如果是日志打印就使用JsonUtils.toJsonOrNull(this)替换,否则使用JsonUtils.toJsonString(this)

反序列化

1,JSON.parseObject(deviceInfoStr, DeviceInfo.class); if为null,则返回null,如果转换异常,就抛异常

使用**JsonUtils.parseObject(deviceInfoStr, DeviceInfo.class)**替换

2,JSON.parseObject(String text);if为null,则返回null,如果转换异常,就抛异常

使用 **JsonUtils.parseMap(String json)**替换

3,JSONObject.parseArray(String text, Class<T> clazz);if为null,则返回null,如果转换异常,就抛异常

使用 **JsonUtils.parseArray(String text, Class<T> clazz)**替换;

通过key获取某种类型的值

1,jsonObject.getLong(String key) ;if为null,则返回null,如果转换异常,就抛异常

使用**JsonUtils.getLong(map, key)**替换;

2,jsonObject.getInteger(String key) ;if为null,则返回null,如果转换异常,就抛异常

使用 **JsonUtils.getInteger(map, key)**替换;

3,jsonObject.getString(String key) ;if为null,则返回null,如果转换异常,就抛异常

使用 **JsonUtils.getString(map, key)**替换;

类型替换

7,返回给前端的是JSONObject使用**Map<String, Object>**替换

8,返回给前端的是JSONArray使用**List<Object>**替换

二,Springboot工程中序列化的使用场景

  1. 控制器(Controller):控制器负责处理 HTTP 请求和响应,其中涉及到请求参数的反序列化和响应结果的序列化。SpringMVC 使用消息转换器(MessageConverter)来处理请求和响应的序列化和反序列化,常见的消息转换器包括 JSON、XML、Form 表单等。
  2. RESTful API:如果您的 Spring Boot 项目是基于 RESTful API 架构的,那么在请求和响应的过程中,需要进行对象和 JSON/XML 数据之间的序列化和反序列化。Spring Boot 使用消息转换器来自动处理这些转换过程。
  3. 数据库操作:当使用对象关系映射(ORM)框架(如 Hibernate、Spring Data JPA)进行数据库操作时,需要将 Java 对象与数据库记录之间进行序列化和反序列化。ORM 框架会自动将对象转换为数据库记录(序列化),或将数据库记录转换为对象(反序列化)。
  4. 缓存操作:在使用缓存(如 Redis、Memcached)时,需要将对象存储到缓存中或从缓存中获取对象。这涉及到将对象进行序列化和反序列化,以便在缓存中进行存储和检索。
  5. 消息队列:如果在 Spring Boot 项目中使用消息队列(如 RabbitMQ、Kafka)进行异步消息处理,那么消息的生产者和消费者之间需要进行对象的序列化和反序列化,以便在消息传递过程中正确地传递和处理对象数据。
  6. 文件存储:当将Java对象以文件形式存储时,可能需要将其序列化为JSON或其他格式,以便于读取和写入。

三,SpringMVC框架中的Http消息转换器

1,原理:

利用SpringMVC框架,可以使得我们在开发时,只要在代码中使用**@RequestBody@ResponseBody两个注解,就可以分别完成从请求报文到对象和从对象到响应报文的转换。而在源码内部,其实这种灵活的消息转换机制就是利用HttpMessageConverter**来实现的。

HttpMessageConverter的调用是在RequestResponseBodyMethodProcessor类的解析请求参数的方法resolveArgument()和处理返回值的方法handleReturnValue()中进行调用的。

在这里插入图片描述

Http消息转换器接口

org.springframework.http.converter.HttpMessageConverter 3

public interface HttpMessageConverter<T> {
    boolean canRead(Class<?> var1, @Nullable MediaType var2);

    boolean canWrite(Class<?> var1, @Nullable MediaType var2);

    List<MediaType> getSupportedMediaTypes();

    T read(Class<? extends T> var1, HttpInputMessage var2) throws IOException, HttpMessageNotReadableException;

    void write(T var1, @Nullable MediaType var2, HttpOutputMessage var3) throws IOException, HttpMessageNotWritableException;
}

链路

http请求 -DispatcherServlet -RequestMappingHandlerAdapter(处理请求映射的适配器)-ArgumentResolver(参数解析器)/ReturnValueHandlers(返回值处理器)-RequestResponseBodyMethodProcessor(处理请求和返回的参数)-HttpMessageConverter的read,write方法
    

org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#requestMappingHandlerAdapter 1

protected final List<HttpMessageConverter<?>> getMessageConverters() {
        if (this.messageConverters == null) {
            this.messageConverters = new ArrayList();
            //这是一个抽象方法,允许子类覆盖它来配置HTTP消息转换器。开发者可以在子类中实现这个方法来添加自定义的消息转换器。
            this.configureMessageConverters(this.messageConverters);
            if (this.messageConverters.isEmpty()) {
                //中添加一组默认的HTTP消息转换器。这些默认转换器是Spring MVC框架提供的,用于支持常见的数据格式,如JSON、XML等。
                this.addDefaultHttpMessageConverters(this.messageConverters);
            }
            //这是一个可选的方法,允许子类进一步扩展或修改已经配置的HTTP消息转换器。开发者可以在子类中实现这个方法来对已有的消息转换器进行额外的定制。
            this.extendMessageConverters(this.messageConverters);
        }

        return this.messageConverters;
    }

有几种类型的转换器:

在这里插入图片描述

ByteArrayHttpMessageConverter:负责读取二进制格式的数据和写出二进制格式的数据;

StringHttpMessageConverter:负责读取字符串格式的数据和写出二进制格式的数据(当返回值是或者接受值是String类型时,是由这个处理)

ResourceHttpMessageConverter:负责读取资源文件和写出资源文件数据;

ResourceRegionHttpMessageConverter:用于支持分块传输(Chunked Transfer Encoding)的响应。它允许将资源按照指定的区块大小进行切分,分块传输响应给客户端。

SourceHttpMessageConverter:用于处理以XML格式或其他文本格式表示的数据。它支持处理一些Java源数据(Source)类型,如javax.xml.transform.Source(XML数据的源表示)和org.springframework.core.io.Resource(资源文件的源表示)。

AllEncompassingFormHttpMessageConverter:它是一个综合性的表单数据转换器,用于处理表单数据的请求和响应。

Jaxb2RootElementHttpMessageConverter:用于处理XML数据,并支持Java对象与XML数据之间的转换。它主要依赖于Java Architecture for XML Binding (JAXB) API来实现XML数据的序列化和反序列化。

MappingJackson2HttpMessageConverter:负责读取和写入json格式的数据;(当返回值是对象或者List,就由这个处理)

org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor 2

2,自定义消息转换器

一般默认的转换器不能满足我们的需求,需要自定义消息转换器,可以创建自己的转换器类(Fastjson,Jackson消息转换器),并在 Spring Boot 配置中进行注册。通常情况下,只需要注册您的自定义转换器,Spring Boot 将自动将其应用于适当的请求和响应。

Fastjson序列化消息转换器定义:

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        //使用fastjson converter
        FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
        FastJsonConfig config = new FastJsonConfig();
        config.setSerializerFeatures(
            SerializerFeature.DisableCircularReferenceDetect,
            SerializerFeature.WriteNullListAsEmpty,
            SerializerFeature.WriteMapNullValue,
            SerializerFeature.WriteNullStringAsEmpty,
            SerializerFeature.WriteBigDecimalAsPlain);
        config.setSerializeFilters(ValueDesensitizeFilter.INSTANCE);

        // serialize config
        SerializeConfig serializeConfig = SerializeConfig.getGlobalInstance();
        serializeConfig.put(BigDecimal.class, ToStringSerializer.instance);
        serializeConfig.put(LocalDateTime.class, LocalDateTimeSerializer.instance);
        serializeConfig.put(Long.class, ToStringSerializer.instance);
        serializeConfig.put(Long.TYPE, ToStringSerializer.instance);
        config.setSerializeConfig(serializeConfig);
        converter.setFastJsonConfig(config);
        converters.add(0, converter);
    }
}

Jackson序列化消息转换器定义:

@Configuration
public class JacksonConfig {
    @Bean
    @ConditionalOnMissingBean(ObjectMapper.class)
    public ObjectMapper objectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        // 通过该方法对mapper对象进行设置,所有序列化的对象都将按改规则进行序列化
        // Include.Include.ALWAYS 默认
        // Include.NON_DEFAULT 属性为默认值不序列化
        // Include.NON_EMPTY 属性为 空("") 或者为 NULL 都不序列化,则返回的json是没有这个字段的。这样对移动端会更省流量
        // Include.NON_NULL 属性为NULL 不序列化
        objectMapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
        //解析数组集合、List对象 为[]
        objectMapper.setSerializerFactory(objectMapper.getSerializerFactory().withSerializerModifier(new SerializerModifier()));

        SimpleModule simpleModule = new SimpleModule();
        simpleModule.addSerializer(BigDecimal.class, ToStringSerializer.instance);
        simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
        simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
        simpleModule.addSerializer(LocalDateTime.class, new LocalDateTimeToTimestampSerializer());
        simpleModule.addSerializer(LocalDate.class, new LocalDateSerializer());
        simpleModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeSerializer());
        simpleModule.addDeserializer(LocalDate.class, new LocalDateDeSerializer());
        objectMapper.registerModule(simpleModule);

        return objectMapper;
    }
}

如何优雅地使用Jackson进行序列化和反序列化操作?

定义一个通用的工具类,对于属性特殊的规则,可以在属性上加注解。

3,Jackson常用注解自定义序列化规则

@JsonFormat 注解来自定义日期格式。

public class User {
    private String name;
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date birthday; 
}

@JsonIgnore 注解来排除不想序列化的字段。

public class User {
    private String name;
    @JsonIgnore
    private String password;
}

@JsonProperty 注解来自定义字段名称。

public class User {
    @JsonProperty("username")
    private String name;
}

@JsonInclude 注解来指定字段的空值处理策略。

public class User {
    private String name;
    @JsonInclude(JsonInclude.Include.NON_NULL)
    private String email;
}

使用 @JsonSerialize 和 @JsonDeserialize 注解来指定自定义的序列化器和反序列化器。

public class User {
    private String name;
    
    @JsonSerialize(using = LocalDateTimeSerializer.class)
    @JsonDeserialize(using = LocalDateTimeDeSerializer.class)
    private LocalDateTime birthday;
}

自定义反序列化器:

/**
 * 新建这个反序列化器的目的:源String串中extendFieldJson属性是对象类型,目标对象DeviceInfo中的extendFieldJson属性是String类型,转换的时候会报类型不匹配的错误。
 *
 * @Date: 2023/9/19 18:00
 */
public class ObjectToStringDeSerializer extends JsonDeserializer<String> {

    @Override
    public String deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
        // 从 JSON 中读取属性的对象值
        Object objectValue = jsonParser.readValueAs(Object.class);
        // 将对象值转换为json字符串
        if (objectValue != null) {
            return JsonUtil.toJsonString(objectValue);
        }
        return null;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/182734.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Visio学习笔记

1. 常用素材 1.1 立方体&#xff1a;张量, tensor 操作路径&#xff1a;更多形状 ⇒ 常规 ⇒ 基本形状 自动配色 在选择【填充】后Visio会自动进行配色&#xff1b;

【C/C++】排序算法代码实现

这里&#xff0c;汇总了常见的排序算法具体代码实现。使用C语言编写。 排序算法实现 插入排序冒泡排序选择排序快速排序希尔排序归并排序 插入排序 #include <stdio.h> #include <stdlib.h>void InsertSort(int arr[],int n){int i,j,temp;for(i 1;i < n;i){ …

初识Java 18-3 泛型

目录 边界 通配符 编译器的能力范畴 逆变性 无界通配符 捕获转换 本笔记参考自&#xff1a; 《On Java 中文版》 边界 在泛型中&#xff0c;边界的作用是&#xff1a;在参数类型上增加限制。这么做可以强制执行应用泛型的类型规则&#xff0c;但还有一个更重要的潜在效果…

vue el-table (固定列+滚动列)【横向滚动条】确定滚动条是在列头还是列尾

效果图&#xff1a; 代码实现&#xff1a; html&#xff1a; <script src"//unpkg.com/vue2/dist/vue.js"></script> <script src"//unpkg.com/element-ui2.15.14/lib/index.js"></script> <div id"app" style&quo…

实战JVM高CPU、内存问题分析定位

背景&#xff1a; 业务中台组件MOSC开展压测工作&#xff0c;并发场景下发现CPU使用率达到100%&#xff0c;虽然程序没有报错&#xff0c;但是这种情况显然已经达到性能瓶颈&#xff0c;对服务带来了验证的效能影响&#xff0c;所以针对该CPU问题必须进行详细的根因分析处理。…

浅谈Python中的鸭子类型和猴子补丁

文章目录 前言一、鸭子类型二、猴子补丁关于Python技术储备一、Python所有方向的学习路线二、Python基础学习视频三、精品Python学习书籍四、Python工具包项目源码合集①Python工具包②Python实战案例③Python小游戏源码五、面试资料六、Python兼职渠道 前言 Python 开发者可能…

AdaBoost提升分类器性能

目录 AdaBoost算法原理 AdaBoost工作详情 初始权重分配 第一轮 第二轮 后续轮次 最终模型 AdaBoost的API解释 AdaBoost 对房价进行预测 AdaBoost 与决策树模型的比较 结论 AdaBoost算法原理 在数据挖掘中&#xff0c;分类算法可以说是核心算法&#xff0c;其中 Ada…

如何应用ChatGPT撰写、修改论文及工作报告,提供写作能力及优化工作??

如果我想让gpt从pdf文档中提取相关关键词的内容&#xff0c;可以怎么做呢&#xff1f;&#xff1f;我们评论区讨论 ChatGPT 在论文写作与编程方面也具备强大的能力。无论是进行代码生成、错误调试还是解决编程难题&#xff0c;ChatGPT都能为您提供实用且高质量的建议和指导&am…

flink和机器学习模型的常用组合方式

背景 flink是一个低延迟高吞吐的系统&#xff0c;每秒处理的数据量高达数百万&#xff0c;而机器模型一般比较笨重&#xff0c;虽然功能强大&#xff0c;但是qps一般都比较低&#xff0c;日常工作中&#xff0c;我们一般是如何把flink和机器学习模型组合起来一起使用呢? fli…

9.Docker的虚悬镜像-Dangling Image

1.虚悬镜像的概念 虚悬镜像 (Dangling Image) 指的是仓库名 (镜像名) 和标签 TAG 都是 的镜像。 2.构建本地虚悬镜像 这里我以unbuntu为例来说明。 2.1 编写Dockerfile文件 FROM ubuntu:22.042.2 根据Dockerfile文件构建虚悬镜像 docker build .上面这段命令&#xff0c…

C#开发的OpenRA游戏之属性RenderSprites(8)

C#开发的OpenRA游戏之属性RenderSprites(8) 本文开始学习RenderSprites属性,这个属性是跟渲染有关的,因此它就摄及颜色相关的内容,所以我们先来学习一下调色板,这是旧游戏的图片文件保存的格式,如果放在现代来看,不会再采用这种方法,毕竟现在存储空间变大,便宜了,并…

做流体分析需要知道的两大核心问题:内流和外流

SOLIDWORKS Flow Simulation 是直观的流体力学 (CFD) 分析软件&#xff0c;可以快速轻松的分析产品内部或外部流体的流动情况&#xff0c;以用来改善产品性能和功能。SOLIDWORKS Flow Simulation将专业的流体分析进行功能优化&#xff0c;让普通机械设计师也能进行流体力学分析…

【Linux系统编程二十】:(进程通信2)--命名管道/共享内存

【Linux系统编程二十】&#xff1a;命名管道/共享内存 一.命名管道1.创建管道2.打开管道3.进行通信(server/client) 二.共享内存1.实现原理2.申请内存3.挂接4.通信5.去关联6.释放共享内存7.特性&#xff1a; 一.命名管道 上一篇介绍的一个管道是没有名字的 因为你打开那个文件…

在Python中调用imageJ开发

文章目录 一、在ImageJ中进行Python开发二、在Python中调用imageJ开发2.1、简介2.2、环境配置2.3、测试一2.4、测试二 Python imageJ 解决方案&#xff0c;采坑记录 一、在ImageJ中进行Python开发 原生ImageJ仅支持JS脚本&#xff08;JAVAScript&#xff09;&#xff0c;而Im…

蓝桥杯物联网竞赛_STM32L071_2_继电器控制

Stm32l071原理图&#xff1a; PA11与PA12连接着UNL2803 ULN2803是一种集成电路芯片&#xff0c;通常被用作高电压和高电流负载的驱动器。 ULN2803是一个达林顿阵列&#xff0c;当输入引脚&#xff08;IN1至IN8&#xff09;被连接到正电源时&#xff0c;相应的输出引脚&#xff…

大数据-计算框架选型与对比

计算框架选型与对比 一、大数据平台二、计算框架分类1.批处理架构2.实时流处理架构3.流批一体处理架构 三、计算框架关键指标1.处理模式2.可伸缩性3.消息传递3.1 至少一次&#xff08;at least once&#xff09;3.2 至多一次&#xff08;ai most once&#xff09;3.3 恰好一次&…

Redis报错:JedisConnectionException: Could not get a resource from the pool

1、问题描述&#xff1a; redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool 2、简要分析&#xff1a; redis.clients.util.Pool.getResource会从JedisPool实例池中返回一个可用的redis连接。分析源码可知JedisPool 继承了 r…

【git】使用ssh

前言 git之前一直使用https&#xff0c;因为很方便随时随地都可以用。最近把代码托管到GitHub&#xff0c;使用https就使用不了。后面听同事说GitHub使用ssh是没问题的&#xff0c;就想着尝试一下。 git ssh配置 设置用户名和邮箱 git config --global use.name username g…

FFmpeg常用命令讲解及实战二

文章目录 前言一、ffmpeg 常用命令1、ffmpeg 的封装转换2、ffmpeg 的编转码3、ffmpeg 的基本编转码原理 二、ffprobe 常用参数1、show_format2、show_frames3、show_streams4、print_format5、select_streams 三、ffplay 的常用命令1、ffplay 常用参数2、ffplay 高级参数3、ffp…

教你看现货黄金实时报价

现货黄金投资市场上的交易软件众多&#xff0c;很多人不知道选择什么软件好&#xff0c;但选择主流软件MT4&#xff0c;基本就可以满足投资者不同的需求。本文为大家讲讲&#xff0c;为什么有那么多的投资者&#xff0c;都选择通过MT4获取实时的行情报价。 现货黄金市场波动激烈…