8、資源操作 Resource

目錄

  • 8.1、Spring Resources概述
    • 補充:什么是 low-level 資源?
      • 1. 文件系統資源
      • 2. 類路徑資源
      • 3. URL資源
      • 4. 內嵌資源
      • 5. InputStream資源
      • 6. ServletContext資源
      • 示例代碼
      • 結論
  • 8.2、Resource接口
  • 8.3、Resource的實現類
    • 8.3.1、UrlResource訪問網絡資源
      • 1)訪問基于HTTP協議的網絡資源
      • 2)在項目根路徑下創建文件,從文件系統中讀取資源
    • 8.3.2 ClassPathResource 訪問類路徑下資源
      • 1)實驗:在類路徑下創建文件atguigu.txt,使用ClassPathResource 訪問
    • 8.3.3、FileSystemResource 訪問文件系統資源
      • 8.3.4、ServletContextResource
      • 8.3.5、InputStreamResource
      • 8.3.6、ByteArrayResource
  • 8.4、Resource類圖
  • 8.5、ResourceLoader 接口
    • 8.5.1、使用演示
    • 8.5.3、ResourceLoader 總結
  • 8.6、ResourceLoaderAware 接口
  • 8.7 應用程序上下文和資源路徑
    • 8.8.1、ApplicationContext實現類指定訪問策略

8.1、Spring Resources概述

Java的標準java.net.URL類和各種URL前綴的類無法滿足所有對low-level資源的訪問。

比如:沒有標準化的 URL 實現訪問需要從類路徑相對于 ServletContext 獲取的資源。并且缺少某些Spring所需要的功能,例如檢測某資源是否存在等。

Spring的Resource聲明了訪問low-level資源的能力。

在這里插入圖片描述

補充:什么是 low-level 資源?

在Spring框架中,Resource接口是一個抽象接口,用于統一訪問各種低級別(low-level)的資源。低級別資源指的是那些需要通過底層I/O操作進行讀取和寫入的資源。具體來說,這些資源可以包括:

1. 文件系統資源

  • 本地文件:在文件系統中的文件,例如文本文件、配置文件、圖像文件等。
    Resource resource = new FileSystemResource("/path/to/file.txt");
    

2. 類路徑資源

  • 類路徑中的資源:通常是項目中的配置文件、靜態資源等,位于類路徑下。
    Resource resource = new ClassPathResource("config/application.properties");
    

3. URL資源

  • 網絡資源:通過URL訪問的資源,可以是HTTP、HTTPS、FTP等協議。
    Resource resource = new UrlResource("http://example.com/resource.txt");
    

4. 內嵌資源

  • 內嵌在JAR包或WAR包中的資源:通過類路徑訪問的資源,常用于讀取內部配置文件或嵌入式資源。
    Resource resource = new ClassPathResource("META-INF/spring.factories");
    

5. InputStream資源

  • 輸入流資源:從輸入流中讀取的資源,通常用于處理非文件系統的流數據。
    InputStream inputStream = new ByteArrayInputStream("sample data".getBytes());
    Resource resource = new InputStreamResource(inputStream);
    

6. ServletContext資源

  • Web應用程序上下文中的資源:在Web應用的Servlet上下文中訪問資源。
    Resource resource = new ServletContextResource(servletContext, "/WEB-INF/config.xml");
    

示例代碼

下面是一些示例代碼,展示了如何使用Spring的Resource接口訪問不同類型的資源:

import org.springframework.core.io.Resource;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.UrlResource;
import org.springframework.core.io.InputStreamResource;import java.io.IOException;
import java.io.InputStream;public class ResourceExample {public static void main(String[] args) throws IOException {// 1. 訪問文件系統中的資源Resource fileSystemResource = new FileSystemResource("/path/to/file.txt");printResourceContent(fileSystemResource);// 2. 訪問類路徑中的資源Resource classPathResource = new ClassPathResource("config/application.properties");printResourceContent(classPathResource);// 3. 訪問URL中的資源Resource urlResource = new UrlResource("http://example.com/resource.txt");printResourceContent(urlResource);// 4. 訪問輸入流資源InputStream inputStream = new ByteArrayInputStream("sample data".getBytes());Resource inputStreamResource = new InputStreamResource(inputStream);printResourceContent(inputStreamResource);}private static void printResourceContent(Resource resource) throws IOException {try (InputStream is = resource.getInputStream()) {byte[] buffer = new byte[is.available()];is.read(buffer);String content = new String(buffer);System.out.println("Resource content: " + content);}}
}

結論

Spring的Resource接口提供了一種統一的方式來訪問各種低級別的資源,無論這些資源是本地文件、類路徑資源、URL資源還是輸入流資源。通過使用Resource接口,開發人員可以輕松地讀取和管理不同類型的資源,提升了代碼的可維護性和靈活性。


8.2、Resource接口

Spring 的 Resource 接口位于 org.springframework.core.io 中。 旨在成為一個更強大的接口,用于抽象對低級資源的訪問。以下顯示了Resource接口定義的方法

public interface Resource extends InputStreamSource {boolean exists();default boolean isReadable() {return this.exists();}default boolean isOpen() {return false;}default boolean isFile() {return false;}URL getURL() throws IOException;URI getURI() throws IOException;File getFile() throws IOException;default ReadableByteChannel readableChannel() throws IOException {return Channels.newChannel(this.getInputStream());}long contentLength() throws IOException;long lastModified() throws IOException;Resource createRelative(String relativePath) throws IOException;@NullableString getFilename();String getDescription();
}

Resource接口繼承了InputStreamSource接口,提供了很多InputStreamSource所沒有的方法。InputStreamSource接口,只有一個方法:

public interface InputStreamSource {InputStream getInputStream() throws IOException;}

其中一些重要的方法:
getInputStream(): 找到并打開資源,返回一個InputStream以從資源中讀取。預計每次調用都會返回一個新的InputStream(),調用者有責任關閉每個流
exists(): 返回一個布爾值,表明某個資源是否以物理形式存在
isOpen: 返回一個布爾值,指示此資源是否具有開放流的句柄。如果為true,InputStream就不能夠多次讀取,只能夠讀取一次并且及時關閉以避免內存泄漏。對于所有常規資源實現,返回false,但是InputStreamResource除外。
getDescription(): 返回資源的描述,用來輸出錯誤的日志。這通常是完全限定的文件名或資源的實際URL。

其他方法:
isReadable(): 表明資源的目錄讀取是否通過getInputStream()進行讀取。
isFile(): 表明這個資源是否代表了一個文件系統的文件。
getURL(): 返回一個URL句柄,如果資源不能夠被解析為URL,將拋出IOException
getURI(): 返回一個資源的URI句柄
getFile(): 返回某個文件,如果資源不能夠被解析稱為絕對路徑,將會拋出FileNotFoundException
lastModified(): 資源最后一次修改的時間戳
createRelative(): 創建此資源的相關資源
getFilename(): 資源的文件名是什么 例如:最后一部分的文件名 myfile.txt

8.3、Resource的實現類

Resource 接口是 Spring 資源訪問策略的抽象,它本身并不提供任何資源訪問實現,具體的資源訪問由該接口的實現類完成——每個實現類代表一種資源訪問策略。Resource一般包括這些實現類:UrlResource、ClassPathResource、FileSystemResource、ServletContextResource、InputStreamResource、ByteArrayResource

8.3.1、UrlResource訪問網絡資源

Resource的一個實現類,用來訪問網絡資源,它支持URL的絕對路徑。

http:------該前綴用于訪問基于HTTP協議的網絡資源。
ftp:------該前綴用于訪問基于FTP協議的網絡資源
file: ------該前綴用于從文件系統中讀取資源

1)訪問基于HTTP協議的網絡資源

