运费微服务和redis存热点数据

目录

运费模板微服务

接收前端发送的模板实体类

插入数据时使用的entity类对象

 BaseEntity类

查询运费模板服务

新增和修改运费模块

整体流程

代码实现

运费计算 

整体流程

总的代码 

 查找运费模板方法

计算重量方法

Redis存入热点数据

1.从nacos导入共享redis配置

2.自定义RedisTemplate,自定义序列化和反序列化方式

 3.修改代码

4.存入数据时报错


运费模板微服务

接收前端发送的模板实体类

这里对实体类的每一个成员类变量使用了javax.validation.constraints注解来限制成员变量的值

package com.sl.ms.carriage.domain.dto;import io.swagger.annotations.ApiModelProperty;
import lombok.Data;import javax.validation.constraints.DecimalMin;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import java.time.LocalDateTime;
import java.util.List;/*** 运费模板对象*/
@Data
public class CarriageDTO {/*** 运费模板id*/@ApiModelProperty(value = "运费模板id")private Long id;/*** 模板类型:1-同城寄,2-省内寄,3-经济区互寄,4-跨省*/@ApiModelProperty(value = "模板类型:1-同城寄,2-省内寄,3-经济区互寄,4-跨省", required = true)@Max(value = 4, message = "类型值必须是1、2、3、4")@Min(value = 1, message = "类型值必须是1、2、3、4")@NotNull(message = "模板类型不能为空")private Integer templateType;/*** 运送类型:1-普快,2-特快*/@ApiModelProperty(value = "运送类型:1-普快,2-特快", required = true)@Max(value = 2, message = "类型值必须是1、2")@Min(value = 1, message = "类型值必须是1、2")@NotNull(message = "运送类型不能为空")private Integer transportType;/*** 关联城市:1-全国,2-京津冀,3-江浙沪,4-川渝,5-黑吉辽*/@ApiModelProperty(value = "关联城市:1-全国,2-京津冀,3-江浙沪,4-川渝,5-黑吉辽", required = true)@NotNull(message = "关联城市不能为空")private List<String> associatedCityList;/*** 首重价格*/@ApiModelProperty(value = "首重价格", required = true)@DecimalMin(value = "0.1", message = "首重价格必须大于0")@NotNull(message = "首重价格不能为空")private Double firstWeight;/*** 续重价格*/@ApiModelProperty(value = "续重价格", required = true)@DecimalMin(value = "0.1", message = "续重价格必须大于0")@NotNull(message = "续重价格不能为空")private Double continuousWeight;/*** 轻抛系数*/@ApiModelProperty(value = "轻抛系数", required = true)@Min(value = 1, message = "轻抛系数必须大于0")@NotNull(message = "轻抛系数不能为空")private Integer lightThrowingCoefficient;/*** 创建时间*/@ApiModelProperty(value = "创建时间")private LocalDateTime created;/*** 更新时间*/@ApiModelProperty(value = "更新时间")private LocalDateTime updated;@ApiModelProperty(value = "运费")private Double expense;@ApiModelProperty(value = "计费重量,单位:kg")private Double computeWeight;
}

插入数据时使用的entity类对象

@Data
@EqualsAndHashCode(callSuper = false)
@AllArgsConstructor
@NoArgsConstructor
@TableName("sl_carriage")
public class CarriageEntity extends BaseEntity {private static final long serialVersionUID = -5358753714676282742L;/*** 模板类型:1-同城寄,2-省内寄,3-经济区互寄,4-跨省*/private Integer templateType;/*** 运送类型:1-普快,2-特快*/private Integer transportType;/*** 关联城市:1-全国,2-京津冀,3-江浙沪,4-川渝,5-黑吉辽*/private String associatedCity;/*** 首重价格*/private Double firstWeight;/*** 续重价格*/private Double continuousWeight;/*** 轻抛系数*/private Integer lightThrowingCoefficient;
}

 BaseEntity类

@Data
public abstract class BaseEntity implements Serializable {@TableIdprivate Long id; //主键id@TableField(fill = FieldFill.INSERT) //MP自动填充private LocalDateTime created;@TableField(fill = FieldFill.INSERT_UPDATE)private LocalDateTime updated;
}

查询运费模板服务

/*** 获取全部运费模板,按照创建时间倒序排序** @return 运费模板对象列表*/

