蒼穹外賣day3--公共字段填充+新增菜品

1.公共字段填充

1.1 問題分析

????????在新增員工或者新增菜品分類時需要設置創建時間、創建人、修改時間、修改人等字段,在編輯員工或者編輯菜品分類時需要設置修改時間、修改人等字段。這些字段屬于公共字段,也就是也就是在我們的系統中很多表中都會有這些字段,如下:

序號字段名含義數據類型
1create_time創建時間datetime
2create_user創建人idbigint
3update_time修改時間datetime
4update_user修改人idbigint

????????而針對于這些字段,目前,在我們的項目中處理這些字段都是在每一個業務方法中進行賦值操作,重復代碼過多,很冗雜,可以使用AOP切面編程 實現公共字段的自動填充

1.2 實現思路

  • 自定義注解 AutoFill,用于標識需要進行公共字段自動填充的方法
  • 自定義切面類 AutoFillAspect,統一攔截加入了 AutoFill 注解的方法,通過反射為公共字段賦值
  • 在 Mapper 的方法上加入 AutoFill 注解

1.3 代碼開發

1.2.1?自定義注解 AutoFill

????????AutoFill類中定義用于標識需要進行公共字段自動填充的方法

  • @Target注解指定該注解可以標注在方法上,用于標識哪些方法需要進行自動填充操作
  • @Retention 注解定義該注解的生命周期為運行時(RUNTIME),確保可以通過反射獲取到該注解信息
package com.sky.annotatin;import com.sky.enumeration.OperationType;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** 自定義注解,用于標識需要自動填充的字段* @Target 注解指定該注解可以標注在方法上,用于標識哪些方法需要進行自動填充操作* @Retention 注解定義該注解的生命周期為運行時(RUNTIME),確保可以通過反射獲取到該注解信息*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {
//    數據庫操作類型:insert、updateOperationType value();}

1.2.2 自定義切面類 AutoFillAspect

????????統一攔截加入了 AutoFill 注解的方法,通過反射為公共字段賦值

定義切點:攔截 com.sky.mapper 包下所有方法,并且要求方法上必須有 @AutoFill 注解

定義前置通知:參數是切入點

package com.sky.aspect;import com.sky.annotatin.AutoFill;
import com.sky.constant.AutoFillConstant;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperationType;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;import java.lang.reflect.Method;
import java.time.LocalDate;
import java.time.LocalDateTime;@Aspect
@Component
@Slf4j
public class AutoFillAspect {/*** 切入點* 定義切點:攔截 com.sky.mapper 包下所有方法,并且要求方法上必須有 @AutoFill 注解*/@Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotatin.AutoFill)")public void autoFillPointCut(){}/*** 前置通知* @param joinPoint*/@Before("autoFillPointCut()")public void autoFill(JoinPoint joinPoint) {log.info("開始進行數據填充");// 獲取當前被攔截的方法上的數據庫操作類型:更新還是插入MethodSignature signature = (MethodSignature) joinPoint.getSignature(); // 獲取方法簽名AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class); // 獲取方法上的注解類型OperationType operationType = autoFill.value(); // 獲取數據庫操作類型// 獲取當前被攔截的方法參數,即實體對象Object[] args = joinPoint.getArgs();
//        如果方法參數為空,則直接返回if (args == null || args.length == 0) {return;}// 獲取需要賦值的對象Object entity = args[0];LocalDateTime now = LocalDateTime.now();Long currentId = BaseContext.getCurrentId();// 根據當前不同的操作類型,為對應的屬性通過反射賦值if (operationType == OperationType.INSERT){try {Method setCreateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);Method setCreateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
//                為對應的屬性賦值setCreateTime.invoke(entity, now);setCreateUser.invoke(entity, currentId);setUpdateTime.invoke(entity, now);setUpdateUser.invoke(entity, currentId);} catch (Exception e) {e.printStackTrace();}}else if (operationType == OperationType.UPDATE){try {Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
//                為對應的屬性賦值setUpdateTime.invoke(entity, now);setUpdateUser.invoke(entity, currentId);} catch (Exception e) {e.printStackTrace();}}}
}

