属性拷贝MapStruct
端请求通过VO对象接收,并通过DTO对象进行流转,最后转换成DO对象与数据库DAO层进行交互,反之亦然。
当业务简单的时候,可以通过手动编码getter/setter函数来复制对象属性。但是当业务变的复杂,对象属性变得很多,那么手写复制属性代码不仅十分繁琐,非常耗时间,并且还可能容易出错。
为了解决这个痛点,在项目初期,项目的解决方法是随手写的转换工具函数:根据变量名进行反射,对基础类型和枚举的变量进行赋值。
总结下目前该工具函数的优缺点:
优点:
- 开发效率高,随时想要转换的时候,传入源对象以及指定class,调用下函数即可。
缺点:
- 项目中大量的反射会严重影响代码执行效率
- 由于使用了反射,所以成员变量的使用被追踪就很麻烦
- 转换失败只有在运行中报错才会发现
- 对于嵌套对象字段的情况无能为力
- 只能对基础类型进行复制
- 对字段名不一致的属性无法赋值
接下来就要介绍MapStruct 这个工具类,这个工具类之所以运行速度与硬编码差不多,这是因为MapStruct在编译期间就生成属性复制的代码,运行期间就无需使用反射或者字节码技术,从而确保了高性能。
另外,由于编译期间就生成了代码,所以如果有任何问题,编译期间就可以提前暴露,这对于开发人员来讲就可以提前解决问题,而不用等到代码应用上线了,运行之后才发现错误。
所以,为了克服项目中当前函数的被提到的五个缺点,笔者引入了MapStruct。
2. 如何引入MapStruct
只需要引入MapStruct的依赖,同时由于MapStruct需要在编译器期间生成代码,所以我们需要maven-compiler-plugin插件中配置
复制
// pom.xml<dependency><groupId>org.MapStruct</groupId><artifactId>MapStruct</artifactId><version>1.4.1.Final</version></dependency>
.高效性:
1.编译期 自动生成映射代码
类型检查报错
2.灵活性:支持复杂映射(对象、集合列表)
支持属性不同字段名、类型的赋值
3.直观性:使用注解来定义映射规则 (根据需求指定返回类型、忽略属性,添加 条件判断来决定是否执行映射操作)
package com.mdgyl.hussar.basic.supplier.changeorder.converter.struct;import com.mdgyl.common.util.DateUtils;
import com.mdgyl.hussar.basic.model.supplier.masterdata.*;
import com.mdgyl.hussar.basic.model.supplier.supplierchangeorder.*;
import com.mdgyl.hussar.basic.supplier.changeorder.domain.*;
import org.apache.commons.lang3.StringUtils;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;@Mapper
public interface ChangeOrderMapperConverter {ChangeOrderMapperConverter INSTANCE = Mappers.getMapper(ChangeOrderMapperConverter.class);@Mappings({@Mapping(target = "score", expression = "java(exchangeRateDO.getScore() == null? null:exchangeRateDO.getScore().toString())"),@Mapping(target = "operatingStartTime", expression = "java(exchangeRateDO.getOperatingStartTime() == null? null:formatDate(exchangeRateDO.getOperatingStartTime()))"),})SupplierChangeOrderModel doToModel(SupplierChangeOrderDo exchangeRateDO);@Mappings({@Mapping(target = "id", ignore = true),@Mapping(source = "tenantId", target = "tenantId"),@Mapping(target = "status", ignore = true),@Mapping(source = "id", target = "supplierDataId"),@Mapping(target = "deleteFlag", constant = "0")})SupplierChangeOrderModel converterSupplierToChangeOrder(SupplierModel supplierModel);@Mappings({@Mapping(target = "id", ignore = true),@Mapping(source = "id", target = "supplierAddressId")})SupplierChangeOrderAddressModel convertAddressesModel(SupplierAddressModel supplierAddressModel);@Mappings({@Mapping(target = "id", ignore = true),@Mapping(source = "id", target = "supplierBankId")})SupplierChangeOrderBankModel convertBankModel(SupplierBankModel supplierBankModel);@Mappings({@Mapping(target = "id", ignore = true),@Mapping(source = "id", target = "supplierContactsId"),})SupplierChangeOrderContactsModel convertContactModel(SupplierContactsModel supplierContactsModel);@Mappings({@Mapping(target = "id", ignore = true),@Mapping(source = "id", target = "supplierInfoId"),})SupplierChangeOrderInfoModel convertOderInfoModel(SupplierInfoModel supplierInfo);@Mappings({@Mapping(target = "score", expression = "java(parseBigDecimal(supplierChangeOrderModel.getScore()))"),@Mapping(target = "operatingStartTime", expression = "java(supplierChangeOrderModel.getOperatingStartTime() == null ? null : parseDate(supplierChangeOrderModel.getOperatingStartTime()))"),})SupplierChangeOrderDo converterModelToDo(SupplierChangeOrderModel supplierChangeOrderModel);@Mappings({@Mapping(target = "taxRate", expression = "java(parseBigDecimal(supplierChangeOrderModel.getTaxRate()))"),@Mapping(target = "staffSize", expression = "java(supplierChangeOrderModel.getStaffSize() == null || supplierChangeOrderModel.getStaffSize().isEmpty() ? null : new Integer(supplierChangeOrderModel.getStaffSize()))"),@Mapping(target = "numberOfInsured", expression = "java(supplierChangeOrderModel.getNumberOfInsured() == null || supplierChangeOrderModel.getNumberOfInsured().isEmpty() ? null : new Integer(supplierChangeOrderModel.getNumberOfInsured()))")})SupplierChangeOrderInfo converterInfoModelToDo(SupplierChangeOrderInfoModel supplierChangeOrderModel);SupplierChangeOrderAddress converterAddressModelToDo(SupplierChangeOrderAddressModel supplierChangeOrderAddressModel);SupplierChangeOrderBank converterBankModelToDo(SupplierChangeOrderBankModel supplierChangeOrderBankModel);SupplierChangeOrderContacts converterContactsModel(SupplierChangeOrderContactsModel supplierChangeOrderContactsModel);@Mappings({@Mapping(target = "taxRate", expression = "java(supplierInfo.getTaxRate() == null? null:supplierInfo.getTaxRate().toString())"),@Mapping(target = "staffSize", expression = "java(supplierInfo.getStaffSize() == null? null:supplierInfo.getStaffSize().toString())"),@Mapping(target = "numberOfInsured", expression = "java(supplierInfo.getNumberOfInsured() == null? null:supplierInfo.getNumberOfInsured().toString())")})SupplierChangeOrderInfoModel converterInfoDoToModel(SupplierChangeOrderInfo supplierInfo);SupplierChangeOrderAddressModel convertAddressesDoToModel(SupplierChangeOrderAddress supplierChangeOrderAddress);SupplierChangeOrderContactsModel convertContactsDoToModel(SupplierChangeOrderContacts supplierChangeOrderContacts);SupplierChangeOrderBankModel convertBankDoToModel(SupplierChangeOrderBank supplierChangeOrderContacts);@Mappings({@Mapping(source = "supplierDataId", target = "id"),@Mapping(source = "status", target = "status", ignore = true),@Mapping(target = "score", expression = "java(parseBigDecimal(changeOrderModel.getScore()))"),@Mapping(target = "operatingStartTime", expression = "java(parseLocalDateTime(changeOrderModel.getOperatingStartTime()))")})SupplierModel converterChangeOrderToSupplier(SupplierChangeOrderModel changeOrderModel);@Mappings({@Mapping(source = "supplierInfoId", target = "id"),@Mapping(target = "staffSize", expression = "java(changeOrderInfo.getStaffSize() == null|| changeOrderInfo.getStaffSize().isEmpty() ? null : Integer.parseInt(changeOrderInfo.getStaffSize()))"),@Mapping(target = "taxRate", expression = "java(parseBigDecimal(changeOrderInfo.getTaxRate()))"),@Mapping(target = "numberOfInsured", expression = "java(changeOrderInfo.getNumberOfInsured() == null || changeOrderInfo.getNumberOfInsured().isEmpty()? null : Integer.parseInt(changeOrderInfo.getNumberOfInsured()))"),})SupplierInfoModel convertOderInfoToSupplierModel(SupplierChangeOrderInfoModel changeOrderInfo);@Mappings({@Mapping(source = "supplierAddressId", target = "id")})SupplierAddressModel convertAddressesToSupplierModel(SupplierChangeOrderAddressModel supplierChangeOrderAddressModel);@Mappings({@Mapping(source = "supplierBankId", target = "id")})SupplierBankModel convertBankToSupplierModel(SupplierChangeOrderBankModel supplierBankModel);@Mappings({@Mapping(source = "supplierContactsId", target = "id"),})SupplierContactsModel convertContactToSupplierModel(SupplierChangeOrderContactsModel supplierContactsModel);default Date parseDate(String dateString) {SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");try {return format.parse(dateString);} catch (Exception e) {e.printStackTrace();return null;}}default BigDecimal parseBigDecimal(String taxRate) {if (StringUtils.isEmpty(taxRate)) {return null;}return new BigDecimal(taxRate);}default String formatDate(Date date) {SimpleDateFormat format = new SimpleDateFormat(DateUtils.YYYY_MM_DD);return format.format(date);}// 自定义方法用于解析日期字符串default LocalDate parseLocalDate(String dateString) {if (dateString == null) {return null;}DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DateUtils.YYYY_MM_DD);try {LocalDateTime dateTime = LocalDateTime.parse(dateString, formatter);return dateTime.toLocalDate();} catch (Exception e) {return null;}}// 自定义方法用于解析日期字符串default LocalDateTime parseLocalDateTime(String dateStr) {if (StringUtils.isBlank(dateStr)) {return null;}try {DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DateUtils.YYYY_MM_DD_HH_MM_SS);return LocalDateTime.parse(dateStr, formatter);} catch (Exception e) {return null;}}
}
package com.mdgyl.hussar.basic.supplier.changeorder.converter.service;import com.google.common.collect.Lists;
import com.jxdinfo.hussar.support.audit.plugin.mongodb.support.query.entity.Page;
import com.mdgyl.common.helper.CollectionHelper;
import com.mdgyl.common.helper.MapHelper;
import com.mdgyl.hussar.basic.enums.SupplierChangeOrderStatusEnum;
import com.mdgyl.hussar.basic.enums.SupplierStatusEnum;
import com.mdgyl.hussar.basic.model.supplier.masterdata.SupplierAddressModel;
import com.mdgyl.hussar.basic.model.supplier.masterdata.SupplierBankModel;
import com.mdgyl.hussar.basic.model.supplier.masterdata.SupplierContactsModel;
import com.mdgyl.hussar.basic.model.supplier.masterdata.SupplierModel;
import com.mdgyl.hussar.basic.model.supplier.supplierchangeorder.*;
import com.mdgyl.hussar.basic.supplier.changeorder.converter.struct.ChangeOrderMapperConverter;
import com.mdgyl.hussar.basic.supplier.changeorder.domain.*;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;public class ChangeOrderServiceConverter {public static SupplierChangeOrderModel converterModel(SupplierChangeOrderDo supplierChangeOrderDo) {if (supplierChangeOrderDo == null) {return null;}SupplierChangeOrderModel supplierChangeOrderModel = ChangeOrderMapperConverter.INSTANCE.doToModel(supplierChangeOrderDo);supplierChangeOrderModel.setStatus(SupplierChangeOrderStatusEnum.getDescByCode(supplierChangeOrderDo.getStatus()));return supplierChangeOrderModel;}public static Page<SupplierChangeOrderModel> converterModelPage(Page<SupplierChangeOrderDo> supplierChangeOrderDos) {if (supplierChangeOrderDos == null) {return new Page<SupplierChangeOrderModel>(); // 如果输入是 null,返回一个空的 Page}// 转换数据列表List<SupplierChangeOrderModel> modelList = supplierChangeOrderDos.getRecords().stream().map(ChangeOrderServiceConverter::converterModel).collect(Collectors.toList());// 创建并返回新的 Page<SupplierChangeOrderModel> 对象Page<SupplierChangeOrderModel> page = new Page<>(supplierChangeOrderDos.getCurrent(), supplierChangeOrderDos.getSize(), supplierChangeOrderDos.getTotal());page.setRecords(modelList);return page;}public static SupplierChangeOrderModel converterSupplierToChangeOrderModel(SupplierModel supplierModel) {if (supplierModel == null) {return null;}SupplierChangeOrderModel supplierChangeOrderModel = ChangeOrderMapperConverter.INSTANCE.converterSupplierToChangeOrder(supplierModel);SupplierStatusEnum supplierStatus = supplierModel.getStatus();supplierChangeOrderModel.setAddresses(CollectionHelper.collectNotNullList(supplierModel.getAddresses(), ChangeOrderMapperConverter.INSTANCE::convertAddressesModel));supplierChangeOrderModel.setBanks(CollectionHelper.collectNotNullList(supplierModel.getBanks(), ChangeOrderMapperConverter.INSTANCE::convertBankModel));supplierChangeOrderModel.setContacts(CollectionHelper.collectNotNullList(supplierModel.getContacts(), ChangeOrderMapperConverter.INSTANCE::convertContactModel));SupplierChangeOrderInfoModel supplierChangeOrderInfoModel = ChangeOrderMapperConverter.INSTANCE.convertOderInfoModel(supplierModel.getSupplierInfo());if (ObjectUtils.isEmpty(supplierChangeOrderInfoModel)) {supplierChangeOrderInfoModel=new SupplierChangeOrderInfoModel();supplierChangeOrderInfoModel.setSupplierDataId(supplierModel.getId());}supplierChangeOrderInfoModel.setSupplierStatus(supplierStatus);supplierChangeOrderModel.setChangeOrderInfo(supplierChangeOrderInfoModel);return supplierChangeOrderModel;}public static SupplierChangeOrderModel converterToChangeOrderModel(SupplierChangeOrderDo supplierChangeOrder, SupplierChangeOrderInfo changeOrderInfoDo, List<SupplierChangeOrderAddress> addresses, List<SupplierChangeOrderBank> banks, List<SupplierChangeOrderContacts> contacts) {if (supplierChangeOrder == null) {return null;}SupplierChangeOrderModel supplierChangeOrderModel = ChangeOrderMapperConverter.INSTANCE.doToModel(supplierChangeOrder);supplierChangeOrderModel.setAddresses(CollectionHelper.collectNotNullList(addresses, ChangeOrderMapperConverter.INSTANCE::convertAddressesDoToModel));supplierChangeOrderModel.setBanks(CollectionHelper.collectNotNullList(banks, ChangeOrderMapperConverter.INSTANCE::convertBankDoToModel));supplierChangeOrderModel.setContacts(CollectionHelper.collectNotNullList(contacts, ChangeOrderMapperConverter.INSTANCE::convertContactsDoToModel));supplierChangeOrderModel.setChangeOrderInfo(ChangeOrderMapperConverter.INSTANCE.converterInfoDoToModel(changeOrderInfoDo));return supplierChangeOrderModel;}public static SupplierChangeOrderDo converterModelToDo(SupplierChangeOrderModel supplierChangeOrderModel) {if (supplierChangeOrderModel == null) {return null;}return ChangeOrderMapperConverter.INSTANCE.converterModelToDo(supplierChangeOrderModel);}public static SupplierChangeOrderInfo converterInfoModelToDo(SupplierChangeOrderInfoModel supplierChangeOrderInfoModel) {if (supplierChangeOrderInfoModel == null) {return null;}return ChangeOrderMapperConverter.INSTANCE.converterInfoModelToDo(supplierChangeOrderInfoModel);}public static List<SupplierChangeOrderAddress> converterAddressModelToDoList(List<SupplierChangeOrderAddressModel> supplierChangeOrderAddressList) {if (CollectionUtils.isEmpty(supplierChangeOrderAddressList)) {return Lists.newArrayList();}return supplierChangeOrderAddressList.stream().map(ChangeOrderMapperConverter.INSTANCE::converterAddressModelToDo).collect(Collectors.toList());}public static List<SupplierChangeOrderBank> converterBankModelToDoList(List<SupplierChangeOrderBankModel> supplierChangeOrderBankList) {if (CollectionUtils.isEmpty(supplierChangeOrderBankList)) {return Lists.newArrayList();}return supplierChangeOrderBankList.stream().map(ChangeOrderMapperConverter.INSTANCE::converterBankModelToDo).collect(Collectors.toList());}public static List<SupplierChangeOrderContacts> converterContactsModelToDoList(List<SupplierChangeOrderContactsModel> supplierChangeOrderContactList) {if (CollectionUtils.isEmpty(supplierChangeOrderContactList)) {return Lists.newArrayList();}return supplierChangeOrderContactList.stream().map(ChangeOrderMapperConverter.INSTANCE::converterContactsModel).collect(Collectors.toList());}public static List<SupplierChangeOrderAddressModel> converterChangeOrderAddressList(List<SupplierChangeOrderAddress> addressesList) {if (CollectionUtils.isEmpty(addressesList)) {return Lists.newArrayList();}return addressesList.stream().map(ChangeOrderMapperConverter.INSTANCE::convertAddressesDoToModel).collect(Collectors.toList());}public static List<SupplierChangeOrderAddressModel> converterAddressList(List<SupplierAddressModel> addressesList) {if (CollectionUtils.isEmpty(addressesList)) {return Lists.newArrayList();}return addressesList.stream().map(ChangeOrderMapperConverter.INSTANCE::convertAddressesModel).collect(Collectors.toList());}public static List<SupplierChangeOrderBankModel> converterBankList(List<SupplierBankModel> bankList) {if (CollectionUtils.isEmpty(bankList)) {return Lists.newArrayList();}return bankList.stream().map(ChangeOrderMapperConverter.INSTANCE::convertBankModel).collect(Collectors.toList());}public static List<SupplierChangeOrderContactsModel> converterContactsList(List<SupplierContactsModel> bankList) {if (CollectionUtils.isEmpty(bankList)) {return Lists.newArrayList();}return bankList.stream().map(ChangeOrderMapperConverter.INSTANCE::convertContactModel).collect(Collectors.toList());}public static SupplierChangeOrderInfoModel converterInfoModel(SupplierChangeOrderInfo supplierInfo) {if (supplierInfo == null) {return null;}return ChangeOrderMapperConverter.INSTANCE.converterInfoDoToModel(supplierInfo);}public static List<SupplierChangeOrderContactsModel> converterChangeOrdeContactsList(List<SupplierChangeOrderContacts> contactList) {if (CollectionUtils.isEmpty(contactList)) {return Lists.newArrayList();}return contactList.stream().map(ChangeOrderMapperConverter.INSTANCE::convertContactsDoToModel).collect(Collectors.toList());}public static List<SupplierChangeOrderBankModel> converterChangeOrdeBankList(List<SupplierChangeOrderBank> banks) {if (CollectionUtils.isEmpty(banks)) {return Lists.newArrayList();}return banks.stream().map(ChangeOrderMapperConverter.INSTANCE::convertBankDoToModel).collect(Collectors.toList());}public static List<Long> getAddressDeleteIds(List<SupplierChangeOrderAddressModel> supplierAddressModels, Map<Long, SupplierChangeOrderAddressModel> addressUpdateMap) {// 对比出删除的现场考察数据return CollectionHelper.collectNotNullList(supplierAddressModels, param -> {Long addressId = param.getId();SupplierChangeOrderAddressModel supplierChangeOrderAddressModel = MapHelper.getValue(addressUpdateMap, addressId);if (supplierChangeOrderAddressModel == null) {return addressId;}return null;});}public static List<Long> getBankDeleteIds(List<SupplierChangeOrderBankModel> supplierBankModels, Map<Long, SupplierChangeOrderBankModel> bankUpdateMap) {// 对比出删除的样品检测数据return CollectionHelper.collectNotNullList(supplierBankModels, param -> {Long bankId = param.getId();SupplierChangeOrderBankModel supplierChangeOrderBankModel = MapHelper.getValue(bankUpdateMap, bankId);if (supplierChangeOrderBankModel == null) {return bankId;}return null;});}public static List<Long> getContactsDeleteIds(List<SupplierChangeOrderContactsModel> supplierContactsModels, Map<Long, SupplierChangeOrderContactsModel> contactUpdateMap) {// 对比出删除的资质审查数据return CollectionHelper.collectNotNullList(supplierContactsModels, param -> {Long contactsId = param.getId();SupplierChangeOrderContactsModel supplierChangeOrderContactsModel = MapHelper.getValue(contactUpdateMap, contactsId);if (supplierChangeOrderContactsModel == null) {return contactsId;}return null;});}public static SupplierModel converterChangeOrderToSupplierModel(SupplierChangeOrderModel changeOrderModel) {if (changeOrderModel == null) {return null;}SupplierModel supplierModel = ChangeOrderMapperConverter.INSTANCE.converterChangeOrderToSupplier(changeOrderModel);supplierModel.setStatus(changeOrderModel.getChangeOrderInfo().getSupplierStatus());supplierModel.setAddresses(CollectionHelper.collectNotNullList(changeOrderModel.getAddresses(), ChangeOrderMapperConverter.INSTANCE::convertAddressesToSupplierModel));supplierModel.setBanks(CollectionHelper.collectNotNullList(changeOrderModel.getBanks(), ChangeOrderMapperConverter.INSTANCE::convertBankToSupplierModel));supplierModel.setContacts(CollectionHelper.collectNotNullList(changeOrderModel.getContacts(), ChangeOrderMapperConverter.INSTANCE::convertContactToSupplierModel));supplierModel.setSupplierInfo(ChangeOrderMapperConverter.INSTANCE.convertOderInfoToSupplierModel(changeOrderModel.getChangeOrderInfo()));return supplierModel;}
}
相关文章:

属性拷贝MapStruct
端请求通过VO对象接收,并通过DTO对象进行流转,最后转换成DO对象与数据库DAO层进行交互,反之亦然。 当业务简单的时候,可以通过手动编码getter/setter函数来复制对象属性。但是当业务变的复杂,对象属性变得很多&#x…...

Chromium 添加书签功能浅析c++
1、在点击添加书签时候此UI控制逻辑代码在 chrome\browser\ui\views\bookmarks\bookmark_bar_view.cc chrome\browser\ui\views\bookmarks\bookmark_bar_view.h 可以在此看到完成 移除 按钮逻辑,以及书签监听事件等。。。 // Implementation for BookmarkNodeAdd…...

Spring Cloud Netflix Ribbon 负载均衡详解和案例示范
1. 引言 在传统的集中式架构中,负载均衡器一般是放置在服务器端的,例如 Nginx等。随着微服务架构的兴起,服务实例的数量和部署地点变得更加动态和分布式,这使得在客户端进行负载均衡成为了一种可行且更灵活的方案。Netflix Ribbo…...

Armeria gPRC 高级特性 - 装饰器、无框架请求、阻塞处理器、Nacos集成、负载均衡、rpc异常处理、文档服务......
文章目录 定义一个示例高级特性装饰器概述简单案例多种装饰方式 无框架请求概述使用方式 阻塞任务处理器背景概述多种使用方式 rpc 异常统一处理使用方式更详细的异常信息 Armeria 提供 gRPC 客户端多种调用方式同步调用异步调用使用装饰器 负载均衡简单案例Armeria 提供的所有…...
如何制作一个企业网站,建设网站的基本步骤有哪些?
企业网站是企业的门面和名片,决定网民对企业的第一印象,因此,现在很多公司想做一个属于自己网站,但是不知道怎么做,更不知道从何做起,更别说做成了。为了能够让大家清楚如何做一个企业网站,现在…...

01-python+selenium自动化测试-基础学习
前言 基于python3和selenium3做自动化测试,俗话说:工欲善其事必先利其器;没有金刚钻就不揽那瓷器活,磨刀不误砍柴工,因此你必须会搭建基本的开发环境,掌握python基本的语法和一个IDE来进行开发,…...

【redis-05】redis保证和mysql数据一致性
redis系列整体栏目 内容链接地址【一】redis基本数据类型和使用场景https://zhenghuisheng.blog.csdn.net/article/details/142406325【二】redis的持久化机制和原理https://zhenghuisheng.blog.csdn.net/article/details/142441756【三】redis缓存穿透、缓存击穿、缓存雪崩htt…...
写一个登录判断机制py
创建一个简单的登录机制涉及到用户输入的验证和与数据库中存储的凭证的比较。以下是一个使用Python语言和SQLite数据库的示例。这个例子仅用于教学目的,实际应用中应该使用更安全的方法来存储和验证密码,比如使用密码哈希。 首先,你需要安装…...
特征点检测与匹配是计算机视觉中的基础任务之一,广泛应用于图像配准、物体识别、运动估计、三维重建等领域。
特征点检测与匹配是计算机视觉中的基础任务之一,广泛应用于图像配准、物体识别、运动估计、三维重建等领域。下面是一些关键的知识点: 1. 特征点检测 特征点检测的目的是从图像中找到独特的、稳定的点,这些点在图像变化(如旋转、…...

python——Echarts现交互式动态可视化
数据展示 20192018201720162015201420132012北京5817.15785.91765430.78755081.264723.864027.16093661.10973314.934天津2410.252106.23972310.35522723.52667.112390.35182079.07161760.0201河北3742.673513.86433233.83322849.872649.182446.61662295.62032084.2825山西234…...

【含开题报告+文档+PPT+源码】基于SSM框架的民宿酒店预定系统的设计与实现
开题报告 随着人们旅游需求的增加,民宿行业呈现出快速发展的趋势。传统的住宿方式逐渐无法满足人们对个性化、舒适、便捷的需求,而民宿作为一种新型的住宿选择,逐渐受到人们的青睐。民宿的特点是具有独特的风格、便捷的地理位置、相对亲近的…...
正确理解协程
import asyncio# 定义一个异步函数(协程) async def say_after(delay, what):# 等待指定的时间await asyncio.sleep(delay)# 打印消息print(what)# 定义另一个异步函数 async def main():# 同时启动两个协程,并等待这2个协程结束await say_af…...
蒙特卡罗方法 - 采样和蒙特卡罗方法篇
序言 蒙特卡罗( Monte Carlo \text{Monte Carlo} Monte Carlo)方法,也被称为计算机随机模拟方法,是一种基于“随机数”的计算方法。这一方法源于美国在第二次世界大战期间研制原子弹的“曼哈顿计划”。其核心思想是使用随机数&am…...

论文阅读:InternVL v1.5| How Far Are We to GPT-4V? 通过开源模型缩小与商业多模式模型的差距
论文地址:https://arxiv.org/abs/2404.16821 Demo: https://internvl.opengvlab.com Model:https://huggingface.co/OpenGVLab/InternVL-Chat-V1-5 公开时间:2024年4月29日 InternVL1.5,是一个开源的多模态大型语言模…...

什么是电能表PTB认证
电能表PTB认证是指电能表产品经过德国国家计量研究所(Physikalisch-Technische Bundesanstalt,简称PTB)的认证和审核过程。PTB是德国联邦政府在计量、物理、材料和测试领域的技术专家和合作伙伴,拥有世界领先的技术水平和专业知识…...
C# 单例模式继承
简介:单例模式是软件工程中最著名的模式之一。从本质上讲,singleton 是一个只允许创建自身的单个实例的类,并且通常提供对该实例的简单访问。最常见的是,单例不允许在创建实例时指定任何参数 - 否则,对实例进行第二次请…...

ESP8266模块(WIFI STM32)
目录 一、介绍 二、传感器原理 1.原理图 2.引脚描述 3.ESP8266基础AT指令介绍 4.ESP8266基础工作模式 三、程序设计 main.c文件 esp8266.h文件 esp8266.c文件 四、实验效果 五、资料获取 项目分享 一、介绍 ESP8266是一款嵌入式系统级芯片,它集成了Wi…...
微信小程序学习实录9:掌握wx.chooseMedia实现多图片文件上传功能(选择图片、预览图片、上传图片)
要实现多图片上传到服务器,需要在小程序前端和PHP后端分别进行相应的设置。 基本流程 微信小程序提供了丰富的API来支持多图片上传功能。在微信小程序中实现多图片的选择、预览以及上传到服务器的功能: 1. 选择图片 使用 wx.chooseImage API 可以让用…...

助动词的分类及其缩略形式
助动词的分类及其缩略形式 1. 助动词 (auxiliary verb)2. 基本助动词 (primary auxiliary)2.1. 基本助动词 be、do 和 have2.2. 实义动词 be、do 和 have 3. 情态助动词 (modal auxiliary)3.1. 情态助动词取代情态动词 4. 半助动词 (semi-auxiliary)4.1. 不能与 it ... that-cl…...

Redis——分布式锁
在一个分布式系统中,只要涉及到多个节点访问同一个公共资源的时候,就需要加锁来实现互斥,从而达到线程安全的问题。 但是呢,分布式系统不同一些,因为分布式系统部署在不同的服务器上,很可能大量的请求打到…...
Python|GIF 解析与构建(5):手搓截屏和帧率控制
目录 Python|GIF 解析与构建(5):手搓截屏和帧率控制 一、引言 二、技术实现:手搓截屏模块 2.1 核心原理 2.2 代码解析:ScreenshotData类 2.2.1 截图函数:capture_screen 三、技术实现&…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...

ESP32读取DHT11温湿度数据
芯片:ESP32 环境:Arduino 一、安装DHT11传感器库 红框的库,别安装错了 二、代码 注意,DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...

抖音增长新引擎:品融电商,一站式全案代运营领跑者
抖音增长新引擎:品融电商,一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中,品牌如何破浪前行?自建团队成本高、效果难控;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...

Linux-07 ubuntu 的 chrome 启动不了
文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了,报错如下四、启动不了,解决如下 总结 问题原因 在应用中可以看到chrome,但是打不开(说明:原来的ubuntu系统出问题了,这个是备用的硬盘&a…...
鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/
使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题:docker pull 失败 网络不同,需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列,以便知晓哪些列包含有价值的数据,…...

AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机
这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机,因为在使用过程中发现 Airsim 对外部监控相机的描述模糊,而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置,最后在源码示例中找到了,所以感…...

push [特殊字符] present
push 🆚 present 前言present和dismiss特点代码演示 push和pop特点代码演示 前言 在 iOS 开发中,push 和 present 是两种不同的视图控制器切换方式,它们有着显著的区别。 present和dismiss 特点 在当前控制器上方新建视图层级需要手动调用…...

打手机检测算法AI智能分析网关V4守护公共/工业/医疗等多场景安全应用
一、方案背景 在现代生产与生活场景中,如工厂高危作业区、医院手术室、公共场景等,人员违规打手机的行为潜藏着巨大风险。传统依靠人工巡查的监管方式,存在效率低、覆盖面不足、判断主观性强等问题,难以满足对人员打手机行为精…...