Java Webアプリケーションセルフアーキテクチャ4 Log 4 j 2ログ管理


前編ではDAOを汎用的に実現しましたが、続ける前に何か忘れてしまったようです.どんなプログラムを作るにも欠かせないもので、プログラムの機能には何の役にも立たず、忘れられがちですが、どの方法にも必要なものがあります.それはログです.
 
筆者のこれまでの経験ではLog 4 jをSpringに配置して使用していたが、これに沿ってlog 4 jの公式サイトにアクセスし、さらに新東東log 4 j 2を見て紹介した.log 4 jよりも優れた性能で、logbackの実現を行い、logbackの固有の問題を解決し、多くのfacadeフレームワークをサポートした.悪くないですね.そこでSpringにこれを加える考えを働かせて、ネット上で娄を探してひっくり返しました.のはい、私は物が少ないことを認めて、公式の英語のドキュメントにdebugの状態をつけてソースコードを見るしかありません.
 
log 4 j 2の公式サイトhttp://logging.apache.org/log4j/2.x/で、左側のナビゲーションバーをちらっと見て、大体中に入って見てみます:APIで言う必要はJDK 1.5以上、Architectureのクラスアーキテクチャ図、log 4 jとの統合や変換など.これらはすべて重要ではありません.今は使っていないので、後で遅く見に来なければなりません.私たちのポイントはコンフィギュレーションです.コンフィギュレーションページに入って、詳しく読んでみましょう.
 
コンフィギュレーションで説明されているように、構成はxml形式であってもよいし、json形式であってもよいし、符号化方式であってもよい.Spring@Configuration注記のApplicationContext.JAvaの中の方式、もちろん符号化の方式で、二言三言言わないで、直接その指すとおりに、ExtendingLog 4 j 2の中でどのように言いますかを見てみましょう.@Pluginなどの注釈構成が山積みで、大喜びです.しかし、長い間、効果がなかった.使いやすくてもSpringに配置するのは骨が折れることだと思いますが、やはりDebugに行きましょう.Logの使い方はこうです.
 
Logger logger = LogManager.getLogger(this.getClass());

 
この藤に沿って、瓜を触ることができる.LogManagerにはLog 4 jContextFactoryがあり、LoggerContextの生成を選択する.Contextという言葉を見ると、名前で得られた唯一の一例をたくさん積んだ容器が何をしているのか、簡単に考えられます.一例というのは自然にLoggerです.そのため、LogManagerのこのLogger Contextはクラス名でloggerを1つずつ対応することができます.OK、くだらないことを言わないで、続けて:LoggerContextがインスタンス化されたとき、属性コンフィギュレーションも同時にインスタンス化され、この例はDefaultコンフィギュレーションタイプである.インスタンス化後FacotryはまたContextを起動し、LoggerContextを呼び出した.start()メソッド.reconfiguraion()を使用します.このreconfiguration()は、システムの下での構成検索を行います.つまり、私たちが見ている公式サイトのAutomaticConfigurationに書かれている構成順序で検索します.(複数口:ここでDebugの過程でシステムデフォルトのClassLoaderを探して注釈された構成を探していることも確認されました.そして、私の注釈のクラスがClassLoaderにあるのを見て、なぜロードされていないのか、ずっと分かりません).Debugを続けると、最後に何も見つかりませんでした.DefaultConfigurationをもう一度ロードします.
 
そして筆者は頭を働かせ、Eclipseのコードヒント機能でpublicのない方法で構成をリダイレクトできるようにした.案の定、見つけました.方法は以下の通りです.
 
Logger logger = LogManager.getLogger(this.getClass());
LoggerContext loggerContext =(LoggerContext)LogManager.getContext();
loggerContext.setConfiguration(new BaseConfiguration(){});

 
探してみると大変ですが、フレームワークは汎用性のライブラリとして、考えていることは周到で、私たちが今使っているのはこれだけで、直接貼って理解して使うのがもっと便利で速いです.もっと深くそれを見極めたい友达については、Debugの過程での楽しみを邪魔しません.
 
前述のBaseConfigurationクラスでは、そのまま匿名で実現すればよいのですが、なぜインタフェースConfigurationを使わないのかというと、見てみればわかりますが、DefaultConfigurationは構造方法を簡単に書いて継承すれば使えますが、匿名でConfigurationインタフェースを実装すれば、煩雑になります.筆者はこのように匿名でconfig()の方法を書いて、直接returnthisして、類体の後ろで直接.config()呼び出しは簡単にわかりやすく表示されます.これは主にConfigurationをしています.でもやってみたが、やはり使いにくい.さらにDefaultConfigurationがどのようにしてやったのかを見てみましょう:doConfigure()を空にして、Configurationにあるからです.start()後、呼び出されて多くのappenderがロードされ、自分で調製したものをカバーします.以上のように、上記のコードの最後の文は
 
