资源读取

资源读取是个很广的说法,开发中涉及到的资源读取有哪些?我总结了以下内容。

前端访问后端的静态资源

前端访问后端的静态资源说的就是springboot的静态资源映射,之前有写过相关的博客,这里复习总结一遍
静态资源映射指的是当用户发出请求的时候,服务器端应该按照哪些规则查找静态资源返回给用户。

下面是springboot中涉及到资源映射的知识点

  • springboot中默认存放静态资源的位置
    当前端请求是一个请求静态资源文件时,springboot会在resources目录下的这四种目录中查找静态资源文件

    "classpath:/META‐INF/resources/", 
    "classpath:/resources/",
    "classpath:/static/",
    "classpath:/public/"
    
    classpath指的是target下classes目录,因为程序在编译后会将src下的java目录,resources目录中
    的文件放到target下classes目录中,所以一般在路径中会加上classpath
    
    上面4个路径说的是,springboot会在resources目录下的META-INF/resources目录
    resources目录,static目录,public目录中查找静态资源文件

    例如,前端请求:http://localhost:8080/wanyi.png,则springboot会依次查找上面四个目录下有无资源文件

  • 自定义请求资源路径,自定义静态资源目录

    • 自定义请求资源路径
      上面我们可以看到请求静态资源路径是根目录,即/wanyi.png,这样做其实并不太好,
      开发中常把所有资源文件都映射到某个路径之下,例如如果我是访问静态资源,
      我需要请求/static/wanyi.png,使得所有静态资源请求都携带一个static路径
      这就需要我们自定义请求资源路径了

      我们有两种方式实现自定义请求资源路径

      1. 直接在springboot配置文件中配置:

        spring:
          mvc:
            static-path-pattern: /static/**		#默认是/**
      2. 实现WebMvcConfigurer接口,重写addResourceHandlers

        @Configuration
        public class WebMvcConfig implements WebMvcConfigurer {
         
            @Override
            public void addResourceHandlers(ResourceHandlerRegistry registry) {
                registry.addResourceHandler("/static/**") //过滤策略
                        .addResourceLocations("classpath:/static/"); // 静态资源路径
                /*
                	classpath:/static/,表示去resources目录下static目录下找静态资源文件
                      你也可以配置.addResourceLocations("file:"+"d:/voice/");
                      即收到请求后去本地相应目录下去寻找资源文件
                      这个路径还可以配置到springboot配置文件中,不必写死
                  */
            }
        }
        /*
        	这里配置的是:请求如果带有/static/**路径,则去resources目录下static目录下查找
        	仔细想想,我这里还可以去改成resources目录下其他文件夹中查找静态资源文件
        */
    • 自定义静态资源目录
      其实上面已经写了,如果我们想把静态资源放其他文件夹,不想把静态资源文件放在上面四个目录
      你可以配置springboot配置文件如下:

      # 自定义静态资源访问路径,可以指定多个,之间用逗号隔开
      spring.resources.static-locations=classpath:/myabc/,classpath:/myhhh

      也可以通过java代码方式实现,同上。

  • 默认访问首页和图标文件
    默认情况下,我们只需将index.html首页,favicon.ico网站图标,放在四个静态资源目录下就行
    注意,文件名不能改成其他的,不然springboot找不到

开发中操作文件

开发中操作文件指的就是使用各种文件工具类读取或写出文件数据,IO这部分内容其实并不难
主要是太多了,一段时间不用就基本忘的差不多了,所以我觉得还是用用hutools中FileUtil工具类比较简单点
这个hutools中封装了很多其他的工具类,我感觉如果能把这么多工具类的使用学会,开发能力都能提升很大
废话不多说,来看看使用hutools中FileUtil工具类的使用吧

@Test
void contextLoads() throws IOException {
    /*
    	案例中参数使用的是本地文件路径,你也可以使用URL,或者file对象作为方法参数
    */

    String filePath = "C:\\Users\\Coco\\Desktop\\项目内容.txt";

    //读取本地文件,返回字符串
    String fileStr = FileUtil.readString(filePath, Charset.defaultCharset());
    String fileStr2 = FileUtil.readUtf8String(filePath);

    //读取本地文件,返回字节数组
    byte[] bytes = FileUtil.readBytes(filePath);

    //读取本地文件,按行的方式读取,返回字符串数组
    List<String> strings = FileUtil.readLines(filePath, Charset.defaultCharset());
    List<String> strings2 = FileUtil.readUtf8Lines(filePath);
    strings.forEach(System.out::println);

    //读取本地文件,返回字符缓冲输入输出流
    BufferedReader bufferedReader = FileUtil.getUtf8Reader(filePath);
    BufferedWriter bufferedWriter = FileUtil.getWriter(filePath, Charset.defaultCharset(), true);
    bufferedWriter.write("万一爱自由");
    bufferedWriter.flush();

    //读取本地文件,返回字节缓冲输入输出流
    BufferedInputStream bufferedInputStream = FileUtil.getInputStream(filePath);
    BufferedOutputStream bufferedOutputStream = FileUtil.getOutputStream(filePath);
}

开发中读取properties,yaml中的数据