这里是通过工具类批量把entity类对象转换成dto对象,然后返回给前端

    @Overridepublic List<CarriageDTO> findAll() {// 构造查询条件,按创建时间倒序LambdaQueryWrapper<CarriageEntity> wrapper = Wrappers.<CarriageEntity>lambdaQuery().orderByDesc(CarriageEntity::getCreated);// 查询数据库List<CarriageEntity> carriageEntities = baseMapper.selectList(wrapper);// 将结果转换为DTO类型  使用CarriageUtils工具类return carriageEntities.stream().map(CarriageUtils::toDTO).collect(Collectors.toList());}

新增和修改运费模块

整体流程

流程说明:

  • 根据传入的CarriageDTO对象参数进行查询模板,判断模板是否存在,如果不存在直接落库
  • 如果存在,需要进一步的判断是否为经济区互寄,如果不是,说明模板重复,不能落库
  • 如果是经济区互寄,再进一步的判断是否有重复的城市,如果是,模板重复,不能落库
  • 如果不重复,落库,响应返回

模板为什么不能重复?

因为运费的计算是通过模板进行的,如果存在多个模板,该基于哪个模板计算呢?所以模板是不能重复的。

代码实现

        // 校验运费模板是否存在,如果不存在直接插入 (查询条件: 模板类型  运输类型   如果是修改排除当前id)
        LambdaQueryWrapper<CarriageEntity> wrapper = Wrappers.<CarriageEntity>lambdaQuery()
                .eq(CarriageEntity::getTemplateType, carriageDto.getTemplateType())
                .eq(CarriageEntity::getTransportType, carriageDto.getTransportType())
                //如果有id字段值,就说明是更新操作,那么就需要把与自己id值一样的模板排除掉,不然会与自己模板类型一致冲突
                .ne(ObjectUtil.isNotEmpty(carriageDto.getId()), CarriageEntity::getId, carriageDto.getId());

这段代码构建的条件查询对象,特别注意ne()方法,如果dto对象的id成员变量不为null,说明就是更新操作,就说明在数据库中,有与这个对象一模一样的模板,所以需要排除掉这个存在与数据库中的模板(根据id主键值)

 // 如果是经济区互寄类型,需进一步判断关联城市是否重复,通过集合取交集判断是否重复
        List<String> assCities = carriageEntityList.stream().map(CarriageEntity::getAssociatedCity)//获得每一个数据关联的城市字符串
                .map(s -> {
                    return s.split(",");//将每一个字符串变成一个字符串数组
                })
                .flatMap(Arrays::stream)//将每一个字符串数组重新变成流对象
                //TODO:不然直接收集的是List<String[]>类型
                .collect(Collectors.toList());
        Collection<String> intersection = CollUtil.intersection(assCities, carriageDto.getAssociatedCityList());

在数据库中,关联城市字段是 2,3,4 使用,间隔的字符串类型,2是城市id。

所以需要把这个字符串分割成字符数组。 

.flatMap(Arrays::stream)

将每一个字符串数组重新变成流对象,不然直接收集的是List<String[]>类型,

assCities是数据表中所有的关联城市集合,最后判断与dto传入的关联城市集合是否有重复

    /*** 流程说明:* ● 根据传入的CarriageDTO对象参数进行查询模板,判断模板是否存在,如果不存在直接落库* ● 如果存在,需要进一步的判断是否为经济区互寄,如果不是,说明模板重复,不能落库* ● 如果是经济区互寄,再进一步的判断是否有重复的城市,如果是,模板重复,不能落库* ● 如果不重复,落库,响应返回* 模板为什么不能重复?* 因为运费的计算是通过模板进行的,如果存在多个模板,该基于哪个模板计算呢?所以模板是不能重复的。* @param carriageDto 新增/修改运费对象* @return** 模板类型常量 {@link com.sl.ms.carriage.domain.constant.CarriageConstant}**/@Overridepublic CarriageDTO saveOrUpdate(CarriageDTO carriageDto) {// 校验运费模板是否存在,如果不存在直接插入 (查询条件: 模板类型  运输类型   如果是修改排除当前id)LambdaQueryWrapper<CarriageEntity> wrapper = Wrappers.<CarriageEntity>lambdaQuery().eq(CarriageEntity::getTemplateType, carriageDto.getTemplateType()).eq(CarriageEntity::getTransportType, carriageDto.getTransportType())//如果有id字段值,就说明是更新操作,那么就需要把与自己id值一样的模板排除掉,不然会与自己模板类型一致冲突.ne(ObjectUtil.isNotEmpty(carriageDto.getId()), CarriageEntity::getId, carriageDto.getId());List<CarriageEntity> carriageEntityList = super.list(wrapper);// 如果没有重复的模板,可以直接插入或更新操作 (DTO 转 entity 保存成功 entity 转 DTO)if (CollUtil.isEmpty(carriageEntityList)){return saveOrUpdateCarriage(carriageDto);}// 如果存在重复模板,需要判断此次插入的是否为经济区互寄,非经济区互寄是不可以重复的if(ObjectUtil.notEqual(carriageDto.getTemplateType(),CarriageConstant.ECONOMIC_ZONE)){throw new SLException(CarriageExceptionEnum.NOT_ECONOMIC_ZONE_REPEAT);}// 如果是经济区互寄类型,需进一步判断关联城市是否重复,通过集合取交集判断是否重复List<String> assCities = carriageEntityList.stream().map(CarriageEntity::getAssociatedCity)//获得每一个数据关联的城市字符串.map(s -> {return s.split(",");//将每一个字符串变成一个字符串数组}).flatMap(Arrays::stream)//将每一个字符串数组重新变成流对象//TODO:不然直接收集的是List<String[]>类型.collect(Collectors.toList());Collection<String> intersection = CollUtil.intersection(assCities, carriageDto.getAssociatedCityList());// 如果没有重复,可以新增或更新 (DTO 转 entity 保存成功 entity 转 DTO)if(CollUtil.isEmpty(intersection)){return saveOrUpdateCarriage(carriageDto);}else{throw new SLException(CarriageExceptionEnum.ECONOMIC_ZONE_CITY_REPEAT);}}public CarriageDTO saveOrUpdateCarriage(CarriageDTO carriageDTO){CarriageEntity entity = CarriageUtils.toEntity(carriageDTO);super.saveOrUpdate(entity);return CarriageUtils.toDTO(entity);}

运费计算 

整体流程

说明:

  • 运费模板优先级:同城>省内>经济区互寄>跨省
  • 将体积转化成重量,与重量比较,取大值

总的代码 

/*** ● 运费模板优先级:同城>省内>经济区互寄>跨省* ● 将体积转化成重量,与重量比较,取大值* @param waybillDTO 运费计算对象* @return**  */@Overridepublic CarriageDTO compute(WaybillDTO waybillDTO) {// 根据参数查找运费模板 调用findCarriage方法CarriageEntity carriage = findCarriage(waybillDTO);// 计算重量,最小重量为1kg 调用getComputeWeight方法double weight = getComputeWeight(waybillDTO, carriage);// 计算运费  运费 = 首重价格 + (实际重量 - 1) * 续重架构double money=carriage.getFirstWeight()+(weight-1)*carriage.getContinuousWeight();// 结果四舍五入保留一位小数money=NumberUtil.round(money,1).doubleValue();// 封装运费和计算重量到 CarriageDTO,并返回CarriageDTO carriageDTO = CarriageUtils.toDTO(carriage);carriageDTO.setComputeWeight(weight);carriageDTO.setExpense(money);return carriageDTO;}
 查找运费模板方法
/*** 根据参数查找运费模板* 运费模板优先级:同城>省内>经济区互寄>跨省* @param waybillDTO 参数* @return 运费模板*/@Resourceprivate AreaFeign areaFeign;private CarriageEntity findCarriage(WaybillDTO waybillDTO) {// 如果 发件的城市id 和 收件的城市id相同, 查询同城模板 调用findByTemplateType方法if(ObjectUtil.equal(waybillDTO.getSenderCityId(),waybillDTO.getReceiverCityId())){CarriageEntity carriageEntity = findByTemplateType(CarriageConstant.SAME_CITY);if(ObjectUtil.isNotEmpty(carriageEntity)){return carriageEntity;}}// 如果没查到或不是同城,则获取收寄件地址省份id  使用AreaFeign结构查询//根据areaFeign接口获取这个市所属的省idLong receiveProvinceId = areaFeign.get(waybillDTO.getReceiverCityId()).getParentId();Long senderProvinceId = areaFeign.get(waybillDTO.getSenderCityId()).getParentId();// 如果 收发件的省份id相同,查询同省的模板  调用findByTemplateType方法if(ObjectUtil.equal(receiveProvinceId,senderProvinceId)){CarriageEntity carriageEntity = findByTemplateType(CarriageConstant.SAME_PROVINCE);if(ObjectUtil.isNotEmpty(carriageEntity)){return carriageEntity;}}// 如果没查到或不是同省,则查询是否为经济区互寄  调用findEconomicCarriage方法查询CarriageEntity carriageEntity = findEconomicCarriage(receiveProvinceId,senderProvinceId);if(ObjectUtil.isNotEmpty(carriageEntity)){return carriageEntity;}// 如果没查到或不是经济区互寄,直接查跨省运费模板carriageEntity = findByTemplateType(CarriageConstant.TRANS_PROVINCE);if(ObjectUtil.isNotEmpty(carriageEntity)){return carriageEntity;}// 如果最后没查到,直接抛自定义异常,提示模板未找到if(ObjectUtil.isEmpty(carriageEntity)){throw new SLException(CarriageExceptionEnum.NOT_FOUND);}return null;}/*** 根据模板类型查询模板* @param templateType 模板类型:1-同城寄,2-省内寄,3-经济区互寄,4-跨省* @return 运费模板*/private CarriageEntity findByTemplateType(Integer templateType) {// 根据模板类型,及运输类型 = CarriageConstant.REGULAR_FAST 查询模板LambdaQueryWrapper<CarriageEntity> wrapper = Wrappers.<CarriageEntity>lambdaQuery().eq(CarriageEntity::getTemplateType, templateType).eq(CarriageEntity::getTransportType,CarriageConstant.REGULAR_FAST);return super.getOne(wrapper);}
计算重量方法
/*** 根据体积参数与实际重量计算计费重量** @param waybillDTO 运费计算对象* @param carriage   运费模板* @return 计费重量*/private double getComputeWeight(WaybillDTO waybillDTO, CarriageEntity carriage) {// 计算体积,如果传入体积则不需要计算Integer volume = waybillDTO.getVolume();if(ObjectUtil.isEmpty(volume)){try {volume=waybillDTO.getMeasureHigh()*waybillDTO.getMeasureLong()*waybillDTO.getMeasureWidth();} catch (Exception e) {//防止有null值throw new RuntimeException(e);}}// 计算体积重量  = 体积 / 轻抛系数  tips: 使用NumberUtil工具类计算 保留一位小数BigDecimal weightByV = NumberUtil.div(volume, carriage.getLightThrowingCoefficient(), 1);// 重量取大值 = 体积重量 和 实际重量 tips: 使用NumberUtil工具类计算   保留一位小数double weight = NumberUtil.max(weightByV.doubleValue(), NumberUtil.round(waybillDTO.getWeight(), 1).doubleValue());// 计算续重,规则:不满1kg,按1kg计费;if(weight<=1){return 1;}// 10kg以下续重以0.1kg计量保留1位小数;if(weight<=10){return weight;}// 100kg以上四舍五入取整  举例:108.4kg按照108kg收费 108.5kg按照109kg收费// tips: 使用NumberUtil工具类计算if(weight>=100){return NumberUtil.round(weight,0).doubleValue();}// 10-100kg续重以0.5kg计量保留1位小数;// 0.5为一个计算单位,举例:18.8kg按照19收费, 18.4kg按照18.5kg收费 18.1kg按照18.5kg收费int i=NumberUtil.round(weight, 0, RoundingMode.DOWN).intValue();//向下取整if(NumberUtil.sub(weight,i)==0){return weight;}else if(NumberUtil.sub(weight,i)<=0.5){return NumberUtil.add(i,0.5);}else{return NumberUtil.add(i,1);}}

Redis存入热点数据

思考:根据模板类型查询模板时需要频繁的查询数据库,性能较低,而且模板数据不会频繁变化,查询次数多,属于热点数据

所以可以使用redis存储模板entity类数据,

使用hash结构。大key->template 小key->发件城市id_收件城市

1.从nacos导入共享redis配置

spring:cloud:nacos:username: nacospassword: nacosserver-addr: 192.168.150.101:8848discovery:namespace: ecae68ba-7b43-4473-a980-4ddeb6157bdcip: 192.168.150.1config:namespace: ecae68ba-7b43-4473-a980-4ddeb6157bdcshared-configs: #共享配置- data-id: shared-spring-seata.ymlgroup: SHARED_GROUPrefresh: false- data-id: shared-spring-mysql.ymlgroup: SHARED_GROUPrefresh: false- data-id: shared-spring-mybatis-plus.ymlgroup: SHARED_GROUPrefresh: false
#            导入redis共享配置- data-id: shared-spring-redis.ymlgroup: SHARED_GROUPrefresh: false

这是共享redis配置文件的内容,可以发现里面的值并没有进行定义,那在哪定义了呢

其实共享配置文件是定义了文件的结构,具体的内容由微服务的配置文件自己配置 

具体的配置在sl-express-ms-carriage.properties运费微服务自己的配置文件当中定义

 

2.自定义RedisTemplate,自定义序列化和反序列化方式

存入value值时使用json序列

@Configuration//告诉Spring这是一个配置类,并让Spring加载这个类
public class RedisConfig extends CachingConfigurerSupport {@Beanpublic RedisTemplate<Object,Object> redisTemplate(RedisConnectionFactory factory){RedisTemplate<Object,Object> redisTemplate = new RedisTemplate<>();//默认的key序列化器为:JdkSerializationRedisSerializer//我们改成StringRedisSerializer//键序列化redisTemplate.setKeySerializer(new StringRedisSerializer());//值序列化// 创建一个json的序列化方式GenericJackson2JsonRedisSerializer jackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();// 设置value用jackjson进行处理redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);//key hashMap序列化redisTemplate.setHashKeySerializer(new StringRedisSerializer());//value hashMap序列化redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);//连接工厂redisTemplate.setConnectionFactory(factory);return redisTemplate;}}

 3.修改代码

    @Resourceprivate RedisTemplate redisTemplate;@Overridepublic CarriageDTO compute(WaybillDTO waybillDTO) {//TODO day02 计算运费HashOperations operations = redisTemplate.opsForHash();// 根据参数查找运费模板 调用findCarriage方法//CarriageEntity carriage = findCarriage(waybillDTO);/** 根据模板类型查询模板时需要频繁的查询数据库,性能较低,而且模板数据不会频繁变化,查询次数多,属于热点数据* 可以存于redis中,使用hash结构。大key->template 小key->发件城市id_收件城市*///组装小keyString sKey = String.join("_", waybillDTO.getSenderCityId() + "", waybillDTO.getReceiverCityId() + "");//先从redis中查数据CarriageEntity carriage= (CarriageEntity) operations.get(RedisConstant.templateCode, sKey);if(ObjectUtil.isEmpty(carriage)){//redis没有改数据,就从数据库中查询carriage=findCarriage(waybillDTO);if(ObjectUtil.isEmpty(carriage)){return null;}//将数据存入redisoperations.put(RedisConstant.templateCode,sKey,carriage);}// 计算重量,最小重量为1kg 调用getComputeWeight方法double weight = getComputeWeight(waybillDTO, carriage);// 计算运费  运费 = 首重价格 + (实际重量 - 1) * 续重架构double money=carriage.getFirstWeight()+(weight-1)*carriage.getContinuousWeight();// 结果四舍五入保留一位小数money=NumberUtil.round(money,1).doubleValue();// 封装运费和计算重量到 CarriageDTO,并返回CarriageDTO carriageDTO = CarriageUtils.toDTO(carriage);carriageDTO.setComputeWeight(weight);carriageDTO.setExpense(money);return carriageDTO;}

4.存入数据时报错

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: 
Java 8 date/time type `java.time.LocalDateTime` not supported by default: add Module 
"com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling (through 
reference chain: java.util.ArrayList[0]->com.zym.entity.Banner["gmtCreate"])

解决:

导入依赖

<dependency><groupId>com.fasterxml.jackson.datatype</groupId><artifactId>jackson-datatype-jsr310</artifactId><version>2.12.3</version></dependency>

给LocalTime数据类型的成员变量规定序列化方式和反序列化方式

@Data
public abstract class BaseEntity implements Serializable {@TableIdprivate Long id; //主键id@TableField(fill = FieldFill.INSERT) //MP自动填充@JsonDeserialize(using = LocalDateTimeDeserializer.class)		// 反序列化@JsonSerialize(using = LocalDateTimeSerializer.class)		// 序列化private LocalDateTime created;@TableField(fill = FieldFill.INSERT_UPDATE)@JsonDeserialize(using = LocalDateTimeDeserializer.class)		// 反序列化@JsonSerialize(using = LocalDateTimeSerializer.class)		// 序列化private LocalDateTime updated;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C++】—— set 与 multiset

【C】—— map 与 set 1 序列式容器和关联式容器2 set 系列的使用2.1 set 和 multiset 参考文档2.2 set 类的介绍2.3 set 的迭代器和构造2.4 set的增删查2.4.1 insert2.4.2 find 与 erase2.4.3 count 2.5 lower_bound 与 upper_bound2.6 multiset 与 set 的差异2.6.1 不再去重2…

Jupyter Notebook认识、安装和启动以及使用

Jupyter Notebook认识、安装和启动以及使用 Jupyter Notebook认识、安装和启动以及使用 Jupyter Notebook认识、安装和启动以及使用一、认识Jupyter Notebook1.1 Jupyter Notebook概述1.2 Jupyter Notebook 重要特性(1)交互式代码执行(2)支持多种编程语言(3)富文本编辑(4)代码高…

算法第一弹-----双指针

目录 1.移动零 2.复写零 3.快乐数 4.盛水最多的容器 5.有效三角形的个数 6.查找总价值为目标值的两个商品 7.三数之和 8.四数之和 双指针通常是指在解决问题时&#xff0c;同时使用两个指针&#xff08;变量&#xff0c;常用来指向数组、链表等数据结构中的元素位置&am…

【后端面试总结】golang channel深入理解

在Go语言中&#xff0c;Channel是一种用于在goroutine之间进行通信和同步的重要机制。它提供了一种安全、类型安全的方式来传递数据&#xff0c;使得并发编程变得更加直观和简单。本文将详细介绍Golang中Channel的基本概念、创建与关闭、发送与接收操作&#xff0c;以及相关的使…

华为、华三交换机纯Web下如何创关键VLANIF、操作STP参数

华为交换机WEB操作 使用的是真机S5735&#xff0c;目前主流的版本都适用&#xff08;V1R5~V2R1的就不在列了&#xff0c;版本太老了&#xff0c;界面完全不一样&#xff0c;这里调试线接的console口&#xff0c;电脑的网络接在ETH口&#xff09; 「模拟器、工具合集」复制整段内…

详解Java数据库编程之JDBC

目录 首先创建一个Java项目 在Maven中央仓库下载mysql connector的jar包 针对MySQL版本5 针对MySQL版本8 下载之后&#xff0c;在IDEA中创建的项目中建立一个lib目录&#xff0c;然后把刚刚下载好的jar包拷贝进去&#xff0c;然后右键刚刚添加的jar包&#xff0c;点击‘添…

网络(TCP)

目录 TCP socket API 详解 套接字有哪些类型&#xff1f;socket有哪些类型&#xff1f; 图解TCP四次握手断开连接 图解TCP数据报结构以及三次握手&#xff08;非常详细&#xff09; socket缓冲区以及阻塞模式详解 再谈UDP和TCP bind(): 我们的程序中对myaddr参数是这样…

【笔记】离散数学 1-3 章

1. 数理逻辑 1.1 命题逻辑的基本概念 1.1.1 命题的概念 命题&#xff08;Proposition&#xff09;&#xff1a;是一个陈述句&#xff0c;它要么是真的&#xff08;true&#xff09;&#xff0c;要么是假的&#xff08;false&#xff09;&#xff0c;但不能同时为真和假。例如…

【Linux篇】权限管理 - 用户与组权限详解

一. 什么是权限&#xff1f; 首先权限是限制人的。人 真实的人 身份角色 权限 角色 事物属性 二. 认识人–用户 Linux下的用户分为超级用户和普通用户 root :超级管理员&#xff0c;几乎不受权限的约束普通用户 :受权限的约束超级用户的命令提示符是#&#xff0c;普通用…

【机器学习】机器学习的基本分类-监督学习-决策树-C4.5 算法

C4.5 是由 Ross Quinlan 提出的决策树算法&#xff0c;是对 ID3 算法的改进版本。它在 ID3 的基础上&#xff0c;解决了以下问题&#xff1a; 处理连续型数据&#xff1a;支持连续型特征&#xff0c;能够通过划分点将连续特征离散化。处理缺失值&#xff1a;能够在特征值缺失的…

2023年MathorCup高校数学建模挑战赛—大数据竞赛B题电商零售商家需求预测及库存优化问题求解全过程文档及程序

2023年MathorCup高校数学建模挑战赛—大数据竞赛 B题 电商零售商家需求预测及库存优化问题 原题再现&#xff1a; 电商平台存在着上千个商家&#xff0c;他们会将商品货物放在电商配套的仓库&#xff0c;电商平台会对这些货物进行统一管理。通过科学的管理手段和智能决策&…

cocotb pytest

打印python中的print &#xff0c; 应该使用 pytest -s pytest --junitxmltest_report.xml --htmlreport.html

【Linux】进程间关系与守护进程

&#x1f30e;进程间关系与守护进程 文章目录&#xff1a; 进程间关系与守护进程 进程组     会话       认识会话       会话ID       创建会话 控制终端     作业控制       作业(job)和作业控制(Job Control)       作业号及作业过程…

QT5.14 QML串口助手

基于 QML的 串口调试助手 这个代码有缺失&#xff0c;补了部分代码 ASCII HEX 工程共享&#xff0c; Qt版本 5.14.1 COM_QML 通过百度网盘分享的文件&#xff1a;COM_QML.zip 链接&#xff1a;https://pan.baidu.com/s/1MH2d6gIPDSoaX-syVWZsww?pwd5tge 提取码&#xff1a;…

IOS ARKit进行图像识别

先讲一下基础控涧&#xff0c;资源的话可以留言&#xff0c;抽空我把它传到GitHub上&#xff0c;这里没写收积分&#xff0c;竟然充值才能下载&#xff0c;我下载也要充值&#xff0c;牛&#xff01; ARSCNView 可以理解画布或者场景 1 配置 ARWorldTrackingConfiguration AR追…

C语言第十五周课——课堂练习

目录 1.输出特定图形 2.求三个数的最小值 3.思考题 1.输出特定图形 要求&#xff1a;输出下面形状在控制台 * * * * * * * * * * * * * * * #include <stdio.h> int main() {int i, j;// 外层循环控制行数for (i 1; i < 5; i){// 内层循环控制每行的星号个数for (…

数据结构 (20)二叉树的遍历与线索化

一、二叉树的遍历 遍历是对树的一种最基本的运算&#xff0c;所谓遍历二叉树&#xff0c;就是按一定的规则和顺序走遍二叉树的所有节点&#xff0c;使每一个节点都被访问一次&#xff0c;而且只被访问一次。二叉树的遍历方式主要有四种&#xff1a;前序遍历、中序遍历、后序遍历…

sscanf与sprintf函数

本期介绍&#x1f356; 主要介绍&#xff1a;sscanf()、sprintf()这对输入/输出函数&#xff0c;并详细讲解了这两个函数的应用场景。 概述&#x1f356; 在C语言的输出和输入库中&#xff0c;有三对及其相似的库函数&#xff1a;printf()、scanf()、fprintf()、fscanf()、spri…

Linux条件变量线程池详解

一、条件变量 【互斥量】解决了线程间同步的问题&#xff0c;避免了多线程对同一块临界资源访问产生的冲突&#xff0c;但同一时刻对临界资源的访问&#xff0c;不论是生产者还是消费者&#xff0c;都需要竞争互斥锁&#xff0c;由此也带来了竞争的问题。即生产者和消费者、消费…

【错误记录】jupyter notebook打开后服务器错误Forbidden问题

如题&#xff0c;在Anaconda Prompt里输入jupyter notebook后可以打开浏览器&#xff0c;但打开具体项目后就会显示“服务器错误&#xff1a;Forbidden”&#xff0c;终端出现&#xff1a; tornado.web.HTTPError: HTTP 403: Forbidden 查看jupyter-server和jupyter notebook版…