网站如何使用cdn,电商网站开发 上海,潍坊建站公司,微网站模板在线公共字段自动填充
问题分析
业务表中的公共字段#xff1a; 而针对于这些字段#xff0c;我们的赋值方式为#xff1a; 在新增数据时, 将createTime、updateTime 设置为当前时间, createUser、updateUser设置为当前登录用户ID。 在更新数据时, 将updateTime 设置为当前时间…
公共字段自动填充
问题分析
业务表中的公共字段 而针对于这些字段我们的赋值方式为 在新增数据时, 将createTime、updateTime 设置为当前时间, createUser、updateUser设置为当前登录用户ID。 在更新数据时, 将updateTime 设置为当前时间, updateUser设置为当前登录用户ID。 问题代码冗余、不便于后期维护 实现思路
有四个公共字段需要在新增/更新中进行赋值操作, 具体情况如下: 实现步骤 自定义注解 AutoFill用于标识需要进行公共字段自动填充的方法自定义切面类 AutoFillAspect统一拦截加入了 AutoFill 注解的方法通过反射为公共字段赋值在 Mapper 的方法上加入 AutoFill 注解 技术点枚举、注解、AOP、反射 java--反射(reflection)_反射 reflection java-CSDN博客 SpringBootWeb 事务AOPday13-CSDN博客 java -- 枚举和注解_java 枚举-CSDN博客 代码开发
•自定义注解 AutoFill
package com.sky.annotation;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;/*** 自定义注解用于标识某个方法需要进行功能字段自行填充
* author 石头
* version 1.0
*/
Target(ElementType.METHOD)
Retention(RetentionPolicy.RUNTIME)
public interface AutoFill {//数据库操作类型UPDATE INSERTOperationType value();
}Java中自定义注解的使用详解_java自定义注解使用-CSDN博客
自定义切面 AutoFillAspect
package com.sky.aspect;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.mapper.*.*(..)) annotation(com.sky.annotation.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 time LocalDateTime.now();Long empId BaseContext.getCurrentId();//根据当前不同的操作类型为对应的属性通过反射赋值if (operationType OperationType.INSERT) {//当前执行的是insert操作为4个字段赋值try {//获得set方法对象----MethodMethod setCreateTime entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);Method setUpdateTime entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);Method setCreateUser entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);Method setUpdateUser entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);//通过反射调用目标对象的方法setCreateTime.invoke(entity, time);setUpdateTime.invoke(entity, time);setCreateUser.invoke(entity, empId);setUpdateUser.invoke(entity, empId);} catch (Exception ex) {log.error(公共字段自动填充失败{}, ex.getMessage());}}else {//当前执行的是update操作为2个字段赋值try {//获得set方法对象----MethodMethod setUpdateTime entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);Method setUpdateUser entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);//通过反射调用目标对象的方法setUpdateTime.invoke(entity, time);setUpdateUser.invoke(entity, empId);} catch (Exception ex) {log.error(公共字段自动填充失败{}, ex.getMessage());}}}}
•在Mapper接口的方法上加入 AutoFill 注解
/*** 插入数据* param category*/
AutoFill(OperationType.INSERT)
Insert(insert into category(type, name, sort, status, create_time, update_time, create_user, update_user) VALUES (#{type}, #{name}, #{sort}, #{status}, #{createTime}, #{updateTime}, #{createUser}, #{updateUser}))
void insert(Category category);/*** 根据id修改分类* param category*/
AutoFill(OperationType.UPDATE)
void update(Category category);
•将业务层为公共字段赋值的代码注释掉
功能测试
通过观察控制台输出的SQL来确定公共字段填充是否完成
新增菜品
需求分析和设计
产品原型 业务规则 菜品名称必须是唯一的菜品必须属于某个分类下不能单独存在新增菜品时可以根据情况选择菜品的口味每个菜品必须对应一张图片 接口设计 • 根据类型查询分类已完成 • 文件上传 • 新增菜品 •根据类型查询分类 •文件上传 •新增菜品 数据库设计dish菜品表和dish_flavor口味表 代码开发
开发文件上传接口
开发文件上传接口
开发新增菜品接口 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 ListDishFlavor flavors new ArrayList();}
开发新增菜品接口
!--useGeneratedKeys:true 表示获取主键值keyPropertyid 表示将主键值赋给id属性
--
insert idinsert useGeneratedKeystrue keyPropertyidinsert into dish (status, name, category_id, price, image, description, create_time, update_time, create_user,update_user)values (#{status}, #{name}, #{categoryId}, #{price}, #{image}, #{description}, #{createTime}, #{updateTime},#{createUser}, #{updateUser})
/insert insert idinsertBatchinsert into dish_flavor(dish_id, name, value) valuesforeach collectionflavors itemdishFlavor separator,(#{dishFlavor.dishId},#{dishFlavor.name},#{dishFlavor.value})/foreach
/insert
功能测试
可以通过接口文档进行测试也可以进行前后端联调测试
菜品分页查询
需求分析和设计
产品原型 业务规则 根据页码展示菜品信息每页展示10条数据分页查询时可以根据需要输入菜品名称、菜品分类、菜品状态进行查询 接口设计
代码开发
根据菜品分页查询接口定义设计对应的DTO
Data
public class DishPageQueryDTO implements Serializable {private int page;private int pageSize;//菜品名称private String name;//分类idprivate Integer categoryId;//状态 0表示禁用 1表示启用private Integer status;}
根据菜品分页查询接口定义设计对应的VO
public class DishVO 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 LocalDateTime updateTime;//分类名称private String categoryName;//菜品关联的口味private ListDishFlavor flavors new ArrayList();}
根据接口定义创建DishController的page分页查询方法
如果前端是通过 URL 的查询字符串query string或路径变量path variables来传递数据的比如 GET 请求中的参数那么在后端就不需要使用 RequestBody
在 DishService 中扩展分页查询方法
在 DishServiceImpl 中实现分页查询方法
在 DishMapper 接口中声明 pageQuery 方法
在 DishMapper.xml 中编写SQL
功能测试
可以通过接口文档进行测试最后完成前后端联调测试即可
删除菜品
需求分析和设计
产品原型 业务规则 可以一次删除一个菜品也可以批量删除菜品起售中的菜品不能删除被套餐关联的菜品不能删除删除菜品后关联的口味数据也需要删除掉 接口设计 数据库设计
代码开发 创建SetmealDishMapper声明getSetmealIdsByDishIds方法并在xml文件中编写SQL
在DishMapper.xml中声明deleteById方法并配置SQL
在DishFlavorMapper中声明deleteByDishId方法并配置SQL
功能测试
通过Swagger接口文档进行测试通过后再前后端联调测试即可
修改菜品
需求分析和设计
产品原型 接口设计 • 根据 id 查询菜品 • 根据类型查询分类已实现 • 文件上传已实现 • 修改菜品 根据id查询菜品 修改菜品 代码开发
根据id查询菜品 接口开发
根据id查询菜品 接口开发
修改菜品 接口开发
功能测试
通过Swagger接口文档进行测试通过后再前后端联调测试即可 上一节
员工管理、分类管理day02-CSDN博客
下一节