首页 > 其他分享 >苍穹外卖学习笔记(六)

苍穹外卖学习笔记(六)

时间:2024-09-16 13:20:38浏览次数:3  
标签:苍穹 sky 笔记 外卖 org employee import com public

文章目录

一.公共字段自动填充

方法一:使用AOP切面编程方式

自定义注解AutoFill,用于标识需要进行公共字段自动填充的方法
自定义切面类AutoFillAspect,统一拦截加入了AutoFill注解的方法,通过反射为公共字段赋值
在Mapper的方法上加入AutoFill注解
  1. AutoFill 注解类
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(ElementType.METHOD)//方法上
@Retention(RetentionPolicy.RUNTIME)//运行时
public @interface AutoFill {
    //数据库操作类型
    OperationType value();
}
  1. AutoFillAspect切面类
import com.sky.annotation.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.Signature;
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.LocalDateTime;

/**
 * 自动填充切面
 */
@Aspect
@Component
@Slf4j
public class AutoFillAspect {

    /**
     * 切入点
     */
    @Pointcut("execution(* com.sky.service.impl.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")
    public void AutoFillPointcut() {
    }

    /**
     * 前置通知
     */
    @Before("AutoFillPointcut()")
    public void autoFill(JoinPoint joinPoint) {
        log.info("自动填充切面执行");
        //获取当前被拦截的方法上的数据库操作类型
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();//获取当前被拦截方法的签名
        AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class);//获取当前被拦截方法的方法名
        OperationType value = 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 (value == 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 (value == 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();
            }
        }
    }
}
  1. impl
package com.sky.service.impl;

import com.alibaba.druid.util.Utils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sky.annotation.AutoFill;
import com.sky.constant.MessageConstant;
import com.sky.constant.PasswordConstant;
import com.sky.constant.StatusConstant;
import com.sky.context.BaseContext;
import com.sky.dto.EmployeeDTO;
import com.sky.dto.EmployeeLoginDTO;
import com.sky.dto.EmployeePageQueryDTO;
import com.sky.dto.EmployeeUppswdDTO;
import com.sky.entity.Employee;
import com.sky.enumeration.OperationType;
import com.sky.exception.AccountLockedException;
import com.sky.exception.AccountNotFoundException;
import com.sky.exception.PasswordErrorException;
import com.sky.mapper.EmployeeMapper;
import com.sky.result.PageResult;
import com.sky.result.Result;
import com.sky.service.EmployeeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;
import org.apache.commons.lang3.StringUtils;

import javax.swing.text.Utilities;
import java.time.LocalDateTime;
import java.util.Base64;

import java.security.SecureRandom;
import java.util.List;

@Slf4j
@Service
public class EmployeeServiceImpl implements EmployeeService {

    @Autowired
    private EmployeeMapper employeeMapper;

    private static final SecureRandom RANDOM = new SecureRandom();//随机数生成器
    private static final int SALT_LENGTH = 16;//盐的长度

    /**
     * 员工登录
     *
     * @param employeeLoginDTO
     * @return
     */


    public Employee login(EmployeeLoginDTO employeeLoginDTO) {
        String username = employeeLoginDTO.getUsername();
        String password = employeeLoginDTO.getPassword();

        //1、根据用户名查询数据库中的数据
        // mybatis-plus的方法
        log.info("username:{}", username);
        LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Employee::getUsername, username);
        Employee employee = employeeMapper.selectOne(queryWrapper);
        log.info("employee:{}", employee);

        //2、处理各种异常情况(用户名不存在、密码不对、账号被锁定)
        if (employee == null) {
            //账号不存在
            throw new AccountNotFoundException(MessageConstant.ACCOUNT_NOT_FOUND);
        }

        //密码比对
        //对前端传来的密码进行md5加盐处理,然后再进行比对
        String salt = employee.getSalt();//盐
        String hashedPassword = hashPassword(password, salt);//加密后的密码

        if (!hashedPassword.equals(employee.getPassword())) {
            //密码错误
            throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR);
        }

        if (employee.getStatus() == StatusConstant.DISABLE) {
            //账号被锁定
            throw new AccountLockedException(MessageConstant.ACCOUNT_LOCKED);
        }

        //3、返回实体对象
        return employee;
    }

    //对密码进行加密
    private String hashPassword(String password, String salt) {
        String saltedPassword = salt + password;
        return DigestUtils.md5DigestAsHex(saltedPassword.getBytes());
    }

    /**
     * 添加员工
     *
     * @param employeeDTO
     * @return
     */
    @Transactional
    @Override