public class UrlResourceDemo {public static void main(String[] args) {//http前綴loadUrlResource("http://www.baidu.com");}//訪問前綴http、filepublic static void loadUrlResource(String path) {try {//創建Resource實現類的對象 UrlResourceUrlResource url = new UrlResource(path);System.out.println(url.exists());System.out.println(url.isReadable());System.out.println(url.isFile());System.out.println(url.getURL());System.out.println(url.getURI());System.out.println(url.getFilename());byte[] bytes = new byte[100];int read = url.getInputStream().read(bytes);System.out.println(new String(bytes));} catch (Exception e) {throw new RuntimeException(e);}}
}

2)在項目根路徑下創建文件,從文件系統中讀取資源

在這里插入圖片描述

public class UrlResourceDemo {public static void main(String[] args) {//file前綴loadUrlResource("file:atguigu.txt");}//訪問前綴http、filepublic static void loadUrlResource(String path) {try {//創建Resource實現類的對象 UrlResourceUrlResource url = new UrlResource(path);System.out.println(url.exists());System.out.println(url.isReadable());System.out.println(url.isFile());System.out.println(url.getURL());System.out.println(url.getURI());System.out.println(url.getFilename());byte[] bytes = new byte[100];int read = url.getInputStream().read(bytes);System.out.println(new String(bytes));} catch (Exception e) {throw new RuntimeException(e);}}
}

8.3.2 ClassPathResource 訪問類路徑下資源

ClassPathResource 用來訪問類加載路徑下的資源,相對于其他的 Resource 實現類,其主要優勢是方便訪問類加載路徑里的資源,尤其對于 Web 應用,ClassPathResource 可自動搜索位于 classes 下的資源文件,無須使用絕對路徑訪問。

1)實驗:在類路徑下創建文件atguigu.txt,使用ClassPathResource 訪問

