Spring 6【Resources资源和资源加载】(九)-全面详解(学习总结---从入门到深化)

news2024/9/28 21:26:03

 

目录

Resources资源和资源加载


Resources资源和资源加载

1.为什么要讲解Resources 

在Java中 java.net.URL类是统一资源定位符的抽象,主要用于描述互联网上资源的一个字符串。一般语 法为:

scheme:[//authority]path[?query][#fragment]

例如:

http://www.smallming.com
file:///C:/users/smallming

代码示例:

@Test
void testURL() throws IOException {
    URL url = new URL("file:///D:/a.txt");
    InputStream is = url.openStream();
    int i =0;
    while((i=is.read())!=-1){
         System.out.print((char) i);
    }
   is.close();
}

但是URL在访问资源时功能并不是特别完善。(有时硬写也能访问,但是可能不是很方便。)

例如访问类路径资源、访问Servlet上下文资源等都没有提供统一的标准。

Spring 框架的Resources就是为了解决这个问题的。

2.Spring框架中Resources是什么

想要了解Resources是什么就需要先说一下InputStreamSource接口。InputStreamSource接口是 Spring框架提供的顶级接口。所有Spring访问通过流访问的资源都通过这个接口。

接口中就一个方法,getInputStream()表示获取低级资源(如文件或类路径资源)的输入流。

public interface InputStreamSource {
   // 返回资源的字节输入流对象
   InputStream getInputStream() throws IOException;
}

 而Resources接口是InputStreamSource接口的子接口。里面提供的方法比InputStreamSource接口更多,可以以更多的形式返回物理文件(如文件或类路径资源)的File、URL、InputStream、byte[]内容。

public interface Resource extends InputStreamSource {
     // 判断资源是否存在
     boolean exists();
     // 判断资源是否可以可读的
     boolean isReadable();
     // 判断资源流是否处于打开状态,如果处于打开状态,不允许重复读取。
     boolean isOpen();
     // 是否是文件
     boolean isFile();
    // 获取URL
    URL getURL() throws IOException;
    // 获取URI
    URI getURI() throws IOException;
    // 获取资源的文件对象
    File getFile() throws IOException;
    // 获取资源字节通道,用作读取
    ReadableByteChannel readableChannel() throws IOException;
    // 内容长度
    long contentLength() throws IOException;
    // 最后一次修改时间的时间戳
    long lastModified() throws IOException;
    // 创建一个相对资源
    Resource createRelative(String relativePath) throws IOException;
    // 获取资源名
    String getFilename();
    // 获取资源描述
    String getDescription();
}

 实际上我们在使用Spring框架时,很多方法参数是String类型资源路径,这个资源路径就是通过 Resources来加载资源的。

Spring框架提供Resources接口就是为了标准化资源访问,对于特定的资源都有统一的前缀进行访问。

3.策略设计模式 

策略(Strategy)设计模式,是23种设计模式(Gang of Four,GoF ,四人组)中一种。

策略设计模式有一系列相对独立的解决方案,用户根据不同情况进行选择,这种情况就可以使用策略模 式。再具体点说就是有一个公共接口,再有一些列实现类,这些类封装了不同算法,根据不同的场景, 选择这些不同的算法。

具体举例说明:编程中不同学科有着不同的学习路线,当我们选择学习Java时,应该按照以java学习路 线学习。学习前端时,按照前端的学习路径学习。我们就以这个现实场景来讲解策略模式。 如果不使用策略模式,也可以写出来代码,这个时候应该用if...else if ...else 结构

String study="java";
if(study.equals("java")){
    System.out.println("java应该先学。。。");
}else if(study.equals("frontend")){
    System.out.println("前端应该先学。。。");
}

 这段代码是不复习面向对象设计原则-开闭原则(OCP,对修改关闭,对扩展开放),当我们还有其他学科的 学习路线时,需要修改代码,继续添加else if。在这种场景下就可以使用策略模式。 我们先来学习下策略模式包含哪些内容。

在策略设计模式中,一般包含三个角色和一个使用者:

  • 策略抽象(Strategy):里面定义公共方法
  • 具体策略(Concrete Strategy):对公共方法的具体实现。
  • 每个实现内容都不同 环境(Context):添加了策略的关联对象。环境是给客户去使用的。
  • 客户:使用者

策略模式代码实现。

// 策略抽象,定义所有学科学习方法
public interface ITStrategy {
     void study();
}
// 具体策略:Java学习方法
public class JavaStrategy implements ITStrategy{
    @Override
    public void study() {
         System.out.println("Java应该先学。。。");
    }
}
// 具体策略:前端学习方法
public class FrontendStrategy implements ITStrategy{
     @Override
     public void study() {
         System.out.println("前端应该先学。。。");
    }
}

// 环境:关联策略抽象
public class ITContext {
     private ITStrategy itStrategy;
     public ITContext() {}
     // 有参构造,传入具体策略
     public ITContext(ITStrategy itStrategy) {
            this.itStrategy = itStrategy;
      }
     // 对外提供方法,执行策略
     public void study(){
          itStrategy.study();
      }
   }
    // 客户:使用环境
     public class Test {
         public static void main(String[] args) {
               ITContext itContext = new ITContext(new JavaStrategy());
               itContext.study();
               ITContext itContext2 = new ITContext(new FrontendStrategy());
               itContext2.study();
      }
}

 通过上面的代码可以看出来,我们后面添加Python的学习方法对代码没有影响,和Java、前端的学习方 法都是相互独立的。

所以我们来总结下,策略模式的优缺点:

优点:

1、不需要使用多重if。

2、高内聚,低耦合,符合OCP原则,便于扩展。

3、具体策略相互独立,客户可以根据不同情况选择不同策略,互不影响。 

缺点:

1、客户必须知道所有具体策略,才能决定使用哪个策略。

2、当策略比较多时,具体策略会很多。

4.Resources的具体实现

Spring框架的Resources就是基于策略模式实现的。我们根据策略模式总结出Spring框架需要知道的类,把这些类都讲完了,Spring框架Resources基本就完事了。同时也知道了Spring框架Resources如何 对策略模式的应用。

Resources接口有很多子接口和具体实现类。整个Resources使用了设计模式中策略模式。

 

Spring框架在实现策略模式时肯定要比我们写的要稍微复杂一些,通过整理后的图形也可以看懂的。

 

4.1 UrlResource 

UrlResource是java.net.URL在Spring框架中的实现。可以通过URL来访问任何资源。每周资源都有固定 的前缀表示:

1、file: 访问文件系统的资源文件, file:///C:/user/smallming/a.txt ,磁盘名开头为绝对路 径,没有以磁盘名开头为当前应用根目录(无论是否以斜杠开头)

2、https: 通过https(超文本安全传输协议)协议访问资源 https://www.baidu.com

3、ftp: 通过ftp(文件传输协议)协议访问资源 ftp://ip:port

这个类属于万能类,当我们在使用Spring框架访问资源时,尤其是在使用String类型参数时,由Spring 框架进行判断到底使用哪个Resources的实现类。如果发现路径没有标准前缀,则使用UrlResource来访问这个资源

 4.2 ClassPathResource

ClassPathResource主要用于操作类路径资源。但是无法操作jar包中类路径资源。

在Maven项目中类路径资源:

    1、src/main/java 中文件最终会被编译到类路径中

    2、src/main/resources中文件最终会被编译到类路径中

在IDEA中看到的target/classes中内容就是类路径资源

当我们想要操作类路径资源时,可以直接使用ClassPathResource的有参构造方法

public ClassPathResource(String path) {
      this(path, (ClassLoader) null);
}

 如果没有使用有参构造方法,属于隐士访问资源,需要在String类型中明确添加 classpath: 作为前缀

4.3 FileSystemResource

FileSystemResource 是 java.io.File 和 java.nio.File.Path 的具体实现。 主要用于获取文件系统资源,返回File或URL类型。同时因为实现了WritableResource接口,不仅仅支持读操作还支持写操作。

文件系统,简单理解为服务器内部文件,例如:

C:\\Users\\smallming\\a.txt 或 file:///C:/Users/smallming/a.txt

从Spring Framework 5.0 开始FileSystemResource 使用NIO.2 进行操作文件。从Spring Framework 5.1 开始支持NIO.2的Path进行构建,虽然支持Path构建但是使用的是Files进行文件操作。

小复习:

NIO.2 是Java 7开始支持一种NIO升级版。用于替代原来java.io.File进行文件操作,来提升性能和 增加操作的简便性。里面常用的就是Path、Paths、Files

使用File获取文件对象: File file = new File("C:\\Users\\smallming","a.txt");

使用NIO.2获取文件:Path path = Paths.get("C:\Users\smallming","a.txt");

 4.4 PathResource

PathResource是一个纯NIO.2中Path的支持,专门是用于Path的。而上面学习的FileSystemResource 是从5.1版本开始支持的,并且FileSystemResource实际还是使用Files进行文件操作。 所有PathResource是一个纯粹的NIO.2中Path实现。用于访问文件系统资源,并返回File或URL。

4.5 ServletContextResource

ServletContextResource 是对jakarta.servlet.ServletContext资源访问的实现。 通过相对路径访问web项目根目录中资源。。 在项目中没有导入Spring框架web模块(spring-web)时,是无法搜索到这个类的。

4.6 InputStreamResource

InputStreamResource是对Java中java.io.InputStream的实现,只有其他Resource实现都没有办法使用 时,才可能会用InputStreamResource。

InputStreamResource访问的资源流一直处于open状态,所以当希望保存资源或者多次读取资源时不要使用。

所以InputStreamResource有一定局限性,主要用于一次性资源读取。

4.7 ByteArrayResource

ByteArrayResource主要用于把byte[]转换为Resource。

5. ResourceLoader

ResourceLoader 接口是Spring框架提供的资源加载器。通过这个接口加载资源,根据加载方式,获取 到Resources接口的哪个实现类。在ApplicationContext接口的实现类中都实现类ResourceLoader,所 以ApplicationContext不同实现类对应使用不同的Resources实现类。 ResourceLoader接口的内容也比较简单。

public interface ResourceLoader {
    // 常量值为 classpath:
    String CLASSPATH_URL_PREFIX = ResourceUtils.CLASSPATH_URL_PREFIX;
    // 加载资源,返回资源对象。不同的加载方式返回不同的资源对象
    Resource getResource(String location);
    // 获取类加载器
    @Nullable
    ClassLoader getClassLoader();
}

特点如下:

1、当使用特定前缀时,则使用前缀对应的Resources接口实现类。和ApplicationContext接口实现类无关。前缀优先级高于ApplicationContext实现类

2、当使用特定类时,不添加前缀,会对应一种Resources实现类。

 通过上面表格也说明了,我们之前一直使用的ClassPathXmlApplicationContext使用的是 ClassPathResource进行资源加载。 所以下面几种写法是等效的,都是使用ClassPathResource进行资源加载。

没有前缀 

ApplicationContext ac = new ClassPathXmlApplicationContext("ac.xml");

有前缀

ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:ac.xml");

使用ApplicationContext其他实现类,但是路径以classpath:前缀开头

ApplicationContext ac = new FileSystemXmlApplicationContext("classpath:ac.xml");
System.out.println(ac.getResource("classpath:ac.xml").getClass().getName());

6.ResourcePatternResolver

ResourcepatternResovler 是 ResourceLoader接口的子接口。

public interface ResourcePatternResolver extends ResourceLoader

所以ResourcePatternResolver也是资源加载器。但是相对于ResourceLoader支持资源加载时,支持 Ant表达式,路径中包含占位符 * 号或 ** 号或 ? 号。

注意:当使用 * 或 ? 时,必须有前缀classpath*:,使用classpath:无效。但是 ** 没有强制要求必须使 用 classpath* ,但是必须以 / 或 classpath 或 classpath* 开头

 

强调: ApplicationContext接口实现的不是ResourceLoader,而是ResourcePatternResovler,所以 ApplicationContext所有实现类,在加载资源时都支持Ant表达式。

public interface ApplicationContext extends EnvironmentCapable,
ListableBeanFactory, HierarchicalBeanFactory,MessageSource ,
ApplicationEventPublisher, ResourcePatternResolver

 7.ResourceLoaderAware

在Spring Framework 3.1 开始提供了一个Aware接口。这个接口是允许Bean获取到IoC容器部分参数或 功能的。这在一定程度上提升了Bean的能力。

Aware接口是一个顶级接口,里面没有任何方法。

public interface Aware {
}

想要让Bean具有哪种功能,需要使用Aware不同的子接口或实现类。直接子接口一共有15个,具体实现 类特别多。

如果只是用Spring框架完成CRUD,Aware这个接口用不上的。但是如果在做一些基于Spring框架的底层 开发时,Aware接口是离不开的。所以Aware接口一定要记住,这是Spring框架的一个隐藏大佬。 

 

ResourceLoaderAware就是Aware接口的子接口。主要作用是让Bean可以获取到ResourceLoader对象。通过ResourceLoader进行加载资源。功能比较简单。 我们写一个小案例,在People类中借助ResourceLoaderAware把外部的一个属性文件加载到属性中。

新建配置文件applicationContext-resources.xml,启动注解扫描 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="com.tong.resource">
    </context:component-scan>
</beans>

新建properties文件

在src/main/resources中新建resources.properties文件,并在文件中随意添加几组键值对

name=smallming
age=16

新建Bean类com.bjsxt.resource.People

类中包含一个Properties类型属性,这个属性不在容器内部进行加载,而是通过代码,在People类中加 载外部属性文件。 所以让类实现ResourceLoaderAware接口。并重写setResourceLoader方法。方法参数 ResourceLoader由IoC容器帮助注入进来。

@Data
@Component
public class People implements ResourceLoaderAware {
    private Properties prop;
    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        try {
              Resource resource = resourceLoader.getResource("resources.properties");
              InputStream is = resource.getInputStream();
              prop = new Properties();// 一定要实例化,否则空指针
              prop.load(is);// 把读取到的输入流加载到prop中。
              is.close();
        } catch (IOException e) {
     throw new RuntimeException(e);
    }
  }
}

 编写测试类

