リソース取得解析


Javaプログラムを開発する過程で、私たちがよくしなければならないことは資源を得ることです.では、資源とは何でしょうか.はっきり言って、コンピュータの中でそれはデータの山です.ただ、このデータの山は私たちのjavaプログラムにはいろいろな表現形式があります.一般的にはFile、URL、InputStreamなどがあります.ファイルだけでは、プロファイル、javaクラスファイル、jpsファイル、ピクチャ、css、jsファイルなど、さまざまな種類があります.この林林総の資源に直面して、私たちは資源を読み取るインタフェースを設計する時、異なる形式の資源に対して方法を提供する必要があります.このようにして、私たちのインタフェースは実際の資源形式と結びついて、完全に抽象的ではありません.またjavaプログラムではリソースの格納場所も異なります.classpathに格納されているものもあれば、ファイルシステムに格納されているものもあれば、webアプリケーションに格納されているものもあります.異なる場所のリソースに対してjavaプログラムがこれらのリソースを取得する方法はそれぞれ異なります.
 
A、classpathのリソースを取得する:
URL url = this.getClass().getResource("resource_name");
URL url = this.getClass().getClassLoader().getResource("resource_name");
URL url = Thread.currentThread().getContextClassLoader().getResource("resource_name");

ではjdkではなぜclasspathの下のリソースを取得するための3つの方法が提供されているのでしょうか.その中にはいくつかの由来がある.1行目のコードはClassクラスのインスタンスを使用して取得され、2行目のコードは現在のクラスをロードしたclassloaderを使用して取得されます.jdkのソースコードを見ると、classクラスのインスタンスが最後にclassloaderをロードしてリソースを取得するように依頼されたことがわかります.
    public java.net.URL getResource(String name) {
        name = resolveName(name);
        ClassLoader cl = getClassLoader0();
        if (cl==null) {
            // A system class.
            return ClassLoader.getSystemResource(name);
        }
        return cl.getResource(name);
    }

上記のコードから,リソースのロードに対してクラスロードのような親委任メカニズムはないことが分かる.現在のクラスのclassloaderがnullでない場合、現在のクラスのclassloaderからリソースをロードします.現在のクラスのclassloaderがnullの場合にのみsystem classloaderからリソースをロードします.これにより、カスタム構成クラスがデフォルトの構成を上書きできるようになります.もちろん、j 2 seアプリケーションでclassloaderを特にカスタマイズしていない場合、自分で書いたクラスはsystem classloaderにロードされます.いったいclassを利用してリソースを取得するのとclassloaderを利用してリソースを取得するのとではどのような違いがありますか?違いはresolveName(name)という方法にあります.2つの方法は、リソース名の表示方法が異なります.次に、クラスパスのルート/|-comを表す簡単なパケット構造を示す.cn.test    |-Test.class    |-test2.txt  |-test1.txt
//                
URL url1 = this.getClass().getResource("test2.txt");
//   com.cn.test     ,  /
URL url2 = this.getClass().getResource("/com/cn/test/test2.txt");
//           
URL url3 = this.getClass().getClassLoader().getResource("test1.txt");
//    com.cn.test     
URL url4 = this.getClass().getResource("com/cn/test/test2.txt");


さらにservletでは、
this.getClass().getClassLoader().getResource("/").getPath();

これにより、classesディレクトリへのフルパスが取得されます.たとえば、E:/eclipseM 9/workspace/tree/WEB-INF/classes/この方法は、Web環境でもパスを決定することができます.
B、ファイルシステム中の資源を取得する
// 1、  File  
File file = new File("test.txt");
// 2、  File      
InputStream in = new FileInputStream(file);

