জারের ভিতরে ফাইলটি বসন্তের জন্য দৃশ্যমান নয়


107

সব

আমি নীচের MANIFEST.MF এর সাথে একটি জার ফাইল তৈরি করেছি:

Manifest-Version: 1.0
Ant-Version: Apache Ant 1.8.3
Created-By: 1.6.0_25-b06 (Sun Microsystems Inc.)
Main-Class: my.Main
Class-Path: . lib/spring-core-3.2.0.M2.jar lib/spring-beans-3.2.0.M2.jar

এর মূলে মাইকনফিগ নামে একটি ফাইল রয়েছে যা আমার বসন্ত-প্রসঙ্গে context এক্সএমএলে রেফারেন্স করা আছে:

<bean id="..." class="...">
    <property name="resource" value="classpath:my.config" />
</bean>

আমি যদি জারটি চালাই, তবে নির্দিষ্ট ফাইলটি লোড হওয়ার জন্য সবকিছুই দুর্দান্ত দেখায়:

Caused by: java.io.FileNotFoundException: class path resource [my.config] cannot be resolved to absolute file path because it does not reside in the file system: jar:file:/D:/work/my.jar!/my.config
        at org.springframework.util.ResourceUtils.getFile(ResourceUtils.java:205)
    at org.springframework.core.io.AbstractFileResolvingResource.getFile(AbstractFileResolvingResource.java:52)
    at eu.stepman.server.configuration.BeanConfigurationFactoryBean.getObject(BeanConfigurationFactoryBean.java:32)
    at eu.stepman.server.configuration.BeanConfigurationFactoryBean.getObject(BeanConfigurationFactoryBean.java:1)
    at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:142)
    ... 22 more
  • ক্লাসগুলি জারের ভিতরে থেকে লোড করা হয়
  • বসন্ত এবং অন্যান্য নির্ভরতা পৃথক জারগুলি থেকে বোঝা হয়
  • বসন্ত প্রসঙ্গে লোড করা হয়েছে (নতুন ক্লাসপ্যাথএক্সএমএল অ্যাপ্লিকেশন কনটেক্সট ("বসন্ত-প্রসঙ্গ / অ্যাপ্লিকেশনকন্টেক্সটেক্স। এক্সএমএল"))
  • my.properties প্রোপার্টিপ্লেসহোল্ডার কনফিগারার ("শ্রেণিপথ: my.properties") এ লোড করা হয়
  • আমি যদি আমার .config ফাইলটি ফাইল সিস্টেমের বাইরে রাখি এবং উত্স url কে 'ফাইল:' তে পরিবর্তন করি তবে সবকিছু ঠিক আছে বলে মনে হচ্ছে ...

কোন টিপস?

উত্তর:


217

যদি আপনার স্প্রিং-কনটেক্সট.এক্সএমএল এবং মাইকনফাইগ ফাইলগুলি বিভিন্ন জারে থাকে তবে আপনার ব্যবহারের দরকার হবে classpath*:my.config?

আরও তথ্য এখানে

এছাড়াও, জার ফাইলের ভিতরে থেকে লোড করার সময় আপনি ব্যবহার করছেন resource.getInputStream()না তা নিশ্চিত resource.getFile()করুন।


4
তারা একই জারে রয়েছে, তবে আমি একই সমাধানে আপনার সমাধানটি চেষ্টা করেছি: java.io.FileNotFoundException: শ্রেণীর পথের সংস্থান [ক্লাসপাথ *: মাইকনফিগ] ইউআরএল-তে সমাধান করা যায় না কারণ এটি বিদ্যমান নেই
বিটাকাকস

14
আবার খুঁজছেন, আপনার কিছু কলিং কোড (সম্ভবত বিয়ান কনফিগারেশনফ্যাক্টরিবিয়ান) জাভা.আইও.ফাইলে লোড করার চেষ্টা করছে। ফাইল ফাইল সিস্টেমের ফাইলগুলিকে বোঝায় যা কোন জারে প্রবেশকারী নয়। কলিং কোডটি একটি জারটি লোড করার পরিবর্তে রিসোর্স.জেটইনপুট স্ট্রিম ব্যবহার করা উচিত।
sbk

60
... এবং এই উত্তরটি ... ধন্যবাদ! জারের অভ্যন্তরে
রিসোর্স.জেটফিল

4
কোন সুযোগ আছে "কেন?" একটি জারের ভিতরে getFile () ব্যবহার না করার পিছনে? এটি কি সহজভাবে ফাইলটি জারের ভিতরে রয়েছে এবং তাই "ফাইল "টি জার ফাইলটি ??
রকমিটহার্ডপ্লেস

8
এটাই. একটি java.io.File ডিরেক্টরি সিস্টেমের মধ্যে ফাইল সিস্টেমে একটি ফাইল উপস্থাপন করে। জারটি java.io.File। তবে সেই ফাইলের মধ্যে যে কোনও কিছু জাভা.আইও.ফাইলে নাগালের বাইরে। যতদূর জাভা সম্পর্কিত, এটি সঙ্কুচিত হওয়া অবধি, জার ফাইলের একটি শ্রেণি একটি শব্দের ডকুমেন্টের শব্দের চেয়ে আলাদা নয়।
এসবিকে

53

আমি জানি এই প্রশ্নের উত্তর ইতিমধ্যে দেওয়া হয়েছে। তবে, বসন্ত বুট যারা ব্যবহার করেন তাদের ক্ষেত্রে, এই লিঙ্কটি আমাকে সহায়তা করেছে - https://smarterco.de/java-load-file-classpath-spring-boot/