? ? ? ? 為了避免字符串出錯,在constant包下定義了一個AutoFillConstant?類,定義實體類中的方法名稱。

package com.sky.constant;/*** 公共字段自動填充相關常量*/
public class AutoFillConstant {/*** 實體類中的方法名稱*/public static final String SET_CREATE_TIME = "setCreateTime";public static final String SET_UPDATE_TIME = "setUpdateTime";public static final String SET_CREATE_USER = "setCreateUser";public static final String SET_UPDATE_USER = "setUpdateUser";
}

1.2.3 在 Mapper 的方法上加入 AutoFill 注解

  • EmployeeMapper

  • CategoryMapper

? ? ? ? 將impl實現類中補全創建人、創建時間、修改人、修改時間的代碼注掉?

    /*** 新增分類* @param categoryDTO*/public void save(CategoryDTO categoryDTO) {Category category = new Category();//屬性拷貝BeanUtils.copyProperties(categoryDTO, category);//分類狀態默認為禁用狀態0category.setStatus(StatusConstant.DISABLE);//設置創建時間、修改時間、創建人、修改人
//        category.setCreateTime(LocalDateTime.now());
//        category.setUpdateTime(LocalDateTime.now());
//        category.setCreateUser(BaseContext.getCurrentId());
//        category.setUpdateUser(BaseContext.getCurrentId());categoryMapper.insert(category);}/*** 修改分類* @param categoryDTO*/public void update(CategoryDTO categoryDTO) {Category category = new Category();BeanUtils.copyProperties(categoryDTO,category);//設置修改時間、修改人
//        category.setUpdateTime(LocalDateTime.now());
//        category.setUpdateUser(BaseContext.getCurrentId());categoryMapper.update(category);}

1.4 功能測試

? ? ? ? 重啟項目,登錄系統新增修改員工進行測試:

1.5 將代碼推送到遠程倉庫


2. 新增菜品

2.1 需求分析與設計

2.1.1 產品原型

后臺系統中可以管理菜品信息,通過 新增功能來添加一個新的菜品,在添加菜品時需要選擇當前菜品所屬的菜品分類,并且需要上傳菜品圖片。

新增菜品原型:

業務規則:

  • 菜品名稱必須是唯一的

  • 菜品必須屬于某個分類下,不能單獨存在

  • 新增菜品時可以根據情況選擇菜品的口味

  • 每個菜品必須對應一張圖片

2.1.2 接口設計

接口設計:

  • 根據類型查詢分類(已完成)

  • 文件上傳

  • 新增菜品

接下來需要分析每個接口,明確每個接口的請求方法、請求路徑、傳入參數以及返回值。

  • 根據類型查詢分類

  • 文件上傳

  • 新增菜品

2.1.3 表設計

通過原型圖進行分析:

????????新增菜品,其實就是將新增頁面錄入的菜品信息插入到dish表,如果添加了口味做法,還需要向dish_flavor表插入數據。所以在新增菜品時,涉及到兩個表:

表名說明
dish菜品表
dish_flavor菜品口味表

1). 菜品表:dish

字段名數據類型說明備注
idbigint主鍵自增
namevarchar(32)菜品名稱唯一
category_idbigint分類id邏輯外鍵
pricedecimal(10,2)菜品價格
imagevarchar(255)圖片路徑
descriptionvarchar(255)菜品描述
statusint售賣狀態1起售 0停售
create_timedatetime創建時間
update_timedatetime最后修改時間
create_userbigint創建人id
update_userbigint最后修改人id

2). 菜品口味表:dish_flavor

