java 类加载 解析_在Java中加载和解析资源的便捷方法

java 类加载 解析

I am working at Elasticsearch expert company and in my daily life, I see a lot of JSON: requests, responses, mappings, settings, etc. In 90% of cases, the functionality of software we make involves the manipulation of JSON. And it’s pretty common for us to have JSON files inside resources of Java code.

我在Elasticsearch专家公司工作,在日常生活中,我看到很多JSON :请求,响应,映射,设置等。在90%的情况下,我们制作的软件功能涉及JSON的操纵。 在我们的Java代码资源中包含JSON文件对我们来说是很常见的。

One day, after writing code to load and parse JSON for 100500th time I understood one thing: reading content of resources in Java is harder than it should be!

有一天,在编写了用于加载和解析JSON的代码的第100500次之后,我了解了一件事: 用Java读取资源内容比应该做的难

Just take a look. Let’s assume we have a resource com/adelean/junit/jupiter/resource.txt containing text:

看看吧 假设我们有一个包含文本的资源com / adelean / junit / jupiter / resource.txt

“The quick brown fox jumps over the lazy dog.”

“敏捷的棕色狐狸跳过了懒狗。”

This is one of existing ways to load its content:

这是加载其内容的现有方法之一:

Looks scary, doesn’t it? Need to open and close multiple streams/readers, handle IOException, all just to get text content.

看起来很吓人,不是吗? 需要打开和关闭多个流/阅读器,处理IOException ,所有这些都只是为了获取文本内容。

