【外卖系统】分类管理业务

news2024/9/20 18:17:25

公共字段自动填充

需求分析

对于之前的开发中,有创建时间、创建人、修改时间、修改人等字段,在其他功能中也会有出现,属于公共字段,对于这些公共字段最好是在某个地方统一处理以简化开发,使用Mybatis Plus提供的公共字段自动填充功能

代码实现

  • 在实体类的属性上加入@TableField注解,指定自动填充的策略
  • 按照框架要求编写元数据对象处理器,在此类中统一为公共字段赋值,此类需要实现MetaObjectHandler接口

修改步骤

  • 先在实体类中的公共字段加上自动填充的注释
 private Integer status;
    @TableField(fill = FieldFill.INSERT)//插入时填充字段
    private LocalDateTime createTime;

    @TableField(fill = FieldFill.INSERT_UPDATE)//插入和更新时填充字段
    private LocalDateTime updateTime;

    @TableField(fill = FieldFill.INSERT)//插入时填充字段
    private Long createUser;

    @TableField(fill = FieldFill.INSERT_UPDATE)//插入和更新时填充字段
    private Long updateUser;
  • 修改控制类中的一些代码

在这里插入图片描述在这里插入图片描述

将这些属性的值统一的在insertFill方法中实现。

package com.springboot.reggie.common;

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

@Component
@Slf4j
/**
 * 自定义元数据处理器
 */

/**
 * 插入操作,自动填充
 * @param metaObject
 */

public  class MyMetaObjecthandler implements MetaObjectHandler {
    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("公共字段自动填充[insert]...");
        log.info(metaObject.toString());
        metaObject.setValue("createTime", LocalDateTime.now());
        metaObject.setValue("updateTime",LocalDateTime.now());
        metaObject.setValue("createUser",new Long(1));
        metaObject.setValue("updateUser",new Long(1));

    }
/**
 * 更新操作,自动填充
 * @param metaObject
 */

    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("公共字段自动填充[update]...");
        log.info(metaObject.toString());
        metaObject.setValue("updateTime",LocalDateTime.now());
        metaObject.setValue("updateUser",new Long(1));
    }
}

问题:自动填充时设置的用户id是固定值,目的是要动态获取当前登录用户的id
解决办法:使用ThreadLocal(用户登录成功,我们将用户id存在了HttpSession中,但是在MyMetaObjectHandler类中是不能获取HttpSession对象的)

关于ThreadLocal

客户端每次发送的http请求,对于的服务端都会分配一个新的线程来处理
LoginCheckFilter中的doFilter方法、EmployeeController中的update方法、MyMetaObjectHandlerupdateFill方法都属于相同的一个线程
即一次请求,对应的线程id都是相同的,所以可以得到相同的值

package com.springboot.reggie.common;
/**
 * 基于ThreadLocal封装工具类 用于保存和获取当前登录用户的id
 */

public class BaseContext {
    private static ThreadLocal<Long>/*用户id是Long型*/ threadLocal = new ThreadLocal<>();



    /**
     *设置值
     * @param  id
     */
    public static  void setCurrentId(Long id)//设置成静态的 因为这是工具方法
    {
        threadLocal.set(id);
    }
    /**
     * 获取值
     * @return  id
     */

    public static Long getCurrentId()
    {
        return threadLocal.get();
    }
}
package com.springboot.reggie.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.springboot.reggie.common.R;
import com.springboot.reggie.entity.Employee;
import com.springboot.reggie.service.EmployeeService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;

@Slf4j
@RestController
@RequestMapping("/employee")
public class EmployeeController {

    @Autowired
    private EmployeeService employeeService;

    /**
     * 员工登录
     * @param request
     * @param employee
     * @return
     */
    @PostMapping("/login")
    public R<Employee> login(HttpServletRequest request,@RequestBody Employee employee){

        //1、将页面提交的密码password进行md5加密处理
        String password = employee.getPassword();
        password = DigestUtils.md5DigestAsHex(password.getBytes());

        //2、根据页面提交的用户名username查询数据库
        LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Employee::getUsername,employee.getUsername());
        Employee emp = employeeService.getOne(queryWrapper);

        //3、如果没有查询到则返回登录失败结果
        if(emp == null){
            return R.error("登录失败");
        }

