Ресурс Classpath не найден при запуске от имени jar
имея эту проблему как в Spring Boot 1.1.5, так и в 1.1.6 - я загружаю ресурс classpath с помощью аннотации @Value, которая отлично работает, когда я запускаю приложение из STS (3.6.0, Windows). Однако, когда я запускаю пакет mvn, а затем пытаюсь запустить jar, я получаю filenotfound исключения.
ресурсе, сообщение.txt, находится в src/main / resources. Я проверил банку и проверил, что она содержит сообщение файла".тхт" на верхнем уровне (на уровне приложение.свойства.)
вот приложение:
@Configuration
@ComponentScan
@EnableAutoConfiguration
public class Application implements CommandLineRunner {
private static final Logger logger = Logger.getLogger(Application.class);
@Value("${message.file}")
private Resource messageResource;
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Override
public void run(String... arg0) throws Exception {
// both of these work when running as Spring boot app from STS, but
// fail after mvn package, and then running as java -jar
testResource(new ClassPathResource("message.txt"));
testResource(this.messageResource);
}
private void testResource(Resource resource) {
try {
resource.getFile();
logger.debug("Found the resource " + resource.getFilename());
} catch (IOException ex) {
logger.error(ex.toString());
}
}
}
исключение:
c:UsersglyoderDocumentsworkspace-sts-3.5.1.RELEASEclasspath-resource-proble
mtarget>java -jar demo-0.0.1-SNAPSHOT.jar
. ____ _ __ _ _
/ / ___'_ __ _ _(_)_ __ __ _
( ( )___ | '_ | '_| | '_ / _` |
/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |___, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v1.1.5.RELEASE)
2014-09-16 08:46:34.635 INFO 5976 --- [ main] demo.Application
: Starting Application on 8W59XV1 with PID 5976 (C:Usersglyo
derDocumentsworkspace-sts-3.5.1.RELEASEclasspath-resource-problemtargetdemo
-0.0.1-SNAPSHOT.jar started by glyoder in c:UsersglyoderDocumentsworkspace-s
ts-3.5.1.RELEASEclasspath-resource-problemtarget)
2014-09-16 08:46:34.640 DEBUG 5976 --- [ main] demo.Application
: Running with Spring Boot v1.1.5.RELEASE, Spring v4.0.6.RELEA
SE
2014-09-16 08:46:34.681 INFO 5976 --- [ main] s.c.a.AnnotationConfigA
pplicationContext : Refreshing org.springframework.context.annotation.Annotation
ConfigApplicationContext@1c77b086: startup date [Tue Sep 16 08:46:34 EDT 2014];
root of context hierarchy
2014-09-16 08:46:35.196 INFO 5976 --- [ main] o.s.j.e.a.AnnotationMBe
anExporter : Registering beans for JMX exposure on startup
2014-09-16 08:46:35.210 ERROR 5976 --- [ main] demo.Application
: java.io.FileNotFoundException: class path resource [message.
txt] cannot be resolved to absolute file path because it does not reside in the
file system: jar:file:/C:/Users/glyoder/Documents/workspace-sts-3.5.1.RELEASE/cl
asspath-resource-problem/target/demo-0.0.1-SNAPSHOT.jar!/message.txt
2014-09-16 08:46:35.211 ERROR 5976 --- [ main] demo.Application
: java.io.FileNotFoundException: class path resource [message.
txt] cannot be resolved to absolute file path because it does not reside in the
file system: jar:file:/C:/Users/glyoder/Documents/workspace-sts-3.5.1.RELEASE/cl
asspath-resource-problem/target/demo-0.0.1-SNAPSHOT.jar!/message.txt
2014-09-16 08:46:35.215 INFO 5976 --- [ main] demo.Application
: Started Application in 0.965 seconds (JVM running for 1.435)
2014-09-16 08:46:35.217 INFO 5976 --- [ Thread-2] s.c.a.AnnotationConfigA
pplicationContext : Closing org.springframework.context.annotation.AnnotationCon
figApplicationContext@1c77b086: startup date [Tue Sep 16 08:46:34 EDT 2014]; roo
t of context hierarchy
2014-09-16 08:46:35.218 INFO 5976 --- [ Thread-2] o.s.j.e.a.AnnotationMBe
anExporter : Unregistering JMX-exposed beans on shutdown
8 ответов:
resource.getFile()
ожидает, что сам ресурс будет доступен в файловой системе, т. е. он не может быть вложен в файл jar. Вот почему он работает, когда вы запускаете приложение в STS, но не работает, как только вы построили свое приложение и запустите его из исполняемого файла jar. Вместо того, чтобы использоватьgetFile()
чтобы получить доступ к содержимому ресурса, я бы рекомендовал использоватьgetInputStream()
вместо. Это позволит вам читать содержимое ресурса независимо от того, где он находится.
если вы используете Spring framework, то чтение
ClassPathResource
наString
- это довольно просто с помощью весенние рамкиFileCopyUtils
:String data = ""; ClassPathResource cpr = new ClassPathResource("static/file.txt"); try { byte[] bdata = FileCopyUtils.copyToByteArray(cpr.getInputStream()); data = new String(bdata, StandardCharsets.UTF_8); } catch (IOException e) { LOG.warn("IOException", e); }
Если вы хотите использовать файл:
ClassPathResource classPathResource = new ClassPathResource("static/something.txt"); InputStream inputStream = classPathResource.getInputStream(); File somethingFile = File.createTempFile("test", ".txt"); try { FileUtils.copyInputStreamToFile(inputStream, somethingFile); } finally { IOUtils.closeQuietly(inputStream); }
когда spring boot project работает как jar и нужно прочитать какой-то файл в classpath, я реализую его с помощью кода ниже
Resource resource = new ClassPathResource("data.sql"); BufferedReader reader = new BufferedReader(new InputStreamReader(resource.getInputStream())); reader.lines().forEach(System.out::println);
Я столкнулся с этим ограничением и создал эту библиотеку, чтобы преодолеть эту проблему: spring-boot-jar-resources Это в основном позволяет зарегистрировать пользовательский ResourceLoader с Spring Boot, который извлекает ресурсы classpath из JAR по мере необходимости, прозрачно.
Я создал ClassPathResourceReader класс в java 8 способ сделать легко читать файлы из classpath
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.stream.Collectors; import org.springframework.core.io.ClassPathResource; public final class ClassPathResourceReader { private final String path; private String content; public ClassPathResourceReader(String path) { this.path = path; } public String getContent() { if (content == null) { try { ClassPathResource resource = new ClassPathResource(path); BufferedReader reader = new BufferedReader(new InputStreamReader(resource.getInputStream())); content = reader.lines().collect(Collectors.joining("\n")); reader.close(); } catch (IOException ex) { throw new RuntimeException(ex); } } return content; } }
использование:
String content = new ClassPathResourceReader("data.sql").getContent();
Нью-Джерси должна быть распакована банки.
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <requiresUnpack> <dependency> <groupId>com.myapp</groupId> <artifactId>rest-api</artifactId> </dependency> </requiresUnpack> </configuration> </plugin> </plugins> </build>
to get list of data from src/main/resources/data folder -- first of all mention your folder location in properties file as - resourceLoader.file.location=data inside class declare your location. @Value("${resourceLoader.file.location}") @Setter private String location; private final ResourceLoader resourceLoader; public void readallfilesfromresources() { Resource[] resources; try { resources = ResourcePatternUtils.getResourcePatternResolver(resourceLoader).getResources("classpath:" + location + "/*.json"); for (int i = 0; i < resources.length; i++) { try { InputStream is = resources[i].getInputStream(); byte[] encoded = IOUtils.toByteArray(is); String content = new String(encoded, Charset.forName("UTF-8")); } } } catch (IOException e) { throw new UncheckedIOException(e); } }