软件中总免不了要使用诸如 Log4net, Log4j, Tracer 等东东来写日志,不管用什么,这些东东大多是大同小异的,一般都提供了这样5个日志级别:
    × Debug
    × Info
    × Warn
    × Error
    × Fatal
        一个等级比一个高,但是在具体开发中,关于应该如何选择适应的等级,却没有找到好的文章进行说明。记录一下自己的一些看法,以便日后使用吧。

=== Debug ===
        这个级别最低的东东,一般的来说,在系统实际运行过程中,一般都是不输出的。

因此这个级别的信息,可以随意的使用,任何觉得有利于在调试时更详细的了解系统运行状态的东东,比如变量的值等等,都输出来看看也无妨。

当然,在每一个 Debug 调用之前,一定要加上 If 判断。

=== Info ===
        这个应该用来反馈系统的当前状态给最终用户的,所以,在这里输出的信息,应该对最终用户具有实际意义,也就是最终用户要能够看得明白是什么意思才行。

从某种角度上说,Info 输出的信息可以看作是软件产品的一部分(就像那些交互界面上的文字一样),所以需要谨慎对待,不可随便。

=== Warn、Error、Fatal ===
        警告、错误、严重错误,这三者应该都在系统运行时检测到了一个不正常的状态,他们之间的区别,要区分还真不是那么简单的事情。我大致是这样区分的:

所谓警告,应该是这个时候进行一些修复性的工作,应该还可以把系统恢复到正常状态中来,系统应该可以继续运行下去。

所谓错误,就是说可以进行一些修复性的工作,但无法确定系统会正常的工作下去,系统在以后的某个阶段,很可能会因为当前的这个问题,导致一个无法修复的错误(例如宕机),但也可能一直工作到停止也不出现严重问题。

所谓Fatal,那就是相当严重的了,可以肯定这种错误已经无法修复,并且如果系统继续运行下去的话,可以肯定必然会越来越乱。这时候采取的最好的措施不是试图将系统状态恢复到正常,而是尽可能地保留系统有效数据并停止运行。

也就是说,选择 Warn、Error、Fatal 中的具体哪一个,是根据当前的这个问题对以后可能产生的影响而定的,如果对以后基本没什么影响,则警告之,如果肯定是以后要出严重问题的了,则Fatal之,拿不准会怎么样,则 Error 之。

示例代码:

/**
 * <p>Title: 用户登录处理</p>
 * <p>Description: </p>
 * @param loginId
 * @return  redirect page
 */