This Stackoverflow topic (https://stackoverflow.com/questions/15749192/how-do-i-load-a-file-from-resource-folder), and many others, explain how to load resources. You can give it a look, or better, to skip it and continue to read this article.

这个Stackoverflow主题( https://stackoverflow.com/questions/15749192/how-do-i-load-a-file-from-resource-folder )以及许多其他主题,说明了如何加载资源。 您可以看一下,或者更好地跳过它,并继续阅读本文。

Luckily for us, there are great libraries like google Guava, that significantly simplify the task. Here is the same operation made with Guava:

对我们来说幸运的是,有很多很棒的库,例如google Guava,可以大大简化任务。 这是使用番石榴进行的相同操作:

Even if it’s simpler, it is still too complicated for a task that probably must be done with one line. And we still have to handle exceptions.

即使比较简单,对于可能必须用一行完成的任务来说,它仍然太复杂。 而且我们仍然必须处理异常。

I always found it surprising why we must handle exceptions while loading java resources. While exception handling is justified for the files, because file can be absent, or doesn’t have right permissions, the situation is different for resources.

我总是感到很奇怪,为什么我们在加载Java资源时必须处理异常。 尽管有理由对文件进行异常处理,但是由于文件可能不存在或没有正确的权限,因此资源的情况有所不同。

Resources lay on the classpath of Java application, not on the filesystem. You almost never will have IOException, unless you made a mistake in your code. Loading of resources is closer to class import than to reading of file from the filesystem. You don’t surround your imports with try-catch, do you ?

资源位于Java应用程序的类路径上,而不位于文件系统上。 除非您在代码中犯了错误,否则您几乎永远不会有IOException 。 资源的加载比从文件系统读取文件更接近类导入。 您不会用try-catch包围进口,是吗?

That's where @InjectResources library (https://github.com/hosuaby/inject-resources) comes to rescue. It offers a fluid Java DSL for loading and parsing of resources without boilerplate code. It also provides extensions for Spring, and testing frameworks (JUnit4/5). With @InjectResources, resource reading can become as simple as adding annotation on the class field:

这就是@InjectResources库( https://github.com/hosuaby/inject-resources )抢救的地方。 它提供了流畅的Java DSL,无需样板代码即可加载和解析资源。 它还提供了Spring和测试框架( JUnit4 / 5 )的扩展。 使用@InjectResources ,资源读取可以变得像在类字段上添加注释一样简单:

@TextResource("com/adelean/junit/jupiter/resource.txt")
private String text;

Let’s take a look how it works!

让我们看看它是如何工作的!

The core of @InjectResources (https://hosuaby.github.io/inject-resources/0.1.0/asciidoc/#inject-resources-core) is a convenient and fluid Java DSL that takes away all boilerplate code like opening/closing of input streams and handling of I/O exceptions. First, you will need to add inject-resources-core to your project.

@InjectResources ( https://hosuaby.github.io/inject-resources/0.1.0/asciidoc/#inject-resources-core )的核心是方便且流畅的Java DSL,它消除了所有样板代码,如打开/关闭输入流和I / O异常的处理。 首先,您需要将inject-resources-core添加到您的项目中。

With Gradle:

使用Gradle

compile group: 'com.adelean', name: 'inject-resources-core', version: '0.1.0'

Or with Maven:

或使用Maven

<repositories>
<repository>
<snapshots>
<enabled>false</enabled>
</snapshots>
<id>central</id>
<name>bintray</name>
<url>https://jcenter.bintray.com</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.adelean</groupId>
<artifactId>inject-resources-core</artifactId>
<version>0.1.0</version>
</dependency>
</dependencies>

The entry point of DSL is method InjectResources.resource. It’s recommended to import that method statically:

DSL的入口点是方法InjectResources.resource 。 建议静态导入该方法:

import static com.adelean.inject.resources.core.InjectResources.resource;

After we can use fluent syntax to get content of any resource:

在我们可以使用流利的语法获取任何资源的内容之后:

var text = resource()
.withPath("/com/adelean/junit/jupiter", "resource.txt")
.text();

This syntax also offers various methods to open resources as binary InputStream or text Reader.

此语法还提供了各种方法来打开资源(如二进制InputStream或文本阅读器)

var schema = JavaPropsSchema
.emptySchema()
.withoutPathSeparator();
var reader = new JavaPropsMapper()
.readerFor(DbConnection.class)
.with(schema);
DbConnection dbConnection = resource()
.withPath("/com/adelean/junit/jupiter", "db.properties")
.asInputStream()
.parseChecked(reader::readValue);

Resources can also be read line by line in functional way:

资源也可以通过功能方式逐行读取:

var header = new AtomicReference<String>();
var lines = new ArrayList<String>();resource()
.onClassLoaderOf(getClass())
.withPath("/com/adelean/junit/jupiter", "cities.csv")
.asLines()
.onFirstLine(header::set)
.forEachLine(lines::add);

Some method names finish with word Checked. Those methods can accept lambdas that may throw checked exceptions. They are very convenient to avoid exception handling while using parsers that may throw exceptions:

一些方法名称以单词Checked结尾 。 这些方法可以接受可能引发检查异常的lambda。 它们在使用可能引发异常的解析器时避免异常处理非常方便:

Instead of this:

代替这个:

var dbConnection = resource()
.withPath("db.properties")
.asInputStream()
.parse(inputStream -> {
try {
return reader.readValue(inputStream);
} catch (IOException parsingException) {
throw new RuntimeException(parsingException);
}
});

We can write this:

我们可以这样写:

var dbConnection = resource()
.withPath("db.properties")
.asInputStream()
.parseChecked(reader::readValue);

inject-resources-core is a great alternative to low level libraries like Apache Commons or Google Guava. If you are interested, check the user guide for more information and examples: https://hosuaby.github.io/inject-resources/0.1.0/asciidoc/#inject-resources-core

inject-resources-core是Apache Commons或Google Guava等低级库的绝佳替代品。 如果您有兴趣,请查看用户指南以获取更多信息和示例: https : //hosuaby.github.io/inject-resources/0.1.0/asciidoc/#inject-resources-core

But if you are using Spring, you even can get your resources parsed and injected directly into your beans. Next section will discuss integration of @InjectResources with Spring.

但是,如果您使用的是Spring ,那么您甚至可以解析资源并将其直接注入到bean中。 下一节将讨论@InjectResourcesSpring的集成。

Spring has its own mechanism for resource loading. First we need to get reference to resource by one of three proposed methods. Using ResourceLoader:

Spring有其自己的资源加载机制。 首先,我们需要通过三种建议的方法之一来引用资源。 使用ResourceLoader

@Autowired
private ResourceLoader resourceLoader;// Later...var resource = resourceLoader
.getResource("classpath:com/adelean/junit/jupiter/resource.txt");

Using ResourceUtils:

使用ResourceUtils

var file = ResourceUtils
.getFile("classpath:com/adelean/junit/jupiter/resource.txt");

Or using Value annotation:

或使用值注释:

@Value("classpath:com/adelean/junit/jupiter/resource.txt")
private Resource resource;

After we got a reference to resource, we can read its content:

引用资源后,我们可以阅读其内容:

var textContent = Files.readString(resource.getFile().toPath());

Module inject-resources-spring (https://hosuaby.github.io/inject-resources/0.1.0/asciidoc/#inject-resources-spring) makes it possible to read content of resources with a single annotation. It also knows how to handle resources in various formats: binary, text, java properties, JSON and YAML.

模块inject-resources-spring ( https://hosuaby.github.io/inject-resources/0.1.0/asciidoc/#inject-resources-spring ) 使使用单个注释读取资源内容成为可能。 它还知道如何处理各种格式的资源:二进制,文本,java属性,JSON和YAML。

First, add dependency to your project.

首先,将依赖项添加到您的项目中。

With Gradle:

使用Gradle

compile group: 'com.adelean', name: 'inject-resources-spring', version: '0.1.0'

Or with Maven:

或使用Maven

<dependency>
<groupId>com.adelean</groupId>
<artifactId>inject-resources-spring</artifactId>
<version>0.1.0</version>
</dependency>

then enable resource injection

然后启用资源注入

@Configuration
@EnableResourceInjection
public class MyConfig {
}

After content of resources can be injected into components:

将资源内容注入组件之后:

@Component
public class BeanWithTextResource {
@TextResource("/com/adelean/junit/jupiter/resource.txt")
private String text;
}

Until that moment, we only saw how to dial with text resources, but @InjectResources can do much more. We can load and parse automatically java properties.

在那一刻之前,我们只看到了如何使用文本资源进行拨号,但是@InjectResources可以做更多的事情。 我们可以自动加载和解析java属性。

@Component
public class BeanWithPropertiesResource {
@PropertiesResource("/com/adelean/junit/jupiter/db.properties")
private Properties dbProperties;
}

and JSON documents

和JSON文档

@Component
public class BeanWithJsonResource {
@JsonResource("/com/adelean/junit/jupiter/sponge-bob.json")
private Map<String, Object> jsonAsMap;
}

and YAML documents

和YAML文件

@Component
public class BeanWithYamlResource {
@YamlResource("/com/adelean/junit/jupiter/sponge-bob.yaml")
Person spongeBob;
}

Annotations JsonResource and YamlResource will automatically convert resource content to the right types. But in order to work, they need parser. JsonResource uses ObjectMapper from Jackson or Gson object as parser. Ensure that you have one in application context:

批注JsonResourceYamlResource将自动将资源内容转换为正确的类型。 但是为了工作,他们需要解析器。 JsonResource使用来自Jackson的 ObjectMapper Gson对象作为解析器。 确保在应用程序上下文中有一个:

@Configuration
public class JacksonConfig {
@Bean
public ObjectMapper defaultObjectMapper() {
return new ObjectMapper();
}
}

YamlResource is using Snakeyaml, so bean of type Yaml must be present in context:

YamlResource使用的是Snakeyaml ,因此Yaml类型的bean必须存在于上下文中:

@Configuration
public class SnakeyamlConfig {
@Bean
public Yaml defaultYaml() {
return new Yaml();
}
}

This was an introduction into @InjectResource. This library is very simple but powerful. Don’t hesitate to take a look into documentation for more info and examples: https://hosuaby.github.io/inject-resources/0.1.0/asciidoc/#inject-resources-spring

这是@InjectResource的简介 。 该库非常简单,但功能强大。 不要犹豫,查看文档以获取更多信息和示例: https : //hosuaby.github.io/inject-resources/0.1.0/asciidoc/#inject-resources-spring

In the following article “A convenient way to read a resource file in Java unit test” we will see how to inject resource content into JUnit tests.

在下面的文章“在Java单元测试中读取资源文件的便捷方法”中,我们将看到如何将资源内容注入JUnit测试。

翻译自: https://medium.com/swlh/a-convenient-way-to-load-and-parse-resources-in-java-4061681f68bd

java 类加载 解析

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java是一种功能强大的编程语言,可以很好地处理超大文本解析存库的需求。在处理超大文本时,我们可以使用Java提供的各种库和技术来实现高效的解析和存储。 首先,我们可以使用Java的输入输出流来读取超大文本文件。通过逐行读取文本文件,我们可以避免一次性将整个文件加载到内存,从而减少了内存的消耗。同时,我们也可以使用缓冲流来提高读写效率。 其次,我们可以使用Java提供的字符串处理函数和正则表达式来解析和提取超大文本的数据。通过使用合适的字符串处理方法,我们可以快速准确地提取出所需的信息,并进行必要的格式转换和数据清洗。 在解析过程,我们可以使用Java的多线程技术来提高解析速度。通过将文本分割成多个子任务,每个子任务由一个独立的线程处理,可以并行地进行解析操作,从而大大加快了整个解析过程。 最后,我们可以使用Java的数据库连接技术将解析得到的数据存储到数据库Java提供了多种数据库连接方式,如JDBC、Hibernate等,可以方便地将解析得到的数据插入到数据库,实现持久化存储。 总的来说,Java提供了丰富的库和技术,可以很好地解决超大文本解析存库的问题。通过合理地选择和使用Java提供的功能,我们可以高效地处理大量的文本数据,并将其存储到数据库,为后续的分析和应用提供便利。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值