log4j在web工程中的应用

这是来某外包公司的第五个星期,时间过得真快啊,又到了周一,也意味着来这里打了4周的酱油啦。

公司没人对我负责,基本上处于放羊的状态,指派的任务无人讲解,看起来遥遥无期,口袋空空(没钱),更惨的是精神世界也空空(主要一天敲不到50行代码,看着其他同学在其他公司BAT啦,网易啦,突飞猛进,感觉好虚),这么久啥都没学到?

也不是吧,回忆一下上周老大给讲的log4j,于是决定趁着没忘干净赶快整理一下,主要借助了其他博客的精华,回忆着老大的谆谆教诲,整理一下。

说正事之前先吐槽一下艹蛋的win10系统,强制自动更新,在8.10分抛给我一个10分钟后自动重启的通知,之后就趁我早晨脑袋蒙圈在10分钟后强制重启进行了更新,

自动重启了N次,更新了一个半钟头,比重装还慢...而且更新之后也没发现哪里有不一样的地方。事后琢磨如果不想更新可以这么做:把系统时间往前调整(逃软件试用期也用过这一招),或者在控制面板中设置禁止自动更新。

在配置log4j的过程中回顾了一下以前的知识,提出了3个问题。

 

一.web基础回顾

1.1什么是web工程

  

一个web工程,就是符合一套web标准(工程组织形式个人理解就是源代码,中间代码,各种文件怎么放),因为只有符合一个统一的标准,服务器才能更好的识别,运行。

左图:下面没有介绍的基本没用到,所以也懒得理解了...

  是eclipse中一个名为web_log4j的web工程,src顾名思义就是源码,下面存放着若干.java文件,我们面向对象编程就是在这里写类,写方法

  jreSystemLibrary是java运行依赖的类库,自动生成

  webApplibrary下面是工程引用的外部jar包,一个引用过程是这样的:将jar包文件拷贝到工程中,右击buildpath,buildpath相当于将jar包里面的类引入,

  比如之前【beanUtile.封装】这样的代码是没有提示的,buildpath之后,该代码出现了提示,按照提示import之后就可以使用beanUtil这个工具类,

  前后对比说明buildpath完成了jar包中的类导入到工程中的作用。引用外部类还可以采用直接引用的方式[add external jars],不利于代码移植性,就不介绍啦。

  (举个例子,你电脑上log4j.jar在c盘,换了一台电脑跑,程序还去c盘找这个文件,找不到就会报错)

  这里要说清楚所谓引用类,就不得不说一下什么是jar包,jar包其实就是打包压缩好的一堆.class文件,引用就是把外部的.class文件组合到工程里面的过程。如果想要查看jar包的源码,

  还需要导入源码。有趣的是自己也可以将一堆.class文件在cmd命令下打成jar包,自创jar包。

  在一个web工程中,依靠的是工程名:web_log4j提供对外访问,对内web_log4j抽象成根目录/(内部总使用相对路径访问),对于路径问题有篇博客解释的超级精辟:java获取路径问题,

  (一个常用做法是从当前类拿到完整路径,或者是通过容器得到)

  获得路径可以通过IO流做输入输出,还有读取配置文件也需要路径,所以路径很重要。

  这里插播一个有趣的问题,下面的代码是错误的,错在哪里?

  public static String s1=this.getClass().getClassLoader().getResource("/").getPath();

  或者说:java的static方法里面为什么不能用this关键字?

  这和jvm有关,jvm首先加载的是静态部分,而this的含义是指当前对象,静态部分加载进入的时候对象还没有创建。

  这里再插播一个对比jdk,jre,jvm,

  我们利用JDK(调用JAVA API)开发了属于我们自己的JAVA程序后,通过JDK中的编译程序(javac)将我们的文本java文件编译成JAVA字节码,

  在JRE上运行这些JAVA字节码,JVM解析这些字节码,映射到CPU指令集或OS的系统调用

  回到web工程的主题:

右图:build文件夹下存放着编译好的.class文件,src放源码,webcontent下面的web-info存放着jar包和配置文件

工程运行所依赖的配置文件(.properties文件:比如用于配置数据库连接的用户名,密码;.xml文件,配置类,常数等关系的文件);.class文件(外部jar包,src编译形成的.class文件)

至此全部介绍完毕,其中大部分位于web-inf目录下,由此可见这是一个很重要的目录。而web.xml关系到一个web工程全局的初始化设置,接下来就说一说我所见过的配置,看明白了web.xml文件,这个工程用到哪些技术,是怎样一个结构基本上有了一个全局性的了解。

 

1.2一个web.xml文件的解读

 