@RequestMapping("/user/login.vw")
public String login(HttpServletRequest request, HttpServletResponse response, 
ModelMap model, @ModelAttribute("login") @Validated CusLogin login,
BindingResult bindingResult) throws Exception {
log.debug("用户登录开始......");
//1.检查登录信息对象:null判断
if (null ==  login) {
log.error("用户登录失败-登录信息不存在");
bindingResult.addError(
new FieldError(
ErrorMsg.USERNOTEXIST[0], 
ErrorMsg.USERNOTEXIST[0],
ErrorMsg.USERNOTEXIST[1]));  
request.getSession().setAttribute(LOGINSTATE, "1");
login = new CusLogin();
//1:代表登录时用户输入的信息有误
login.setLoginState("1");
login.setPasswd("");
model.addAttribute("login", login);
return INDEX;
}
//2字段格式检查
if (bindingResult.hasErrors()) {
List<ObjectError> ers = bindingResult.getAllErrors();
for (ObjectError e : ers) {
log.error(e.getDefaultMessage());
}
//has error
log.error("用户登录失败-请求参数错误;username=" + login.getLoginNm());
//redirect index.jsp
request.getSession().setAttribute(LOGINSTATE, "1");
login.setLoginState("1");
login.setPasswd("");
model.addAttribute("login", login);
return INDEX;
}

//3. 第一登录失败,再次登录需输入验证码,判断验证码是否正确
if("1".equals(request.getSession().getAttribute(LOGINSTATE))){
if (login.getVerCode() == null || !login.getVerCode().equalsIgnoreCase(VerCodeMaker.verImgGet(session))) {
VerCodeMaker.verImgDel(request);
log.error("用户登录失败-验证码检查失败;username=" + login.getLoginNm());
bindingResult.addError(
new FieldError(
ErrorMsg.VERCODEEROOR[0], 
ErrorMsg.VERCODEEROOR[0],
ErrorMsg.VERCODEEROOR[1]));  
request.getSession().setAttribute(LOGINSTATE, "1");
login.setLoginState("1");
login.setPasswd("");
model.addAttribute("login", login);
return INDEX;
}
}

try {
//no error 
//4.获取登录用户信息:条件为用户名和用户类型
LoginUsersDto dto = loginService.login(login);
if (null == dto || StringUtility.isEmpty(dto.getLoginName())) {
bindingResult.addError(
new FieldError(
ErrorMsg.USERNOTEXIST[0], 
ErrorMsg.USERNOTEXIST[0],
ErrorMsg.USERNOTEXIST[1]));  
log.error("用户登录-查询用户信息失败,不存在或DB数据错误;username=" + login.getLoginNm());
request.getSession().setAttribute(LOGINSTATE, "1");
login.setLoginState("1");
login.setPasswd("");
model.addAttribute("login", login);
return INDEX;
}

//4. 密码检查
boolean isPwdExist = loginService.passwordChk( dto.getLoginName(), login.getPasswd(), dto.getPassword());
if (!isPwdExist) {
bindingResult.addError(
new FieldError(
ErrorMsg.PWDERROR[0], 
ErrorMsg.PWDERROR[0], 
ErrorMsg.PWDERROR[1]));  
request.getSession().setAttribute(LOGINSTATE, "1");
login.setLoginState("1");
login.setPasswd("");
model.addAttribute("login", login);
log.error("用户登录-密码检查失败;username=" + login.getLoginNm());
return INDEX;
}

//3.获取用户认证及支付信息
PayAuthInfoDto payInfoDto = payService.getPayAuthInfoByCusCode(dto.getCusCode());
//4. 创建SESSION数据
User user = new User();
if (null != payInfoDto) {
user = UserSession.userSet(dto , payInfoDto);
} else {
user = UserSession.userSet(dto);
}
UserSession.setUser(request, user);
log.debug("用户登录结束");

} catch (BizException e) {
log.info("用户登录失败;username=" + login.getLoginNm(),e);
bindingResult.addError(
new FieldError(
ErrorMsg.UNKNOWEXPCTION[0], 
ErrorMsg.UNKNOWEXPCTION[0], 
ErrorMsg.UNKNOWEXPCTION[1])); 
login.setPasswd("");
model.addAttribute("login", login);
return INDEX;
} catch (Exception e) {
log.info("用户登录失败,username=" + login.getLoginNm(),e);
bindingResult.addError(
new FieldError(
ErrorMsg.UNKNOWEXPCTION[0], 
ErrorMsg.UNKNOWEXPCTION[0], 
ErrorMsg.UNKNOWEXPCTION[1]));  
login.setPasswd("");
model.addAttribute("login", login);
return INDEX;
} finally{
request.getSession().removeAttribute(LOGINSTATE);
}

return REUSERINDEX;
}

心得:

log.error() 一般是需要if()的;

log.info()一般是在try  catch 里面

log.debug() 做记录一般标志着方法的开始和结束。