তবে, resourceLoader.getResource("classpath:file.txt").getFile();এই সমস্যাটি সৃষ্টি করছিল এবং এসবিকের মন্তব্য:

এটাই. একটি java.io.File ডিরেক্টরি সিস্টেমের মধ্যে ফাইল সিস্টেমে একটি ফাইল উপস্থাপন করে। জারটি java.io.File। তবে সেই ফাইলের মধ্যে যে কোনও কিছু জাভা.আইও.ফাইলে নাগালের বাইরে। যতদূর জাভা সম্পর্কিত, এটি সঙ্কুচিত হওয়া অবধি, জার ফাইলের একটি শ্রেণি একটি শব্দের ডকুমেন্টের শব্দের চেয়ে আলাদা নয়।

getInputStream()পরিবর্তে কেন ব্যবহার করতে হবে তা বুঝতে আমাকে সহায়তা করেছিল । এটা এখন আমার জন্য কাজ করে!

ধন্যবাদ!


39

বসন্ত জারের প্যাকেজে আমি নতুন ব্যবহার করি ClassPathResource(filename).getFile()যা ব্যতিক্রম ছুঁড়ে ফেলে:

পরম ফাইল পাথের সমাধান করা যায় না কারণ এটি ফাইল সিস্টেম: জারে থাকে না

তবে ব্যবহার করা new ClassPathResource(filename).getInputStream()এই সমস্যার সমাধান করবে। কারণটি হ'ল জারে কনফিগারেশন ফাইল অপারেটিং সিস্টেমের ফাইল ট্রিতে বিদ্যমান নেই, তাই অবশ্যই ব্যবহার করতে হবে getInputStream()


2

টমক্যাট ..x ব্যবহার করার সময় আমারও একই সমস্যা ছিল এবং আমি যে পরামর্শগুলি পেয়েছি সেগুলির কোনওটিই সহায়তা করছে না। শেষে আমি workফোল্ডারটি (টমক্যাটের) মুছলাম এবং সমস্যাটি চলে গেল।

আমি জানি এটি অযৌক্তিক তবে ডকুমেন্টেশনের উদ্দেশ্যে ...


1

@Sbk এর উত্তরটি আমাদের মতে স্প্রিং-বুট পরিবেশে (@ ভ্যালু ("$ {ক্লাসপাথ *:})) বাদে আমাদের করা উচিত। জার..আমি কিছু ভুল করেছি।

তবে এটি এটি করার অন্য একটি উপায় হতে পারে,

InputStream is = this.getClass().getClassLoader().getResourceAsStream(<relative path of the resource from resource directory>);

1

আমার সমস্যা আরও জটিল ছিল কারণ আমার একই নামের একাধিক ফাইল রয়েছে, একটি মূল স্প্রিং বুট জারে এবং অন্যরা মূল ফ্যাট জারের অভ্যন্তরে জারে থাকে। আমার সমাধানটি একই নামের সাথে সমস্ত সংস্থান পেয়েছিল এবং এর পরে প্যাকেজের নামে ফিল্টারিংয়ের জন্য আমার প্রয়োজন হয়। সমস্ত ফাইল পেতে:

ResourceLoader resourceLoader = new FileSystemResourceLoader();
final Enumeration<URL> systemResources = resourceLoader.getClassLoader().getResources(fileNameWithoutExt + FILE_EXT);

0

আমার স্প্রিং অ্যাপ্লিকেশনটিতে পুনরাবৃত্তভাবে সংস্থানগুলি লোড করার একটি সমস্যা আমার ছিল এবং আমি খুঁজে পেয়েছি যে সমস্যাটি আমার ব্যবহার করা উচিত resource.getInputStream। এখানে কতটা যাও recursively সমস্ত ফাইল মধ্যে পড়তে একটি উদাহরণ config/myfilesযে jsonফাইল।

উদাহরণ.জভা

private String myFilesResourceUrl = "config/myfiles/**/";
private String myFilesResourceExtension = "json";

ResourceLoader rl = new ResourceLoader();

// Recursively get resources that match. 
// Big note: If you decide to iterate over these, 
// use resource.GetResourceAsStream to load the contents
// or use the `readFileResource` of the ResourceLoader class.
Resource[] resources = rl.getResourcesInResourceFolder(myFilesResourceUrl, myFilesResourceExtension);

// Recursively get resource and their contents that match. 
// This loads all the files into memory, so maybe use the same approach 
// as this method, if need be.
Map<Resource,String> contents = rl.getResourceContentsInResourceFolder(myFilesResourceUrl, myFilesResourceExtension);

রিসোর্সলোডার.জভা

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.util.StreamUtils;

public class ResourceLoader {
  public Resource[] getResourcesInResourceFolder(String folder, String extension) {
    ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
    try {
      String resourceUrl = folder + "/*." + extension;
      Resource[] resources = resolver.getResources(resourceUrl);
      return resources;
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  public String readResource(Resource resource) throws IOException {
    try (InputStream stream = resource.getInputStream()) {
      return StreamUtils.copyToString(stream, Charset.defaultCharset());
    }
  }

  public Map<Resource, String> getResourceContentsInResourceFolder(
      String folder, String extension) {
    Resource[] resources = getResourcesInResourceFolder(folder, extension);

    HashMap<Resource, String> result = new HashMap<>();
    for (var resource : resources) {
      try {
        String contents = readResource(resource);
        result.put(resource, contents);
      } catch (IOException e) {
        throw new RuntimeException("Could not load resource=" + resource + ", e=" + e);
      }
    }
    return result;
  }
}

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.