[苍穹外卖]-04菜品管理接口开发
效果预览
新增菜品
需求分析
查看产品原型分析需求, 包括用到哪些接口, 业务的限制规则
业务规则
- 菜品名称必须是唯一的
- 菜品必须属于某个分类下, 不能单独存在
- 新增菜品时可以根据情况选择菜品的口味
- 每个菜品必须对应一张图片
接口设计
根据类型查询分类接口
文件上传接口
新增菜品接口
数据表设计
设计dish菜品表 和 dish_flavor口味表
分类查询接口
在分类管理模块中已完成
文件上传接口
定义文件上传的Controler
/*** 通用接口*/
@RestController
@RequestMapping("/admin/common")
@Api(tags = "通用接口")
@Slf4j
public class CommonController {/*** 文件上传** @param file* @return*/@PostMapping("/upload")@ApiOperation("文件上传")public Result<String> update(MultipartFile file) {log.info("文件上传:{}", file);return null;}
}
配置阿里云OSS参数: 通常把application.yml作为主配置文件, 根据运行环境引用其他配置文件的值
// 配置属性类
@Component
@ConfigurationProperties(prefix = "sky.alioss")
@Data
public class AliOssProperties {private String endpoint;private String accessKeyId;private String accessKeySecret;private String bucketName;}
- 使用 @ConfigurationProperties(prefix = "sky.alioss")注解 定义配置属性类
- 配置属性类的作用就是读取配置文件中的属性, 把属性的值封装到对象中
- 配置文件中用横线分隔, 配置属性类使用驼峰命名法
- springboot框架可以自动进行驼峰命名映射
spring:profiles:active: devsky:alioss: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}
- 在主配置文件中配置OSS连接信息
- 程序运行时动态引用环境配置文件中的值
- active: dev 该属性指定引用开发环境的信息
- 使用 active 属性可以实现代码环境的快捷切换
sky:alioss:endpoint: oss-cn-beijing.aliyuncs.comaccess-key-id: ....access-key-secret: ....bucket-name: sky-itcast-cangqiongwaimai
- 在开发环境配置文件中配置具体的oss连接参数
准备工具类: 已经提供了用于文件上传的工具类
@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对象
@Configuration // 声明配置类
@Slf4j
public class OssConfiguration {@Bean // 程序启动时创建阿里云OSS对象并交给IOC容器管理@ConditionalOnMissingBean //条件装配注解, 指定该对象为单例模式, 只创建一个public AliOssUtil aliOssUtil(AliOssProperties aliOssProperties) {// 通过参数注入的形式注入aliOssProperties对象// 通过该对象可以拿到属性配置类封装好的的属性log.info("开始创建阿里云文件上传工具类对象: {}", aliOssProperties);return new AliOssUtil(aliOssProperties.getEndpoint(),aliOssProperties.getAccessKeyId(),aliOssProperties.getAccessKeySecret(),aliOssProperties.getBucketName());}}
使用aliOssUtil对象, 完成文件上传功能, 为了防止文件重名覆盖, 需要构建新的文件名
/*** 通用接口*/
@RestController
@RequestMapping("/admin/common")
@Api(tags = "通用接口")
@Slf4j
public class CommonController {@Autowiredprivate AliOssUtil aliOssUtil;/*** 文件上传** @param file* @return*/@PostMapping("/upload")@ApiOperation("文件上传")public Result<String> update(MultipartFile file) {log.info("文件上传:{}", file);try {// 原始文件名String originalFilename = file.getOriginalFilename();// 截取原始文件名的后缀(xxx.png)String extension = originalFilename.substring(originalFilename.lastIndexOf("."));// 构建新文件名String objectName = UUID.randomUUID().toString() + extension;// 文件上传String filePath = aliOssUtil.upload(file.getBytes(), objectName);return Result.success(filePath);} catch (IOException e) {log.info("文件上传失败:{}", e);}return Result.error(MessageConstant.UPLOAD_FAILED);}
}
新增菜品接口
准备DishDTO用来封装前端传递的菜品数据
@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<>();}
准备DishFlavor实体类, 用来封装菜品的口味数据
/*** 菜品口味*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class DishFlavor implements Serializable {private static final long serialVersionUID = 1L;private Long id;//菜品idprivate Long dishId;//口味名称private String name;//口味数据listprivate String value;}
新建DishController
/*** 菜品管理*/
@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();}
}
新建 DishService接口 以及 DishServiceImpl实现类
public interface DishService {/*** 新增菜品和对应的口味* @param dishDTO*/public void saveWithFlavor(DishDTO dishDTO);
}
@Service
@Slf4j
public class DishServiceImpl implements DishService {@Autowiredprivate DishMapper dishMapper;@Autowiredprivate DishFlavorMapper dishFlavorMapper;/*** 新增菜品和对应的口味** @param dishDTO*/@Transactionalpublic void saveWithFlavor(DishDTO dishDTO) {Dish dish = new Dish();BeanUtils.copyProperties(dishDTO, dish);// 向菜品表插入1条数据dishMapper.insert(dish);// 向口味表插入n条数据Long dishId = dish.getId(); //拿到菜品id, SQL中已开启List<DishFlavor> flavors = dishDTO.getFlavors(); //拿到口味数据if (flavors != null && flavors.size() > 0) {flavors.forEach(dishFlavor -> {// 设置口味关联的菜品iddishFlavor.setDishId(dishId);});dishFlavorMapper.insertBatch(flavors);}}
}
@SpringBootApplication
@EnableTransactionManagement //开启注解方式的事务管理
@Slf4j
public class SkyApplication {public static void main(String[] args) {SpringApplication.run(SkyApplication.class, args);log.info("server started");}
}
- 一个方法中操作多个表, 使用@Transactional注解开启事务管理
- @EnableTransactionManagement注解不是严格必须的, 但是显示的声明能够确保Spring容器能够识别并管理
@Transactional
注解标记的方法 - 使用 BeanUtils.copyProperties(数据源对象, 目标对象) 方法进行对象属性拷贝, 可以轻松的进行对象属性的赋值, 前提是两个对象的属性名完全一致
新建DishMapper操作菜品表
@Mapper
public interface DishMapper {/*** 插入菜品** @param dish*/@AutoFill(value = OperationType.INSERT) // 公共字段填充void insert(Dish dish);}
<?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">// 新增菜品<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>
- useGeneratedKeys="true" 开启sql执行完毕返回数据
- keyProperty="id" 指定返回id字段
新建DishFlavorMapper操作菜品口味表
@Mapper
public interface DishFlavorMapper {/*** 批量插入口味数据* @param flavors*/void insertBatch( List<DishFlavor> flavors);
}
<?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>
联调测试
录入的数据项比较多, 直接采用前后端联调进行测试
菜品分页查询
分析和设计
查看产品原型, 分析业务规则
- 根据页码展示菜品信息
- 每页展示10条数据
- 分页查询时可以根据需要输入菜品名称, 菜品分类, 菜品状态进行查询
接口设计, 分类名称需要根据菜品id查询分类表得到
代码开发
根据前端请求参数定义对应的DTO
根据接口返回的结果定义对应的VO
Controller
/*** 菜品管理*/
@RestController
@RequestMapping("/admin/dish")
@Api(tags = "菜品相关接口")
@Slf4j
public class DishController {@Autowiredprivate DishService dishService;/*** 菜品分页查询** @param dishPageQueryDTO* @return*/@GetMapping("/page")@ApiOperation("菜品分页查询接口")public Result<PageResult> page(DishPageQueryDTO dishPageQueryDTO) {log.info("菜品分页查询:{}", dishPageQueryDTO);PageResult pageResult = dishService.pageQuery(dishPageQueryDTO);return Result.success(pageResult);}
}
Service
public interface DishService {/*** 菜品分页查询* @param dishPageQueryDTO* @return*/PageResult pageQuery(DishPageQueryDTO dishPageQueryDTO);
}
@Service
@Slf4j
public class DishServiceImpl implements DishService {@Autowiredprivate DishMapper dishMapper;/*** 菜品分页查询** @param dishPageQueryDTO* @return*/public PageResult pageQuery(DishPageQueryDTO dishPageQueryDTO) {// 开启分页查询PageHelper.startPage(dishPageQueryDTO.getPage(), dishPageQueryDTO.getPageSize());// 查询业务Page<DishVO> page = dishMapper.pageQuery(dishPageQueryDTO);// 返回数据return new PageResult(page.getTotal(), page.getResult());}
}
Mapper
@Mapper
public interface DishMapper {/*** 菜品分页查询** @param dishPageQueryDTO* @return*/Page<DishVO> pageQuery(DishPageQueryDTO dishPageQueryDTO);}
<?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"><select id="pageQuery" resultType="com.sky.vo.DishVO">select d.*, c.name as categoryName from dish d left outer join category c on d.category_id = c.id<where><if test="name != null">and d.name like concat('%',#{name},'%')</if><if test="categoryId != null">and d.category_id = #{categoryId}</if><if test="status != null">and d.status = #{status}</if></where>order by d.create_time desc</select>
</mapper>
- 对于比较复杂的查询语句, 可以在SQL图形化工具中, 编写语句并测试, 提高测试效率
功能测试
接口测试
前后端联调
删除菜品
分析和设计
需求分析: 查看产品原型, 确定业务规则
- 可以一次删除一个菜品, 也可以批量删除菜品
- 起售中的菜品不能删除
- 被套餐关联的菜品不能删除
- 删除菜品后, 关联的口味数据也需要删除
接口设计
数据表设计: 删除菜品涉及到三张表的操作, 菜品表, 菜品口味表, 菜品和口味中间表
代码开发
Controller
/*** 菜品管理*/
@RestController
@RequestMapping("/admin/dish")
@Api(tags = "菜品相关接口")
@Slf4j
public class DishController {@Autowiredprivate DishService dishService;/*** 菜品批量删除** @param ids* @return*/@DeleteMapping@ApiOperation("菜品批量删除")public Result delete(@RequestParam List<Long> ids) {// @RequestParam注解// 可以自动把query参数中的参数封装到List<long> ids容器中// "1,2,3,4" --> [1,2,3,4]log.info("菜品批量删除:{}", ids);dishService.deleteBath(ids);//删除缓存数据cleanCache("dish_*");return Result.success();}
}
Service
public interface DishService {/*** 批量删除菜品* @param ids*/void deleteBath(List<Long> ids);
}
@Service
@Slf4j
public class DishServiceImpl implements DishService {@Autowiredprivate DishMapper dishMapper;@Autowiredprivate DishFlavorMapper dishFlavorMapper;@Autowiredprivate SetmealDishMapper setmealDishMapper;/*** 批量删除菜品** @param ids*/@Transactional // 开启事务管理public void deleteBath(List<Long> ids) {log.info("根据菜品id删除口味数据:{}", ids);// 判断当前菜品是否能够删除---是否存在起售中的菜品for (Long id : ids) {Dish dish = dishMapper.getById(id);if (dish.getStatus() == StatusConstant.ENABLE) {// 当前菜品处于起售中, 不能删除throw new DeletionNotAllowedException(MessageConstant.DISH_ON_SALE);}}// 判断当前菜品是否能够删除---是否被套餐关联了List<Long> setmealIds = setmealDishMapper.getSetmealIdsByDishIds(ids);if (setmealIds != null && setmealIds.size() > 0) {// 当前菜品被套餐关联, 不能删除throw new DeletionNotAllowedException(MessageConstant.DISH_BE_RELATED_BY_SETMEAL);}// 删除菜品表中的数据(优化前)for (Long id : ids) {// 删除菜品数据dishMapper.deleteById(id);// 删除菜品关联的口味数据dishFlavorMapper.deleteByDishId(id);}}
}
Mapper
@Mapper
public interface DishMapper {/*** 根据id查询菜品** @param id* @return*/@Select("select * from dish where id = #{id}")Dish getById(Long id);/*** 根据id删除菜品数据** @param id*/@Delete("delete from dish where id = #{id}")void deleteById(Long id);
}
@Mapper
public interface SetmealDishMapper {/*** 根据菜品id查询套餐id* @param dishIds* @return*/List<Long> getSetmealIdsByDishIds(List<Long> dishIds);}
<?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.SetmealDishMapper"><select id="getSetmealIdsByDishIds" resultType="java.lang.Long">select setmeal_id from setmeal_dish where dish_id in<foreach collection="dishIds" item="dishId" separator="," open="(" close=")">#{dishId}</foreach></select></mapper>
@Mapper
public interface DishFlavorMapper {/*** 根据id删除对应的口味数据* @param dishId*/@Delete("delete from dish_flavor where dish_id = #{dishId}")void deleteByDishId(Long dishId);
}
代码优化
优化前: sql语句的数量不固定, 删除多个菜品就调用多次sql
优化后: sql语句的数量是固定的, 删除多个菜品也是调用两条sql
@Service
@Slf4j
public class DishServiceImpl implements DishService {@Autowiredprivate DishMapper dishMapper;@Autowiredprivate DishFlavorMapper dishFlavorMapper;/*** 批量删除菜品** @param ids*/@Transactionalpublic void deleteBath(List<Long> ids) {... ...// 删除菜品表中的数据(优化前)// for (Long id : ids) {// 删除菜品数据// dishMapper.deleteById(id);// 删除菜品关联的口味数据// dishFlavorMapper.deleteByDishId(id);// }// 优化后// 批量删除菜品数据dishMapper.deleteByIds(ids);// 批量删除菜品关联的口味数据log.info("根据菜品id删除口味数据:{}", ids);dishFlavorMapper.deleteByDishIds(ids);}
}
@Mapper
public interface DishMapper {/*** 根据ids批量删除菜品数据* @param ids*/void deleteByIds(List<Long> ids);
}
<?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"><delete id="deleteByIds">delete from dish where id in<foreach collection="ids" close=")" open="(" separator="," item="id">#{id}</foreach></delete></mapper>
@Mapper
public interface DishFlavorMapper {/*** 根据菜品ids批量删除口味数据* @param dishIds*/void deleteByDishIds(List<Long> dishIds);}
<?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"><delete id="deleteByDishIds">delete from dish_flavor where dish_id in<foreach collection="dishIds" item="dishId" separator="," open="(" close=")">#{dishId}</foreach></delete></mapper>
功能测试
修改菜品
分析和设计
查看原型: 完成菜品信息的回显和更新
接口设计
根据id查询菜品
Controller
/*** 菜品管理*/
@RestController
@RequestMapping("/admin/dish")
@Api(tags = "菜品相关接口")
@Slf4j
public class DishController {@Autowiredprivate DishService dishService;/*** 根据id查询菜品** @param id* @return*/@GetMapping("/{id}")@ApiOperation("根据id查询菜品")public Result<DishVO> getById(@PathVariable long id) {log.info("根据id查询菜品:{}", id);DishVO dishVO = dishService.getByIdWithFlavor(id);return Result.success(dishVO);}}
Service
public interface DishService {/*** 根据id查询菜品* @param id* @return*/DishVO getByIdWithFlavor(long id);
}
@Service
@Slf4j
public class DishServiceImpl implements DishService {@Autowiredprivate DishMapper dishMapper;@Autowiredprivate DishFlavorMapper dishFlavorMapper;/*** 根据id查询菜品和对应的口味数据** @param id* @return*/public DishVO getByIdWithFlavor(long id) {// 根据id查询菜品数据Dish dish = dishMapper.getById(id);// 根据菜品id查询口味数据List<DishFlavor> dishFlavors = dishFlavorMapper.getByDishId(id);// 把查询结果封装到VODishVO dishVO = new DishVO();BeanUtils.copyProperties(dish, dishVO);dishVO.setFlavors(dishFlavors);return dishVO;}
}
Mapper
@Mapper
public interface DishMapper {/*** 根据id查询菜品** @param id* @return*/@Select("select * from dish where id = #{id}")Dish getById(Long id);
}
@Mapper
public interface DishFlavorMapper {/*** 根基菜品id查询对应的口味数据* @param dishId* @return*/@Select("select * from dish_flavor where dish_id = #{dishId}")List<DishFlavor> getByDishId(long dishId);
}
根据id修改菜品
Controller
/*** 菜品管理*/
@RestController
@RequestMapping("/admin/dish")
@Api(tags = "菜品相关接口")
@Slf4j
public class DishController {@Autowiredprivate DishService dishService;/*** 修改菜品** @param dishDTO* @return*/@PutMapping@ApiOperation("修改菜品")public Result update(@RequestBody DishDTO dishDTO) {log.info("修改菜品: {}", dishDTO);dishService.updateWithFlavor(dishDTO);//删除缓存数据cleanCache("dish_*");return Result.success();}
}
Service
public interface DishService {/*** 修改菜品和对应的口味* @param dishDTO*/void updateWithFlavor(DishDTO dishDTO);
}
@Service
@Slf4j
public class DishServiceImpl implements DishService {@Autowiredprivate DishMapper dishMapper;@Autowiredprivate DishFlavorMapper dishFlavorMapper;/*** 修改菜品和对应的口味** @param dishDTO*/public void updateWithFlavor(DishDTO dishDTO) {Dish dish = new Dish();BeanUtils.copyProperties(dishDTO, dish);// 修改菜品基本信息dishMapper.update(dish);// 删除原有的口味数据dishFlavorMapper.deleteByDishId(dishDTO.getId());// 重新插入口味数据List<DishFlavor> flavors = dishDTO.getFlavors();if (flavors != null && flavors.size() > 0) {for (DishFlavor flavor : flavors) {flavor.setDishId(dishDTO.getId());}// 向口味表插入n条数据dishFlavorMapper.insertBatch(flavors);}}
}
Mapper
@Mapper
public interface DishMapper {/*** 根据id修改菜品数据* @param dish*/@AutoFill(value = OperationType.UPDATE)void update(Dish dish);
}
<?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"><update id="update">update dish<set><if test="name != null">name = #{name},</if><if test="categoryId != null">category_id = #{categoryId},</if><if test="price != null">price = #{price},</if><if test="image != null">image = #{image},</if><if test="description != null">description = #{description},</if><if test="status != null">status = #{status},</if><if test="updateTime != null">update_time = #{updateTime},</if><if test="updateUser != null">update_user = #{updateUser},</if></set>where id = #{id}</update></mapper>
@Mapper
public interface DishFlavorMapper {/*** 批量插入口味数据* @param flavors*/void insertBatch( List<DishFlavor> flavors);/*** 根据id删除对应的口味数据* @param dishId*/@Delete("delete from dish_flavor where dish_id = #{dishId}")void deleteByDishId(Long dishId);
}
<?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>
功能测试
相关文章:

[苍穹外卖]-04菜品管理接口开发
效果预览 新增菜品 需求分析 查看产品原型分析需求, 包括用到哪些接口, 业务的限制规则 业务规则 菜品名称必须是唯一的菜品必须属于某个分类下, 不能单独存在新增菜品时可以根据情况选择菜品的口味每个菜品必须对应一张图片 接口设计 根据类型查询分类接口 文件上传接口 …...

gitlab 启动/关闭/启用开机启动/禁用开机启动
文章目录 启动 gitlab关闭 gitlab查看 gitlab 运行状态启用 gitlab 开机启动禁用 gitlab 开机启动GitlabGit启动 gitlab hxstrive@localhost:~$ sudo gitlab-ctl start ok: run: alertmanager: (pid 65953) 0s ok: run: gitaly: (pid 65965) 0s ok: run: gitlab-exporter: (pi…...

中间件解析漏洞(附环境搭建教程)
⼀:IIS解析漏洞 环境资源: https://download.csdn.net/download/Nai_zui_jiang/89717504 环境安装 windows2003iis6 1.创建新的虚拟机 2.在下⼀步中选择我们的iso⽂件镜像 vm已主动识别到windows2003 3.产品密钥⽹上搜⼀个 密码自己设置一个简单的&…...

matlab实现kaiser窗+时域采样序列(不管原信号拉伸成什么样子)是一样的,变到频谱后再采样就是一样的频域序列。
下图窗2的频谱在周期化的时候应该是2(w-k*pi/T)我直接对2w减得写错了 可见这两个kaiser窗频谱不一样,采样间隔为2T的窗,频谱压缩2倍,且以原采样频率的一半周期化。 但是这两个不同的kaiser窗在频域采样点的值使完全一…...

git为不同的项目设置不同的提交作者
方法1:找到项目的.git文件夹打开 打开config在下面添加自己作者信息 [user]name 作者名email 邮箱方法2:直接在.git文件夹设置作者名(不使用–global参数) git config user.name "xxxxx"如果想要修改之前提交的…...

防爆定位信标与防爆定位基站有什么区别?
新锐科技 https://baijiahao.baidu.com/s?id1804974957959442238&wfrspider&forpc http://www.xinruikc.cn/biaoqian/52.html http://www.xinruikc.cn/xinbiao/...

QT 编译报错:C3861: ‘tr‘ identifier not found
问题: QT 编译报错:C3861: ‘tr’ identifier not found 原因 使用tr的地方所在的类没有继承自 QObject 类 或者在不在某一类中, 解决方案 就直接用类名引用 :QObject::tr( )...

谈谈ES搜索引擎
一 ES的定义 ES 它的全称是 Elasticsearch,是一个建立在全文搜索引擎库Lucene基础上的一个开源搜索和分析引擎。ES 它本身具备分布式存储,检索速度快的特性,所以我们经常用它来实现全文检索功能。目前在 Elastic 官网对 ES 的定义,…...

【MySQL】MySQL基础
目录 什么是数据库主流数据库基本使用MySQL的安装连接服务器服务器、数据库、表关系使用案例数据逻辑存储 MySQL的架构SQL分类什么是存储引擎 什么是数据库 mysql它是数据库服务的客户端mysqld它是数据库服务的服务器端mysql本质:基于C(mysql)…...

Spring中Bean的相关注解
目录 1.Spring IoC&DI 2.关于Bean存储的相关注解(类注解与方法注解) Bean的获取方式 类注解和方法注解的重命名 2.1 类注解 2.1.1 Controller 2.1.2 Service 2.1.3 Repository 2.1.4 Component 2.1.5 Configuration 2.2 方法注解-Bean 2.2.1 定义多个对象 2.2…...

Golang | Leetcode Golang题解之第385题迷你语法分析器
题目: 题解: func deserialize(s string) *NestedInteger {if s[0] ! [ {num, _ : strconv.Atoi(s)ni : &NestedInteger{}ni.SetInteger(num)return ni}stack, num, negative : []*NestedInteger{}, 0, falsefor i, ch : range s {if ch - {negati…...

【Java 优选算法】双指针(上)
欢迎关注个人主页:逸狼 创造不易,可以点点赞吗~ 如有错误,欢迎指出~ 目录 移动零 分析 代码 复写零 分析 代码 快乐数 分析 代码 盛最多水的容器 分析 代码 移动零 题目链接 分析 双指针算法,利用两个指针cur和dest将数组划分为三个区间…...

【自动驾驶】控制算法(八)横向控制Ⅰ | 算法与流程
写在前面: 🌟 欢迎光临 清流君 的博客小天地,这里是我分享技术与心得的温馨角落。📝 个人主页:清流君_CSDN博客,期待与您一同探索 移动机器人 领域的无限可能。 🔍 本文系 清流君 原创之作&…...

Android SSE 单向接收数据
Server-Sent Events(SSE)是一种在客户端和服务器之间实现单向实时通信的技术。它允许服务器向客户端推送数据,但客户端无法使用 SSE 向服务器发送数据。这使得其适用于需要持续接收服务器数据的应用场景(如实时通知、股票行情、社…...

排序《数据结构》
排序 《数据结构》 1.排序的概念及其运用1.1 排序的概念1.2 排序运用1.3常见的排序算法1.4 排序动图演示 2.常见排序算法的实现2.1 插入排序2.2希尔排序2.3 快排左边做keyi,右边先走,可以保证相遇位置比keyi小 2.4 快速排序优化快排(非递归&a…...

flutter 提示框2 Dialog
flutter 提示框 写在点击的方法体中 child里放自己喜欢的 showDialog( context: context, builder: (BuildContext context) { final Dialog alertDialog Dialog( backgroundColor: Colors.transparent,shadowColor:Colors.transparent,child: Container(height: mediawi…...

如何选择SDR无线图传方案
在开源软件定义无线电(SDR)领域,有几个项目提供了无线图传的解决方案。以下是一些开源SDR无线图传方案: 1. **OpenHD**:这是一个远程高清数字图像传输的开源解决方案,它使用SDR技术来实现高清视频的无线传…...

关于Python类中方法__init__()解析
# import numpy as npclass Car():def __init__(self, maker, name, year):self.maker makerself.name nameself.year yearprint(self.searchMakrt() "123")def searchMakrt(self):print("汽车制作厂家为: " self.maker)# passreturn &quo…...

微信小程序 自定义组件
1. 微信小程序 自定义组件 微信小程序支持组件化开发,这有助于我们复用代码,提高开发效率。下面我将给出一个简单的微信小程序组件化示例,包括一个自定义组件的创建和使用。 1.1. 创建自定义组件 首先,在项目的 components 目录…...

Mac+Pycharm配置PyQt6教程
安装包 pip install PyQt6 PyQt6-tools #查看Qt版本 pip show PyQt6 pip show pyqt6-tools 配置扩展工具 QTD(界面设计) Program:/Users/wan/PycharmProjects/NewDemo/venv/lib/python3.11/site-packages/qt6_applications/Qt/bin/Designer.app Working directo…...

如何保证Redis与Mysql双写一致性?
https://www.cnblogs.com/coderacademy/p/18137480 延迟双删 对于上面链接的文章,里面的延迟双删没有给出具体的例子,也没有直接指出具体解决的问题是针对那种缓存策略,这里补充一下,延时双删缓存针对的是Cache aside pattern(缓…...

9.8笔试记录
1.在c中哪些运算符不能重载? 在 C 中,有以下几个运算符不能被重载: . :成员访问运算符。例如obj.member中的.不能被重载。 :: :作用域解析运算符。用于指定命名空间、类等的作用域,不能被重载。 ?: ࿱…...

SRE-系统管理篇
SRE-系统管理篇 进程管理 进程的概念: 运行起来的程序,命令,服务等等都可以称作进行,进程都是运行在内存当中的。 程序的概念: 一般指安装包,程序代码,应用它们存放在磁盘上面的。 守护进程的概念: 守护进程,一直运行的进程,也可以叫做服务。 进程的分类 僵…...
傅里叶级数,傅里叶变换
先读文章:傅里叶分析之掐死教程(完整版)更新于2014.06.06 - 知乎 (zhihu.com) 傅里叶级数 一、内容:每个周期性函数都可以表示为无穷多个不同频率的正弦函数的叠加。 二、公式: 三、从时域到频域所保留的三点信息&…...

零知识证明在BSV网络上的应用
发表时间:2023年6月15日 2024年7月19日,BSV区块链主网上成功通过使用零知识证明验证了一笔交易。 零知识证明是一种技术,它允许一方(证明者)在不透露任何秘密的情况下,向另一方(验证者&…...

无任何门槛!3分钟5步,发布属于你的第一个智能体小程序,99%的人还不知道怎么用
相信大家都用微信小程序,但是大部分人应该还没有过属于自己的小程序吧。 今天程哥就带大家花三分钟用五步,来创建一个属于自己的微信小程序。 之前Coze在发布渠道里也有发布小程序的渠道,但是试过的人都知道,这个是有一定门槛的…...

怎么强制撤销excel工作表保护?
经常不是用的Excel文件设置了工作表保护,偶尔打开文件的时候想要编辑文件,但是发现忘记了密码,那么这种情况,我们怎么强制撤销excel工作表保护?今天分享两种解决方法。 方法一、 将excel文件转换为其他文件格式&…...

每天学习一个字符串类函数之memmove函数
目录 前言: 一、头文件 二、memmove函数的作用 三、理解memmove函数的定义 1、返回类型 2、参数 四、使用memmove函数 案例1: 案例2: 五、解决数据拷贝之前被覆盖的方法 六、模拟实现memmove函数 前言: 上一篇博客,我…...

【机器人工具箱Robotics Toolbox开发笔记(十三)】三自由度机器人圆弧轨迹规划仿真实例
在实际应用场景中,我们通常预先明确了目标末端的运动轨迹,随后引导机器人进行相应的动作。本实例具体展示了如何基于给定的两个点,计算出末端的精确位姿,并以此为基础,进一步规划出一条平滑的圆弧轨迹供机器人执行。这样的流程确保了机器人能够沿着预定的路径,精准且高效…...

软件工程-图书管理系统的概要设计
软件概要设计说明书 目录 软件概要设计说明书 一、引言 1.1 编写目的 1.2 背景 1.3 定义 1.3.1特定对象 1.3.2专业术语 1.4 参考资料 二、总体设计 2.1 需求规定 2.1.1信息要求 2.1.2功能要求 2.2 运行环境 2.3 基本概要设计和处理流程 2.4 体系结构设计 2.5 模…...