log 的 debug()、 error()、 info()方法的区别的更多相关文章

  1. logger.debug,logger.info,logger.warn,logger.error,logger.fatal的区别

    logger.debug,logger.info,logger.warn,logger.error,logger.fatal的区别 logger.debug,logger.info,logger.wa ...

  2. 多线程、同步实现方法及Error和Exception的区别与联系

    多线程.同步实现方法? 实现线程有两种方法: 继承Thread类 实现Runnable接口 实现同步也有两种方法 一种是用同步方法:同步方法就是在方法返回类型后面加上synchronized, 比如: ...

  3. Android学习笔记——log无法输出的解决方法和命令行查看log日志

    本人邮箱:JohnTsai.Work@gmail.com,欢迎交流讨论. 欢迎转载,转载请注明网址:http://www.cnblogs.com/JohnTsai/p/3983936.html. 知识 ...

  4. toString方法和valueof()方法的区别

    JavaScript引用类型之Array数组的toString()和valueof()方法的区别   一.转换方法 1.在JavaScript中几乎所有对象都具有toLocaleString().to ...

  5. sleep、wait方法之间区别

    sleep.wait方法之间区别 1.所属的类不同 sleep是Thread类的静态方法,而wait是Object类的成员方法 2.锁机制不一样 sleep方法:会让出资源调度器为当前线程分配的时间片 ...

  6. 正则表达式中的exec和match方法的区别

    正则表达式中的exec和match方法的区别 字符串的正则方法有:match().replace().search().split() 正则对象的方法有:exec().test() 1.match m ...

  7. PHP include()和require()方法的区别

    本文总结了PHP的include()和require()两种包含外部文件的方法的不同之处.基本上就是,加载失败的处理方法,性能,以及使用弹性方面的不同. PHP的include()和require() ...

  8. error和exception的区别,RuntimeException和非RuntimeException的区别

    error和exception的区别,RuntimeException和非RuntimeException的区别   1. 异常机制       异常机制是指当程序出现错误后,程序如何处理.具体来说, ...

  9. Debug和Release之本质区别

    转自Debug和Release之本质区别 Debug 和 Release 编译方式的本质区别 Debug 通常称为调试版本,它包含调试信息,并且不作任何优化,便于程序员调试程序.Release 称为发 ...

  10. 转:PHP include()和require()方法的区别

    文章来自于:http://developer.51cto.com/art/200909/153687.htm 本文总结了PHP的include()和require()两种包含外部文件的方法的不同之处. ...

随机推荐

  1. C# DataTable转换成实体列表 与 实体列表转换成DataTable

    /// <summary> /// DataTable转换成实体列表 /// </summary> /// <typeparam name="T"&g ...

  2. Android6.0-运行时权限处理

    为什么需要有运行时权限? 大家都知道在Android6.0之前,权限在应用安装过程中只询问一次,以列表的形式展现给用户,如果点击取消(即不认可应用所申请的权限),则会取消应用的安装.而用户出于安装应用 ...

  3. vmware和centOS的安装

    如果勾上了,会立即在本机开辟20g的空间,需要很长时间 选择电脑中ISO镜像的位置,之后点击开启虚拟机! 这个密码是root用户的密码!管理员密码! 可以选择我们的Minimal没有界面的!

  4. 页面中的平滑滚动——smooth-scroll.js的使用

    正常的本页面锚链接跳转的时候跟PPT似的,特别生硬,用户体验非常差. 这时候我们就可以借助smooth-scroll.js这个插件,来实现本页面的平滑的跳转. 1首先,导入必须的JS文件 <sc ...

  5. 初学JVM

    最近在读周志明的<深入理解Java虚拟机:JVM高级特性与最佳实践>,从中学到了很多,有些人可能会问为什么我们要学习JVM,他有什么用?在这里我想说一下,并不是这本书是大家都推荐的说有用处 ...

  6. 15.Three Sum

    思路 直接暴力,\(O(n^4 log(n))\),不出意外的超时了.. class Solution { public: vector<vector<int>> threeS ...

  7. HTML/XML/XPATH基础

    Html超文本标记语言 网页上单击右键→查看源文件/查看源代码 Html基本结构 <html>               为文档根元素,所有元素都在内部进行 <head>   ...

  8. jQuery之stop()

    开启第一篇原创博客,内容朴实,但绝对属实. 先来看看w3c的定义和语法: 定义:stop() 方法停止当前正在运行的动画. 语法:$(selector).stop(stopAll,goToEnd) 参 ...

  9. 最新开源DBLayer,原来数据库操作可以这么简单

    DBLayer,我最近开源的数据库轻量级orm框架,目前支持sqlserver.mysql.oracle, 特别做了分页的封装. 这个框架从七八年前开始逐渐升级而来,也经历了不少项目,希望可以将大家从 ...

  10. Aop初步了解

    AOP(aspect-oriented programming) aspect是一种新型的模块化机制,用来描述分散在对象,类或函数中横切关注点.从关注点中分离出横切关注点是面向切面的程序设计的核心概念 ...