//訪問類路徑下資源
public class ClassPathResourceDemo {public static void loadClasspathResource(String path) {//創建對象ClassPathResourceClassPathResource resource = new ClassPathResource(path);System.out.println(resource.getFilename());System.out.println(resource.getDescription());//獲取文件內容try {InputStream in = resource.getInputStream();byte[] b = new byte[1024];while(in.read(b)!=-1) {System.out.println(new String(b));}} catch (IOException e) {throw new RuntimeException(e);}}public static void main(String[] args) {loadClasspathResource("atguigu.txt");}
}

在這里插入圖片描述

8.3.3、FileSystemResource 訪問文件系統資源

Spring 提供的 FileSystemResource 類用于訪問文件系統資源,使用 FileSystemResource 來訪問文件系統資源并沒有太大的優勢,因為 Java 提供的 File 類也可用于訪問文件系統資源。

8.3.4、ServletContextResource

8.3.5、InputStreamResource

8.3.6、ByteArrayResource

8.4、Resource類圖

在這里插入圖片描述

8.5、ResourceLoader 接口

在ResourceLoader接口里有如下方法:
(1)Resource getResource(String location) : 該接口僅有這個方法,用于返回一個Resource實例。ApplicationContext實現類都實現ResourceLoader接口,因此ApplicationContext可直接獲取Resource實例。

8.5.1、使用演示

實驗一:ClassPathXmlApplicationContext獲取Resource實例

package com.atguigu.spring6.resouceloader;import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.Resource;public class Demo1 {public static void main(String[] args) {ApplicationContext ctx = new ClassPathXmlApplicationContext();
//        通過ApplicationContext訪問資源
//        ApplicationContext實例獲取Resource實例時,
//        默認采用與ApplicationContext相同的資源訪問策略Resource res = ctx.getResource("atguigu.txt");System.out.println(res.getFilename());}
}

實驗二:FileSystemApplicationContext獲取Resource實例

package com.atguigu.spring6.resouceloader;import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import org.springframework.core.io.Resource;public class Demo2 {public static void main(String[] args) {ApplicationContext ctx = new FileSystemXmlApplicationContext();Resource res = ctx.getResource("atguigu.txt");System.out.println(res.getFilename());}
}

8.5.3、ResourceLoader 總結

當Spring應用需要進行資源訪問時,實際上并不需要直接使用Resource實現類,而是調用ResourceLoader實例的getResource()方法來獲得資源,ReosurceLoader將會負責選擇Reosurce實現類,也就是確定具體的資源訪問策略,從而將應用程序和具體的資源訪問策略分離開來


8.6、ResourceLoaderAware 接口

ResourceLoaderAware接口實現類的實例將獲得一個ResourceLoader的引用,ResourceLoaderAware接口也提供了一個setResourceLoader()方法,該方法將由Spring容器負責調用,Spring容器會將一個ResourceLoader對象作為該方法的參數傳入。

==具體看 Spring Bean生命周期 --> 初始化Bean 中的 —> invokeAware ==

如果把實現ResourceLoaderAware接口的Bean類部署在Spring容器中,Spring容器會將自身當成ResourceLoader作為setResourceLoader()方法的參數傳入。由于ApplicationContext的實現類都實現了ResourceLoader接口,Spring容器自身完全可作為ResorceLoader使用

實驗:演示ResourceLoaderAware使用

第一步 創建類,實現ResourceLoaderAware接口

package com.atguigu.spring6.resouceloader;import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.ResourceLoader;public class TestBean implements ResourceLoaderAware {private ResourceLoader resourceLoader;//實現ResourceLoaderAware接口必須實現的方法//如果把該Bean部署在Spring容器中,該方法將會有Spring容器負責調用。//SPring容器調用該方法時,Spring會將自身作為參數傳給該方法。public void setResourceLoader(ResourceLoader resourceLoader) {this.resourceLoader = resourceLoader;}//返回ResourceLoader對象的應用public ResourceLoader getResourceLoader(){return this.resourceLoader;}}

第二步 創建bean.xml文件,配置TestBean

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="testBean" class="com.atguigu.spring6.resouceloader.TestBean"></bean>
</beans>

第三步 測試

package com.atguigu.spring6.resouceloader;import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;public class Demo3 {public static void main(String[] args) {//Spring容器會將一個ResourceLoader對象作為該方法的參數傳入ApplicationContext ctx = new ClassPathXmlApplicationContext("bean.xml");TestBean testBean = ctx.getBean("testBean",TestBean.class);//獲取ResourceLoader對象ResourceLoader resourceLoader = testBean.getResourceLoader();System.out.println("Spring容器將自身注入到ResourceLoaderAware Bean 中 ? :" + (resourceLoader == ctx));//加載其他資源Resource resource = resourceLoader.getResource("atguigu.txt");System.out.println(resource.getFilename());System.out.println(resource.getDescription());}
}

8.7 應用程序上下文和資源路徑

不管以怎樣的方式創建ApplicationContext實例,都需要為ApplicationContext指定配置文件,Spring允許使用一份或多分XML配置文件。當程序創建ApplicationContext實例時,通常也是以Resource的方式來訪問配置文件的,所以ApplicationContext完全支持ClassPathResource、FileSystemResource、ServletContextResource等資源訪問方式。

ApplicationContext確定資源訪問策略通常有兩種方法:

  • (1)使用ApplicationContext實現類指定訪問策略。
  • (2)使用前綴指定訪問策略。

8.8.1、ApplicationContext實現類指定訪問策略

創建ApplicationContext對象時,通常可以使用如下實現類:
(1) ClassPathXMLApplicationContext : 對應使用ClassPathResource進行資源訪問。
(2)FileSystemXmlApplicationContext : 對應使用FileSystemResource進行資源訪問。
(3)XmlWebApplicationContext : 對應使用ServletContextResource進行資源訪問。

當使用ApplicationContext的不同實現類時,就意味著Spring使用響應的資源訪問策略。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/20645.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/20645.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/20645.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

LIO-EKF: 運行數據UrbanNav與mid360設備詳細教程

一、代碼連接 代碼下載連接&#xff1a; YibinWu/LIO-EKF: Maybe the simplest LiDAR-inertial odometry that one can have. (github.com) 編譯步驟&#xff1a; cd srcgit clone gitgithub.com:YibinWu/LIO-EKF.gitcatkin_makesource devel/setup.bash 運行步驟&#xff1a; …

為什么要保持方差為1

1.數值穩定性&#xff1a; 在機器學習和深度學習中&#xff0c;維持激活函數輸入的方差在一個合理范圍內&#xff08;如1&#xff09;是很重要的&#xff0c;這有助于防止在訓練過程中發生梯度消失或梯度爆炸的問題。如果方差過大或過小&#xff0c;經過多層網絡后輸出結果的方…

java并發處理機制

在Java中&#xff0c;并發處理機制主要是通過線程來實現的。Java提供了豐富的類和接口來支持多線程編程&#xff0c;主要集中在 java.util.concurrent 包中。以下是一些關鍵的并發處理機制&#xff1a; 1.線程創建&#xff1a;可以通過繼承 Thread 類或實現 Runnable 接口來創建…

公園【百度之星】/圖論+dijkstra

公園 圖論dijkstra #include<bits/stdc.h> using namespace std; typedef long long ll; typedef pair<ll,ll> pii; vector<ll> v[40005]; //a、b、c分別是小度、度度熊、終點到各個點的最短距離 ll a[40005],b[40005],c[40005],dist[40005],st[40005]; void…

原碼、反碼和真值都不存在!

文章目錄 補碼的理解十進制計算二進制計算 補碼和真值換算數制轉換負數補碼轉真值負數真值轉補碼 注&#xff1a;均來自 做而論道 答主的理解。 補碼的理解 在計算機系統中&#xff0c;根本就沒有原碼和反碼&#xff0c;真值也是不存在的。在計算機系統中&#xff0c;并不使用…

java 遠程調試

1.遠程啟動時 jdk1.8-32\jre\bin\java.exe -Dfile.encodingUTF-8 -Djava.library.pathlib -agentlib:jdwptransportdt_socket,servery,suspendn,address5005 -jar local-com.yuetai.service-0.0.1-SNAPSHOT.jar --spring.config.locationapplication.yml 2.本地調試項目連接遠…

2024-06-01 Win 11 升級 TPM 2 問題

點擊 Windows 更新&#xff0c;遇到報錯&#xff0c;說是不支持 CPU 和 TPM 等&#xff0c;先是朋友給了一個鏈接文章&#xff0c;說是可以繞過&#xff0c;嘗試后&#xff0c;只是少了 CPU 的報錯&#xff0c;但 TPM 2 過不了。 后來在網上找到這篇文章&#xff0c; 先試了幾…

JCR一區級 | Matlab實現TCN-BiGRU-MATT時間卷積雙向門控循環單元多特征分類預測

JCR一區級 | Matlab實現TCN-BiGRU-MATT時間卷積雙向門控循環單元多特征分類預測 目錄 JCR一區級 | Matlab實現TCN-BiGRU-MATT時間卷積雙向門控循環單元多特征分類預測分類效果基本介紹程序設計參考資料 分類效果 基本介紹 1.Matlab實現TCN-BiGRU-MATT時間卷積雙向門控循環單元多…

一維時間序列信號的小波模極大值分解與重建(matlab R2018A)

數學上稱無限次可導函數是光滑的或沒有奇異性&#xff0c;若函數在某處有間斷或某階導數不連續&#xff0c;則稱函數在此處有奇異性&#xff0c;該點就是奇異點。奇異性反映了信號的不規則程度&#xff0c;因為信號的奇異點和突變部分往往攜帶者重要信息&#xff0c;因此信號的…

JDK1.8新特性1

JDK1.8新特性1 JDK1.8新特性&#xff1a;Lambda表達式&#xff1a;使用&#xff1a;無參數無返回值&#xff1a;單參數無返回值&#xff1a;多參數無返回值&#xff1a;多參數有返回值&#xff1a; 案例&#xff1a;案例1&#xff1a;案例2&#xff1a;案例3&#xff1a; 函數式…

代碼隨想錄訓練營Day 42|力扣62.不同路徑、63. 不同路徑 II

1.不同路徑 代碼隨想錄 視頻講解&#xff1a;動態規劃中如何初始化很重要&#xff01;| LeetCode&#xff1a;62.不同路徑_嗶哩嗶哩_bilibili 代碼&#xff1a; class Solution { public:int uniquePaths(int m, int n) {// dp[i][j] 表示從起點走到坐標為i&#xff0c;j的地方…

全自動打包封箱機:解析其在產品質量與安全保障方面的作用

在當今快節奏的生產環境中&#xff0c;全自動打包封箱機以其高效、精準的特點&#xff0c;正逐漸成為生產線上的得力助手。它不僅提升了生產效率&#xff0c;更在產品質量與安全保障方面發揮著舉足輕重的作用。星派將詳細解析全自動打包封箱機在產品質量與安全保障方面的作用。…

css簡單介紹

1.css介紹 css指的是層疊樣式(Cascadingstyle sheets)&#xff0c;是用來給HTML標簽添加樣式的語言。他可以設置HTML頁面中 文字大小&#xff0c;顏色&#xff0c;對齊方式及元素的 寬高&#xff0c; 位置 等樣式。 一個完整的網頁是由HTML、CSS、Javascript三部分組成。HT…

CLIP--Learning Transferable Visual Models From Natural Language Supervision

參考&#xff1a;CLIP論文筆記--《Learning Transferable Visual Models From Natural Language Supervision》_visual n-grams模型-CSDN博客 openAI&#xff0c;2021&#xff0c;將圖片和文字聯系在一起&#xff0c;----->得到一個能非常好表達圖片和文字的模型主題&#…

網絡安全-釣魚篇-利用cs進行釣魚

一、環境 自行搭建&#xff0c;kill&#xff0c;Windows10&#xff0c;cs 二、原理 如圖所示 三、釣魚演示 首先第一步&#xff1a;打開System Profiler-分析器功能 選擇克隆www.baidu.com頁面做釣魚 之后我們通過包裝域名&#xff0c;各種手段讓攻擊對象訪問&#xff1a;h…

Java面試題:Redis1_Redis的使用場景和如何解決Redis緩存穿透問題

Redis使用場景常見問題 緩存 緩存三兄弟(穿透,擊穿,雪崩) 雙寫一致 持久化 數據過期策略 數據淘汰策略 分布式鎖 setnx,redisson 消息隊列,延遲隊列 … 解決Redis緩存穿透問題 緩存穿透問題 請求->redis緩存->mysql數據庫 當一個新請求到來時,先會訪問redi…

JVM(Java虛擬機)筆記

面試常見&#xff1a; 請你談談你對JVM的理解?java8虛擬機和之前的變化更新?什么是OOM&#xff0c;什么是棧溢出StackOverFlowError? 怎么分析?JVM的常用調優參數有哪些?內存快照如何抓取&#xff1f;怎么分析Dump文件&#xff1f;談談JVM中&#xff0c;類加載器你的認識…

前端最新面試題(基礎模塊HTML/CSS/JS篇)

目錄 一、HTML、HTTP、WEB綜合問題 1 前端需要注意哪些SEO 2 img的title和alt有什么區別 3 HTTP的幾種請求方法用途 4 從瀏覽器地址欄輸入url到顯示頁面的步驟 5 如何進行網站性能優化 6 HTTP狀態碼及其含義 7 語義化的理解 8 介紹一下你對瀏覽器內核的理解? 9 html…

【C++】vector常見的使用方式

前言&#xff1a;在上一篇中我們講到了string類的模擬實現&#xff0c;今天我們將進一步的去學習vector的一些常用的使用方法。 &#x1f496; 博主CSDN主頁:衛衛衛的個人主頁 &#x1f49e; &#x1f449; 專欄分類:高質量&#xff23;學習 &#x1f448; &#x1f4af;代碼倉…

命運方舟臺服注冊 命運方舟臺服怎么注冊?不會操作看這里

命運方舟臺服注冊 命運方舟臺服怎么注冊&#xff1f;不會操作看這里 命運方舟作為今年備受矚目的一款MMORPG類型游戲&#xff0c;在上線前的預約數量已經一次又一次創下新高。這款游戲的開發商Smile gate真是給玩家們帶來了一款讓人眼前一亮的作品。游戲創建在虛幻引擎的基礎…