<?xml version="1.0" encoding="UTF-8"?>  
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    xmlns="http://java.sun.com/xml/ns/javaee"  
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"  
    id="WebApp_ID" version="3.0">  
    <display-name>LogLearning</display-name>  

    <servlet>  
        <servlet-name>Log4JTestServlet</servlet-name>  
        <servlet-class>com.mucfc.Log4JTestServlet</servlet-class>  
    </servlet>  

    <servlet-mapping>  
        <servlet-name>Log4JTestServlet</servlet-name>  
        <url-pattern>/test</url-pattern>  
    </servlet-mapping>   

        <!-- Spring 容器加载 -->  
    <listener>  
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  
    </listener>  
    <context-param>  
        <param-name>contextConfigLocation</param-name>  
        <param-value>classpath:applicationContext.xml</param-value>  
    </context-param>   

    <!-- 设置根目录 -->  
    <context-param>    
        <param-name>webAppRootKey</param-name>    
        <param-value>webapp.root</param-value>    
    </context-param>    

    <context-param>  
        <param-name>log4jConfigLocation</param-name>  
        <param-value>/WEB-INF/classes/log4j.properties</param-value>  
    </context-param>  
    <!-- 3000表示 开一条watchdog线程每60秒扫描一下配置文件的变化;这样便于日志存放位置的改变 -->  
    <context-param>    
         <param-name>log4jRefreshInterval</param-name>    
         <param-value>3000</param-value>    
    </context-param>   
    <listener>  
        <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>  
    </listener>   

</web-app>

 

最前面是约束,这个web.xml中主要配置了servlet和listener

servlet包含两个标签<servlet>和<servlet-mapping>

其中servlet-name可以随便起,但是俩标签里的name一定要一致,之所以这样做,是因为前一个servlet绑定了servlet类(拿到request,response处理并且返回的代码,说简单点,控制代码就写在<servlet-class>指定的类里面,而且指定了初始化参数),后一个url-mapping(假设配成/test)则是提供了访问路径:如localhost:8080/web_log4j/test,就是在访问这个servlet呢,访问路径和后台代码要绑定,靠的是共有的名字,所谓的servlet之所以能实现交互的原因就是这样。既有访问路径,又有后台处理代码,request和response是一堆邮差,扮演了信息载体的角色。

listener标签则配置了监听器,其中org类位于jar包中,这里所谓的监听器到底是什么东西呢?

1.随着web应用的启动开始启动,也就是说一开始就发挥了作用

2.不负责响应用户的请求,也就是说只有一行<listener>类</listener>,无需配置url

第一个监听器:ContextLoaderListener和

<context-param>

<param-name>contextConfigLocation</param-name>

<param-value>classpath:applicationContext.xml</param-value>

</context-param>

搭配使用,使得context载入配置文件applicationContext.xml(里面放置着配置好的bean),所谓classpath指代的是web-info/classes目录,直接把spring的配置关系载入了

webapp.root可以用于获取系统根目录,具体代码System.getRoot("...")

第二个监听器:log4jConfigListener

<context-param>

<param-name>log4jConfigLocation</param-name>

<param-value>/WEB-INF/classes/log4j.properties</param-value>

</context-param>

搭配使用载入了log4j文件的位置。
对监听器作用理解如下:
只有一行,配置指向jar包里面的某个类,和某些特定参数配合使用,为其指定初始化模式(比如显示了配置文件位置)
这里也可以做一个逆向思考:计算机不是人,怎么读取配置文件呢?web.xml首先是web默认的全局配置文件,里面配置了监听器从应用启动开始启动
通过一些参数来找到配置文件。

 

二 log4j的使用

2.1log4j介绍

就是跟日志挂钩的东西,大部分web应用部署在linux上,要想时时刻刻记录运行状态,就得依靠一种叫日志的东西,运行状态,出错,异常统统记录在案,出问题了回头也能查到,日志的实体就是.log后缀的文件。

Log4j由三个重要的组件构成:日志信息的优先级,日志信息的输出目的地,日志信息的输出格式。日志信息的优先级从高到低有ERROR、WARN、 INFO、DEBUG,分别用来指定这条日志信息的重要程度;日志信息的输出目的地指定了日志将打印到控制台还是文件中;而输出格式则控制了日志信息的显 示内容。

2.2log4j.properties文件解读

 

### 设置###
log4j.rootLogger = debug,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 级别以上的日志到=E://logs/error.log ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = E://logs/log.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 级别以上的日志到=E://logs/error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =E://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.rootLogger = debug,stdout,D,E

定义”顶“为debug,意为debug以下的信息都可以输出,appenderName1为stdout(用于控制台输出),D(debug),E(error)
PatternLayout表示按照指定格式输出,才有后面的规则
[%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n:
除了特殊含义字符,其他字符按照原样输出
p:[debug]级别,d:日期样式,l:输出日志事件发生的位置,n:回车换行,m:指定的消息(这才是重点)

除了控制台,还指定了error.log和debug.log作为输出文件
2.3log4j的代码应用
static Logger logger = Logger.getLogger ( ServerWithLog4j.class.getName ()[一般是当前类,因为记载了当前类的debug信息] )
PropertyConfigurator.configure ( String configFilename) :读取使用Java的特性文件编写的配置文件。
[这一步也可以在spring中配置指定的路径]
Logger.debug ( Object message ) ; :跟上面对应的m一样,输出debug信息
三遗留问题
3.1上面仅仅是做了一个实验,相当于helloword,在实际应用中,log4j是如何记载产生的异常的?
  或者说,上面的message是自己写的,如果一段代码跑崩了,日志是怎样记录信息的?
3.2每天产生数以万计的日志记录,如何查看?里面有没有什么技巧?



 

 




 

 

 

 

  

 

  

 


 

posted on 2016-08-16 09:24  小王20150901  阅读(2462)  评论(0编辑  收藏  举报