测试查看,Bean中prop属性是否已经有值

@SpringJUnitConfig
@ContextConfiguration("classpath:applicationContext-resource.xml")
public class ResourceTest {
     @Autowired
     People people;
     @Test
     void test(){
        System.out.println(people.getProp());
   }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/803843.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JavaScript学习 -- HMAC算法基本原理

HMAC&#xff08;Hash-based Message Authentication Code&#xff09;算法是一种基于哈希算法的消息认证码算法。它可以用于验证和保护数据在传输过程中的完整性和真实性。在JavaScript中&#xff0c;我们可以使用HMAC算法来保证数据的安全性。本篇文章将介绍HMAC算法的基本原…

超详细三子棋(保姆级教学)

超详细三子棋&#xff08;保姆级教学&#xff09; 一、模块化程序设计&#xff08;多文件编程&#xff09;介绍1.概述2.传统编程的方式3.模块化程序设计的方法二、三子棋(含多子棋)代码设计思路三、三子棋代码设计1.创建菜单函数2.实现多子棋3.棋盘初始化4.打印棋盘格式5.玩家下…

使用express搭建后端服务

目录 1 创建工程目录2 初始化3 安装express依赖4 启动服务5 访问服务总结 上一篇我们利用TDesign搭建了前端服务&#xff0c;现在的开发讲究一个前后端分离&#xff0c;后端的话需要单独搭建服务。后端服务的技术栈还挺多&#xff0c;有java、php、python、nodejs等。在众多的技…

hbase(1)-基础

1、hbase产生背景 hadoop只能执行批量处理&#xff0c;并且只能以顺序方式访问数据&#xff0c;这意味着即使最简单的搜索工作&#xff0c;也必须搜索整个数据集。那么当处理一个庞大的数据集&#xff0c;也是按照顺序处理一个巨大的数据集。 基于上述hadoop的限制&#xff0…

股东分红税高达20%,该怎么节税?

股东分红税高达20%&#xff0c;该怎么节税&#xff1f; 别吃大亏了!股东分红个税高达20%&#xff0c;这样做节税很实在&#xff01; 《税筹顾问》专注于园区招商、企业税务筹划&#xff0c;合理合规助力企业节税&#xff01; 企业成立的初衷就是为了赚钱&#xff0c;以盈利为…

ts中声明引入未使用的报错——解决方案

在编写ts项目的时候&#xff0c;经常会出现如下报错&#xff1a; 导入声明中的所有导入都未使用 这是因为导入的模块暂时没有使用&#xff0c;ts给的一个提示信息 解决方案&#xff1a; 在ts.config.json中 把noUnusedLocals 设置为false即可 {"compilerOptions"…

进阶 vue自定义指令 vue中常用自定义指令以及应用场景,案例书写

文章目录 vue3自定义指令1.什么是自定义指令&#xff1f;2.注册自定义指令2.1 全局注册2.2 局部注册<script setup>中注册&#xff1a;<script>中使用&#xff1a; 3.钩子函数参数详解4.指令传值5.总结 常用自定义指令案例v-longpress 长按v-debounce 防抖v-thrott…

微信怎么实现自动通过好友请求后自动回复呢?

每天都很忙碌 今天特别忙“录” 每天打开微信后&#xff0c; 第一件事就是回复客户&#xff0c; 但是经过一个小时、两个小时后发现&#xff0c; 只回复了昨晚留言的那一批客户&#xff0c; 还没有来得及回复刚刚发来的信息。 此外&#xff0c;通讯录中有99个客户等待手动…

代理模式-对象的间接访问

现在朋友圈有好多做香港代购的微商&#xff0c;大部分网民无法自己去香港购买想要的商品&#xff0c;于是委托这些微商&#xff0c;告诉他们想要的商品&#xff0c;让他们帮我们购买。我们只需要付钱给他们&#xff0c;他们就会去香港购买&#xff0c;然后把商品寄给我们。这就…

测试常见前端bug

目录 协作 测试方法 标签&#xff1a;标签 内容/ref/ 判断 arr&&arr.length 交互 样式不生效&#xff1a;devtools查找&#xff0c;编译前的标签&#xff0c;运行时不一定存在 可交互的需要提示 hover样式 没有交互逻辑&#xff0c;就不要设置交互 无法交互…

pytorch学习——模型选择

一.概念 模型选择是机器学习中的重要环节&#xff0c;它涉及到从各种统计&#xff0c;机器学习或深度学习模型中选取最佳模型的过程。这涉及到许多关键概念&#xff0c;包括偏差与方差&#xff0c;过拟合与欠拟合&#xff0c;训练误差和泛化误差&#xff0c;交叉验证&#xff0…

【Linux下6818开发板(ARM)】硬件空间挂载

(꒪ꇴ꒪ ),hello我是祐言博客主页&#xff1a;C语言基础,Linux基础,软件配置领域博主&#x1f30d;快上&#x1f698;&#xff0c;一起学习&#xff01;送给读者的一句鸡汤&#x1f914;&#xff1a;集中起来的意志可以击穿顽石!作者水平很有限&#xff0c;如果发现错误&#x…

HTML基础知识点总结

目录 1.HTML简介 2.HTML基础结构 主要字符&#xff1a; 3.基础知识 &#xff08;一&#xff09;p标签 &#xff08;二&#xff09;hr标签 &#xff08;三&#xff09;尖角号 &#xff08;四&#xff09;版权号 (五)div和span div span (六)列表 &#xff08;1&…

Python爬虫实战(进阶篇)—6获取微某博信息(附完整代码)

转眼将就来到了我们爬虫基础课的第 6 节课,今天我们来获取微某博信息来进行阅读学习! PS前面几节课的内容在专栏这里,欢迎大家考古:点我 首先第一步我们先登录一下微x博:点我 点击左上角的搜索框,找到你想获取的用户: 大家可以看到这里有两种搜索方式: 1、按照关键字…

linux+Jenkins+飞书机器人发送通知(带签名)

文章目录 如何使用在linux 上安装python 环境发送消息python脚本把脚本上传倒linux上 jenkins 上执行脚本 如何使用 自定义机器人使用指南飞书官网https://open.feishu.cn/document/client-docs/bot-v3/add-custom-bot 在linux 上安装python 环境 yum install python3 python…

Skin Shader 使用自动生成的Thickness

Unity2023.2的版本&#xff0c;Thickness 自动化生成&#xff0c;今天测试了一把&#xff0c;确实不错。 1.Render 设置 在Project Settings->Graphics->HDRP Global Settings中 Frame Setting->Rendering->Compute Thickness 打开 2.Layer设置 2.1添加Layer&…

python基本知识学习

一、输出语句 在控制台输出Hello,World! print("Hello,World!") 二、注释 单行注释&#xff1a;以#开头 # print("你好") 多行注释&#xff1a; 选中要注释的代码Ctrl/三单引号三双引号 # print("你好") # a1 # a2 print("Hello,World!&…

【c语言进阶】字符函数和字符串函数知识总结

字符函数和字符串函数 前期背景求字符串长度函数strlen函数strlen函数三种模拟实现 长度不受限制的字符串函数strcpy函数strcpy函数模拟实现strcat函数strcat函数模拟实现strcmp函数strcmp函数模拟实现 长度受限制的字符串函数strncpy函数strncpy函数模拟实现strncat函数strnca…

推理和训练

监督学习与非监督学习 Supervised Learning有监督式学习: 输入的数据被称为训练数据&#xff0c;一个模型需要通过一个训练过程&#xff0c;在这个过程中进行预期判断&#xff0c;如果错误了再进行修正&#xff0c;训练过程一直持续到基于训练数据达到预期的精确性。其关键方法…

【Python机器学习】实验04(2) 机器学习应用实践--手动调参

文章目录 机器学习应用实践1.1 准备数据此处进行的调整为&#xff1a;要所有数据进行拆分 1.2 定义假设函数Sigmoid 函数 1.3 定义代价函数1.4 定义梯度下降算法gradient descent(梯度下降) 此处进行的调整为&#xff1a;采用train_x, train_y进行训练 1.5 绘制决策边界1.6 计算…