这部分我暂且也认为是资源读取的操作吧,我们在读取配置文件中数据时可能有很多种方式
下面是我总结的内容:

  • 使用ResourceBundle工具类
    这是java中自带的读取资源文件中数据的工具类,不过它只能读取properties结尾的资源文件
    而不能读取yaml结尾的资源文件数据,基本使用如下:

    //jdbc.properties资源文件,放在resource资源目录下
    mysql_driver=com.mysql.cj.jdbc.Driver
    my_url=jdbc:mysql://localhost:3306/wechat?
    serverTimezone=GMT&useSSL=false&characterEncoding=utf-8
    my_user=root
    my_password=123765
    
    //资源读取
    ResourceBundle application = ResourceBundle.getBundle("jdbc");
    System.out.println(application.getObject("mysql_driver"));
    System.out.println(application.getString("my_url"));
    
    /*
    	注意:这里不仅可以读取独立的资源文件,即resources目录下的jdbc.properties
    	还可以读取springboot配置文件中的数据,即application.properties
    */
  • 使用类加载方式读取资源文件
    这种方式可以将配置文件(不论是yaml,还是properties)文件转成流的形式读取出来
    不过这种方式读取properties方式还可以,读取yaml方式就有点麻烦了,下面是案例:

    • 读取properties文件

      Properties properties = new Properties();
      InputStream stream = ResourceReadTestApplicationTests.class
                  .getClassLoader().getResourceAsStream("application.properties");
      properties.load(stream);	
      System.out.println(properties.getProperty("server.address"));
    • 读取yaml文件

      LinkedHashMap<String,Map<String, Object>> yamlMap = new LinkedHashMap<>();
      InputStream stream = ResourceReadTestApplicationTests.class
                  .getClassLoader().getResourceAsStream("application.yaml");
      yamlMap = YamlUtil.load(stream,yamlMap.getClass());
      System.out.println(yamlMap.get("spring"));
      Map<String, Object> serverKey = yamlMap.get("server");
      System.out.println(serverKey.get("port"));
      
      /*
      Yaml是hutools的工具类,你也可以使用Yaml对象代替,即Yaml yaml = new Yaml();
      
      输出结果
      {application={name=resource-read}, mvc={static-path-pattern=/static/**, format={date=dd/MM/yyyy}}}
      8080
      */

      可以看到,这种方式读取yaml文件还是非常不好的,springboot中一般使用注解方式,这个等下再说

    • 2023-7-24更新

      //模板文件保存在springboot项目的resources/static下
      Resource resource = new ClassPathResource("static/数据批量导出模板.xlsx");
      
      //也是通过类加载器的方式获取资源流数据,上面是通过类,这里通过对象获取类加载器
      InputStream templateFileInputStream = this.getClass().getClassLoader().getResourceAsStream("templateFile2.xlsx");
      
      //创建一个默认的资源读取对象,有些多余,没必要使用,仅仅记录下来
      ResourceLoader resourceLoader = new DefaultResourceLoader();
      InputStream in = resourceLoader.getResource("templates/export_demo.xlsx").getInputStream();
  • 原始的spring读取properties配置文件

    1)druid资源文件,放在resource资源目录下
        jdbc.url=jdbc:mysql://localhost:3306/restofmvc?
            serverTimezone=GMT&useSSL=false&characterEncoding=utf-8
        jdbc.driver=com.mysql.cj.jdbc.Driver
        jdbc.username=root
        jdbc.password=123765
    
    2)数据源的配置使用
        2.1)开启context名称空间,并开启引用资源文件的标签
            <context:property-placeholder location="classpath:druid.properties">
            </context:property-placeholder>
        2.2)配置数据源
            <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
                <property name="url" value="${jdbc.url}"></property>
                <property name="driverClassName" value="${jdbc.driver}"></property>
                <property name="username" value="${jdbc.username}"></property>
                <property name="password" value="${jdbc.password}"></property>
            </bean>
  • SpringBoot注解读取资源配置文件
    这是开发中最常用的方式,下面来看下案例:

    • 首先在application.yaml中配置数据

      keyi:
        name: 万一
        age: 23
    • 创建相应的实体类,使用注解将数据注入

      @ConfigurationProperties("keyi") //可以读取springboot配置文件的yaml和properties
      @Component                
      @Data
      public class User {
          private String name;
          private String age;
      }
    • 使用@Autowired或Resource注解自动导入容器中对象

      @SpringBootTest
      class ResourceReadTestApplicationTests {
      
          @Autowired
          User user;
      
          @Test
          void contextLoads(){
              System.out.println(user);
          }
      }
      //输出:User(name=万一, age=23)

    如果你读取的是独立的配置文件数据,而不是SpringBoot的配置文件中数据,
    可以使用@PropertySource注解指定外部配置文件,当然该注解只能读取properties文件读取不了yaml文件

    • resources目录下创建jdbc.properties文件

      db.mysql_driver=com.mysql.cj.jdbc.Driver
      db.my_url=jdbc:mysql://localhost:3306/wechat?
      db.serverTimezone=GMT&useSSL=false&characterEncoding=utf-8
      db.my_user=root
      db.my_password=123765
    • 创建对象绑定数据,额外使用@PropertySource注解指定外部配置文件

      @Data
      @Component
      @ConfigurationProperties("db")
      @PropertySource("classpath:jdbc.properties",encoding = "UTF-8")
      public class DBData {
          private String mysql_driver;
          private String my_url;
          private String serverTimezone;
          private String my_user;
          private String my_password;
      }
    • 使用@Autowired或Resource注解自动导入容器中对象

      @SpringBootTest
      class ResourceReadTestApplicationTests {
          @Autowired
          DBData dbData;
      
          @Test
          void contextLoads(){
              System.out.println(dbData);
          }
      }

    总结:通过@ConfigurationProperties(“xxx”)注解可以绑定项目配置文件中的数据,
    即application.yaml,application.properties文件中数据都可以,而如果需要绑定独立文件中的数据
    如jdbc.properties,那么就需要使用@PropertySource注解指定外部文件的名称,这种读取外部文件方式
    只能读取properties不能读取yaml文件中数据。