SpringのRestTemplate
を使用して応答をログに記録したい。最初はClientHttpRequestInterceptor
を使用してそれを実行する必要があると思いましたが、すべてのリクエストのセットを別のファイルに記録する必要があるため、すべてのリクエストセットに対して新しいRestTemplate
を使用して新しいClientHttpRequestInterceptor
を作成する必要があることがわかりました(他のすべての構成は同じ)。
しかし、RestTemplate
は作成に非常に負荷がかかるオブジェクトであり、作成時間の約70%がMessageConverters
を作成しているときにわかりました。
それで-この要件を実装するより良い方法はありますか?複数のMessageConverters
インスタンスでRestTemplate
を共有して、パフォーマンスを大幅に向上させることは可能ですか?
[〜#〜] edit [〜#〜]これが私のコードのサンプルです:
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>>(){});
}
OutputFileはどこに追加できますか?
さて、私はこの質問で考えていました、そしてこれは私が得るものです:
引用質問の所有者:
しかし、RestTemplateは作成するのにかなり高価なオブジェクトであり、作成時間の約70%がMessageConvertersを作成しているのを見ました。
概念的には、JdbcTemplate、JmsTemplate、およびSpring Frameworkやその他のポートフォリオプロジェクトにあるその他のさまざまなテンプレートと非常に似ています。これは、たとえば、RestTemplateが構築されるとスレッドセーフであることを意味します
この最後の機能は、構築後にRestTemplateを変更しないことを推奨しています。だから私は新しいインターセプターを追加したり削除したりしません
私たちはシステムとその要件、境界などに関する多くの詳細を見逃しています...
これらのファイルの目的がわかりません。そのため、提案するソリューションの妥当性が損なわれます。
私が正しい場合、 Appache Log4J が構成されています。 (@ナティはチャットで教えてくれました)。
そこで、Log4jをロガーツールとして使用することにしました。ただし、Drawbacksセクションを確認してください。 (この答えを読んでいる誰かが私の疑問を払拭してくれることを願っています)
なぜ自分のファイル管理の代わりにLog4jを使用するのですか?Log4jに次の機能を委任したかったので、ファイルへのアクセス、パターンの使用法、フィルターの使用法(オプション)、レベルの使用法、...
可能な限りカップリングの少ないレイヤーを介してソリューションを移植できるように、ヘルパーを実装しました。
_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);
}
}
_
所有者のコードにソリューションを添付する
_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;
}
_
注:実装は、getInterfaces
bucleを持っている(私が思う)for
呼び出し元に移動することもでき、 outputFile
。次に、getCustomFileLogger(...)
が1回だけ呼び出されます。
_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");
}
}
_
私が得た出力
_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
_
これは提案です。それは提案や改善に開かれています。私の解決策にも疑問があります。 (私は解決策を強調しませんでした):
Log4jを使用したのは、ロガーを分離して全員を独自のファイルに印刷することを要件とすることを念頭に置いていたためです。しかし、ログトレースのみが含まれることを期待しています(詳細なレビューまたはデバッグの場合)。
ただし、ファイルのコンテンツが重要である場合、コンテンツが重要であると、ソリューションは適切ではありません。
コンテンツが重要で、ファイル管理を実装したくない場合は、これらのログをnoSQLdb's( mongoDB、または私たちのプラットフォームに適したその他のすべて)。これも大量のデータをサポートできます。データは後で適切な要求で取得できます