Exception时信息的记录

系统总有出现异常的时候,那么出现异常时应该如何处理?

 

一直以来,我都以为这么处理就足够的:

  • 在日志中打印Exception的堆栈信息,以便排查原因
  • 反馈给用户系统xxx出现问题
package com.nicchagil.util.requestlogger;

import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;

public class RequestDemoServlet extends HttpServlet {
    
    private final Logger logger = Logger.getLogger(RequestDemoServlet.class);
       
    public RequestDemoServlet() {
        super();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
        ResultSet rs = null;
        PreparedStatement pstmt = null;
        Connection conn = null;
        try {
            Class.forName("oracle.jdbc.driver.OracleDriver");
            conn = DriverManager.getConnection(
                    "jdbc:oracle:thin:@hostname:port:sid", "username",
                    "password");
            
            pstmt = conn.prepareStatement("select * from t_xxx t where t.id = ? ");
            
            pstmt.setString(1, "paramter");
            rs = pstmt.executeQuery();
            
            while (rs.next()) {
                System.out.println("'" + rs.getString("result1") + "' - " + "'" + rs.getString("result2") + "'");
            }
            
        } catch (ClassNotFoundException e) {
            // Print exception logs
            logger.error("Failed to query xxx", e);
            
            // Prompt that system error
            response.getWriter().write("Failed to query xxx!");
            
        } catch (SQLException e) {
            // Print exception logs
            logger.error("Failed to query xxx", e);
            
            // Prompt that system error
            response.getWriter().write("Failed to query xxx!");
            
        } catch (Throwable t) {
            // Print exception logs
            logger.error("System error", t);
            
            // Prompt that system error
            response.getWriter().write("System error!");
            
        } finally {
            try {
                if (rs != null) {
                    rs.close();
                    rs = null;
                }
                if (pstmt != null) {
                    pstmt.close();
                    pstmt = null;
                }
                if (conn != null) {
                    conn.close();
                    conn = null;
                }
            } catch (SQLException e) {
                // Print exception logs
                logger.error("System error", e);
                
                // Prompt that system error
                response.getWriter().write("System error!");
            }
        }
    
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request, response);
    }

}
RequestDemoServlet

 

日前,得到一位资深同事Glen的指点,深知以上的操作是不足够的。

简单来说,我们需要记录,谁在什么时候做了什么事情

尽量详细地记录这些信息,让我们拥有更详细的信息用于排查问题(不知道请求参数的情况下,确实难以定位问题);在和其他团队作联合调试时,我们也可以提供足够的信息,不致陷于尴尬、被动地位。

  • 当前登录用户的ID或代号(在系统需要登录并用户已登录的前提下)
  • 当前请求的URL
  • 当前的请求参数

 

一般情况下,Web Project是在Servlet(或使用框架时所称的Action、Controller、Ctrl)处理Exception的。

除了“当前的请求参数”外,其他的都较好处理。因为每个请求的参数不尽一致,在每个Servlet都hardcode来打印各个参数,这是一个累人的活。

这里,分享一个静态方法用于打印HttpServletRequest的全部请求参数,这样就不致于每次都hardcode打印请求参数了。

package com.nicchagil.util.requestlogger;

import java.util.Iterator;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

public class RequestLogger {
    
    /**
     * toString for HttpServletRequest Parameters
     * @param request
     * @return
     */
    public static String toString(HttpServletRequest request) {
        
        Map map = request.getParameterMap();
        
        /* Since there are String[] in the map, can not return map.toString() directly. */
        
        if (map == null || map.isEmpty()) {
            return "";
        }
        
        StringBuffer sb = new StringBuffer();
        Object key = null;
        String[] value = null;
        Iterator iterator = map.keySet().iterator();
        
        while (iterator.hasNext()) {
            key = iterator.next();
            value = (String[])map.get(key);
            
            sb.append(key.toString()).append(" : ").append(toString(value, true));
            sb.append("\n");
        }
        
        return sb.toString();
    }
    
    /**
     * toString for String Array 
     * @param stringArray
     * @return
     */
    public static String toString(String[] stringArray, boolean alwaysArray) {
        
        if (stringArray == null || stringArray.length == 0) {
            return "";
        }
        
        if (!alwaysArray) {
            if (stringArray.length == 1) {
                return stringArray[0];
            }
        }
        
        StringBuffer sb = new StringBuffer();
        sb.append("[");
        
        for (int i = 0; i < stringArray.length; i++) {
            sb.append(stringArray[i]);
            
            if (i < stringArray.length - 1) {
                sb.append(", ");
            }
        }
        
        sb.append("]");
        
        return sb.toString();
    }

}
RequestLogger

 

posted @ 2014-07-28 18:52  nick_huang  阅读(1374)  评论(0编辑  收藏  举报