字段名數據類型說明備注
idbigint主鍵自增
dish_idbigint菜品id邏輯外鍵
namevarchar(32)口味名稱
valuevarchar(255)口味值

2.2 代碼開發

? ? ? ? 查詢分類的接口已經實現過,所以只需要開發文件上傳新增菜品兩個功能

2.2.1 文件上傳實現

???????因為在新增菜品時,需要上傳菜品對應的圖片(文件),包括后緒其它功能也會使用到文件上傳,故要實現通用的文件上傳接口。

????????文件上傳,是指將本地圖片、視頻、音頻等文件上傳到服務器上,可以供其他用戶瀏覽或下載的過程。文件上傳在項目中應用非常廣泛,我們經常發抖音、發朋友圈都用到了文件上傳功能。

?????????在本項目選用阿里云的OSS服務進行文件存儲

1)首先登錄阿里云,按以下操作創建一個文件上傳的空間

?

?

?2)定義OSS相關配置

????????application.yml

sky:jwt:# 設置jwt簽名加密時使用的秘鑰admin-secret-key: itcast# 設置jwt過期時間admin-ttl: 7200000# 設置前端傳遞過來的令牌名稱admin-token-name: tokenalioss:endpoint: ${sky.alioss.endpoint}access-key-id: ${sky.alioss.access-key-id}access-key-secret: ${sky.alioss.access-key-secret}bucket-name: ${sky.alioss.bucket-name}

????????application-dev.yml

注意:如果Bucket位于北京地域,請使用 oss-cn-beijing.aliyuncs.com

sky:datasource:driver-class-name: com.mysql.cj.jdbc.Driverhost: localhostport: 3306database: sky_take_outusername: rootpassword: 1234alioss:endpoint: oss-cn-beijing.aliyuncs.comaccess-key-id: LTAI5txxxxxxxxxxm5CSJEPdaccess-key-secret: WLfGxxxxxxxxxxxxvKpZ58clAcTnT6Lbucket-name: sky-xiaoyang
3). 讀取OSS配置

在sky-common模塊中,已定義

package com.sky.properties;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;@Component
@ConfigurationProperties(prefix = "sky.alioss")
@Data
public class AliOssProperties {private String endpoint;private String accessKeyId;private String accessKeySecret;private String bucketName;}

4). 生成OSS工具類對象

? ? ? ? 在common.utils.AliOssUtil類中將endpoint、accessKeyId、accessKeySecret、bucketName賦好值,在upload方法中進行拼接,返回得到的就是上傳文件的路徑

