Java系统日志管理「建议收藏」

Java系统日志管理「建议收藏」在一个系统中日志管理是一个很重要的部分,因为当系统发布到线网后出了问题只能看系统日志了,这个时候系统日志起到了一个错误排查功能,同时也可以通过系统日志统计用户吞吐量等等,总之系统日志是系统管理一个重点。本系统架构为SpringMVC,myBatis,Shrio等等。1.SpringMVC异常处理SpringMVC负责接收用户请求并进行处理然后将结果返回给用户,那么为了不让异常抛给用户,我们一般在C…

大家好,又见面了,我是你们的朋友全栈君。在一个系统中日志管理是一个很重要的部分,因为当系统发布到线网后出了问题只能看系统日志了,这个时候系统日志起到了一个错误排查功能,同时也可以通过系统日志统计用户吞吐量等等,总之系统日志是系统管理一个重点。

本系统架构为SpringMVC,myBatis,Shrio等等。

1.SpringMVC异常处理

SpringMVC负责接收用户请求并进行处理然后将结果返回给用户,那么为了不让异常抛给用户,我们一般在Controller类下每个方法都加上一个try{}catch(Exception e){},实例代码如下:

/**
	 * pengweikang 20170220 用户登陆
	 * 
	 * @param cgbUser
	 *            用户信息
	 * @param session
	 * @return
	 */
	@RequestMapping(value = "/login", method = RequestMethod.POST)
	public @ResponseBody String userLogin(HttpServletRequest request) {
		try {
		     .....	 //Service方法调用
		} catch (Exception e) {
		     .....      //异常处理
		} 
		return null;
	}

该方法的缺点是代码冗余,不利于维护,一看就不想是一个专业的软件工程师应该写的,优化办法如下:

其实SpringMVC给我们提供了一个控制器增强标签,名称为@ControllerAdvice,通过这个标签就可以统一实现异常处理,代码如下:
创建统一的异常处理类CGBExceptionHandler.java

import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

import ch.qos.logback.classic.Level;
import net.sf.json.JSONObject;

/**
*@author		create by pengweikang
*@date		2018年6月27日--下午12:49:23
*@problem
*@answer
*@action
*/
@ControllerAdvice
public class CGBExceptionHandler {
	ch.qos.logback.classic.Logger loggerback = (ch.qos.logback.classic.Logger)LoggerFactory.getLogger("error");
	{
		loggerback.setLevel(Level.ERROR);
	}
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public Object handleException(Exception e,HttpServletRequest rquest) {
    	loggerback.error("错误日志记录");
    	Map dataMap  = rquest.getParameterMap();
        Set<String> keySet = 	dataMap.keySet();
        for(String key : keySet) {
            String [] datas = (String[])dataMap.get(key);
            String value = new String();
            for(String data : datas) {
    	        value +=data+",";
            }
    	    loggerback.error("Param:"+key+" = "+ value.substring(0, value.length() - 1));//将请求参数保存在日志中
        }
    	loggerback.error(ExceptionUtils.getFullStackTrace(e));  // 记录错误信息
        String msg = e.getMessage();
        if (msg == null || msg.equals("")) {
            msg = "服务器出错";
        }
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("message", msg);
        jsonObject.put("state", 0);
        return jsonObject.toString();
    }
}

这个时候你的Controller就不用在添加try-catch异常捕获了, 一但方法出了异常就会跳转到CGBExceptionHandler.java这个类的handleException方法。

2.logback日志管理

