苍穹外卖项目---------收获以及改进(3-4天)

①公共字段填充----mybatis

第一步:自定义注解
/**
 * 自定义注解用于标识某个方法需要进行功能字段的填充
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {

    //枚举:数据库操作类型: update insert
    OperationType value();
}

 枚举类:

/**
 * 数据库操作类型
 */
public enum OperationType {

    /**
     * 更新操作
     */
    UPDATE,

    /**
     * 插入操作
     */
    INSERT

}
第二步:自定义切面类
/**
 * 自定义切面,实现公共字段自动填充处理逻辑
 */
@Aspect
@Component
@Slf4j
public class AutoFillAspect {

    /**
     * 切入点
     */
    //指定拦截哪些mapper类    拦截所有的mapper中的所有方法 && 方法上加入了自定义注解的方法
    @Pointcut("execution(* com.sky.service.*.*(..)) && @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 {
                //获得属性的set方法
                Method setCreatTime = entity.getClass().getDeclaredMethod("setCreatTime", LocalDateTime.class);
                Method setCreateUser = entity.getClass().getDeclaredMethod("setCreateUser", Long.class);
                Method setUpdateTime = entity.getClass().getDeclaredMethod("setUpdateTime", LocalDateTime.class);
                Method setUpdateUser = entity.getClass().getDeclaredMethod("setUpdateUser", Long.class);
                //反射赋值
                setCreatTime.invoke(entity,now);
                setCreateUser.invoke(entity,currentId);
                setUpdateTime.invoke(entity,now);
                setUpdateUser.invoke(entity,currentId);
            } catch (Exception e) {
                e.printStackTrace();
            }

        }else if (operationtype == OperationType.UPDATE){
            //为两个公共字段赋值
            try {
                //获得属性的set方法
                Method setUpdateTime = entity.getClass().getDeclaredMethod("setUpdateTime", LocalDateTime.class);
                Method setUpdateUser = entity.getClass().getDeclaredMethod("setUpdateUser", Long.class);
                //反射赋值
                setUpdateTime.invoke(entity,now);
                setUpdateUser.invoke(entity,currentId);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }


    }
}
第三步:在mapper层的方法上加上我们的自定义注解以及类型

②公共字段填充----mybatisPlus

第一步:字段上添加注解
    @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;
第二步:编写元数据处理类
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.sky.context.BaseContext;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;

//元数据处理器
@Component
@Slf4j
public class MyMetaObjecthandler implements MetaObjectHandler    {
    @Override
    public void insertFill(MetaObject metaObject) {

        log.info("公共字段自动填充---新增 :{}",metaObject);
        //设置数据
        metaObject.setValue("createTime",LocalDateTime.now());
        metaObject.setValue("createUser",BaseContext.getCurrentId());
        metaObject.setValue("updateTime", LocalDateTime.now());
        metaObject.setValue("updateUser", BaseContext.getCurrentId());
    }

    @Override
    public void updateFill(MetaObject metaObject) {

        log.info("公共字段自动填充---更新 :{}",metaObject);
        //设置数据
        metaObject.setValue("updateTime", LocalDateTime.now());
        metaObject.setValue("updateUser", BaseContext.getCurrentId());

    }
}

 这样就可以实现mybatisPlus的公共字段填充,之后在写实体类的相关字段时就可以不用自己去set,用这个控制器去自动完成可以

③阿里云OSS----文件上传

前端上传:

后端接收:

后端进行文件存储-----存储在本地(transferTo):

后端进行文件存储-----存储在云(阿里云OSS,object storage service)

 

第一步:引入依赖
<dependency>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>aliyun-sdk-oss</artifactId>
    <version>3.15.1</version>
</dependency>

//如果java 版本9以上则要添加以下依赖
<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.3.1</version>
</dependency>
<dependency>
    <groupId>javax.activation</groupId>
    <artifactId>activation</artifactId>
    <version>1.1.1</version>
</dependency>
<!-- no more than 2.3.3-->
<dependency>
    <groupId>org.glassfish.jaxb</groupId>
    <artifactId>jaxb-runtime</artifactId>
    <version>2.3.3</version>
</dependency>
第二步:改配置,存文件
        // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        // 填写Bucket名称,例如examplebucket。
        String bucketName = "examplebucket";
        // 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
        String objectName = "exampledir/exampleobject.txt";
        // 填写本地文件的完整路径,例如D:\\localpath\\examplefile.txt。
        // 如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件流。
        String filePath= "D:\\localpath\\examplefile.txt";

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);

        try {
            InputStream inputStream = new FileInputStream(filePath);
            // 创建PutObjectRequest对象。
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, inputStream);
            // 创建PutObject请求。
            PutObjectResult result = ossClient.putObject(putObjectRequest);
        } 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();
            }
        }