package com.sky.utils;import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.io.ByteArrayInputStream;@Data
@AllArgsConstructor
@Slf4j
public class AliOssUtil {private String endpoint;private String accessKeyId;private String accessKeySecret;private String bucketName;/*** 文件上傳** @param bytes* @param objectName* @return*/public String upload(byte[] bytes, String objectName) {// 創建OSSClient實例。OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);try {// 創建PutObject請求。ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(bytes));} catch (OSSException oe) {System.out.println("Caught an OSSException, which means your request made it to OSS, "+ "but was rejected with an error response for some reason.");System.out.println("Error Message:" + oe.getErrorMessage());System.out.println("Error Code:" + oe.getErrorCode());System.out.println("Request ID:" + oe.getRequestId());System.out.println("Host ID:" + oe.getHostId());} catch (ClientException ce) {System.out.println("Caught an ClientException, which means the client encountered "+ "a serious internal problem while trying to communicate with OSS, "+ "such as not being able to access the network.");System.out.println("Error Message:" + ce.getMessage());} finally {if (ossClient != null) {ossClient.shutdown();}}//文件訪問路徑規則 https://BucketName.Endpoint/ObjectNameStringBuilder stringBuilder = new StringBuilder("https://");stringBuilder.append(bucketName).append(".").append(endpoint).append("/").append(objectName);log.info("文件上傳到:{}", stringBuilder.toString());return stringBuilder.toString();}
}

? ? ? ? 但是現在數據都是空的,需要定義一個配置類,用于創建AliOssUtil對象,在OssConfiguration 中定義:

package com.sky.config;import com.sky.properties.AliOssProperties;
import com.sky.utils.AliOssUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** 配置類,用于創建AliOssUtil對象*/
@Configuration
@Slf4j
public class OssConfiguration {/*** 創建AliOssUtil實例的配置方法* 該方法會在Spring容器中不存在AliOssUtil類型的Bean時生效* 通過注入的AliOssProperties參數獲取阿里云OSS配置信息,創建并返回AliOssUtil實例** @param aliOssProperties 包含阿里云OSS配置信息的參數對象* @return 配置好的AliOssUtil實例*/@Bean@ConditionalOnMissingBeanpublic AliOssUtil aliOssUtil(AliOssProperties aliOssProperties) {log.info("開始創建阿里云文件上傳工具類對象:{}", aliOssProperties);return new AliOssUtil(aliOssProperties.getEndpoint(),aliOssProperties.getAccessKeyId(),aliOssProperties.getAccessKeySecret(),aliOssProperties.getBucketName());}
}

我整理了一張截圖,方便大家理解

4)CommonController類編寫請求
package com.sky.controller.admin;import com.sky.constant.MessageConstant;
import com.sky.result.Result;
import com.sky.utils.AliOssUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;import java.io.IOException;
import java.util.UUID;@RestController
@RequestMapping("/admin/common")
@Api(tags = "通用接口")
@Slf4j
public class CommonController {@Autowiredprivate AliOssUtil aliOssUtil;@PostMapping("/upload")@ApiOperation("文件上傳")public Result<String> upload(MultipartFile file) {log.info("文件上傳:{}", file);try {//1.獲取原始文件String originalFilename = file.getOriginalFilename();
//        獲取后綴名String extension = originalFilename.substring(originalFilename.lastIndexOf("."));
//        構建新文件名String name = UUID.randomUUID().toString() + extension;//        文件的請求路徑String filePath = aliOssUtil.upload(file.getBytes(), name);return Result.success(filePath);} catch (IOException e) {log.info("文件上傳失敗:{}",e);}//2.返回訪問路徑return Result.error(MessageConstant.UPLOAD_FAILED);}
}

? ? ? ? 啟動項目,進行測試,是可以存儲到阿里云OSS的

? ? ? ? 注意:可能會出現圖片可以存儲到阿里云OSS,但是前端頁面回顯是出現錯誤的,這是因為我們在創建桶的時候默認是組織公共訪問的,需要修改成公共訪問,就可以成功回顯了?

?

2.2.2 新增菜品

1). 設計DTO類

在sky-pojo模塊中

package com.sky.dto;import com.sky.entity.DishFlavor;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;@Data
public class DishDTO implements Serializable {private Long id;//菜品名稱private String name;//菜品分類idprivate Long categoryId;//菜品價格private BigDecimal price;//圖片private String image;//描述信息private String description;//0 停售 1 起售private Integer status;//口味private List<DishFlavor> flavors = new ArrayList<>();}
2). Controller層

????????DishController

package com.sky.controller.admin;import com.sky.dto.DishDTO;
import com.sky.result.Result;
import com.sky.service.DishService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** 菜品管理*/
@RestController
@RequestMapping("/admin/dish")
@Api(tags = "菜品相關接口")
@Slf4j
public class DishController {@Autowiredprivate DishService dishService;/*** 新增菜品** @param dishDTO* @return*/@PostMapping@ApiOperation("新增菜品")public Result save(@RequestBody DishDTO dishDTO) {log.info("新增菜品:{}", dishDTO);dishService.saveWithFlavor(dishDTO);//后緒步驟開發return Result.success();}
}

3). Service層接口

package com.sky.service;import com.sky.dto.DishDTO;
import com.sky.entity.Dish;public interface DishService {/*** 新增菜品和對應的口味** @param dishDTO*/public void saveWithFlavor(DishDTO dishDTO);}

4). Service層實現類