在这个方法中我们将方法调用的的错误消息都记录在日志中,并且将方法调用的参数也报错在错误日志中,logback配置内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<configuration
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="http://www.padual.com/java/logback.xsd"
    debug="false" scan="true" scanPeriod="30 second">

    <property name="PROJECT" value="recognizeSystem" /> 
    <property name="ROOT" value="/opt/apache-tomcat-7.0.82/logs/${PROJECT}/" />
    <property name="FILESIZE" value="50MB" />
    <property name="MAXHISTORY" value="100" />
    <timestamp key="DATETIME" datePattern="yyyy-MM-dd HH:mm:ss" />
    <!-- 控制台打印 -->
     <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
     	
     	<filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
     
        <encoder charset="utf-8">
            <pattern>[%-5level] %d{${DATETIME}} [%thread] %logger{36} - %m%n
            </pattern>
        </encoder>
    </appender>
    <!-- ERROR 输入到文件,按日期和文件大小 -->
    <appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <encoder charset="utf-8">
            <pattern>[%-5level] %d{${DATETIME}} [%thread] %logger{36} - %m%n
            </pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${ROOT}%d/error.%i.log</fileNamePattern>
            <maxHistory>${MAXHISTORY}</maxHistory>
            <timeBasedFileNamingAndTriggeringPolicy
                class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>${FILESIZE}</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
    </appender>
    
    <!-- WARN 输入到文件,按日期和文件大小 -->
    <appender name="WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <encoder charset="utf-8">
            <pattern>[%-5level] %d{${DATETIME}} [%thread] %logger{36} - %m%n
            </pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>WARN</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${ROOT}%d/warn.%i.log</fileNamePattern>
            <maxHistory>${MAXHISTORY}</maxHistory>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>${FILESIZE}</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
    </appender>
    
    <!-- INFO 输入到文件,按日期和文件大小 -->
    <appender name="INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <encoder charset="utf-8">
            <pattern>[%-5level] %d{${DATETIME}} [%thread] %logger{36} - %m%n
            </pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${ROOT}%d/info.%i.log</fileNamePattern>
            <maxHistory>${MAXHISTORY}</maxHistory>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>${FILESIZE}</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
    </appender>
    <!-- DEBUG 输入到文件,按日期和文件大小 -->
    <appender name="DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <encoder charset="utf-8">
            <pattern>[%-5level] %d{${DATETIME}} [%thread] %logger{36} - %m%n
            </pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>DEBUG</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${ROOT}%d/debug.%i.log</fileNamePattern>
            <maxHistory>${MAXHISTORY}</maxHistory>
            <timeBasedFileNamingAndTriggeringPolicy
                class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>${FILESIZE}</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
    </appender>
    <!-- TRACE 输入到文件,按日期和文件大小 -->
    <appender name="TRACE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <encoder charset="utf-8">
            <pattern>[%-5level] %d{${DATETIME}} [%thread] %logger{36} - %m%n
            </pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>TRACE</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <rollingPolicy
            class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${ROOT}%d/trace.%i.log</fileNamePattern>
            <maxHistory>${MAXHISTORY}</maxHistory>
            <timeBasedFileNamingAndTriggeringPolicy
                class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>${FILESIZE}</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
    </appender>
    
    <!-- SQL相关日志输出-->
    <logger name="org.apache.ibatis" level="INFO" additivity="false" />
    <logger name="org.mybatis.spring" level="INFO" additivity="false" />
    <logger name="com.github.miemiedev.mybatis.paginator" level="INFO" additivity="false" />
    
    <!-- Logger 根目录 -->
    <root level="DEBUG">
         <appender-ref ref="STDOUT" />
         <appender-ref ref="DEBUG" /> 
        <appender-ref ref="ERROR" />
        <appender-ref ref="WARN" />
        <appender-ref ref="INFO" /> 
        <appender-ref ref="TRACE" />
    </root>
</configuration>

该配置文件内容为将不同类型的日志按不同文件进行报错,并且每天记录不同的日志,文件夹按日期进行命名,儿控制台只打印错误日志。

3.测试

测试代码如下:

@Controller
@RequestMapping(value="/test")
public class TestController {
@RequestMapping(value="/exception")
	public @ResponseBody String throwexcep(int data) throws Exception {
		int a = data/0;// 一定会抛出 java.lang.ArithmeticException: / by zero		
		return null;
	}
}

请求 http://localhost:8080/logSystem/test/exception?data=100

首先看tomcat的log文件夹如下图所示:

Java系统日志管理「建议收藏」

error.0.log日志记录如下:

[ERROR] 2018-07-06 15:05:39 [http-bio-8080-exec-3] error - 错误日志记录
[ERROR] 2018-07-06 15:09:30 [http-bio-8080-exec-2] error - 错误日志记录
[ERROR] 2018-07-06 15:09:30 [http-bio-8080-exec-2] error - Param:data = 100
[ERROR] 2018-07-06 15:09:30 [http-bio-8080-exec-2] error - ParameterMap:org.apache.catalina.util.ParameterMap@c7832d1
[ERROR] 2018-07-06 15:09:30 [http-bio-8080-exec-2] error - java.lang.ArithmeticException: / by zero
	at com.goldenbridge.recognizesystem.controller.ActivitiController.throwexcep(ActivitiController.java:137)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:222)
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:814)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:737)
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:969)
	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:860)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:624)
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:845)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
	at com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:123)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
	at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:61)
	at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)
	at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)
	at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
	at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66)
	at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:449)
	at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365)
	at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90)
	at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83)
	at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:383)
	at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362)
	at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
	at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
	at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:121)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
	at com.goldenbridge.recognizesystem.utils.SimpleCORSFilter.doFilter(SimpleCORSFilter.java:34)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:110)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:506)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:169)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
	at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:962)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:445)
	at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1115)
	at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:637)
	at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:748)

到此系统日志管理配置完成!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/136403.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 基于web的酒店管理系统_新锐酒店管理系统

    基于web的酒店管理系统_新锐酒店管理系统小型酒店管理系统一、前言小型酒店管理系统采用Vue前端框架、SpringBoot框架实现项目前后端分离,并通过Mysql存储数据。本系统实现针对不同用户的登录验证;客户信息、前台管理员以及超级管理员等信息存取;客户信息登记、预约、入住、消费等功能;前台管理员对客户操作的管理;超级管理员对客户以及前台管理员操作进行控制等的功能,系统功能基本实现,测试良好。二、系统可行性分析(一)系统开发工具及平台操作系统:Windows10编程语言:Vue、SpringBoot开发工具:WebStorm、I

  • python创意小作品代码_python浪漫表白源码

    python创意小作品代码_python浪漫表白源码这篇文章主要为大家详细介绍了python实现浪漫的烟花秀,具有一定的参考价值,感兴趣的小伙伴们可以参考一下无意中看到一段用Tkinter库写的放烟花的程序,就跟着跑了一遍。设计理念:通过让画面上一个粒子分裂为X数量的粒子来模拟爆炸效果。粒子会发生“膨胀”,意思是它们会以恒速移动且相互之间的角度相等。这样就能让我们以一个向外膨胀的圆圈形式模拟出烟花绽放的画面。经过一定时间后,粒子会进入“自由落体”阶…

  • 初识业务架构图_管理架构图

    初识业务架构图_管理架构图文章目录什么是业务架构图?业务架构图规范宏观微观设计步骤分层分模块分功能实例什么是业务架构图?是将用户需求进行宏观系统抽象进行描述和展示,是表达业务层级和关系的工具,目的是将简单的业务逻辑简单化,降低理解难度,这个图是给用户和各级领导看的。业务架构图规范宏观1.宏观:横向:并列结构,级别是相同的;纵向:要有分层的思想,整体上有层次感,上层是依赖于下层的,越底层的,越是基础服务,同时也更为重要;对称:要讲究对称美,尽可能地功能结构分配均匀;虚线框:多个模块,逻辑上可以归为一块时可以使用虚线

    2022年10月11日
  • SQL注入之联合查询注入

    SQL注入之联合查询注入联合查询注入利用的前提前提条件:页面上有显示位什么是显示位?在一个在一个网站的正常页面,服务端执行SQL语句查询数据库中的数据,客户端将数据展示在页面中,这个展示数据的位置就叫显示位联合注入的过程1、判断注入点2、判断是整型还是字符型3、判断查询列数4、判断显示位5、获取所有数据库名6、获取数据库(test)所有表名7、获取(数据库:test,表:admin)中所有字段名8、获取字段中的数据一、…

  • eclipse自动补全快捷键

    eclipse自动补全快捷键eclipse中补全代码快捷键,默认Alt+/1.完全没有提示的情况:依次打开eclipse上面的windows>>>>preferences>>>>java>>>>editor>>>>contentassist,在右上方有一行“selecttheproposalkindscontainedinthe‘default’contentassistlist”下面,勾选Java

  • x86平台inline hook原理和实现

    x86平台inline hook原理和实现概念inlinehook是一种通过修改机器码的方式来实现hook的技术。原理对于正常执行的程序,它的函数调用流程大概是这样的:0x1000地址的call指令执行后跳转到0x3000地址处执行

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号