        //4、密码比对,如果不一致则返回登录失败结果
        if(!emp.getPassword().equals(password)){
            return R.error("登录失败");
        }

        //5、查看员工状态,如果为已禁用状态,则返回员工已禁用结果
        if(emp.getStatus() == 0){
            return R.error("账号已禁用");
        }

        //6、登录成功,将员工id存入Session并返回登录成功结果
        request.getSession().setAttribute("employee",emp.getId());
        return R.success(emp);
    }

    /**
     * 员工退出
     * @param request
     * @return
     */
    @PostMapping("/logout")
    public R<String> logout(HttpServletRequest request){
        //清理Session中保存的当前登录员工的id
        request.getSession().removeAttribute("employee");
        return R.success("退出成功");
    }

    /**
     * 新增员工
     * @param employee
     * @return
     */
    @PostMapping
    public R<String> save(HttpServletRequest request,@RequestBody Employee employee){
        log.info("新增员工,员工信息:{}",employee.toString());

        //设置初始密码123456,需要进行md5加密处理
        employee.setPassword(DigestUtils.md5DigestAsHex("123456".getBytes()));

       // employee.setCreateTime(LocalDateTime.now());
        //employee.setUpdateTime(LocalDateTime.now());

        //获得当前登录用户的id
        //Long empId = (Long) request.getSession().getAttribute("employee");

        //employee.setCreateUser(empId);
        //employee.setUpdateUser(empId);

        employeeService.save(employee);

        return R.success("新增员工成功");
    }

    /**
     * 员工信息分页查询
     * @param page
     * @param pageSize
     * @param name
     * @return
     */
    @GetMapping("/page")
    public R<Page> page(int page,int pageSize,String name){
        log.info("page = {},pageSize = {},name = {}" ,page,pageSize,name);

        //构造分页构造器
        Page pageInfo = new Page(page,pageSize);

        //构造条件构造器
        LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper();
        //添加过滤条件
        queryWrapper.like(StringUtils.isNotEmpty(name),Employee::getName,name);
        //添加排序条件
        queryWrapper.orderByDesc(Employee::getUpdateTime);

        //执行查询
        employeeService.page(pageInfo,queryWrapper);

        return R.success(pageInfo);
    }

    /**
     * 根据id修改员工信息
     * @param employee
     * @return
     */
    @PutMapping
    public R<String> update(HttpServletRequest request,@RequestBody Employee employee){
        log.info(employee.toString());

        //Long empId = (Long)request.getSession().getAttribute("employee");
       // employee.setUpdateTime(LocalDateTime.now());
        //employee.setUpdateUser(empId);
        employeeService.updateById(employee);

        return R.success("员工信息修改成功");
    }

    /**
     * 根据id查询员工信息
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    public R<Employee> getById(@PathVariable Long id){
        log.info("根据id查询员工信息...");
        Employee employee = employeeService.getById(id);
        if(employee != null){
            return R.success(employee);
        }
        return R.error("没有查询到对应员工信息");
    }
}

解决一下之前“玄学报错”的问题:原因是启动类中少了@ServletComponentScan

下面是引用的某ai的回答,没系统学过springboot,这些东西也不懂,之后还得学。。还有比较长的路要走。

@ServletComponentScan是一个Spring Boot注解,用于扫描和注册Servlet、Filter和Servlet监听器。
在传统的Java Web应用程序中,我们需要在web.xml文件中配置Servlet、Filter和Servlet监听器。但是,使用Spring Boot时,可以使用注解来代替web.xml的配置。
@ServletComponentScan注解可以在Spring Boot的主配置类上使用,它会自动扫描指定包及其子包下的所有Servlet、Filter和Servlet监听器,并将它们注册到Servlet容器中。
使用@ServletComponentScan注解的步骤如下:
在Spring Boot的主配置类上添加@ServletComponentScan注解。
在指定的包及其子包下创建Servlet、Filter和Servlet监听器。
在创建的Servlet、Filter和Servlet监听器类上使用@WebServlet、@WebFilter和@WebListener等注解进行配置。
通过使用@ServletComponentScan注解,Servlet、Filter和Servlet监听器就可以通过注解的方式进行配置和注册,而不需要再手动编写web.xml文件。
需要注意的是,@ServletComponentScan注解只在使用嵌入式Servlet容器(如Tomcat)时有效,对于外部部署的WAR包,它不会生效。
总结:@ServletComponentScan是一个Spring Boot注解,用于自动扫描和注册Servlet、Filter和Servlet监听器,简化了配置和注册的过程。

新增分类

需求分析

菜品分类和套餐分类,添加菜品时选择菜品分类,添加套餐时选择套餐分类。
通过前端和设计的数据库看:
在这里插入图片描述在这里插入图片描述

代码设计

实体类

package com.springboot.reggie.entity;

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.time.LocalDateTime;

/**
 * 分类
 */
