前情提要:
Eclipse版本:
Eclipse Java EE IDE for Web Developers.
Version: Mars.1 Release (4.5.1).
Build id: 20150924-1200
有时候默认的new选项里面可能没有class,package等等选项,就像下面这样:
如果要新建一个class,只能去点最下面的Other
再去选择class。那么怎样自定义这个菜单选项呢?看图说话:
点击菜单window
–>perspective
–>customize perspective...
点击shortcuts
–>勾选java
让我们再来看看效果
The End!
先看下面这个类
package com.dimon.xcrm.controller;
import org.apache.log4j.Logger;
/** * 一句话说明类的作用 * @author Dimon * @createDate 2015年10月18日 下午7:38:15 */
public class MainController {
private static Logger logger = Logger.getLogger(MainController.class);
}
每次新建一个类后,都需要给添加这样一行代码,以启用日志功能:
private static Logger logger = Logger.getLogger(MainController.class);
每次new 一个class,都需要在里面添加一行这样的代码,所不同的只是参数里面的值不一样,作为一只高逼格的码农,任何重复的体力劳动都是我们所不耻的!那么正确的姿势应该是怎样呢?继续往下看。
如果需要让团队成员保持代码模板一致性,我们可以Export All...
导出配置文件,给团队所有人导入模板,免得每个人都要去手动配置啦。下面是我在上面配置完成后导出来的配置文件,别说我不照顾伸手党→_→
<?xml version="1.0" encoding="utf-8"?>
<templates>
<template autoinsert="true" context="gettercomment_context" deleted="false" description="Comment for getter method" enabled="true" id="org.eclipse.jdt.ui.text.codetemplates.gettercomment" name="gettercomment">/** * @return the ${bare_field_name} */</template>
<template autoinsert="true" context="settercomment_context" deleted="false" description="Comment for setter method" enabled="true" id="org.eclipse.jdt.ui.text.codetemplates.settercomment" name="settercomment">/** * @param ${param} the ${bare_field_name} to set */</template>
<template autoinsert="true" context="constructorcomment_context" deleted="false" description="Comment for created constructors" enabled="true" id="org.eclipse.jdt.ui.text.codetemplates.constructorcomment" name="constructorcomment">/** * ${tags} */</template>
<template autoinsert="false" context="filecomment_context" deleted="false" description="Comment for created Java files" enabled="true" id="org.eclipse.jdt.ui.text.codetemplates.filecomment" name="filecomment"/>
<template autoinsert="false" context="typecomment_context" deleted="false" description="Comment for created types" enabled="true" id="org.eclipse.jdt.ui.text.codetemplates.typecomment" name="typecomment">/** * 一句话说明类的作用 * @author ${user} * @createDate ${date} ${time} * ${tags} */</template>
<template autoinsert="true" context="fieldcomment_context" deleted="false" description="Comment for fields" enabled="true" id="org.eclipse.jdt.ui.text.codetemplates.fieldcomment" name="fieldcomment">/** * */</template>
<template autoinsert="true" context="methodcomment_context" deleted="false" description="Comment for non-overriding methods" enabled="true" id="org.eclipse.jdt.ui.text.codetemplates.methodcomment" name="methodcomment">/** * ${tags} */</template>
<template autoinsert="true" context="overridecomment_context" deleted="false" description="Comment for overriding methods" enabled="true" id="org.eclipse.jdt.ui.text.codetemplates.overridecomment" name="overridecomment">/* (non-Javadoc) * ${see_to_overridden} */</template>
<template autoinsert="true" context="delegatecomment_context" deleted="false" description="Comment for delegate methods" enabled="true" id="org.eclipse.jdt.ui.text.codetemplates.delegatecomment" name="delegatecomment">/** * ${tags} * ${see_to_target} */</template>
<template autoinsert="false" context="newtype_context" deleted="false" description="Newly created files" enabled="true" id="org.eclipse.jdt.ui.text.codetemplates.newtype" name="newtype">${filecomment} ${package_declaration} import org.apache.log4j.Logger; ${typecomment} ${type_declaration}</template>
<template autoinsert="false" context="classbody_context" deleted="false" description="Code in new class type bodies" enabled="true" id="org.eclipse.jdt.ui.text.codetemplates.classbody" name="classbody">private static Logger logger=Logger.getLogger(${type_name}.class);</template>
<template autoinsert="true" context="interfacebody_context" deleted="false" description="Code in new interface type bodies" enabled="true" id="org.eclipse.jdt.ui.text.codetemplates.interfacebody" name="interfacebody"></template>
<template autoinsert="true" context="enumbody_context" deleted="false" description="Code in new enum type bodies" enabled="true" id="org.eclipse.jdt.ui.text.codetemplates.enumbody" name="enumbody"></template>
<template autoinsert="true" context="annotationbody_context" deleted="false" description="Code in new annotation type bodies" enabled="true" id="org.eclipse.jdt.ui.text.codetemplates.annotationbody" name="annotationbody"></template>
<template autoinsert="true" context="catchblock_context" deleted="false" description="Code in new catch blocks" enabled="true" id="org.eclipse.jdt.ui.text.codetemplates.catchblock" name="catchblock">// ${todo} Auto-generated catch block ${exception_var}.printStackTrace();</template>
<template autoinsert="true" context="methodbody_context" deleted="false" description="Code in created method stubs" enabled="true" id="org.eclipse.jdt.ui.text.codetemplates.methodbody" name="methodbody">// ${todo} Auto-generated method stub ${body_statement}</template>
<template autoinsert="true" context="constructorbody_context" deleted="false" description="Code in created constructor stubs" enabled="true" id="org.eclipse.jdt.ui.text.codetemplates.constructorbody" name="constructorbody">${body_statement} // ${todo} Auto-generated constructor stub</template>
<template autoinsert="true" context="getterbody_context" deleted="false" description="Code in created getters" enabled="true" id="org.eclipse.jdt.ui.text.codetemplates.getterbody" name="getterbody">return ${field};</template>
<template autoinsert="true" context="setterbody_context" deleted="false" description="Code in created setters" enabled="true" id="org.eclipse.jdt.ui.text.codetemplates.setterbody" name="setterbody">${field} = ${param};</template>
</templates>
那么现在来举一反三,templates
是什么呢?百度翻译告诉我们,它的中文意思就是模板
,上面那张图你们也看到了,搜索templates,发现出来很多结果,有JAVA的,JSP的,HTML的,CSS的等等,自己去发现吧。我比较常用的还有自定义JSP模板,在这篇文章中也有个例子–>传送门
System.out.println();
我们并不需要把它全部敲出来,一般直接输入sysout
,或者syso
然后按Alt+/
就会自动给我们补全了,eclipse是这么做到的呢?还是templates,我们还是看图说话吧。。。
- 可以看到在里面找到了我们常用的syso
了,下面我们也来自定义一个模板,就是上面new class自动生成的log4j的代码模板,我们还可以像下面这样去做:
import
这里还可以同时引入多个包,比如我把log4j改成使用slf4j,可以写成下面这个样子:
${:import (org.slf4j.Logger,org.slf4j.LoggerFactory)}
/** * logging mechanism. */
private static Logger logger = LoggerFactory.getLogger(${enclosing_type}.class);
就是在小括号里面使用","
号分隔开就好了,很简单。
下面是我导出的这个自定义的模板,又一伸手党福利→_→
<?xml version="1.0" encoding="utf-8"?>
<templates>
<template autoinsert="true" context="java" deleted="false" description="自动引入log4j代码" enabled="true" name="autolog">${:import (org.apache.log4j.Logger)} /** * logging mechanism. */ private static Logger logger = Logger.getLogger(${enclosing_type}.class);</template>
</templates>
上面说到了log4j,既然说到这个点,索性在多说一点,精益求精才是高逼格程序猿应有的态度。其实一般我在项目中记录日志不会像上面这样直接使用log4j的,而是使用的slf4j。为什么?简~而~言~之~呢就是~:SLF4J(Simple logging Facade for Java)不是一个真正的日志实现,而是一个抽象层( abstraction layer),它允许你在后台使用任意一个日志类库。如果是在编写供内外部都可以使用的API或者通用类库,那么你真不会希望使用你类库的客户端必须使用你选择的日志类库。巴拉巴拉。。。此处省略一万字。。。总~而~言之!就是slf4j个日志接口,log4j可以看成是它的实现类,当然,实现类还有很多,比如java.util.logging、logback等等。我们都知道使用接口的好处就是~呃。。。假如你是一个没有手脚的人,这时候你家里有个机器人。只需要告诉你的机器人你要见范冰冰,你的机器人就会去把范冰冰带到你的面前,至于它怎么做到的?也许用它自己的魅力勾引过来的,也许是直接使用暴力手段把范爷抗回来的。总之管它呢,女神已经站在你的面前了。嗯,这个比喻的很恰当!在这里我们就以残疾人slf4j和机器人,型号是log4j来做例子简单的讲解一下日志怎么用。
首先,你要明白单独使用slf4j你就想见到女神是不可能的→_→,你必须得要一个机器人去帮你做这件事。但是…目前市面上的机器人型号有很多种,有java.util.logging、logback、Apache log4j等等,我们这里选择长得帅一点的Apache log4j型号,到这里我们已经引入了两个jar包了,分别是:
slf4j-api.jar
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.7</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
</dependency>
可是这样还不够,要想让log4j机器人服从你的命令,你还需要滴血认亲,啊不,叫Binding包,其实就跟JDBC包一样一样的,不过这个比JDBC更简单,这里不需要任何配置,只要你把这3个包放在一起,就能直接让log4j机器人听你差遣了。不过要注意Binding包的版本要和上面log4j的版本要一致,上面的log4j是1.2版本的,对应的就应该是slf4j-log4j12.jar,如下:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.7</version>
</dependency>
其实slf4j原理很简单,他只提供一个核心slf4j api(就是slf4j-api.jar包),这个包只有日志的接口,并没有实现,所以如果要使用就得再给它提供一个实现了些接口的日志包,比如:log4j,common logging,jdk log日志实现包等,但是这些日志实现又不能通过接口直接调用,实现上他们根本就和slf4j-api不一致,因此slf4j又增加了一层Binding来转换各日志实现包的使用。
so…在项目中引入这三个包之后,再配置一下log4j的配置文件,指定日志输出格式,输出目的地等等就能开始为所欲为了。
#定义LOG输出级别
log4j.rootLogger=INFO,Console,File
#定义日志输出目的地为控制台
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.Target=System.out
#可以灵活地指定日志输出格式,下面一行是指定具体的格式
log4j.appender.Console.layout = org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%p[%c] - %m%n
#文件大小到达指定尺寸的时候产生一个新的文件
log4j.appender.File = org.apache.log4j.RollingFileAppender
#指定输出目录
log4j.appender.File.File = ./logs/xcrm.log
#定义文件最大大小
log4j.appender.File.MaxFileSize = 10MB
# 输出所以日志,如果换成DEBUG表示输出DEBUG以上级别日志
log4j.appender.File.Threshold = INFO
log4j.appender.File.layout = org.apache.log4j.PatternLayout
log4j.appender.File.layout.ConversionPattern =[%p]-[%d{yy/MM/dd HH:mm:ss}][%c] - %m%n
测试一下:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LoginLogic {
private static Logger logger = LoggerFactory.getLogger(LoginLogic.class);
public static void main(String[] args) {
logger.debug("输出{}日志","debug");
logger.info("输出{}日志","info");
logger.error("输出{}日志","error");
}
}
之所以没输入debug级别的原因是因为在配置文件中过滤掉了输出。发现和log4j的不同了吗?在log4j中,为了提高运行效率,往往在输出信息之前,还要进行级别判断,以避免无效的字符串连接操作。如下:
if (logger.isDebugEnabled()){
logger.debug("debug:"+name);
}
slf4j巧妙的解决了这个问题:先传入带有占位符{}
的字符串,同时把其他参数传入,在slf4j的内容部实现中,如果级别合适再去用传入的参数去替换字符串中的占位符,否则不用执行。
logger.info("{} is {}", new String[]{"x","y"});
The end!