なお、Fileのコンストラクション関数File(String name)におけるnameパラメータは、相対パスおよび絶対パスであってもよい.相対経路はSystemに対する.getProperties(「user.dir」)の.
C、Webアプリケーションにおけるリソースの取得
servletContext.getResourceAsStream(resource_name);

 
resource_namesはwebrootに対するパス表現です.例えばwebを取得する.xml,resource_nameは「/WEB-INF/web.xml」と表現されていますが、上記で紹介した様々なリソースの表現形式と保存場所に対してjavaでは統一的な処理方式が提供されていませんか?はい、java.net.URL. URL(Uniform Resource Locator)統合リソースロケータを名前から見る.強そうに見えます.しかし、多くの場合、私たちが必要とするリソースに位置付けることはできません.まず、jdkの一般的なURLにアクセスできるプロトコルは非常に限られています(もちろん拡張は可能ですが、面倒です);http、file、ftpなどがよく使われます.classpathやservletContextのリソースの取得方法は提供されていません.また、リソースが存在するか否かを判断する方法は提供されていません.私たちが本当にリソースを取得している間に異常を投げ出してこそ、リソースが取得できないことがわかります.次に、URLというクラスの職責は明確に区分されていません.リソースがリソースを取得するために使用されていることを示します.
 
さらに、
String path = getServletContext().getRealPath("/");

Webプロジェクトのフルパスを取得します.たとえば、E:/eclipseM 9/workspace/treeは私のWebプロジェクトのルートディレクトリです.
 
String webPath = ServletActionContext.getServletContext().getRealPath("/");

サーバのファイル保存アドレスに基づいて、プロジェクトの配置の絶対アドレスが見つかります.
 
以下の内容
From :  http://blog.csdn.net/ruyanhai/archive/2007/11/07/1871663.aspx
 
◆一般的に、相対パスを使用してリソースを取得する柔軟性が大きい.
 
例えば、現在のクラスはcom/bbebfe/Testである.class
 
画像リソース、例えばsample.gifはcom/bbebfe/sampleに置くべきだ.gif
 
これらの画像リソースがiconsディレクトリの下に配置する場合、com/bbebfe/icons/sampleであるべきである.gif
 
現在のクラスファイルのパスからリソースを取得するには、主に次の方法があります.
 
・現在のクラスがcomであると仮定する.bbebfe.Test
 
・パッケージがあるフォルダはbin
String imageName = "icons/sample.gif"
 
1、Classを通ります.getResource()クラスパスの下にあるリソースの位置決め(bin/com/bbebfe/icons/sample.gif)
 
Class clazz = this.getClass();
 
URL url = clazz.getResource(imageName);
 
 
2、ClassLoaderを通ります.getResource()位置決めパッケージのルートディレクトリの下のリソース(bin/icons/sample.gif)
 
Class clazz = this.getClass();

URLClassLoader loader = (URLClassLoader)clazz.getClassLoader();

URL url = loader.getResource(imageName);

3、ClassLoaderを通ります.findResource()は、リソースをカスタマイズする方法を提供します.
URL url = loader.findResource(imageName);

◆では、この3つの方法には違いがあります.私たちはいつどの方法を使うべきですか.
 
· Class.getResource()メソッド
 
この方法は実際にこのClassのClass LoaderのgetResource()メソッドによってリソースを得る、ClassLoaderのgetResource()メソッドを呼び出す前にClass.getResource()メソッドは、リソース名を一定の処理を行い、そのリソースの絶対名(absolute name)を構築します.
 
+リソース名が'/'('/u 002 f')で始まる場合、リソースの絶対名は'/'以降の部分である.
 
imageNameが「/icons/sample.gif」の場合、ここでは「icons/sample.gif」になります.
 
+それ以外の場合、絶対名は次のようになります(リソース名の前にmodified_package_name/):modified_package_name/resource_name(修正されたパッケージ名/リソース名)
 
修正されたパッケージ名は、現在のオブジェクトが存在するパッケージ名の'.'を意味します.('/u 002 e')を'/'に置き換えます.
 
ClassLoader.getResource()メソッドはnullの値を持つURLを返し、Class.getResource()メソッドは、最終的にClassLoader.getSystemResource(java.lang.String)にリソース要求を渡す.
 
· ClassLoader.getResource()メソッド
 
このリソースを検索する、リソース名は'/'で区切られたパスであり、この方法ではまず自分の父親ClassLoaderを検索し、自分の父親ClassLoaderによってリソースを検索する(実際には、父親の父親が空でない場合、父親は検索要求を上に提出する).自分の親ClassLoaderがnullである場合、Java仮想マシンに組み込まれているclass loaderを検索し、リソースリクエストを送信します.これらの操作が失敗すると、ClassLoaderは自分のfindResource()メソッドを呼び出してリソースを検索します.
 