package com.sky.service.impl;import com.sky.dto.DishDTO;
import com.sky.entity.Dish;
import com.sky.entity.DishFlavor;
import com.sky.mapper.DishFlavorMapper;
import com.sky.mapper.DishMapper;
import com.sky.service.DishService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import java.util.List;@Service
public class DishServiceImpl implements DishService {@Autowiredprivate DishMapper dishMapper;@Autowiredprivate DishFlavorMapper dishFlavorMapper;@Transactionalpublic void saveWithFlavor(DishDTO dishDTO) {Dish dish = new Dish();
//        屬性copyBeanUtils.copyProperties(dishDTO, dish);//向菜品表插入1條數據dishMapper.insert(dish);//后緒步驟實現//獲取insert語句生成的主鍵值Long dishId = dish.getId();List<DishFlavor> flavors = dishDTO.getFlavors();if (flavors != null && flavors.size() > 0) {
//            給每一個口味設置菜品idflavors.forEach(dishFlavor -> {dishFlavor.setDishId(dishId);});//向口味表插入n條數據dishFlavorMapper.insertBatch(flavors);//后緒步驟實現}}
}

5). Mapper層

  • ????????DishMapper.java中添加 @AutoFill(value = OperationType.INSERT)
    /*** 插入菜品數據** @param dish*/@AutoFill(value = OperationType.INSERT)void insert(Dish dish);
  • ????????在/resources/mapper中創建DishMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.sky.mapper.DishMapper"><!--  新增之后生成的id會傳給dish  --><insert id="insert" useGeneratedKeys="true" keyProperty="id">insert into dish (name, category_id, price, image, description, create_time, update_time, create_user,update_user, status)values (#{name}, #{categoryId}, #{price}, #{image}, #{description}, #{createTime}, #{updateTime}, #{createUser}, #{updateUser}, #{status})</insert>
</mapper>

  • ????????DishFlavorMapper.java
package com.sky.mapper;import com.sky.entity.DishFlavor;
import java.util.List;@Mapper
public interface DishFlavorMapper {/*** 批量插入口味數據* @param flavors*/void insertBatch(List<DishFlavor> flavors);}
  • ????????在/resources/mapper中創建DishFlavorMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.sky.mapper.DishFlavorMapper"><insert id="insertBatch">insert into dish_flavor (dish_id, name, value) VALUES<foreach collection="flavors" item="df" separator=",">(#{df.dishId},#{df.name},#{df.value})</foreach></insert>
</mapper>

2.3 測試

? ? ? ? 重啟項目,登錄項目進行聯調測試,新增菜品,查看數據庫新增成功

2.4 將代碼推送到遠程倉庫

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/88644.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/88644.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/88644.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

每次選擇都是成本

概述 我們每個人都在做選擇&#xff0c;而且無時無刻不在做選擇。 有的人有的選&#xff0c;而有的人卻沒得選。 因此從側面來說&#xff0c;有的選反而更是一種幸福。 我們學習的目的就是為了讓我們自己在未來能有更好地選擇&#xff0c;也可以底氣十足地選擇不去做什么&a…

AI in CSR Writing: Revolutionizing Clinical Trial Reports

一、AI在CSR撰寫中的實際應用 1.1 自動化數據整合與報告生成 1.1.1 數據提取與匯總 AI自動從EDC、實驗室系統、安全數據庫提取數據,生成統計圖表和表格,如人口統計學、療效終點、安全性事件表,減少人工操作。 1.1.2 動態報告生成 基于預設模板,AI自動填充數據結果,如自動…

《Java反射到底該不該用?性能、靈活性與可維護性三者博弈》

