日志对于项目的重要性不言而喻,现在市面上的日志框架多种多样:logback-classic(SLF4J的亲儿子)、java.util.logging(JDK自带记录日志类)、log4j1(不建议继续使用)、log4j2(log4j1的新一代版本)、reload4j(解决Apache log4j version 1.2.17重要安全问题的分支) 等等,如果没有真正深入了解过,可能会被搞得眼花缭乱。本文将介绍目前Java项目中最常见的Log4j2 + Slf4j的使用组合,这也是我自己项目中目前使用的:MapReduce编程。
两个官网使用教程:SLF4J user manual、Apache Log4j 2
用于绑定日志门面SLF4J与日志框架实现的适配器介绍
用于重定向第三方日志框架到日志门面SLF4J的桥接器介绍(统一多个日志框架的输出)
简单的说,SLF4J提供日志接口以及获取具体日志对象的方法,不与任何日志实现强行绑定,通过适配器绑定具体的日志实现以进行日志的输出,通过桥接器将第三方日志重定向到SLF4J以实现不同日志框架的统一输出。SLF4J结合使用适配器和桥接器,统一了主流框架的输出(适配器+桥接器,多个日志框架输出重定向到指定的日志框架,实现日志的统一输出)、方便了日志输出的改造(桥接器,旧日志框架直接重定向到新的日志框架,不需要修改旧日志打印代码)、简化了日志打印的编程(适配器,不同日志框架使用同一套API)。
pom.xml/opt/logs UTF-8 [%d{yyyy-MM-dd HH:mm:ss.SSS}][%-5p] [%t] [%c{1}:%M %L] %m %n
Maven 指令 mvn:dependency:tree 查看依赖Jar 的关系
WordCountMapper.java4.0.0 com.jieky Hadoop 1.0-SNAPSHOT 3.3.3 UTF-8 junit junit 4.12 org.apache.hadoop hadoop-client 3.3.3 org.slf4j slf4j-api org.slf4j slf4j-log4j12 log4j log4j org.slf4j slf4j-reload4j ch.qos.reload4j reload4j org.apache.logging.log4j log4j-slf4j-impl 2.9.1 org.slf4j jcl-over-slf4j 1.7.36 org.slf4j jul-to-slf4j 1.7.36
import org.apache.hadoop.io.IntWritable; import org.apache.hadoop.io.LongWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.mapreduce.Mapper; import java.io.IOException; public class WordCountMapper extends MapperWordCountReducer.java{ @Override protected void setup(Context context) throws IOException, InterruptedException { System.out.println("setup方法执行了"); } // 复用两个变量 private Text outk = new Text(); private IntWritable outv = new IntWritable(1); @Override protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException { // 获取当前输入的数据(复用java实现的String处理方法) String line = value.toString(); // 切割数据 String[] datas = line.split(" "); // 遍历集合 封装 输出数据的key和value for (String data : datas) { outk.set(data); context.write(outk, outv); } System.out.println("map方法执行了"); } @Override protected void cleanup(Context context) throws IOException, InterruptedException { System.out.println("cleanup执行了"); } }
import org.apache.hadoop.io.IntWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.mapreduce.Reducer; import java.io.IOException; public class WordCountReducer extends ReducerWordCountDriver.java{ // 复用两个变量 private Text outk = new Text(); private IntWritable outv = new IntWritable(); @Override protected void reduce(Text key, Iterable values, Context context) throws IOException, InterruptedException { int total = 0; // 遍历values for (IntWritable value : values) { // 对value累加进行累加 输出结果 total+=value.get(); } // 封装key和value outk.set(key); outv.set(total); context.write(outk, outv); } }
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import java.io.IOException;
public class WordCountDriver {
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
//BasicConfigurator.configure();
// 声明配置对象
Configuration conf = new Configuration();
// 声明Job对象
Job job = Job.getInstance(conf);
// 指定ReduceTask的数量
job.setNumReduceTasks(3);
// 指定当前Job的驱动类(通过反射获得对象的实例)
job.setJarByClass(WordCountDriver.class);
// 指定当前Job的 Mapper和Reducer
job.setMapperClass(WordCountMapper.class);
job.setReducerClass(WordCountReducer.class);
// 指定Map段输出数据的key的类型和输出数据value的类型
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(IntWritable.class);
// 指定最终输出结果的key的类型和value的类型
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
// 指定输入数据的目录 和 输出数据的目录
FileInputFormat.setInputPaths(job, new Path("src/main/data/wcinput"));
FileOutputFormat.setOutputPath(job, new Path("src/main/data/wcoutput"));
//FileInputFormat.setInputPaths(job, new Path(args[0]));
//FileOutputFormat.setOutputPath(job, new Path(args[1]));
// 提交Job
job.waitForCompletion(true);
}
}
参考日志:
Log4j2日志记录框架的使用教程与简单实例
Java日志体系居然这么复杂?——架构篇
SLF4J 用户使用手册
【JAVA】Log4j2日志详解
slf4j 和 log4j、log4j2、logback 依赖 jar 引用关系
Log4j2与Slf4j的最佳实践



