Carregar um recurso como uma string no Spring
1. Visão geral
Neste tutorial, veremos várias maneiras deinject the contents of a resource containing text as a String into our Spring beans.
Veremos como localizar o recurso e ler seu conteúdo.
Além disso, demonstraremos como compartilhar os recursos carregados em vários beans. Mostraremos isso por meio do uso deannotations related to dependency injection, embora o mesmo também possa ser obtido usandoXML-based injectione declarando os beans no arquivo de propriedade XML.
2. UsandoResource
Podemos simplificar a localização de um arquivo de recurso usando a interfaceResource. O Spring nos ajuda a encontrar e ler um recurso usando o carregador de recursos, que decide qual implementaçãoResource escolher, dependendo do caminho fornecido. OResource é efetivamente uma forma de acessar o conteúdo do recurso, ao invés do conteúdo em si.
Vamos ver algumas maneiras deacquire a Resource instance for resources on the classpath.
2.1. UsandoResourceLoader
Podemos usar a classeResourceLoader se preferirmos usar o carregamento lento:
ResourceLoader resourceLoader = new DefaultResourceLoader();
Resource resource = resourceLoader.getResource("classpath:resource.txt");
Também podemos injetarResourceLoader em nosso bean com@Autowired:
@Autowired
private ResourceLoader resourceLoader;
2.2 Using @Resource
Podemos injetar umResource diretamente em um bean Spring com@Value:
@Value("classpath:resource.txt")
private Resource resource;
3. Convertendo deResource emString
Assim que tivermos acesso aResource, precisamos ser capazes de lê-lo emString. Vamos criar uma classe de utilitárioResourceReader com um método estáticoasString para fazer isso por nós.
Primeiro, temos que adquirir umInputStream:
InputStream inputStream = resource.getInputStream();
Nosso próximo passo é pegar esseInputStreame convertê-lo emString. Podemos usar o métodoFileCopyUtils#copyToString do próprio Spring:
public class ResourceReader {
public static String asString(Resource resource) {
try (Reader reader = new InputStreamReader(resource.getInputStream(), UTF_8)) {
return FileCopyUtils.copyToString(reader);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
// more utility methods
}
Háare many other ways of achieving this, por exemplo, usandocopyToString da classeStreamUtils de Spring
Vamos também criar outro método utilitárioreadFileToString, que recuperaráResource para um caminho e chamará o métodoasString para convertê-lo emString.
public static String readFileToString(String path) {
ResourceLoader resourceLoader = new DefaultResourceLoader();
Resource resource = resourceLoader.getResource(path);
return asString(resource);
}
4. Adicionando uma classeConfiguration
Se cada bean tivesse que injetar o recursoStrings individualmente, há uma chance de duplicação de código e mais uso de memória pelos beans tendo sua própria cópia individual deString.
Podemos alcançar uma solução mais limpa injetando o conteúdo do recurso em um ou vários beans Spring ao carregar o contexto do aplicativo. Dessa maneira, podemos ocultar os detalhes de implementação para ler o recurso dos vários beans que precisam usar esse conteúdo.
@Configuration
public class LoadResourceConfig {
// Bean Declarations
}
4.1. Usando um Bean segurando a cadeia de recursos
Vamos declarar os beans para manter o conteúdo do recurso em uma classe@Configuration:
@Bean
public String resourceString() {
return ResourceReader.readFileToString("resource.txt");
}
Vamos agora injetar os beans registrados nos campos adicionando uma anotação@Autowired:
public class LoadResourceAsStringIntegrationTest {
private static final String EXPECTED_RESOURCE_VALUE = "..."; // The string value of the file content
@Autowired
@Qualifier("resourceString")
private String resourceString;
@Test
public void givenUsingResourceStringBean_whenConvertingAResourceToAString_thenCorrect() {
assertEquals(EXPECTED_RESOURCE_VALUE, resourceString);
}
}
Nesse caso, usamos a anotação@Qualifier e o nome do bean, comowe may need to inject multiple fields of the same type -String.
Devemos observar que o nome do bean usado no qualificador é derivado do nome do método que cria o bean na classe de configuração.
5. Usando o SpEL
Finalmente, vamos ver como podemos usar a linguagem Spring Expression para descrever o código necessário para carregar um arquivo de recurso diretamente em um campo em nossa classe.
Vamos usar a anotação@Value para injetar o conteúdo do arquivo no camporesourceStringUsingSpel:
public class LoadResourceAsStringIntegrationTest {
private static final String EXPECTED_RESOURCE_VALUE = "..."; // The string value of the file content
@Value(
"#{T(com.example.loadresourceasstring.ResourceReader).readFileToString('classpath:resource.txt')}"
)
private String resourceStringUsingSpel;
@Test
public void givenUsingSpel_whenConvertingAResourceToAString_thenCorrect() {
assertEquals(EXPECTED_RESOURCE_VALUE, resourceStringUsingSpel);
}
}
Aqui chamamosResourceReader#readFileToString descrevendo a localização do arquivo usando um caminho corrigido“classpath:” –dentro de nossa anotação@Value.
Para reduzir a quantidade de código no SpEL, criamos um método auxiliar na classeResourceReader que usa Apache CommonsFileUtils para acessar o arquivo a partir do caminho fornecido:
public class ResourceReader {
public static String readFileToString(String path) throws IOException {
return FileUtils.readFileToString(ResourceUtils.getFile(path), StandardCharsets.UTF_8);
}
}
6. Conclusão
Neste tutorial, revisamos algumas das maneiras deconvert a resource to a String.
Em primeiro lugar, vimos como produzir umResource para acessar o arquivo e como ler deResource paraString.
A seguir, também mostramos como ocultar a implementação do carregamento de recursos e permitir que o conteúdo da string seja compartilhado entre os beans criando beans qualificados em um@Configuration, permitindo que as strings sejam autowired.
Por fim, usamos o SpEL, que fornece uma solução compacta e imediata, embora exigisse uma função auxiliar personalizada para impedir que se tornasse muito complexo.
Como sempre, o código dos exemplos pode ser encontradoover on GitHub