大家好呀&#xff01;今天我們要聊一個Java中超級強大但也需要謹慎使用的特性——反射機制(Reflection) &#x1f3ad;。我會用最通俗易懂的方式&#xff0c;帶大家徹底搞懂這個"程序界的魔術師"&#xff01; 一、什么是Java反射&#xff1f;&#x1f914; 想象一下…

從Java API調用者到架構思考:我的Elasticsearch認知升級之路

前言&#xff1a;我的Elasticsearch學習歷程 作為一名Java開發者&#xff0c;記得第一次使用ES的Java High Level REST Client時&#xff0c;我被它強大的搜索能力所震撼&#xff0c;但也為復雜的集群調優所困擾。經過多個項目的實戰積累和系統性學習&#xff0c;我終于建立了對…

高云GW5AT-LV60 FPGA圖像處理板

GW5AT-LV60開發板體積小巧&#xff0c;長100mm寬為61.8mm&#xff0c;還沒有一部Ipone SE2體積大&#xff0c;該板卡采用了核心板和載板分離的形式&#xff0c;核心板的形式可方便開發者在項目中根據實際需求來開發自己的載板&#xff0c;只需要為核心板提供5V的電源就能滿足基…

[XILINX]ZYNQ7010_7020_軟件LVDS設計

若該文為原創文章&#xff0c;未經允許不得轉載風釋雪QQ:627833006WX:Cheng18375816918CSDN博客: 風釋雪FPGA知乎&#xff1a;風釋雪FPGA 1.版本說明 日期作者版本說明2024xxxx風釋雪初始版本 2.概述 ZYNQ 7010/7020 HR/HP Bank LVDS Rx/TX&#xff1b; 3.目標 ZYNQ 7010 LVD…

桌面小屏幕實戰課程:DesktopScreen 11 SPI 水墨屏

飛書文檔https://x509p6c8to.feishu.cn/docx/doxcnlzpIgj3gosCZufBTCZxlMb SPI說明 SPI是串行外設接口&#xff08;Serial Peripheral Interface&#xff09;的縮寫&#xff0c;是一種高速的&#xff0c;全雙工&#xff0c;同步的通信總線&#xff0c;并且在芯片的管腳上占用…

SpringCloud Gateway 組件的使用

作者&#xff1a;小凱 沉淀、分享、成長&#xff0c;讓自己和他人都能有所收獲&#xff01; 我發現了一個很有意思的縮寫單詞 gw、wg&#xff0c;都是網關的意思。因為 gw gateway、wg wangguan&#xff0c;所以在各個系統開發中&#xff0c;既有 gw 也有 wg 的存在。而網關…

隨機地址生成器 - Cloudflare Workers

分享一個完全開源免費部署在 Cloudflare Workers 上的隨機地址生成器&#xff0c;支持全球 24 個國家/地區。 &#x1f517; 工具地址: https://address.chat-tempmail.com ? 特性 &#x1f30d; 支持生成 24 個國家/地區的地址&#x1f4f1; 響應式設計&#xff0c;完美支持…

CNN不是一個模型?

CNN不是一個模型&#xff1f; 結論&#xff1a; CNN 是模型架構而非具體模型&#xff0c;其定位類似深度學習領域的 「設計框架」&#xff0c;而非 LSTM&#xff08;具體單元結構&#xff09;或決策樹&#xff08;具體算法實體&#xff09;。CNN 的 「具體模型」 需要結合網絡…

愛基百客與真邁生物達成戰略合作,共推多組學科研服務升級

近日&#xff0c;武漢愛基百客生物科技有限公司&#xff08;以下簡稱“愛基百客”&#xff09;與真邁生物正式簽署戰略合作協議。此次戰略合作將聚焦表觀組學、單細胞時空組學等前沿科研領域&#xff0c;聯合打造基于自主創新技術的多組學科研服務方案&#xff0c;為科研人員提…

吳恩達:從斯坦福到 Coursera,他的深度學習布道之路