第三步:集成!!!!!!!!!

 引入工具类:这个工具类是用来把上传这个动作封装的,之后使用的画就直接把(文件,上传到云端保存的文件名)传入就可以实现上传功能,而其返回的数据就是文件在云端的访问地址

@Data
@AllArgsConstructor
@Slf4j
public class AliOssUtil {

    private String endpoint;
    private String accessKeyId;
    private String accessKeySecret;
    private String bucketName;

    /**
     * 文件上传
     *
     * @param bytes
     * @param objectName
     * @return
     */
    public String upload(byte[] bytes, String objectName) {

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        try {
            // 创建PutObject请求。
            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();
            }
        }

        //文件访问路径规则 https://BucketName.Endpoint/ObjectName
        StringBuilder stringBuilder = new StringBuilder("https://");
        stringBuilder
                .append(bucketName)
                .append(".")
                .append(endpoint)
                .append("/")
                .append(objectName);

        log.info("文件上传到:{}", stringBuilder.toString());

        return stringBuilder.toString();
    }
}

配置云端密钥信息

  alioss:
    endpoint: oss-cn-beijing.aliyuncs.com
    access-key-id: LTAI5t7HRcgiCBRrRfPkzo6f
    access-key-secret: XZOMsLJdTaZvKHKW5qS55nQrhh95Bf
    bucket-name: zzl-test-01

 封装一个实体类去加载我们的yml中的数据

@Component
@ConfigurationProperties(prefix = "sky.alioss")
@Data
public class AliOssProperties {

    private String endpoint;
    private String accessKeyId;
    private String accessKeySecret;
    private String bucketName;

}

创建一个配置类,去创建工具类对象并交给bean容器管理

/**
 * 配置类
 */
@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());
    }
}

在接口中使用OSS工具类

@PostMapping("/upload")
    @ApiOperation("文件上传")
    public Result<String> upload(MultipartFile file){
        log.info("文件上传");
        try {
            //原始文件名
            String originalFilename = file.getOriginalFilename();
            //截取原始文件的类型,即获得文件的拓展名
            String extention = originalFilename.substring(originalFilename.lastIndexOf("."));
            String objectname = UUID.randomUUID().toString() + extention;
            
            //把文件的二进制形式和存储到云端的名字传给工具类,返回在云端的访问路径
            String filePath = aliOssUtil.upload(file.getBytes(), objectname);
            //把文件路径返回
            return Result.success(filePath);
        } catch (IOException e) {
            log.error("文件上传失败:{}",e);
        }

        return Result.error("文件上传失败");
    }

④mp多表联合分页查询,很硬但可以

 先展示一下自己实在直接硬搬代码的蠢办法,连多表查询都不需要:

public PageResult page(DishPageQueryDTO dishPageQueryDTO) {

        //创建Ipage对象
        IPage page = new Page(dishPageQueryDTO.getPage(),dishPageQueryDTO.getPageSize());

        //创建QueryWrapper对象进行条件筛选
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq(dishPageQueryDTO.getCategoryId() != null,"category_id",dishPageQueryDTO.getCategoryId())
                .like(dishPageQueryDTO.getName() != null,"name",dishPageQueryDTO.getName())
                .eq(dishPageQueryDTO.getStatus() != null,"status",dishPageQueryDTO.getStatus());

        //进行查询
        dishMapper.selectPage(page, wrapper);


        List<Dish> records = page.getRecords();
        List<DishVO> dishVOS = new ArrayList<>();
        List<Category> name =new ArrayList<>();
        records.forEach(dish -> {
            DishVO dishVO = new DishVO();
            BeanUtils.copyProperties(dish,dishVO);
            dishVOS.add(dishVO);
            name.add(categoryService.query().eq("id",dish.getCategoryId()).select("name").one());
        });

        for(int i=0;i< dishVOS.size();i++){
            dishVOS.get(i).setCategoryName(name.get(i).getName());
        }


        //返回数据
        return new PageResult(page.getTotal(),dishVOS);
    }

不过再看了瑞吉外面的实现方法确实跟我这个差不了太多,都是直接把id提取出来去查过再放进链表中

        List<Dish> records = page.getRecords();
        List<DishVO> dishVOS = records.stream().map((item) -> {
            DishVO dishVO = new DishVO();
            BeanUtils.copyProperties(item, dishVO);

            Category byId = categoryService.getById(item.getCategoryId());
            dishVO.setCategoryName(byId.getName());

            return dishVO;
        }).collect(Collectors.toList());

        return  new PageResult(page.getTotal(),dishVOS);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值