【java+设计模式】

【前言】

  文件上传走到后台的时候需要填充文件的类型、不同的类型对文件大小有不同的限制,这个if写的话很快但是不太好,想起了策略模式,上网查了一些资料,网上的资料挺多但是…… 怎么说? 看博客或者论坛 感觉思路清晰、逻辑连贯、一气呵成、无可挑剔、废不多话、进入正题

【正文】

   之前写过类似的博客,当然只是说了想法和思路,今天就来代码实践一下吧(本脑跑成功了,泥萌的—自求多福、开玩笑开玩笑)

    

首先将上传资源的分类提取出来结合自定义的类型和标明此类文件最大值的字段

    

上面的主体是我自定义的注解,下面以音频为例看一下文件类型相关的类

@ResourceVerify(maxSize =10485760,type = "audio")//自定义注解
public class Audio implements Type {
    @Override
    public String typeName() {
        //请不要使用中文,音频 二字是错误的示范
        return "音频".trim();
    }
}

判断文件类型及大小,如果符合要求则返回文件类型名称:

package com.giska.resource.tool;

import com.giska.resource.tool.type.ResourceVerify;
import com.giska.resource.tool.type.Type;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by Administrator on 2018/5/25.
 */
@Component
public class GetType {

    private String packageName = "com.giska.resource.tool.type";//上面所述对象所在的包,需要读取包下的类

    private ClassLoader classLoader = getClass().getClassLoader();
    //策略列表 
    private List<Class<? extends Type>> typeList;

    public String resourceType(File file) throws IOException {

        Path path = Paths.get(file.getPath());//获取文件的路径
        String contentType = Files.probeContentType(path);//根据路径获取文件的contentType audio vudio  image ……

        //遍历策略列表
        for (Class<? extends Type> type : typeList) {
            //获取该策略的注解
            ResourceVerify resourceVerify = handleAnnotation(type,contentType);
           if( contentType.contains(resourceVerify.type())){//判断是否是当前Type类的类型
               //是的话我们返回一个当前策略的实例 名称
               if (file.length() < resourceVerify.maxSize()) {
                   try {
                       return type.newInstance().typeName();
                   } catch (Exception e) {
                       e.printStackTrace();
                       throw new RuntimeException("获取类型失败");
                   }
               }else {
                   return "资源大小超过限制了!";
               }
           }
        }
        throw new RuntimeException("获取类型失败");
    }

    /**
     * 处理注解,我们传入一个策略类,返回它的注解
     *
     * @param type
     * @return
     */
    private ResourceVerify handleAnnotation(Class<? extends Type> type,String contentType) {
        Annotation[] annotations = type.getDeclaredAnnotations();//获取类上的注解
        if (annotations == null || annotations.length == 0) {
            return null;
        }
        for (int i = 0; i < annotations.length; i++) {
            if (annotations[i] instanceof ResourceVerify) {
                return (ResourceVerify) annotations[i];//返回注解
            }
        }
        return null;
    }

    public GetType() throws Exception {
        typeList = new ArrayList<Class<? extends Type>>();
        List<Class<?>> list = null;
        File[] resource = getResource(list);//获取文件列表
        Class<Type> typeClass = null;
        //使用相同的加载器加载策略接口
        try {
            typeClass = (Class<Type>) classLoader.loadClass(Type.class.getName());
        } catch (ClassNotFoundException e) {
            throw new RuntimeException("未找到资源类型");
        }
        for (int i = 0; i < resource.length; i++) {
            try {
                //载入包下的类
                Class<?> clss = classLoader.loadClass(packageName + "." + resource[i].getName().replace(".java", ""));
                //判断是否是CalPrice的实现类并且不是CalPrice它本身,满足的话加入到策略列表
                if (Type.class.isAssignableFrom(clss) && clss != typeClass) {
                    typeList.add((Class<? extends Type>) clss);
                }
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 扫描包下所有的class文件
     *
     * @return
     */
    private File[] getResource(List<Class<?>> list) throws Exception {
        File file = new File("");
        String path = file.getCanonicalPath() + File.separator + "src\\main\\java." + packageToDir();
        File dir = new File(path);
        return dir.listFiles();
    }

    public  String packageToDir() {
        String[] array = packageName.split("\\.");//写成路径的形式
        StringBuffer sb = new StringBuffer();
        for (String s : array) {
            sb.append(File.separator).append(s);
        }
        return sb.toString();
    }


}

开始获取包下的文件很是费劲,不过问题使我们成长嘛,查了一下东西,记录下来:

 

File.

    list()返回某个目录下所有文件和目录的文件名,返回string数组

    listFiles()返回某个目录下所有文件和目录的绝对路径,返回file数组

    https://www.cnblogs.com/keyi/p/6293141.html

 

    Separator:用来分隔同一路径字符串中的目录,window下路径分隔符\和Linux的/是不一样的

       考虑跨平台:File myFile = new File("C:" + File.separator + "tmp" + File.separator, "test.txt");

       pathSeparatorChar:与系统有关的路径分隔符,用于分隔以路径列表形式给定的文件序列中的文件名,unix系统字段为: windows为;

    https://blog.csdn.net/chindroid/article/details/7735832

    https://blog.csdn.net/spy19881201/article/details/6218722

    简单来说separator是 \ 或 /  pathSeparatorChar是; 或 : 分平台

    getPath()返回的是构造方法里的路径,不做任何处理

    getAbsolutePath()返回的是执行路径加上构造方法中的路径

    getCanonicalPath()返回的是将符号完全解析的路径,也就是全路径

File f = new File("..\\src\\file");

System.out.println(f.getPath());

System.out.println(f.getAbsolutePath());

System.out.println(f.getCanonicalPath());
//打印结果
 ..\src\file

C:\workspace\Tip\..\src\file

C:\workspace\src\file

    https://www.cnblogs.com/xulianbo/archive/2011/08/26/2154027.html

    isFile():当且仅当此抽象路径名表示的文件存在且是一个标准文件时,返回true;否则返回false;

    Exists()当且仅当此抽象路径名表示的文件或目录存在时,返回true;否则返回false;

    isFile():判断是否文件,也许可能是文件或者目录

    exists():判断是否存在,可能不存在

    isDirectory()是检查一个对象是否是文件夹,如果是返回true,否则返回false。

    调用方法为:对象.isDirectory()  无需指定参数。

    https://www.cnblogs.com/zhengbiyu/p/8391201.html

 修改2018年5月29日09:26:45

        getCanonicalPath()这个单元测试的时候是可以的,上图为证:

论坛 :https://bbs.csdn.net/topics/390716276 

 

【小结】

        设计模式很好的解耦,以后添加类型也不需要动代码,但是目测类型改动可能性很小,这套代码一些过度设计的味道所以项目中没有使用;最近看源码、设计模式真是被用炉火纯青,按捺不住也想写这么一套代码的码农心,加油ヾ(◍°∇°◍)ノ゙ 

 

设计模式学习之策略模式   欢迎大家一起交流,一起进步

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值