@Data
public class Category implements Serializable {

    private static final long serialVersionUID = 1L;

    private Long id;


    //类型 1 菜品分类 2 套餐分类
    private Integer type;


    //分类名称
    private String name;


    //顺序
    private Integer sort;


    //创建时间
    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createTime;


    //更新时间
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updateTime;


    //创建人
    @TableField(fill = FieldFill.INSERT)
    private Long createUser;


    //修改人
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Long updateUser;

}

  • 页面发送ajax请求,将新增分类窗口输入的数据以json形式提交到服务端
  • 服务端Controller接收页面提交的数据并调用Service将数据进行保存
  • Service调用Mapper操作数据,保存数据
    在这里插入图片描述

通过前端发送给后台的请求发现新增菜品和新增套餐分类请求的服务端地址和提交的json数据结构相同,所以服务端只需要提供一个方法统一处理。

添加淮扬菜成功
在这里插入图片描述代码不放了

分类信息分页查询

package com.springboot.reggie.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.springboot.reggie.common.R;
import com.springboot.reggie.entity.Category;
import com.springboot.reggie.service.CategoryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

/**
 * 分类管理
 */
@RestController
@RequestMapping("/category")
@Slf4j
public class CategoryController {
    @Autowired
    private CategoryService categoryService;
    /**
     * 新增分类
     * @param category
     * @return
     */
    @PostMapping
    public R<String> save(@RequestBody Category category)
    {
        log.info("category{}",category);
        categoryService.save(category);
        return R.success("新增分类成功");
    }

/**
 * 分页查询
 * @param page
 * @param pageSize
 * @return
 */

    @GetMapping("/page")
    public R<Page> page(int page,int pageSize)
    {
        //分页构造器
        Page<Category> pageInfo = new Page<>(page,pageSize);
        //条件构造器
        LambdaQueryWrapper<Category> queryWrapper = new LambdaQueryWrapper<>();
        //添加排序条件 根据sort进行排序
        queryWrapper.orderByAsc(Category::getSort);
        //进行分页查询
        categoryService.page(pageInfo,queryWrapper);
        return R.success(pageInfo);
       // return null;
    }
}

删除分类

在这里插入图片描述
在这里插入图片描述

  • 页面发送ajax请求,将参数id提交到服务端
  • 服务端Controller接受页面提交的数据并调用Service删除数据
  • Service调用Mapper操作数据库

简单删除

在这里插入图片描述

 /**
     *删除分类 根据id删除分类
     * @param id
     * @return
     */
    @DeleteMapping
    public R<String> delete(Long id)
    {
        log.info("删除分类,id为:{}",id);
        categoryService.removeById(id);
        return  R.success("删除分类成功...");
        //return null;
    }

在这里插入图片描述

完善删除功能

上述的删除只是简单的直接删除菜品或者是套餐,但是没有检查删除的分类是否关联了菜品或者套餐需要进行完善。
准备好实体类(菜品和菜单)

尝试删除“湘菜”,湘菜是关联了套餐的,删除失败。
在这里插入图片描述添加一个无关联的菜品或者套餐,然后再删除,之前一直是报错,原因是没有添加@Autowired注解。