//    @AutoFill(OperationType.INSERT)
    public void save(EmployeeDTO employeeDTO) {
        Employee employee = new Employee();
        BeanUtils.copyProperties(employeeDTO, employee);
        employee.setStatus(StatusConstant.ENABLE);//默认启用
        //生成盐
        byte[] salt = new byte[SALT_LENGTH];
        RANDOM.nextBytes(salt);
        employee.setSalt(Base64.getEncoder().encodeToString(salt));
        //对密码进行加密,默认密码为123456
        String password = hashPassword(PasswordConstant.DEFAULT_PASSWORD, employee.getSalt());
        employee.setPassword(password);
        //通过注释的方式进行填充
//        //设置创建时间和更新时间
//        employee.setCreateTime(LocalDateTime.now());
//        employee.setUpdateTime(LocalDateTime.now());
//        //设置创建人和更新人
//        employee.setCreateUser(BaseContext.getCurrentId());
//        employee.setUpdateUser(BaseContext.getCurrentId());
        employeeMapper.insert(employee);
    }

    /**
     * 分页查询员工
     *
     * @param employeePageQueryDTO
     * @return
     */
    @Transactional
    @Override
    public PageResult pageQuery(EmployeePageQueryDTO employeePageQueryDTO) {
        // 创建分页对象
        Page<Employee> page = new Page<>(employeePageQueryDTO.getPage(), employeePageQueryDTO.getPageSize());
        // 创建查询条件
        LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper<>();
        // 排除姓名为null的记录
        queryWrapper.isNotNull(Employee::getName);
        // 使用like方法进行模糊查询,参数化防止SQL注入
        if (StringUtils.isNotBlank(employeePageQueryDTO.getName())) {
            queryWrapper.like(Employee::getName, employeePageQueryDTO.getName());
        }
        // 根据创建时间降序排序
        queryWrapper.orderByDesc(Employee::getCreateTime);
        // 执行分页查询
        Page<Employee> employeePage = employeeMapper.selectPage(page, queryWrapper);
        // 提取结果
        long total = employeePage.getTotal();
        List<Employee> records = employeePage.getRecords();
        // 返回结果
        return new PageResult(total, records);
    }

    /**
     * 修改员工状态
     *
     * @param id
     * @param status
     * @return
     */
    @Override
    @AutoFill(OperationType.UPDATE)
    public void startOrStop(Long id, Integer status) {
//        Employee employee = new Employee();
//        employee.setId(id);
//        employee.setStatus(status);
//        employee.setUpdateTime(LocalDateTime.now());
//        employee.setUpdateUser(BaseContext.getCurrentId());
        Employee employee = Employee.builder()
                .id(id)
                .status(status)
//                .updateTime(LocalDateTime.now())
//                .updateUser(BaseContext.getCurrentId())
                .build();
        employeeMapper.updateById(employee);
    }

    /**
     * 根据id查询员工
     *
     * @param id
     * @return
     */
    @Override
    public Employee getById(Long id) {
        Employee employee = employeeMapper.selectById(id);
        employee.setPassword("********");
        return employee;
    }

    /**
     * 修改员工
     *
     * @param employeeDTO
     */
    @Override
    @AutoFill(OperationType.UPDATE)
    public void update(EmployeeDTO employeeDTO) {
        Employee employee = new Employee();
        BeanUtils.copyProperties(employeeDTO, employee);
//        employee.setUpdateTime(LocalDateTime.now());
//        employee.setUpdateUser(BaseContext.getCurrentId());
        employeeMapper.updateById(employee);
    }

    /**
     * 修改密码
     *
     * @param employeeUppswdDTO
     */
    @Override
    @AutoFill(OperationType.UPDATE)
    public void editPassword(EmployeeUppswdDTO employeeUppswdDTO) {
        //1.根据id查询员工
        Employee employee = employeeMapper.selectById(employeeUppswdDTO.getEmpId());
        if (employee == null) {
            throw new AccountNotFoundException("Employee not found");
        }
        //2.对原密码进行加密
        String oldPassword = hashPassword(employeeUppswdDTO.getOldPassword(), employee.getSalt());
        //3.比对原密码是否正确
        if (!oldPassword.equals(employee.getPassword())) {
            throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR);
        }
        //4.对新密码进行加密
        String newPassword = hashPassword(employeeUppswdDTO.getNewPassword(), employee.getSalt());
        //5.修改密码
        employee.setPassword(newPassword);
