前言 最近学习又有点懈怠了,想找个学习搭子一起互相督促学习。今天继续跟着黑马程序员的课程敲全栈项目。
公共字段自动填充 需求
自定义注解AutoFill,用于标识需要进行公共字段自动填充的方法
自定义切面类AutoFillAspect,统一拦截加入了AutoFill注解的方法,通过反射为公共字段赋值
在Mapper的方法上加入AutoFill注解
代码 添加maven依赖 1 2 3 4 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-aop</artifactId > </dependency >
添加自定义注解 注意这个文件类型是注解 com.sky.annotation.AutoFill
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 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 () ; }
添加切面类 com.sky.aspect.AutoFillAspect
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 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.MemberSignature;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 () {} @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 now = LocalDateTime.now(); Long currentId = BaseContext.getCurrentId(); if (operationType == OperationType.INSERT){ try { Method setCreateTimes = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class); Method setCreateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class); Method setUpdateTimes = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class); Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class); setCreateTimes.invoke(entity,now); setCreateUser.invoke(entity,currentId); setUpdateTimes.invoke(entity,now); setUpdateUser.invoke(entity,currentId); }catch (Exception e){ e.printStackTrace(); } }else if (operationType== OperationType.UPDATE){ try { Method setUpdateTimes = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class); Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class); setUpdateTimes.invoke(entity,now); setUpdateUser.invoke(entity,currentId); }catch (Exception e){ e.printStackTrace(); } } } }
在Mapper的方法上加入AutoFill注解 update就加上@AutoFill(OperationType.UPDATE),insert就加上@AutoFill(OperationType.INSERT)
1 2 @AutoFill(OperationType.UPDATE) void update (Category category) ;
注释掉原来的service层的赋值时间和用户的代码 就类似这样
测试效果 我修改了一个员工,时间也自动更新了
新增菜品 阿里云上传图片 配置阿里云 这个首先你要有阿里云的存储OSS,这个很便宜,新账号也有免费体验,反正你就是要搞到
登录进去 首先你先登录进去,按照图示操作
创建用户
创建完成之后 你会得到AccessKeyID和AccessKeySecret,记录下来
创建Bucket 记得设置成可以公开访问的,是否公开写倒没啥关系
创建完成之后 你会得到Bucket名称,记录下来
配置你创建用户的权限
java代码部分
添加maven依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <dependency > <groupId > com.aliyun.oss</groupId > <artifactId > aliyun-sdk-oss</artifactId > <version > 2.4.0</version > </dependency > <dependency > <groupId > commons-fileupload</groupId > <artifactId > commons-fileupload</artifactId > <version > 1.3.1</version > </dependency > <dependency > <groupId > org.jdom</groupId > <artifactId > jdom</artifactId > <version > 1.1.3</version > </dependency >
配置yml文件 在yml里面加上,这里取的是dev环境的,我们还需要去dev里面配置详细信息
1 2 3 4 5 alioss: access-key-id: ${sky.alioss.access-key-id} access-key-secret: ${sky.alioss.access-key-secret} bucket-name: ${sky.alioss.bucket-name} endpoint: ${sky.alioss.endpoint}
dev-yml,这里填入你自己阿里云的信息
1 2 3 4 5 alioss: access-key-id: xxxx access-key-secret: xxxxx bucket-name: codesigner-test-oss endpoint: oss-cn-hangzhou.aliyuncs.com
配置工具类 配置工具类读取配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 package com.sky.config;import com.sky.properties.AliOssProperties;import com.sky.utils.AliOssUtil;import lombok.extern.slf4j.Slf4j;import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configuration @Slf4j public class OssConfiguration { @Bean @ConditionalOnMissingBean public AliOssUtil aliOssUtil (AliOssProperties aliOssProperties) { log.info("开始上传阿里云文件上传工具类:{}" ,aliOssProperties); return new AliOssUtil ( aliOssProperties.getEndpoint(), aliOssProperties.getAccessKeyId(), aliOssProperties.getAccessKeySecret(), aliOssProperties.getBucketName() ); } }
配置controller
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 package com.sky.controller.admin;import com.sky.result.Result;import com.sky.utils.AliOssUtil;import io.swagger.annotations.Api;import io.swagger.annotations.ApiOperation;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.multipart.MultipartFile;import java.io.IOException;import java.util.UUID;@RestController @RequestMapping("/admin/common") @Api(tags="通用接口") @Slf4j public class CommonController { @Autowired private AliOssUtil aliOssUtil; @PostMapping("/upload") @ApiOperation("文件上传") public Result<String> upload (MultipartFile file) { log.info("文件上传:{}" ,file); try { String originalFilename = file.getOriginalFilename(); String extension=originalFilename.substring(originalFilename.lastIndexOf("." )); String objectName= UUID.randomUUID()+extension; String filePath = aliOssUtil.upload(file.getBytes(),objectName); return Result.success(filePath); } catch (IOException e) { log.error("文件上传失败:{}" ,e); } return Result.error(MessageConstant.UPLOAD_FAILED); }
配置上传方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 package com.sky.utils;import com.aliyun.oss.ClientException;import com.aliyun.oss.OSS;import com.aliyun.oss.OSSClientBuilder;import com.aliyun.oss.OSSException;import lombok.AllArgsConstructor;import lombok.Data;import lombok.extern.slf4j.Slf4j;import java.io.ByteArrayInputStream;@Data @AllArgsConstructor @Slf4j public class AliOssUtil { private String endpoint; private String accessKeyId; private String accessKeySecret; private String bucketName; public String upload (byte [] bytes, String objectName) { OSS ossClient = new OSSClientBuilder ().build(endpoint, accessKeyId, accessKeySecret); try { 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(); } } StringBuilder stringBuilder = new StringBuilder ("https://" ); stringBuilder .append(bucketName) .append("." ) .append(endpoint) .append("/" ) .append(objectName); log.info("文件上传到:{}" , stringBuilder.toString()); return stringBuilder.toString(); } }
效果
Your browser does not support the video tag.
controller 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 package com.sky.controller.admin;import com.sky.dto.DishDTO;import com.sky.result.Result;import com.sky.service.DishService;import io.swagger.annotations.Api;import io.swagger.annotations.ApiOperation;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestController @RequestMapping("/admin/dish") @Api(tags="菜品相关接口") @Slf4j public class DishController { @Autowired private DishService dishService; @PostMapping @ApiOperation("新增菜品") public Result save (@RequestBody DishDTO dishDTO) { log.info("新增菜品:{}" ,dishDTO); dishService.saveWithFlavor(dishDTO); return Result.success(); } }
service 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 package com.sky.service;import com.sky.dto.DishDTO;public interface DishService { public void saveWithFlavor (DishDTO dishDTO) ; }
serviceImpl 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 package com.sky.service.impl;import com.sky.dto.DishDTO;import com.sky.entity.Dish;import com.sky.entity.DishFlavor;import com.sky.mapper.DishFlavorMapper;import com.sky.mapper.DishMapper;import com.sky.service.DishService;import lombok.extern.slf4j.Slf4j;import lombok.val;import org.springframework.beans.BeanUtils;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Transactional;import java.util.List;@Service @Slf4j public class DishServiceImpl implements DishService { @Autowired private DishMapper dishMapper; @Autowired private DishFlavorMapper dishFlavorMapper; @Override @Transactional public void saveWithFlavor (DishDTO dishDTO) { Dish dish=new Dish (); BeanUtils.copyProperties(dishDTO,dish); dishMapper.insert(dish); Long dishId=dish.getId(); List<DishFlavor> flavors= dishDTO.getFlavors(); if (flavors!=null && flavors.size()>0 ){ flavors.forEach(dishFlavor -> { dishFlavor.setDishId(dishId); }); dishFlavorMapper.insertBatch(flavors); } } }
mapper DishMapper
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 package com.sky.mapper;import com.sky.annotation.AutoFill;import com.sky.entity.Dish;import com.sky.entity.DishFlavor;import com.sky.enumeration.OperationType;import org.apache.ibatis.annotations.Mapper;import org.apache.ibatis.annotations.Select;import java.util.List;@Mapper public interface DishMapper { @Select("select count(id) from dish where category_id = #{categoryId}") Integer countByCategoryId (Long categoryId) ; @AutoFill(OperationType.INSERT) void insert (Dish dish) ; }
DishFlavorMapper
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 package com.sky.mapper;import com.sky.entity.DishFlavor;import org.apache.ibatis.annotations.Mapper;import org.springframework.stereotype.Service;import java.util.List;@Mapper public interface DishFlavorMapper { void insertBatch (List<DishFlavor> flavors) ; }
xml DishMapper.xml 这里添加了useGeneratedKeys
, keyProperty
这两个属性,这样可以在执行完这个sql之后将主键返回,主键值为id,这时候在实现类中的 Long dishId=dish.getId();才能够有作用
1 2 3 4 5 6 7 8 9 10 11 <?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 >
DishFlavorMapper.xml
1 2 3 4 5 6 7 8 9 10 11 12 <?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 >
测试结果 成功将菜品和口味插入到数据库
分页查询菜品 controller 1 2 3 4 5 6 7 8 9 10 11 @GetMapping("/page") @ApiOperation("菜品分页查询") public Result<PageResult> page (DishPageQueryDTO dishPageQueryDTO) { log.info("菜品分页查询:{}" ,dishPageQueryDTO); PageResult pageResult=dishService.pageQuery(dishPageQueryDTO); return Result.success(pageResult); }
service 1 2 3 4 5 PageResult pageQuery (DishPageQueryDTO dishPageQueryDTO) ;
serviceImpl 1 2 3 4 5 6 7 8 9 10 * 菜品分页查询 * * @param dishPageQueryDTO */ 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 1 2 3 4 5 6 Page<DishVO> pageQuery (DishPageQueryDTO dishPageQueryDTO) ;
xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <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 >
删除菜品 controller 1 2 3 4 5 6 7 @DeleteMapping @ApiOperation("菜品批量删除") public Result delete (@RequestParam List<Long> ids) { log.info("菜品批量删除:{}" ,ids); dishService.deleteBatch(ids); return Result.success(); }
service 1 2 3 4 5 void deleteBatch (List<Long> ids) ;
serviceImpl 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 @Transactional 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> setmealIds=setmealDishMapper.getSetmealIdsByDishIds(ids); if (setmealIds!=null && setmealIds.size()>0 ){ throw new DeletionNotAllowedException (MessageConstant.DISH_BE_RELATED_BY_SETMEAL); } dishFlavorMapper.deleteByDishIds(ids); dishMapper.deleteByIds(ids); }
DishMapper 1 2 3 4 5 6 7 8 @Delete("delete from dish where id = #{id}") void deleteById (Long id) ;void deleteByIds (List<Long> ids) ;
DishMapperXml 1 2 3 4 5 6 <delete id="deleteByIds"> delete from dish where id in <foreach collection="ids" separator="," open="(" close=")" item="id"> #{id} </foreach> </delete>
DishFlavorMapper 1 2 3 4 5 6 7 8 @Delete("delete from dish_flavor where dish_id=#{dishId}") void deleteByDishId (Long dishId) ; void deleteByDishIds (List<Long> dishIds) ;
DishFlavorMapperXml 1 2 3 4 5 6 <delete id ="deleteByDishIds" > delete from dish_flavor where dish_id in <foreach collection ="dishIds" open ="(" close =")" separator ="," item ="dishId" > #{dishId} </foreach > </delete >
SetmealDishMapper 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 package com.sky.mapper;import org.apache.ibatis.annotations.Mapper;import java.util.List;@Mapper public interface SetmealDishMapper { List<Long> getSetmealIdsByDishIds (List<Long> dishIds) ; }
SetmealDishMapperXml 1 2 3 4 5 6 7 8 9 10 11 <?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 >
捕获异常 1 2 3 4 5 @ExceptionHandler public Result exceptionHandler (DeletionNotAllowedException ex) { String message=ex.getMessage(); return Result.error(message); }
菜品编辑 根据id查询 controller 1 2 3 4 5 6 7 8 9 10 11 @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 1 2 3 4 5 DishVO getByIdWithFlavor (Long id) ;
serviceImp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @Override public DishVO getByIdWithFlavor (Long id) { Dish dish=dishMapper.getById(id); List<DishFlavor> dishFlavors=dishFlavorMapper.getByDishId(id); DishVO dishVo=new DishVO (); BeanUtils.copyProperties(dish,dishVo); dishVo.setFlavors(dishFlavors); return dishVo; }
mapper 1 2 3 4 5 6 @Select("select * from dish_flavor where dish_id=#{dishId}") List<DishFlavor> getByDishId (Long dishId) ;
编辑 controller 1 2 3 4 5 6 7 @PutMapping @ApiOperation("修改菜品") public Result update (@RequestBody DishDTO dishDTO) { log.info("修改菜品:{}" ,dishDTO); dishService.updateWithFlavor(dishDTO); return Result.success(); }
service 1 2 3 4 5 void updateWithFlavor (DishDTO dishDTO) ;
serviceImp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 @Override @Transactional 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 ) { flavors.forEach(dishFlavor -> { dishFlavor.setDishId(dishDTO.getId()); }); dishFlavorMapper.insertBatch(flavors); } }
mapper 1 2 3 4 5 6 @AutoFill(value=OperationType.UPDATE) void update (Dish dish) ;
xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 <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 >
结语 本篇文章就到这里了,学java好像的确有点累,可能和我基础不扎实在这硬学有关系,不管了,硬着头皮学吧,这个学完了,我估计以后也不太可能会碰java了。债见