@Autowired是Spring框架中的一个注解,用于自动装配(自动注入)对象的依赖关系。在Spring容器中,使用@Autowired注解可以实现自动装配,即根据指定的类型,自动在容器中查找匹配的bean,并将其注入到目标对象中。
@Autowired可以用在构造方法、成员变量、方法以及参数上。当用在构造方法上时,Spring会自动在容器中查找匹配的bean,并将其作为参数传入构造方法中。当用在成员变量上时,Spring会自动在容器中查找匹配的bean,并将其注入到成员变量中。当用在方法上时,Spring会自动在容器中查找匹配的bean,并将其作为方法的参数传入。当用在方法参数上时,Spring会自动在容器中查找匹配的bean,并将其作为方法参数传入。
使用@Autowired注解可以简化代码,减少手动配置的工作量。它可以减少了因为对象之间的依赖关系而需要手动创建对象和设置依赖关系的繁琐工作。同时,它也增加了代码的可读性和可维护性,使得代码更加清晰和简洁。
需要注意的是,使用@Autowired注解时,需要先确保Spring容器中存在匹配的bean。如果存在多个匹配的bean,可以使用@Qualifier注解或者通过指定名称的方式来指定具体要注入的bean。如果没有找到匹配的bean,会抛出异常。

在这里插入图片描述

package com.springboot.reggie.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.springboot.reggie.common.R;
import com.springboot.reggie.entity.Category;
import com.springboot.reggie.service.CategoryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * 分类管理
 */
@RestController
@RequestMapping("/category")
@Slf4j
public class CategoryController {
    @Autowired
    private CategoryService categoryService;
    public Long id;

    /**
     * 新增分类
     * @param category
     * @return
     */
    @PostMapping
    public R<String> save(@RequestBody Category category)
    {
        log.info("category{}",category);
        categoryService.save(category);
        return R.success("新增分类成功");
    }

/**
 * 分页查询
 * @param page
 * @param pageSize
 * @return
 */

    @GetMapping("/page")
    public R<Page> page(int page,int pageSize)
    {
        //分页构造器
        Page<Category> pageInfo = new Page<>(page,pageSize);
        //条件构造器
        LambdaQueryWrapper<Category> queryWrapper = new LambdaQueryWrapper<>();
        //添加排序条件 根据sort进行排序
        queryWrapper.orderByAsc(Category::getSort);
        //进行分页查询
        categoryService.page(pageInfo,queryWrapper);
        return R.success(pageInfo);
       // return null;
    }

    /**
     *删除分类 根据id删除分类
     * @param id
     * @return
     */
    @DeleteMapping()
   // @RequestParam
    public R<String> delete(Long id)
    {
        //this.ids = ids;
        log.info("删除分类,id为:{}",id);
        categoryService.remove(id);
        return  R.success("删除分类成功...");
        //return null;
    }

}

package com.springboot.reggie.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.springboot.reggie.common.CustomException;
import com.springboot.reggie.entity.Category;

import com.springboot.reggie.entity.Dish;
import com.springboot.reggie.entity.Setmeal;
import com.springboot.reggie.mapper.CategoryMapper;

import com.springboot.reggie.service.CategoryService;

import com.springboot.reggie.service.DishService;
import com.springboot.reggie.service.SetmealService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper,Category> implements CategoryService{

    @Autowired
    private DishService dishService;//录入菜品分类
    @Autowired
    private SetmealService setmealService;//录入套餐分类

    /**
     * 根据id删除分类 删除之前需要进行判断
     * @param id
     */
    @Override
    public void remove (Long id){
        //调用框架中的查询方法
       LambdaQueryWrapper<Dish> dishLambdaQueryWrapper = new LambdaQueryWrapper<>();
       //添加查询条件 根据分类id进行查询
       dishLambdaQueryWrapper.eq(Dish::getCategoryId,id);
       //统计当前分类下关联了几个菜品
       int count = dishService.count(dishLambdaQueryWrapper);
       //如果当前分类下关联的菜品个数大于0 说明有菜品关联 不能删
       //查询当前分类是否关联了菜品 如果已关联 抛出一个业务异常
       if(count>0)
       {
            throw new CustomException("当前分类下关联了菜品,不能删除!");
       }

       //查询当前分类是否关联了套餐 如果已关联 抛出一个业务异常
       LambdaQueryWrapper<Setmeal> setmealLambdaQueryWrapper = new LambdaQueryWrapper<>();
       //添加查询条件 根据分类id进行查询
       setmealLambdaQueryWrapper.eq(Setmeal::getCategoryId,id);
       int cnt = setmealService.count(setmealLambdaQueryWrapper);
       //如果当前分类下关联的菜品个数大于0 说明有套餐关联 不能删
       if(cnt>0)
       {
            throw new CustomException("当前分类下关联了套餐,不能删除!");
       }
       //正常删除分类
       super.removeById(id);


    }

    }

