设计模式之代理模式实战

该博客介绍了如何实现一个分布式文件代理服务器,利用代理模式将文件上传操作分为阿里云OSS和FastDFS两种实现。阿里云OSS主要用于上传大文件如mp4和avi,而FastDFS则用于上传小文件如png和jpg。博客详细展示了配置文件、接口定义、阿里云及FastDFS的上传实现,以及代理类和控制器的代码。通过代理类,根据文件类型选择合适的上传策略。
摘要由CSDN通过智能技术生成

场景

众所周知,视频类文件size比较大,不适合存在本地,适合存在阿里云OSS,向图片这些小文件,存在本地即可(不展示阿里云和本地文件上传,只展示代理模式的逻辑)。
例图

分布式文件代理服务器实现

实现分析

基于代理模式,我画了一个例图:
在这里插入图片描述
具体实现:
1、FileUpload抽象接口,定义了文件上传方法,分别给它写了2种实现。
2、AliyunOSSFileUpload是将文件上传到aliyunOSS,主要上传mp4和avi的视频大文件。
3、FastdfsFileUpoad是将文件上传到FastDFS,主要上传png/jpg等图片小文件。
4、FileUploadProxy是代理对象,供用户访问,调用了FileUpload的文件上传方法,为用户提供不同文件上传调用。
5、FileController是控制器,用于接收用户提交的文件,并调用代理FileUploadProxy实现文件上传。

因为这里没有购买阿里云服务,所以这里就象征性的实现一下,知道原理就行了,以后遇到了,使用公司的就好了。

实现步骤

yml文件

server:
port: 88888
#指定服务处理指定的文件类型
upload:
filemap:
aliyunOSSFileUpload: mp4,avi
fastdfsFileUpload: png,jpg
#FastDFS配置
fastdfs:
url: http://localhost:788888/
#aliyun
aliyun:
oss:
FileUpload接口定义:
AliyunOSSFileUpload实现:
endpoint: oss-cn-shanghia.aliyuncs.com
accessKey: xxxxx
accessKeySecret: xxxxxxxx
bucketName: xxx
key: video/
backurl: xxxxxxxx
#访问地址配置
spring:
servlet:
multipart:
max-file-size: 100MB #上传文件大小配置

FileUpload接口:

public interface FileUpload {

    /**
     * 上传方法
     * @param bytes 文件字节数组
     * @param extName 文件后缀名
     * @return
     */
    String upload(byte[] bytes,String extName);
}

上传阿里云一系列操作:
工具类私信

/**
 * 阿里云上传
 */
@Component(value = "aliyunOSSFileUpload")
public class AliyunOSSFileUpload implements FileUpload {
    @Value("${aliyun.oss.endpoint}")
    private String endpoint;
    @Value("${aliyun.oss.accessKey}")
    private String accessKey;
    @Value("${aliyun.oss.accessKeySecret}")
    private String accessKeySecret;
    @Value("${aliyun.oss.key}")
    private String key;
    @Value("${aliyun.oss.bucketName}")
    private String bucketName;
    @Value("${aliyun.oss.backurl}")
    private String backurl;


    @Override
    public String upload(byte[] bytes, String extName) {
        // 获取随机数
        String fileName = ResultUtil.uuid() + "." + extName;
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKey, accessKeySecret);
        PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, key + fileName,
                new ByteArrayInputStream(bytes));
        // 上传字符串。
        ObjectMetadata objectMetadata = new ObjectMetadata();
        objectMetadata.setContentType(FileUtil.getContentType("." + extName));
        putObjectRequest.setMetadata(objectMetadata);
        ossClient.putObject(putObjectRequest);
        // 关闭OSSClient。
        ossClient.shutdown();
        return backurl + fileName;

    }
}

本地上传

@Component(value = "fastdfsFileUpoad")
public class FastdfsFileUpoad implements FileUpload {
    @Value("${fastdfs.url}")
    private String url;

    /***
     * 初始化tracker信息
     */
    static {
        try {
        //获取tracker的配置文件fdfs_client.conf的位置
            String filePath = new ClassPathResource("fdfs_client.conf").getPath();
            //加载tracker配置信息
            ClientGlobal.init(filePath);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }



    @Override
    public String upload(byte[] bytes, String extName) {
        String[] uploadResults = null;
        try {
                //获取StorageClient对象
            StorageClient storageClient = getStorageClient();
                //执行文件上传
            uploadResults = storageClient.upload_file(bytes, extName, null);
            return url+uploadResults[0]+"/"+uploadResults[1];
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /***
     * 获取StorageClient
     * @return
     * @throws Exception
     */
    public static StorageClient getStorageClient() throws Exception {
    //创建TrackerClient对象
        TrackerClient trackerClient = new TrackerClient();
    //通过TrackerClient获取TrackerServer对象
        TrackerServer trackerServer = trackerClient.getConnection();
    //通过TrackerServer创建StorageClient
        StorageClient storageClient = new StorageClient(trackerServer, null);
        return storageClient;
    }
}

代理类

/**
 * 代理实现
 */
@Data
@Component
@ConfigurationProperties(prefix = "upload")
public class FileUploadProxy implements ApplicationContextAware {
    @Autowired
    private FileUpload aliyunOSSFileUpload;
    @Autowired
    private FileUpload fastdfsFileUpoad;

    private ApplicationContext act;
    // String 方式 list 需要上传的文件类型 例如: 本地 -》 jpg,png
    private Map<String, List<String>> filemap;

    public String upload(MultipartFile file) throws IOException {
        // 文件名字
        String filename = file.getOriginalFilename();
        // 获取文件拓展名
        String extName = StringUtils.getFilenameExtension(filename);
        for (Map.Entry<String, List<String>> entry : filemap.entrySet()){
            List<String> values = entry.getValue();
            for(String value : values){
                if(extName.equalsIgnoreCase(value)){
                    return act.getBean(entry.getKey(),FileUpload.class).upload(file.getBytes(),extName);
                }
            }
        }
        return null;
    }

    //注入容器对象
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws
            BeansException {
        this.act=applicationContext;
    }


}

控制器

@RestController
@RequestMapping(value = "/file")
public class FileController {

    @Autowired
    private FileUploadProxy fileUploadProxy;

    /***
     * 文件上传
     * @param file
     * @return
     * @throws IOException
     */
    @PostMapping(value = "/upload")
    public String upload(MultipartFile file) throws Exception {
        return fileUploadProxy.upload(file);
    }
}

差不多就完成了,明天会更新享元模式,策略模式,状态模式,工厂模式等。
本人才疏学浅,难免有疏漏,如有疏漏,请大佬指出本人必虚心改正。有一些JAVA初学者或者自学者在路上遇到问题,可以私信,我会竭力为你解决一些基本的困惑。谢谢大家观看。

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值