名人說&#xff1a;路漫漫其修遠兮&#xff0c;吾將上下而求索。—— 屈原《離騷》 創作者&#xff1a;Code_流蘇(CSDN)&#xff08;一個喜歡古詩詞和編程的Coder&#x1f60a;&#xff09; 吳恩達&#xff1a;從斯坦福到 Coursera&#xff0c;他的深度學習布道之路 在人工智能…

開疆智能CCLinkIE轉ModbusTCP網關連接測聯無紙記錄儀配置案例

本案例是通過CCLinkIE轉ModbusTCP網關將記錄儀數據傳送到三菱PLC&#xff0c;具體操作過程如下。 &#xff08;1&#xff09; 無紙記錄儀與PT100傳感器連接正確后&#xff0c;將無紙記錄儀和PC通過網線連接&#xff0c;給無紙記錄儀上電&#xff0c;設置無紙記錄儀的IP地址及網…

【軟考高級系統架構論文】# 論軟件設計方法及其應用

論文真題 軟件設計 (Software Design,SD) 根據軟件需求規格說明書設計軟件系統的整體結構、劃分功能模塊、確定每個模塊的實現算法以及程序流程等,形成軟件的具體設計方案。軟件設計把許多事物和問題按不同的層次和角度進行抽象,將問題或事物進行模塊化分解,以便更容易解決…

Spring Boot 3.x 項目搭建 (一)

以下是一個基礎 Spring Boot 項目的創建指南&#xff0c;整合了官方推薦方式和實用配置&#xff0c;幫助您快速搭建可運行的項目骨架。 &#x1f31f; 一、項目創建方式 1. 在線工具 Spring Initializr&#xff08;推薦&#xff09; 步驟&#xff1a; 訪問 Spring Initializr…

《天行數據查詢系統項目介紹》

一、項目概述 天行數據查詢系統是一款功能豐富的 Android 應用程序&#xff0c;旨在為用戶提供便捷的信息查詢服務。該系統集成了多個實用的查詢功能&#xff0c;包括空氣質量查詢、天氣預報查詢、垃圾分類查詢、新聞資訊瀏覽以及身份證信息查詢等&#xff0c;方便用戶一站式獲…

對于服務器企業該如何進行搭建?

企業搭建服務器能夠實現網絡服務、數據存儲和管理等功能&#xff0c;選擇大家服務器不僅能夠實現高效的資源管理和對數據信息進行安全保護&#xff0c;還可以滿足網站運行的需求&#xff0c;下面&#xff0c;小編就主要來為大家介紹一下企業該如何進行服務器搭建&#xff1f; 搭…

重定向攻擊與防御

一、重定向攻擊的主要類型與技術原理 ICMP重定向攻擊 原理&#xff1a;攻擊者偽造網關身份發送虛假ICMP重定向報文&#xff0c;誘導主機修改路由表&#xff0c;將流量導向攻擊者控制的節點。 利用工具&#xff1a;如netwox 86可構造惡意重定向包&#xff0c;源IP偽裝為網關地…

SAP/S4 MM模塊之主數據管理

目錄 一、主要功能 1. 主數據管理 2.采購管理 3. 庫存管理 二、業務價值 三、主數據常見問題 3.1. 物料主數據維護錯誤 3.2. 供應商數據不完整或錯誤 3.3. 數據錄入延遲或遺漏 四、最佳實踐 1. 物料主數據標準化 2. 供應商主數據優化 3.庫存管控精細化 SAP MM&…

Flink Oracle CDC 總結

官方文檔 https://nightlies.apache.org/flink/flink-cdc-docs-release-3.3/zh/docs/connectors/flink-sources/oracle-cdc/ 版本 Flink 1.15.3CDC 2.3.0Oracle 11G 12C &#xff08;官網說支持19&#xff0c;未測試&#xff09; Jar包 https://repo1.maven.org/maven2/co…