<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<scope>testscope>
dependency>
测试的时候仅使用
@Test
method(){...}
直接引入junit
即可。
说明:在spring中使用junit测试(如仅测试dao层),只需maven中加入两个依赖:
spring-test
junit
参考文献:http://blog.51cto.com/983836259/1864248
这里除了Spring以及其他模块所需要的jar包之外,还需要引入:
spring-test-4.2.3.RELEASE.jar
junit-4.10.jar
在maven
中如下即可(版本管理略):
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-coreartifactId>
<exclusions>
<exclusion>
<groupId>commons-logginggroupId>
<artifactId>commons-loggingartifactId>
exclusion>
exclusions>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-testartifactId>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
dependency>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>javax.servlet-apiartifactId>
<version>3.1.0version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<scope>testscope>
dependency>
注意:上述排除了spring
自带的common-logging
,使用了log4j。关于log4j,需要桥接过来。
spring-core
依赖的日志为common-logging
,将其排除后,要使用common-logging接口,将其引入其他接口。
(1)对于jcl转log4j,有以下过程
Component
|
| log to Apache Commons Logging
V
(1)jcl-over-slf4j.jar
— (redirect) —> SLF4j —>
(2)slf4j-log4j12-version.jar
—>
(3)log4j.jar
—> 输出日志
<dependency>
<groupId>org.slf4jgroupId>
<artifactId>jcl-over-slf4jartifactId>
<version>1.7.25version>
dependency>
<dependency>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-log4j12artifactId>
<version>1.7.10version>
dependency>
<dependency>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
<version>1.2.17version>
dependency>
测试代码如下:
@ContextConfiguration("classpath:spring-context.xml")
@RunWith(SpringJUnit4ClassRunner.class)
public class SomeTest {
private static final Logger LOGGER = LoggerFactory.getLogger(XXX.class);//(1)
@Resource
private ***Service ***Service;
@Test
public void fun(){
Set set = new HashSet();
set.add("whb1");
set.add("whb2");
String g** = "gg";
...
**Service.needTestfun(set, groupCode, g**,..);
//在无返回时可以打印到logger
LOGGER.info("--whb success--");
}
}
总结:
@ContextConfiguration
基本spring
配置文件路径
@RunWith(SpringJUnit4ClassRunner.class)
此次使用的配置环境
@Test
标注这是一个Test方法
Assert
类可以用于断言,非空、相等等等。在无返回时也可以打印到log。
说明:
(1) LoggerFactory.getLogger
private static final Logger LOGGER = LoggerFactory.getLogger(com.XXX.class);
中XXX.class
用于绑定类名,在调试的时候会显示,如:
LOGGER.debug("日志信息");
会显示:
com...XXX: 日志信息
web.xml 中指出 spring
配置文件,log
配置文件(固定名称按序加载,略)放在资源目录下自动加载即可。
web.xml:
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<display-name>prodisplay-name>
<context-param>
<param-name>webProparam-name>
<param-value>whbweb.rootparam-value>
context-param>
<servlet>
<servlet-name>springmvcservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>
classpath:spring-context.xml
param-value>
init-param>
<load-on-startup>1load-on-startup>
servlet>
<servlet-mapping>
<servlet-name>springmvcservlet-name>
<url-pattern>/api/*url-pattern>
servlet-mapping>
<filter>
<filter-name>EncodingFilterfilter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
<init-param>
<param-name>encodingparam-name>
<param-value>UTF-8param-value>
init-param>
filter>
<filter-mapping>
<filter-name>EncodingFilterfilter-name>
<servlet-name>springmvcservlet-name>
filter-mapping>
web-app>
注意:关于日志的属性文件不需要在初始化时配置。上述classpath
处只写spring-context.xml
即可。(由spring
容器加载)
均放在资源目录下即可。值得一提的是,log4j属性文件不需要额外指出,直接放在资源目录下即可!
(1)spring-context.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="cn.whbing.pro.web.*"/>
<mvc:annotation-driven enable-matrix-variables="true" />
beans>
(2)log4j.properties(1.x版本以后不再介绍)
### 设置###
#log4j.rootLogger = debug,stdout,D,E
log4j.rootLogger = info,stdout,D,E
#log4j.rootLogger = error,stdout,D,E
### 输出信息到控制台 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
### 输出DEBUG 级别以上的日志到=/home/**/logs/debug.log ###
### 相对目录是相对于整个项目而言的
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = logs/debug.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
### 输出ERROR 级别以上的日志到=/home/admin/logs/error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =logs/error.log
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
目录结构如下:(说明:log4j 1版本以log4j.properties
名称即可)
src
|-main
|-java
|-resources
|- log4j.properties
|-webapp
|-WEB-INF
|-web.xml
工具:
在pom
文件处,在idea
中通过右键Diagrams
查看依赖关系图如下:
通过diagrams可以查看是否存在重复的包对一个接口实现等。
在maven project中查看dependency可以查看包中的包含关系,以便排除多余的依赖,或者减少已经引入进来的依赖。如:spring-context依赖中实际上已经有了spring-core
上述log4j 1.x在spring中使用配置完毕。
log4j.xml等配置文件不用指明,自动识别。
1.x与2.x坐标和名称都有所变化
log4j:(不再维护)
<dependency>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
<version>1.2.17version>
dependency>
log42:(主要依赖有两个core与api)
<dependency>
<groupId>org.apache.logging.log4jgroupId>
<artifactId>log4j-coreartifactId>
<version>2.5version>
dependency>
<dependency>
<groupId>org.apache.logging.log4jgroupId>
<artifactId>log4j-apiartifactId>
<version>2.5version>
dependency>
由于java日志框架众多(common-logging,log4j,slf4j,logback等),引入jar包的时候,就要为其添加对应的日志实现。。
不同的jar包,可能用了不同的日志框架,那引用了之后就得给不同的日志框架添加配置,这个是比较麻烦的。
slf4j
就是为了解决这个麻烦事的。
slf4j
全称为Simple Logging Facade for JAVA
,java简单日志门面。类似于Apache Common-Logging
,是对不同日志框架提供的一个门面封装,可以在部署的时候不修改任何配置即可接入一种日志实现方案。但是,他在编译时静态绑定真正的Log库。使用SLF4J时,如果你需要使用某一种日志实现,那么你必须选择正确的SLF4J的jar包的集合(各种桥接包)。
jcl-over-slf4j.jar --> (jcl -> slf4j) 将Jakarta Commons Logging日志框架到 slf4j 的桥接
log4j-over-slf4j.jar--> (log4j -> slf4j) 将log4j 的日志,桥接到slf4j,所以这个包不能和log4j-over-slf4j.jar同时用,否则会死循环!!
slf4j-log4j12.jar --> (slf4j -> log4j) slf4j 转接到 log4j,所以这个包不能和log4j-over-slf4j.jar同时用,否则会死循环!!
slf4j-api.jar --> slf4j 的api接口jar包
slf4j-ext.jar --> 扩展功能
slf4j-jcl.jar --> (slf4j -> jcl) slf4j 转接到 Jakarta Commons Logging日志输出框架
其他依赖包:
jul-to-slf4j.jar --> (juc -> slf4j) 将java.util.logging的日志桥接到 slf4j
osgi-over-slf4j.jar --> (osgi -> slf4j) 将osgi环境下的日志,桥接到slf4j
slf4j-android.jar --> (android-> slf4j) 将android环境下的日志,桥接到slf4j
slf4j-jdk14.jar --> (slf4j -> jul ) slf4j 转接到 java.util.logging,所以这个包不能和jul-to-slf4j.jar同时用,否则会死循环!!
slf4j-migrator.jar --> 一个GUI工具,支持将项目代码中 JCL,log4j,java.util.logging的日志API转换为slf4j的写法
slf4j-nop.jar --> (slf4j -> null) slf4j的空接口输出绑定,丢弃所有日志输出
slf4j-simple.jar --> (slf4j -> slf4j-simple ) slf4j的自带的简单日志输出接口
说明:上述有部分包,如相互引用,将出现死循环。
一般还会有log4j和log4j2混用的问题。
因为log4j项目已经停止更新了,官方建议用log4j2。
log4j2
里也提供了对各类log
的桥接支持,这里就只列举相关的几个jar包说明。
log4j-1.2-api.jar --> (log4j -> log4j2) 将log4j 的日志转接到log4j2日志框架
log4j-api.jar --> log4j2的api接口jar包
log4j-core.jar --> (log4j2 ) log4j2的日志输出核心jar包
log4j-slf4j-impl.jar--> (slf4j -> log4j2) slf4j 转接到 log4j2 的日志输出框架 (不能和 log4j-to-slf4j同时用)
log4j-to-slf4j.jar --> (log4j2 -> slf4j) 将 log4j2的日志桥接到 slf4j (不能和 log4j-slf4j-impl 同时用)
【说明】
slf4j转log4j2时,
slf4j
包中提供了slf4j-log4j12.jar
将slf4j 转接到 log4j2;同时log4j
包中也提供了log4j-slf4j-impl.jar
将slf4j 转接到 log4j2。两个依赖不能同时出现,否则报重复bindings错误:
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/Users/didi/.m2/repository/org/apache/logging/log4j/log4j-slf4j-impl/2.5/log4j-slf4j-impl-2.5.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/Users/didi/.m2/repository/org/slf4j/slf4j-log4j12/1.7.10/slf4j-log4j12-1.7.10.jar!/org/slf4j/impl/StaticLoggerBinder.class]
因此在spring中排除掉common-logging后,jcl->slf4j->log4j2
过程如下
<dependency>
<groupId>org.slf4jgroupId>
<artifactId>jcl-over-slf4jartifactId>
<version>1.7.25version>
dependency>
<dependency>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-apiartifactId>
<version>${dependency.version.slf4j}version>
dependency>
<dependency>
<groupId>org.apache.logging.log4jgroupId>
<artifactId>log4j-slf4j-implartifactId>
<version>2.5version>
dependency>
log4j2依赖:
<dependency>
<groupId>org.apache.logging.log4jgroupId>
<artifactId>log4j-coreartifactId>
<version>2.5version>
dependency>
<dependency>
<groupId>org.apache.logging.log4jgroupId>
<artifactId>log4j-apiartifactId>
<version>2.5version>
dependency>
【log4j】
这个最简单,单独使用jar包就一个,已经停止更新,当前最新版是 log4j-1.2.17.jar
只有输出功能,没有转接功能。
【log4j2】
同时有日志输出和转接功能。
单独使用时,jar包是 log4j-api-2.x.x.jar 和 log4j-core-2.x.x.jar
配置文件在资源目录下即可。
【log4j -> log4j2 桥接】
官网
去掉 log4j 1.x jar,添加log4j-1.2-api.jar,配合 log4j-api-2.x.x.jar 和 log4j-core-2.x.x.jar 即可,依赖如下
log4j-1.2-api.jar
log4j-api-2.x.x.jar
log4j-core-2.x.x.jar
【log4j2 -> log4j 桥接】
不建议。
本来log4j在2015年停止更新后,就建议转向log4j2,并提供了到log4j2的桥接接口。
所以反过来log4j2到log4j是不建议这么做的,log4j2也没有提供直接支持。
但理清了上面的jar包作用,就会发现,可以通过 log4j2 -> slf4j -> log4j 的方式来实现。
需要的jar包,根据依赖关系分别是:
log4j-api-2.x.x.jar
log4j-to-slf4j.jar
slf4j-api-x.x.x.jar
slf4j-log4j12-x.x.x.jar
log4j-1.2.17.jar
【slf4j】
同时有日志输出和转接功能。
核心jar包是 slf4j-api-x.x.x.jar
因为一般slf4j 只作为桥接用,如果要搭配 slf4j 自带的简单日志输出,那么就加上 slf4j-simple.jar
【log4j -> slf4j】
将代码中的log4j日志桥接到 slf4j,需要如下jar包
log4j-api-2.x.x.jar
log4j-to-slf4j-2.x.x.jar
slf4j-api-x.x.x.jar
【slf4j -> log4j】
将slf4j日志,采用log4j实现进行输出,需要如下jar包
slf4j-api-x.x.x.jar
slf4j-log4j12.jar
log4j-1.2.17.jar
【slf4j -> log4j2】
将slf4j日志,采用log4j2实现进行输出,需要如下jar包
slf4j-api-x.x.x.jar
log4j-slf4j-impl.jar
log4j-api.jar
log4j-core.jar
slf4j的代理绑定和输出组合起来,就实现了从一种日志框架,转到另一种日志实现框架的效果。
建议在这三种日志混用的情况下,采用如下方案
log4j -> log4j2
slf4j -> log4j2
参考:jsl4j与log4j与log4j2那些事
配置文件结构:
src
|-main
|-java
|-resources
|- log4j2.xml
|-webapp
|-WEB-INF
|-web.xml
使用:
import org.slf4j.LoggerFactory;
import org.slf4j.Logger;
private static final Logger LOGGER = LoggerFactory.getLogger(ReadSpecialLineServiceImpl.class);
可以通过以下四种方式配置log4j2
我们一般默认使用log4j2.xml进行命名。如果本地测试,可以先把log4j2-test.xml放到classpath,而正式环境使用log4j2.xml,则在打包部署的时候不要打包log4j2-test.xml
简单配置如下,详解参考:
log4j2配置详解
<configuration status="info">
<appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
Console>
appenders>
<loggers>
<root level="error">
<appender-ref ref="Console"/>
root>
loggers>
configuration>
如下配置:
<configuration status="off" monitorInterval="1800">
<Properties>
<Property name="LOG_HOME">log4j2-pro2Property>
Properties>
<appenders>
<Console name="Console" target="SYSTEM_OUT">
<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="%d{DEFAULT} [%t] %-5level %logger{36} - %msg%n"/>
Console>
<RollingRandomAccessFile name="info_appender"
immediateFlush="true" fileName="${LOG_HOME}/info/info.log"
filePattern="${LOG_HOME}/info/info - %d{yyyy-MM-dd HH_mm_ss}.log.gz">
<PatternLayout>
<pattern>%5p [%t] %d{yyyy-MM-dd HH:mm:ss} (%F:%L) %m%npattern>
PatternLayout>
<Policies>
<SizeBasedTriggeringPolicy size="25MB"/>
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
Policies>
<Filters>
<ThresholdFilter level="warn" onMatch="DENY" onMismatch="NEUTRAL"/>
<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
Filters>
RollingRandomAccessFile>
<RollingRandomAccessFile name="error_appender"
immediateFlush="true" fileName="${LOG_HOME}/error/error.log"
filePattern="${LOG_HOME}/error/error - %d{yyyy-MM-dd HH_mm_ss}.log.gz">
<PatternLayout>
<pattern>%5p [%t] %d{yyyy-MM-dd HH:mm:ss} (%F:%L) %m%npattern>
PatternLayout>
<Policies>
<SizeBasedTriggeringPolicy size="25MB"/>
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
Policies>
<Filters>
<ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
Filters>
RollingRandomAccessFile>
appenders>
<loggers>
<root level="info">
<appender-ref ref="Console"/>
<appender-ref ref="info_appender"/>
root>
loggers>
configuration>