公共字段自动填充 技术点 枚举 自定义注解 AOP切面 反射

java
/**
* 自定义注解 用于标识某个方法需要进行功能字段自动填充处理
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ChengoAutoFill {
//数据库操作类型 UPDATE INSERT
OperationType value();
}
/**
* 自定义切面 实现公共字段自动填充处理逻辑
*/
@Aspect
@Component
@Slf4j
public class ChengoAutoFillAspect {
/**
* 切入点 拦截insert和update操作
*/
@Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.ChengoAutoFill)")
public void autoFillPointCut(){}
/**
* 前置通知 在通知中尽显公共字段的赋值
* @param joinPoint
*/
@Before("autoFillPointCut()")
public void autoFill(JoinPoint joinPoint){
log.info("开始进行公共字段自动填充....");
//获取当前被拦截的方法上的数据库操作类型 反射操作
MethodSignature signature = (MethodSignature) joinPoint.getSignature();//方法签名对象
ChengoAutoFill autoFill = signature.getMethod().getAnnotation(ChengoAutoFill.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(SET_CREATE_TIME, LocalDateTime.class);
Method setCreateUser = entity.getClass().getDeclaredMethod(SET_CREATE_USER, Long.class);
Method setUpdateTime = entity.getClass().getDeclaredMethod(SET_UPDATE_TIME, LocalDateTime.class);
Method setUpdateUser = entity.getClass().getDeclaredMethod(SET_UPDATE_USER, Long.class);
//通过反射为对象属性赋值
setCreateUser.invoke(entity,currentId);
setUpdateUser.invoke(entity,currentId);
setCreateTime.invoke(entity,now);
setUpdateTime.invoke(entity,now);
} catch (Exception e) {
throw new RuntimeException(e);
}
} else if (operationType == OperationType.UPDATE) {
//两个公共字段赋值 修改时间和修改人
try {
Method setUpdateTime = entity.getClass().getDeclaredMethod(SET_UPDATE_TIME, LocalDateTime.class);
Method setUpdateUser = entity.getClass().getDeclaredMethod(SET_UPDATE_USER, Long.class);
//通过反射为对象属性赋值
setUpdateUser.invoke(entity,currentId);
setUpdateTime.invoke(entity,now);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
Mapper里上自定义注解
@ChengoAutoFill(value = OperationType.UPDATE)
void update(Employee employee);
@ChengoAutoFill(value = OperationType.INSERT)
void insert(Employee employee);
增菜品

上传文件需要阿里云oss 配置好自己的信息 写好yml和上传内容即可
java
/**
* 配置类 用于创建AliOssUtil对象
*/
@Configuration
@Slf4j
public class OssConfiguration {
@Bean
@ConditionalOnMissingBean//只创建一个bean 确保程序启动过程中只有一个bean
public AliOssUtil aliOssUtil(AliOssProperties aliOssProperties){
return new AliOssUtil(
aliOssProperties.getEndpoint(),
aliOssProperties.getAccessKeyId(),
aliOssProperties.getAccessKeySecret(),
aliOssProperties.getBucketName()
);
}
}
控制层
@RestController
@RequestMapping("/admin/common")
@Api(tags = "通用接口")
@Slf4j
public class CommonController {
@Autowired
private AliOssUtil aliOssUtil;
/**
* 文件上传
* @param file
* @return
*/
@PostMapping("/upload")
@ApiOperation("文件上传")
public Result<String> upload(@RequestBody MultipartFile file){
log.info("文件上传:{}",file);
try {
//取出原始文件名
String originalFilename = file.getOriginalFilename();
//截取原始文件名的后缀 。。。。.png .jpg
String substring = originalFilename.substring(originalFilename.lastIndexOf("."));
//构建新文件名称
String objectName = UUID.randomUUID().toString() + substring;
//文件请求连接
String filePath = aliOssUtil.upload(file.getBytes(), objectName);
return Result.success(filePath);
} catch (IOException e) {
log.error("文件上传失败:{}",e);
}
return Result.error(MessageConstant.UPLOAD_FAILED);
}
}
上面是怎么上传文件 下面的新增菜品让我烦了好长一段时间 总结经验 不能边看边敲 需要看明白再回来思考 并自己先敲

这个问题折腾了我一个小时 第二次犯了 sql语句写的封装类对象里不能用下划线 并且必须驼峰命名
查询

这里有个VO设计
在这个模块上花了三个小时左右,, 就是因为我服务器太久没动宕机了 很崩溃 不想做了
还是继续做吧'、、、、、、、、、、
删除菜品
java
控制层
/**
* 菜品批量删除
* @param ids
* @return
*/
@DeleteMapping
@ApiOperation("菜品批量删除")
public Result delete(@RequestParam List<Long> ids){
log.info("菜品批量删除:{}",ids);
dishService.deleteBatch(ids);
return Result.success();
}
@Mapper 持久层
public interface SetmealDishMapper {
/**
* 根据菜品id查找套餐id
* @param dishIds
* @return
*/
List<Long> getSetmealIdsByDishIds(List<Long> dishIds);
}
业务实现层
/**
* 菜品批量删除
* @param ids
*/
@Override
public void deleteBatch(List<Long> ids) {
//当前菜品是否能够删除 是否起售
for (Long id : ids) {
Dish dish = dishMapper.getById(id);
if(dish.getStatus() == StatusConstant.ENABLE){
//起售中 不能删除
throw new DeletionNotAllowedException(MessageConstant.DISH_ON_SALE);
}
}
//判断当餐票是否能被删除 --是否被套餐关联
List<Long> setmealIdsByDishIds = setmealDishMapper.getSetmealIdsByDishIds(ids);
if(setmealIdsByDishIds != null && setmealIdsByDishIds.size() > 0){
//当前菜品被套餐关联 不能删除
throw new DeletionNotAllowedException(MessageConstant.DISH_BE_RELATED_BY_SETMEAL);
}
//删除菜品表中的菜品数据
for (Long id : ids) {
dishMapper.deleteById(id);
//删除口味表里的口味数据
dishFlavorMapper.deleteById(id);
}
要删除菜品与其连带的口味数据
/**
* 根据id主键删菜品
* @param id
*/
@Delete("delete from dish where id = #{id};")
void deleteById(Long id);
/**
* 根据菜品id来删口味数据
* @param dishIds
*/
@Delete("delete from dish_flavor where dish_id = #{dishIds}")
void deleteById(Long dishIds);

改菜品

根据id查询菜品 需要分两次查询 第一次查询dish菜品 第二次查询菜品关联的口味
java
业务层
/**
* 根据id查询菜品和对应的口味数据
* @param id
* @return
*/
@Override
public DishVO getByIdWithFlavor(Long id) {
//根据id查询菜品数据
Dish dish = dishMapper.getById(id);
//根据菜品id查询口味数据
List<DishFlavor> dishFlavors = dishFlavorMapper.getByDishId(id);
//把查询到的数据封装到VO
DishVO dishVO = new DishVO();
BeanUtils.copyProperties(dish,dishVO);
dishVO.setFlavors(dishFlavors);
return dishVO;
}
*************************************************
接口层
/**
* 根据id查询菜品和对应的口味数据
* @param id
* @return
*/
DishVO getByIdWithFlavor(Long id);
*************************************************
控制层
@GetMapping("/{id}")
@ApiOperation("根据id查询菜品·")
public Result<DishVO> getById(@PathVariable Long id){
log.info("根据id查询菜品:{}",id);
DishVO dishVO = dishService.getByIdWithFlavor(id);
return Result.success(dishVO);
}
*************************************************
Mapper层
/**
* 根据菜品id查询口味数据
* @param dishId
* @return
*/
@Select("select * from dish_flavor where dish_id = #{dishId}")
List<DishFlavor> getByDishId(Long dishId);
/**
* 查询菜品
* @param id
* @return
*/
@Select("select * from dish where id = #{id}")
Dish getById(Long id);
在这写修改的时候 把控制层的内容写到实体类里了,, 还好发现了
继续加油