属性拷贝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——分布式锁
在一个分布式系统中,只要涉及到多个节点访问同一个公共资源的时候,就需要加锁来实现互斥,从而达到线程安全的问题。 但是呢,分布式系统不同一些,因为分布式系统部署在不同的服务器上,很可能大量的请求打到…...

C++面试速通宝典——13
208. class里面定义int a,如果不实现构造函数,实例化这个类,a的值是? 答:a的值是未定义的(在C标准中成为“未初始化”)。 解释: 在C中,如果一…...

数据结构(二叉树)
1. 树相关术语 父结点/双亲结点:如果一个结点有子结点那么它就是父结点或者双亲结点;例如A是BCDEFG的父结点,J是PQ的父结点等等;子结点:一个结点含有的子树的根节点称为该结点的子结点;如上图的H是D的子结点…...

Windows 通过 Docker 安装 GitLab
1. 安装 Docker Desktop 下载网站:Windows | Docker Docs 2. 拉取 GitLab Docker 镜像 打开 PowerShell 或 命令提示符,拉取 GitLab 镜像: docker pull gitlab/gitlab-ee:latest或则使用社区版: docker pull gitlab/gitlab-ce…...

SQL专项练习第六天
Hive 在处理不同数据需求时的灵活性和强大功能,包括间隔连续问题的处理、行列转换、交易数据查询、用户登录统计以及专利数据分析等方面。本文将介绍五个 Hive 数据处理问题的解决方案,并通过实际案例进行演示。 先在home文件夹下建一个hivedata文件夹&a…...

CSS——属性值计算
CSS——属性值计算 今天来详细讲解一下 CSS的属性值计算过程,这是 CSS 的核心之一(另一个是视觉可视化模型,个人理解,这个相对复杂,以后再讲)。 基本概念 层叠样式表:Cascade Style Sheet&am…...

408算法题leetcode--第26天
496. 下一个更大元素 I 题目地址:496. 下一个更大元素 I - 力扣(LeetCode) 题解思路:单调栈,如注释 时间复杂度:O(n m) 空间复杂度:O(n) 代码: class Solution { public:vector<int&g…...

JavaScript 与浏览器存储
JavaScript提供了两种存储数据的方式:LocalStorage和SessionStorage。这两种方式都是浏览器提供的客户端存储解决方案,可以将数据保存在用户的浏览器中,供网站使用。 LocalStorage和SessionStorage的区别在于数据的作用域和生命周期。 Loca…...

Chromium 如何查找已经定义好的mojom函数实现c++
进程通信定义通常都是用.mojom文件或者idl文件格式 以content\common\frame.mojom里面的BeginNavigation函数为例。 一、如何查找BeginNavigation函数定义,在vscode里面直接搜索BeginNavigation,过滤条件 *.idl,*.mojom,*.cc 效果: 这样…...

图文深入理解Oracle DB Scheduler(续)-调度的创建
List item 今天是国庆假期最后一天。窗外,秋雨淅淅沥沥淅淅下个不停。继续深宅家中,闲来无事,就多写几篇博文。 本篇承接前一篇,继续图文深入介绍Oracle DB Scheduler。本篇主要介绍调度的创建。 1. 创建基于时间的作业 • 可以…...

基于Springboot的宠物咖啡馆平台的设计与实现(源码+定制+参考)
博主介绍: ✌我是阿龙,一名专注于Java技术领域的程序员,全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师,我在计算机毕业设计开发方面积累了丰富的经验。同时,我也是掘金、华为云、阿里云、InfoQ等平台…...