//        employee.setUpdateTime(LocalDateTime.now());
//        employee.setUpdateUser(BaseContext.getCurrentId());
        employeeMapper.updateById(employee);
    }
}

由于我前面使用的MP,所以注解需要放在impl中,并且由于DTO没有对应属性,需要在controller中将DTO参数换成entity实体才行,我这里不再详细写出

方法二:使用mybatis-plus自带的公共字段自动填充

1. 创建实体类并使用注解指定需要自动填充的字段
2. 创建自定义的字段填充处理器
注入Bean然后就可以自动填充了(不需要标注解哦 是不是方便许多

标签:苍穹,sky,笔记,外卖,org,employee,import,com,public
From: https://blog.csdn.net/qq_73340809/article/details/142301868

相关文章

  • 苍穹外卖学习笔记(七)
    四.删除菜品业务规则:可以一次删除一个菜品,也可以一次删除多个菜品起售中的菜品不能删除被套餐关联得菜品不能删除删除菜品后,关联得口味数据也需要删除掉一共需要操作三个表,注意加@Transactional事物注解Controller/***删除菜品*/@DeleteMapping......
  • 前端工程化学习笔记-02(webpack基础用法)
    前端工程化学习笔记-02(webpack基础用法)webpack基础用法快速搭建一个简易的webpack项目使用npminit初始化一个项目;mkdirwebpack-democdwebpack-demonpminit-y本地安装webpack;npminstallwebpackwebpack-cli--save-dev修改package.json文件#删除"main"......
  • 用笔记来记录遇到的问题:发布版本和非发布版本遇到的问题
    这两天接到一个任务,把中秋节的的宣传广告发到app上去。没想到一个项目运营了这么久,竟然没有这种功能我给他们做了3个:开屏广告、首页弹出广告和客服机器人形象换成小兔子。搞完之后,我发布版本给他们测试谁知道我本地运行得好好的,为啥发布给他们的版本没有效果!我震惊了,以为我......
  • (CS231n课程笔记)深度学习之损失函数详解(SVM loss,Softmax,熵,交叉熵,KL散度)
    学完了线性分类,我们要开始对预测结果进行评估,进而优化权重w,提高预测精度,这就要用到损失函数。损失函数(LossFunction)是机器学习模型中的一个关键概念,用于衡量模型的预测结果与真实标签之间的差距。损失函数的目标是通过提供一个差距的度量,帮助模型进行优化,最终减少预测误差。......
  • 基于python和django网上订餐系统在线点餐系统外卖系统
    前言......
  • Python重温笔记
    1.Python解释器将Python代码翻译为二进制,交给计算机去运行。是Python.exe程序2.python中数字有四种类型整数、布尔型、浮点数和复数。即int型,bool(true与false),float,,a+bj的复数等变量不需要声明,但是在使用的时候需要提前赋值。print(变量名)输出变量值,也可以输出数字;prin......
  • 学习笔记-二分图
    二分图二分图当且仅当图中没有奇数环.染色法//染色法模板intn;//n表示点数inth[N],e[M],ne[M],idx;//邻接表存储图intcolor[N];//表示每个点的颜色,-1表示未染色,0表示白色,1表示黑色//参数:u表示当前节点,c表示当前点的颜色booldfs(intu......
  • 【Python学习笔记】 第8章 列表与字典
    列表Python的列表是:任意对象的有序集合通过偏移访问可变长度、异构以及任意嵌套属于“可变序列”的分类对象引用数组下表是常见/具有代表性的列表对象操作:操作解释L=[]一个空的列表L=[123,'abc',1.23,{}]有四个项的列表,索引从0到3L=......
  • 个人学习笔记7-6:动手学深度学习pytorch版-李沐
    #人工智能##深度学习##语义分割##计算机视觉##神经网络#计算机视觉13.11全卷积网络全卷积网络(fullyconvolutionalnetwork,FCN)采用卷积神经网络实现了从图像像素到像素类别的变换。引入l转置卷积(transposedconvolution)实现的,输出的类别预测与输入图像在像素级别上具有......
  • AutoSar AP平台的SOMEIP文档的理解笔记
    前言前段时间,阅读了AutoSarAP的SOME/IP的标准文档(《SOME/IPProtocolSpecification.pdf》),并以PPT的图文并茂的形式做了理解笔记,内容主要是SOME/IP的协议规范,由SOME/IP报文格式和协议部分。1.SOMEIP报文格式1.1SOME/IP消息格式:头格式1.2SOME/IP头格式:RequestID(Clie......