loggerContext.setConfiguration(new BaseConfiguration(){
	public BaseConfiguration config(){
		setName("MyConfig");
		Layout<?> layout = PatternLayout.createLayout("%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n",null, null, null);
	    Appender<?> appender = ConsoleAppender.createAppender(layout, null, "SYSTEM_OUT", "Console", "true");
		appender.start();
		addAppender(appender);
		LoggerConfig root = getRootLogger();
		root.addAppender(appender, null, null);
		String levelName = System.getProperty("org.apache.logging.log4j.level");
		        Level level = levelName != null && Level.valueOf(levelName) != null ? Level.valueOf(levelName) : Level.ERROR;
		root.setLevel(level);
		return this;
	}
		
	@Override
	protected void doConfigure() {}
}.config());

 
テストして、そうだ、前にずっといくつかの操作が役に立たないと言っていましたが、どうやって見ましたか.答えは、書かれたコードのlayoutのPattenのいくつかのフォーマットパラメータを位置を変えて出力を見て、配属されたLayoutで出力されたかどうかを見るだけです.上記のconfigメソッド内のコードは完全にDefaultConfiguration構築メソッドの文であるため、layoutがコンソールから出力文字列が元の順序で打たれた場合、その構成はDefaultConfigurationであるかを変更する.以下の4行のコードを通常のJUnit 4の@Testメソッドに入れると、loggerは確かにクラス名が永遠に1つのインスタンスしか得られず、コンソールから出力された文字が自分で構成したlayoutに従って出力されたことをテストすることができます.構成が成功したことを証明します.
Logger logger = loggerContext.getLogger(this.getClass().getName());
Logger logger0 = loggerContext.getLogger(this.getClass().getName());
Assert.assertSame(logger,logger0);
logger.error("Test Error2");

 
以下、このlog 4 j 2の配置をSpringに入れておきますが、第1編を見てみると、この配置は簡単だと思いますが、Springの@Configuration注記のApplicationContext.JAvaでは,@Bean注釈の方法を書き,ReturnはLoggerContextを1つ出せばよいが,このLoggerContexは任意のSpringのBeanに注入してそのBeanをLogとして利用できる.もちろん共通のLog Beanを生成することもできる.では、コードセグメントを次のように貼ります.
@Bean
public LoggerContext log4j2Context() {
	LoggerContext loggerCtx = (LoggerContext) LogManager.getContext();
	loggerCtx.setConfiguration(new BaseConfiguration() {
		public BaseConfiguration config() {
			setName("webmodel-log-Config");
			Layout<?> consolelayout = PatternLayout.createLayout(
						"%d{HH:mm:ss.SSS} [%thread] %logger{36} %-5level - %msg%n",null, null, null);
			Appender<?> consoleAppender = ConsoleAppender.createAppender(consolelayout,null, "SYSTEM_OUT", "Console","true");
				
			Layout<?> fileLayout = HTMLLayout.createLayout("true", "Webmodel Error Log", "text/html", null, "x-small", "arial,serif");
			String fileName =this.getClass().getResource("/").getFile().replace("/classes/", "/log/")+"systemErrorLog.html";
			Appender<?> fileAppender = FileAppender.createAppender(fileName, "true", "false", "errorLog","true","true", "true", fileLayout, null);
				
			this.addAppender(consoleAppender);
			this.addAppender(fileAppender);
				
			LoggerConfig root = getRootLogger();
			root.setLevel(Level.ALL);
			root.addAppender(consoleAppender, Level.ERROR, null);
			root.addAppender(fileAppender, Level.INFO, null);
				
			return this;
		}

		@Override
		protected void doConfigure() {}
	}.config());
	return loggerCtx;
	}
	
	@Configuration
	static class LoggerConfiguration{
		private LoggerContext lctx;

		public LoggerContext getLctx() {
			return lctx;
		}
		@Resource
		public void setLctx(LoggerContext lctx) {
			this.lctx = lctx;
		}
		
		@Bean 
		public Logger commonLogger(){
			return lctx.getLogger("com.gxino.webmodel.CommonLogger");
		}
	}

 
このコードの配置は上よりupdateがあり、コンソールでError以上のレベルしか出力しないシステムログファイルを保存してINFO以上のレベルのログを出力したいので、デバッグの仕事もたくさんしました.まず、Appenderはstart()を使わない.BaseConfigurationのためだ.start()の時にします.次にrootではありませんaddAppender(appender,appenderLevel,appenderFilter);その後、logはこのレベルでログを作ることができます.1つのlogEventが応答する場合、loggerはisEnablerによってこの応答が奏効しないと判断し、その中でLogger Configすなわちrootによって判断し、logEventが応答する場合、各Appenderの具体的なレベルを見に行くからだ.どこでも、すべてのレベルはデフォルトでレベルです.ERROR、だからrootのLevelをALLに調整してisEnablelを過ぎさせて、具体的なAppenderのLevelを見に行きます.最後に、Htmlのファイルログはいいですね.この内容を終わらせるために図を貼ってください.
ベテランたちはすでに気づいているはずだが、あちこちにあふれているログを合わせると、煩雑になったり、いつも書くのを忘れたりして、解決する方法はないだろうか.すなわち,各メソッドの固定位置にログを自動的に書かせる.では、この固定位置は接面Aspectと見ることができますか?
 
OK,次編では,AOPを導入し,フェースプログラミングに向かう.