SpringMVC最小依赖+Junit单元测试+log解析(log4j及log4j2)

  • 1. junit
      • 1.1 最小junit
  • 2. springMVC+Junit最小依赖
      • 1.1 springmvc + junit
      • 使用log4j依赖(1.x版本下示例)
  • 3. web项目配置
  • 4. spring-context.xml 及 log4j.properties
      • 【springweb+log4j中注意点】
        • web.xml中初始化classpath中不要写log配置文件路径!
  • 5. log4j2详解
    • log4j与log4j2
    • 关于slf4j、log4j、log4j2
        • 【slj4j常用依赖】
        • 【log4j2常用依赖】
        • 【关于几种log包的总结】
  • log4j2.xml配置
      • xml方式log4j配置
      • 系统选择配置的文件的优先级如下:

1. junit

1.1 最小junit


<dependency>
    <groupId>junitgroupId>
    <artifactId>junitartifactId>
    <scope>testscope>
dependency>

测试的时候仅使用

@Test
method(){...}

直接引入junit即可。

说明:在spring中使用junit测试(如仅测试dao层),只需maven中加入两个依赖:

  • spring-test
  • junit

2. springMVC+Junit最小依赖

参考文献:http://blog.51cto.com/983836259/1864248

这里除了Spring以及其他模块所需要的jar包之外,还需要引入:

  • spring-test-4.2.3.RELEASE.jar
  • junit-4.10.jar

1.1 springmvc + junit

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 —> 输出日志

使用log4j依赖(1.x版本下示例)



<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: 日志信息

3. web项目配置

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容器加载)

4. spring-context.xml 及 log4j.properties

均放在资源目录下即可。值得一提的是,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查看依赖关系图如下:
    SpringMVC最小依赖+Junit单元测试+log解析(log4j及log4j2)_第1张图片
    通过diagrams可以查看是否存在重复的包对一个接口实现等。

  • 在maven project中查看dependency可以查看包中的包含关系,以便排除多余的依赖,或者减少已经引入进来的依赖。如:spring-context依赖中实际上已经有了spring-core
    SpringMVC最小依赖+Junit单元测试+log解析(log4j及log4j2)_第2张图片

上述log4j 1.x在spring中使用配置完毕。


【springweb+log4j中注意点】

web.xml中初始化classpath中不要写log配置文件路径!

log4j.xml等配置文件不用指明,自动识别。


5. log4j2详解

log4j与log4j2

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>

关于slf4j、log4j、log4j2

由于java日志框架众多(common-logging,log4j,slf4j,logback等),引入jar包的时候,就要为其添加对应的日志实现。。

不同的jar包,可能用了不同的日志框架,那引用了之后就得给不同的日志框架添加配置,这个是比较麻烦的。

slf4j就是为了解决这个麻烦事的。

slf4j全称为Simple Logging Facade for JAVA,java简单日志门面。类似于Apache Common-Logging,是对不同日志框架提供的一个门面封装,可以在部署的时候不修改任何配置即可接入一种日志实现方案。但是,他在编译时静态绑定真正的Log库。使用SLF4J时,如果你需要使用某一种日志实现,那么你必须选择正确的SLF4J的jar包的集合(各种桥接包)。

SpringMVC最小依赖+Junit单元测试+log解析(log4j及log4j2)_第3张图片

【slj4j常用依赖】

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的自带的简单日志输出接口  

说明:上述有部分包,如相互引用,将出现死循环。

【log4j2常用依赖】

一般还会有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>

        

【关于几种log包的总结】

【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.xml配置

xml方式log4j配置

可以通过以下四种方式配置log4j2

  • 通过一个格式为xml或json的配置文件
  • 以编程方式,通过创建一个ConfigurationFactory工厂和Configuration实现
  • 以编程方式,通过api暴露在配置界面添加组件的博人方式
  • 以编程方式,通过调用Logger内部类上的方法
    配置文件优先级及存放位置
    log4j2不在支持log2j1中的.properties后缀的文件配置方式。log4j2版本配置文件后缀只能为xml、json或jsn。

系统选择配置的文件的优先级如下:

  1. classpath下的名为log4j2-test.json或者log4j-test.jsn文件
  2. classpath下名为log4j2-test.xml的文件
  3. classpath下名为log4j2.json或者log4j2.jsn的文件
  4. classpath下名为log4j2.xml的文件

我们一般默认使用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>

你可能感兴趣的:(java架构,java,spring,junit,log,log4j)