苍穹外卖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.tpcf.cn/diannao/88644.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈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…