修改分类

需求分析

点击修改按钮,弹出修改窗口,在修改窗口回显分类信息并进行修改,最后点击确定按钮完成修改操作

代码

 /**
     * 根据id修改分类信息
     * @param category
     * @return
     */
    @PutMapping
    public R<String> update(@RequestBody  Category category)
    {
        log.info("修改分类信息:{}",category);
        categoryService.updateById(category);
        return R.success("修改分类信息成功...");
    }

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/812374.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

简单记录牛客top101算法题(初级题C语言实现)判断回文字符串 反转字符串 合并两个有序的数组

1. 判断是否为回文字符串 给定一个长度为 n 的字符串&#xff0c;请编写一个函数判断该字符串是否回文。如果是回文请返回true&#xff0c;否则返回false。   字符串回文指该字符串正序与其逆序逐字符一致。 //示例 输入&#xff1a;"ranko" 返回值&#xff1a;fa…

DevOps系列文章之 自动化测试大全(单测和集成测试)

自动化测试业界主流工具 核心目标&#xff1a; 主要是功能测试和覆盖率测试 业界常用主流工具 GoogleTest GoogleTest是一个跨平台的(Liunx、Mac OS X、Windows 、Cygwin 、Windows CE and Symbian ) C单元测试框架&#xff0c;由google公司发布&#xff0c;为在不同平台上为编…

案例:缺陷个数与返工工作量强相关

某公司积累了21个项目缺陷个数与返工工作量的数据&#xff0c;如下表所示&#xff1a; 项目序号缺陷修复工时缺陷数1943314452299040536347446471385496071061370246774066812232189276652810830213781162678126111511381110514209032015144023516516078417710010301875601239…

3.Makefile变量的用法(附示例)

一、本节概要 本专栏所有内容围绕Makefile官方文档进行刨析,给出详细具体示例做辅助理解手撕Makefile官方手册 二、Makefile中的变量 1、没有使用变量的makefile 以下是不使用变量的makefile完整示例: edit: main.o kbd.o command.o display.o insert.o search.o files…

django channels实战(websocket底层原理和案例)

1、websocket相关 1.1、轮询 1.2、长轮询 1.3、websocket 1.3.1、websocket原理 1.3.2、django框架 asgi.py在django项目同名app目录下 1.3.3、聊天室 django代码总结 小结 1.3.4、群聊&#xff08;一&#xff09; 前端代码 后端代码 1.3.5、群聊&#xff08;二&#xff09…

网络编程 IO多路复用 [epoll版] (TCP网络聊天室)

//head.h 头文件 //TcpGrpSer.c 服务器端 //TcpGrpUsr.c 客户端 通过IO多路复用实现服务器在单进程单线程下可以与多个客户端交互 API epoll函数 #include<sys/epoll.h> int epoll_create(int size); 功能&#xff1a;创建一个epoll句柄//创建红黑树根…

TypeScript算法题实战——剑指 Offer篇(5)

目录 一、平衡二叉树1.1、题目描述1.2、题解 二、数组中数字出现的次数2.1、题目描述2.2、题解 三、数组中数字出现的次数 II3.1、题目描述3.2、题解 四、和为s的两个数字4.1、题目描述4.2、题解 五、和为s的连续正数序列5.1、题目描述5.2、题解 六、翻转单词顺序6.1、题目描述…

《cuda c编程权威指南》01- 用gpu输出hello world

学习一门新语言的最好方式就是用它来编写程序。 目录 1. 使用cpu输出hello world 2. 使用gpu输出hello world 3. CUDA编程结构 1. 使用cpu输出hello world hello.cu #include <stdio.h>void helloFromCPU() {printf("hello world from cpu!\n"); }int m…

Zabbix分布式监控配置和使用

目录 1 Zabbix监控的配置流程2 添加主机组3 添加模板4 添加主机5 配置图形6 配置大屏7 新建监控项7.1 简介7.2 添加监控项7.3 查看数据7.4 图表 8 新建触发器8.1 概述8.2 添加触发器8.3 显示触发器状态 1 Zabbix监控的配置流程 在Zabbix-Web管理界面中添加一个主机&#xff0c;…

【Golang 接口自动化00】为什么要用Golang做自动化?

