Registrazione delle risposte di RestTemplate

5

Voglio registrare le risposte utilizzando% di% co_de di Spring. All'inizio pensavo di doverlo fare usando un RestTemplate , ma poiché ogni serie di richieste dovrebbe essere registrata su un file diverso, ho capito che dovrei creare un nuovo ClientHttpRequestInterceptor con un nuovo RestTemplate per ogni serie di richieste (sebbene tutte le altre configurazioni siano uguali).

Ma ho visto che ClientHttpRequestInterceptor è un oggetto piuttosto costoso da creare, quando circa il 70% del tempo di creazione sta creando RestTemplate .

Quindi - c'è un modo migliore per implementare questo requisito? È possibile condividere MessageConverters su più istanze di MessageConverters , quindi migliorare significativamente le prestazioni?

Modifica Ecco un esempio del mio codice:

protected MyResponse<MyInterface> getInterfaces(RestTemplate restClient, RestParams inputParams, String cookie, File outputFile) {

    Request devInterfacesRequest = getRequest(RequestType.INTERFACES, inputParams, cookie);

    return restClient.postForObject(inputParams.getUrl(), devInterfacesRequest , new ParameterizedTypeReference<MyResponse<MyInterface>>(){});
}

Dove posso aggiungere il file di output?

    
posta Nati 19.04.2016 - 23:10
fonte

1 risposta

1

Beh, ho pensato a questa domanda e questo è ciò che ottengo:

Restrizioni

Cita il proprietario della domanda:

  1. Per implementare il mio RestTemplate è troppo pesante

But I saw that RestTemplate is pretty expensive object to create, when about 70% of the creation time, is creating the MessageConverters.

  1. RestTemplate non è thread-safe dopo la costruzione. Ma non è dopo la costruzione . Vedi altro Il thread di RestTemplate è sicuro?

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

Questa ultima funzione suggerisce di non modificare un RestTemplate dopo la sua costruzione. Quindi non aggiungerei né alcun nuovo Interceptor, né rimuoverlo

  1. Ci mancano molti dettagli sul sistema e sui suoi requisiti, limiti, ecc ...

  2. Non sappiamo a cosa servono questi file. Quindi compromette l'adeguatezza della soluzione che propongo.

Che cosa abbiamo?

Se ho ragione, abbiamo configurato Appache Log4J . ( @Nati mi ha detto per chat ).

Quindi ho deciso di usare Log4j come strumento di registrazione. Tuttavia, consulta la sezione Svantaggi . ( spero che qualcun altro a leggere questa risposta possa dissipare i miei dubbi )

Perché Log4j invece della mia gestione dei file? Perché volevo delegare a Log4j le seguenti funzionalità: accesso ai file , utilizzo dei pattern , utilizzo dei filtri (facoltativo) , utilizzo dei livelli , ...

Soluzione

LoggerHelper

Ho implementato un helper per rendere la soluzione portatile attraverso qualsiasi livello con il minor accoppiamento possibile.

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);
    }
}

Attuazione

Allegare la soluzione al codice proprietario

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;
}

Nota : L'implementazione potrebbe anche essere spostata in getInterfaces chiamante che ha (suppongo) un for bucle e decide anche il outputFile . Quindi getCustomFileLogger(...) verrebbe invocato una sola volta.

test

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");
    }
}

file.txt

L'output che ho ottenuto

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

Dubbi

Questo è un suggerimento. È aperto a suggerimenti o miglioramenti. Ho anche i miei dubbi sulla mia soluzione. ( Non ho sottolineato la soluzione ):

  1. È File outputFile bloccato (aperto) da qualsiasi altro processo? Quindi verrà lanciata IOException.
  2. Home page qualsiasi diverso outputFile sono? 10,100,1000? Possiamo tenere un sacco di Logger in Log4j?
  3. Questi outputFile verranno spostati in runtime? Se qualcuno viene spostato / eliminato / sostituito log4j, non sarà in grado di continuare ad accedere.
  4. Prenderemo IOException invece di lasciarlo andare ?. Delega a LoggerHelper l'utente per decidere cosa fare ...

Ho usato Log4j perché ho avuto in mente che il requisito è di tenere separati i logger che stampano tutti sul proprio file. Ma mi aspetto che contengano solo tracce di registro ( per ulteriori recensioni o debug ).

Tuttavia, se il contenuto del file è importante, se il contenuto è importante per noi, la soluzione non è adatta.

Se il contenuto conta e non voglio implementare una gestione dei file , penserei di archiviare questi log in noSQL db's (mongoDB o qualsiasi altro più adatto per la nostra piattaforma) che è anche in grado di supportare un volume elevato di dati. I dati possono essere ottenuti in seguito con richieste appropriate

    
risposta data 03.05.2016 - 14:29
fonte

Leggi altre domande sui tag