· ClassLoader.findResource()メソッド
 
このメソッドは内部で指定されたリソースを検索し、自分のClass Loaderを実現した場合は、このメソッドを再ロードして自分の特定の方法でクラスファイルとリソースを検索する必要があります.
 
 
 
◆以上のまとめにより、三つの点を見ることができる.
 
1,getResource()にしてもfindResource()にしても、これらの方法はリソースの位置決め方法にすぎず、最終的にはURLを返すだけで、リソースの位置決めにすぎず、私たちはその後、自分の方法でこれらのリソースを読み取るべきである.ClassとClassLoaderで定義されているgetResourceAsStreamメソッドは、getResourceの拡張版であり、ここでは説明しない.
 
 
2クラスを相対パスとしてリソースを検索する必要がある場合はClassを呼び出す.getResource()メソッドは、ClassLoaderを直接呼び出さないでください.getResource()メソッドまた、ClassLoaderを定義してfindResourceメソッドを再ロードしない限り、ClassLoaderを直接呼び出す必要はありません.Class.getResource()メソッドでは、リソース名について一定の処理が行われます.ここでは、次の例を示します.
 
現在のクラスがEclipseエンジニアリングデータベースの下にあると仮定し、クラスが存在するパッケージはcomです.bbebfe.test、iconsディレクトリはbin/com/bbebfe/test/ディレクトリの下に置いて、icons/sampleを得る必要があります.gifファイルのURLは、thisを呼び出します.getClass().getResource()で得られたURLは、
 
       file:/E:/MyLife/MyProjects/Eclipse3.2/Database/bin/com/bbebfe/test/icons/disremove.gif
 
 
 
3、あるjarライブラリの画像リソースを同じiconsの下で統一的に管理したい場合があります.パケットの下のClassごとにiconsを構築するのではなく、ライブラリを相対パスとしてリソースを検索する必要がある場合があります.この場合、ClassLoaderを呼び出す必要があります.getResource()メソッド、例を挙げます.
 
・ある工事には以下のようなパッケージ構造がある.
 
       com.bbebfe.ui
 
       com.bbebfe.test
 
       com.bbebfe.database
 
・クラスを相対パスとする場合、各パケットの下にiconsディレクトリを作成し、対応するリソースファイルを配置する必要がある.次のようになります.
 
       com.bbebfe.ui/icons/...
 
       com.bbebfe.test/icons/...
 
       com.bbebfe.database/icons/...
 
・ルートディレクトリの下にiconsディレクトリを配置し、すべてのリソースをここに配置して管理することで、リソースの重複を防止することができる.次のような形です
 
       com.bbebfe.ui
 
       com.bbebfe.test
 
       com.bbebfe.database
 
       icons/sample.gif ...
 
ClassLoaderを呼び出すべきだgetResourceメソッドは、リソース名を処理する、つまり修正されたパケット名をリソース名の前に追加していないため、クラスが存在するパケットのルート下でリソースを検索する.(Javaプログラムを実行する構文はjava com.bbebfe.ui.Testであるため、ルートディレクトリはcomディレクトリの上位ディレクトリである).
 
 
 
◆最後に、Javaでは、リソースを特定する方法がいくつかありますが、Eclipseソースコードには、ファイルリソースを特定するコードが次のようなものがあります.まだ研究する時間がありません.
 
ProtectionDomain domain = Main.class.getProtectionDomain();

CodeSource source = null;

URL result = null;

if (domain != null)

source = domain.getCodeSource();//  code source

if (source != null)

      result = source.getLocation();//  URL

          

String path = decode(result.getFile());//

// normalize to not have leading / so we can check the form

File file = new File(path);

path = file.toString().replace('//', '/');

// create a file URL (via File) to normalize the form (e.g., put

// the leading / on if necessary)

path = new File(path).toURL().getFile();

 
 
転載は出典を明記してください:http://lucien-zzy.iteye.com/admin/blogs/2001768