Bem, eu tenho pensado nessa questão e é isso que eu recebo:
Restrições
Citando o proprietário da pergunta:
- Implementar meu próprio RestTemplate é pesado
But I saw that RestTemplate is pretty expensive object to create, when about 70% of the creation time, is creating the MessageConverters.
- RestTemplate não é thread-safe após a construção. Mas não é após a construção . Veja mais O segmento RestTemplate é seguro?
Conceptually, it is very similar to the JdbcTemplate, JmsTemplate, and the various other templates found in the Spring Framework and other portfolio projects. This means, for instance, that the RestTemplate is thread-safe once constructed
Este último recurso está sugerindo não modificar um RestTemplate após sua construção. Então eu não adicionaria nenhum novo Interceptor nem o removeria
-
Sentimos falta de muitos detalhes sobre o sistema e seus requisitos, limites, etc.
-
Não sabemos para que servem esses arquivos. Por isso, compromete a adequação da solução que proponho.
O que temos?
Se eu estiver certo, temos Log4J do Appache configurado. ( @Nati me contou por chat ).
Então, decidi usar o Log4j como ferramenta de registro. No entanto, confira a seção Desvantagens . ( espero que alguém que leia esta resposta possa dissipar minhas dúvidas )
Por que Log4j ao invés do meu próprio gerenciamento de arquivos? Porque eu queria delegar ao Log4j os seguintes recursos: acesso a arquivos , uso de padrões , uso de filtros (opcional) , uso de níveis , ...
Solução
LoggerHelper
Eu implementei um auxiliar para tornar a solução portátil através de qualquer camada com o menor acoplamento possível.
package org.myworkouts.helper;
import java.io.File;
import java.io.IOException;
import org.apache.log4j.FileAppender;
import org.apache.log4j.Level;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;
public class LoggerHelper {
// Helper's own logger
private static final Logger LOGGER = LogManager
.getLogger(LoggerHelper.class);
private static final String DEFAULT_LOG_PATTERN = "%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n";
private static final String LOGGER_PREFIX = "logger";
private static final String APPENDER_PREFIX = "appender";
private static LoggerHelper instance = null;
// Singleton
private LoggerHelper() {
super();
}
public static LoggerHelper getInstance() {
if (instance == null) {
instance = new LoggerHelper();
}
return instance;
}
/**
* Get the logger by its name or create if never was instanciated previously
*
* @throws IOException
*/
public Logger getCustomFileLogger(String filePath) throws IOException {
String loggerName = resolveLoggerName(filePath);
Logger logger = LogManager.exists(loggerName);
if (logger == null) {
LOGGER.info("Creating new Logger: ".concat(loggerName));
logger = LogManager.getLogger(loggerName);
}
setLevel(logger, Level.INFO).addFileAppender(logger, filePath);
return logger;
}
private LoggerHelper addFileAppender(Logger logger, String filePath)
throws IOException {
if (logger != null) {
String appenderName = resolveAppenderName(filePath);
if (logger.getAppender(appenderName) == null) {
logger.addAppender(new FileAppender(new PatternLayout(
DEFAULT_LOG_PATTERN), filePath, Boolean.TRUE));
}
}
return this;
}
private LoggerHelper setLevel(Logger logger, Level level) {
if (logger != null) {
logger.setLevel(level);
}
return this;
}
/* Optionl. Generate a custom name for a new Appender */
private String resolveAppenderName(String filePath) {
return APPENDER_PREFIX.concat(File.pathSeparator).concat(
getNameWithoutExtension(filePath));
}
/* Optionl. Generate a custom name for a new Logger */
private String resolveLoggerName(String filePath) {
return LOGGER_PREFIX.concat(File.pathSeparator).concat(
getNameWithoutExtension(filePath));
}
//Took from com.google.common.io.Files
//I had it in my workspace but I didn't want to use it at this
//class
private String getNameWithoutExtension(String filePath) {
String fileName = new File(filePath).getName();
int dotIndex = fileName.lastIndexOf('.');
return (dotIndex == -1) ? fileName : fileName.substring(0, dotIndex);
}
}
Implementação
Anexando a solução ao código do proprietário
protected MyResponse<MyInterface> getInterfaces(RestTemplate restClient, RestParams inputParams, String cookie, File outputFile) {
Request devInterfacesRequest = getRequest(RequestType.INTERFACES, inputParams, cookie);
MyResponse<MyInterface> response = restClient.postForObject(inputParams.getUrl(), devInterfacesRequest , new ParameterizedTypeReference<MyResponse<MyInterface>>(){});
try{
Logger customLogger = LoggerHelper.getInstance().getCustomFileLogger(outputFile.getPath());
//... we can also to parse it to Json, XML, whatever...
customLogger.info(response.toString());
}catch(IOException ex){
//... what do we have to do if logger could not be instanciated?
}
return response;
}
Observação : A implementação também pode ser movida para getInterfaces
do chamador que tem (eu suponho) um for
bucle e também decide o outputFile
. Então getCustomFileLogger(...)
seria invocado apenas uma vez.
Teste
public class LoggerHelperTest {
public static final Logger LOGGER = LogManager.getLogger(LoggerHelperTest.class);
@Test
public void getCustomLoggerTest() throws IOException{
Logger customLogger = LoggerHelper.getInstance().getCustomFileLogger("file.txt");
Assert.assertNotNull("CustomLogger should not be null",customLogger);
Assert.assertEquals("CustomLogger's level should be INFO by default",Level.INFO, customLogger.getLevel());
Assert.assertTrue("CustomLogger's name should contain file's name on its name",customLogger.getName().contains("file"));
customLogger.info("Trace 1");
customLogger.info("Trace 2");
customLogger.info("Trace 3");
}
}
arquivo.txt
A saída que recebi
2016-05-03 13:38:56 INFO logger:file:47 - Trace 1
2016-05-03 13:38:56 INFO logger:file:48 - Trace 2
2016-05-03 13:38:56 INFO logger:file:49 - Trace 3
Dúvidas
Esta é uma sugestão. Está aberto a sugestões ou melhorias. Eu também tenho minhas dúvidas sobre minha solução. ( eu não enfatizei a solução ):
- O arquivo
- Início quaisquer diferenças outputFile são? 10,100,1000? Podemos ter tantos loggers no Log4j?
- Esses outputFile serão movidos em tempo de execução? Se alguma for movida / excluída / substituída, o log4j não conseguirá manter o login.
- Vamos pegar o IOException em vez de deixá-lo ir ?. Eu delego ao usuário do LoggerHelper para decidir o que fazer ...
Eu usei o Log4j porque tenho em mente que o requisito é manter os registradores separados, imprimindo todos em seu próprio arquivo. Mas eu espero que eles só contenham rastreamentos de log ( para mais revisões ou debugs ).
No entanto, se o conteúdo do arquivo for importante, se o conteúdo for importante para nós, a solução não será adequada.
Se o conteúdo é importante e eu não quero implementar um gerenciamento de arquivos , eu pensaria em armazenar esses logs em noSQL db (mongoDB ou qualquer outro mais adequado para nossa plataforma) que também é capaz de suportar um alto volume de dados. Os dados podem ser obtidos posteriormente com solicitações adequadas