目录 为什么使用Golang做自动化 最终想实现的效果 怎么做&#xff1f; 写在后面 资料获取方法 为什么使用Golang做自动化 顺应公司的趋势学习了Golang之后&#xff0c;因为没有太多时间和项目来实践&#xff0c;怕止步于此、步Java缺少练习遗忘殆尽的后尘&#xff0c;决定…

【C++进阶之路】多态篇

文章目录 前言一、概念1.分类2.实现条件①重写虚函数1.1总结三重1.2 final与override ②父类的指针或者引用2.1普通调用VS多态调用 3.抽象类3.1. 纯虚函数3.2. 接口继承和实现继承 二、原理及使用1.虚函数表 —— 虚表2.默认成员函数2.1构造函数2.2析构函数 3. 多继承3.1普通的…

python速成之循环分支结构学习

循环结构 应用场景 我们在写程序的时候&#xff0c;一定会遇到需要重复执行某条或某些指令的场景。例如用程序控制机器人踢足球&#xff0c;如果机器人持球而且还没有进入射门范围&#xff0c;那么我们就要一直发出让机器人向球门方向移动的指令。在这个场景中&#xff0c;让…

AD21原理图的高级应用(六)原理图设计片段的使用

&#xff08;六&#xff09;原理图设计片段的使用 Altium Designer 的片段功能可以很方便地重复使用一些单元模块,其中包括原理图的电路模块、PCB(包括布线)和代码模块。例如在工程中需要设计电源模块,而别的工程中又恰好有比较完善的电源模块,这时就可以通过片段功能重复地使用…

一文了解 Android 车机如何处理中控的旋钮输入?

前言 上篇文章《从实体按键看 Android 车载的自定义事件机制》带大家了解了 Android 车机支持自定义输入的机制 CustomInputService。事实上&#xff0c;除了支持自定义事件&#xff0c;对于中控上常见的音量控制、焦点控制的旋钮事件&#xff0c;Android 车机也是支持的。 那…

测试|测试用例方法篇

测试|测试用例方法篇 文章目录 测试|测试用例方法篇1.测试用例的基本要素&#xff1a;测试环境&#xff0c;操作步骤&#xff0c;测试数据&#xff0c;预期结果…2.测试用例带来的好处3.测试用例的设计思路&#xff0c;设计方法&#xff0c;具体设计方法之间的关系**设计测试用…

linux设备驱动的poll与fasync

什么是fasync 在 Linux 驱动程序中&#xff0c;fasync 是一种机制&#xff0c;用于在异步事件发生时通知进程。它允许进程在等待设备事件时&#xff0c;不必像传统的轮询方式那样持续地查询设备状态。 具体来说&#xff0c;当进程调用 fcntl(fd, F_SETFL, O_ASYNC) 函数时&am…

lib-flexible修改配置适配更多不同分辨率

找到设置宽度的地方 然后根据你的屏幕最大多大呀&#xff0c;最小多小呀设置一下 if (width / dpr < 1980) { width 1980 * dpr; } else if (width / dpr > 5760) { width 5760 * dpr; }

Python 教程之标准库概览

概要 Python 标准库非常庞大&#xff0c;所提供的组件涉及范围十分广泛&#xff0c;使用标准库我们可以让您轻松地完成各种任务。 以下是一些 Python3 标准库中的模块&#xff1a; 「os 模块」 os 模块提供了许多与操作系统交互的函数&#xff0c;例如创建、移动和删除文件和…

【Linux】进程篇Ⅱ:进程开始、进程终止、进程等待

文章目录 五、fork 函数&#xff0c;创建进程写时拷贝 六、进程终止1. 退出码2. 如何终止程序 七、进程等待1. 概念2. wait 函数waitpid 函数 &#x1f53a; 3. 阻塞等待 五、fork 函数&#xff0c;创建进程 #include <unistd.h>   pid_t fork(void);   返回值&#xf…

动态SQL 语句-更复杂的查询业务需求也能轻松拿捏

文章目录 动态SQL 语句-更复杂的查询业务需求动态SQL-官方文档为什么需要动态SQL动态SQL-基本介绍基本介绍动态SQL 必要性解决方案分析 动态SQL 常用标签动态SQL-案例演示if 标签应用实例where 标签应用实例choose/when/otherwise 应用实例forEach 标签应用实例trim 标签应用实…