项目异常处理

来源:互联网 发布:mac玩qq游戏大厅 编辑:程序博客网 时间:2024/05/22 01:09

下面是我们项目的异常处理机制,在此记录一下。

一、自定义异常

首先,我们自定义了两种类型的异常:DataWarningException和ServerErrorException

DataWarningException.java

package com.augmentum.ot.exception;public class DataWarningException extends Exception {    private static final long serialVersionUID = -1462714485890122558L;    public DataWarningException(String message, Throwable cause) {        super(message, cause);    }    public DataWarningException(String message) {        super(message);    }    public DataWarningException(Throwable cause) {        super(cause);    }}

ServerErrorException.java

package com.augmentum.ot.exception;public class ServerErrorException extends Exception {    private static final long serialVersionUID = -1462714485890122558L;    public ServerErrorException(String message, Throwable cause) {        super(message, cause);    }    public ServerErrorException(String message) {        super(message);    }    public ServerErrorException(Throwable cause) {        super(cause);    }}

其中,当发生数据异常,比如说操作数据库失败,数据验证错误,在service抛出ServerErrorException;当出现业务逻辑错误,在service抛出 DataWarningException.


二、定义并初始化异常信息

在自定义完异常后,我们有创建了一个Exception.xml文件来记录异常信息,内容如下:

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE PUBLIC><!-- 其中errorMessageKey表示的是传给前台的错误信息;logMessage表示的是当异常发生时打印的log信息;flag表示的是是否要跳页面,如果flag=1表示要跳页面,flag=0表示不跳页面  --><exception>    <!-- Server internal error -->    <errorCode id="E0001">        <errorMessageKey></errorMessageKey>        <logMessage>Exception error.</logMessage>        <flag>1</flag>    </errorCode>    <errorCode id="E0002">        <errorMessageKey></errorMessageKey>        <logMessage>Validation failure.</logMessage>        <flag>1</flag>    </errorCode>    <errorCode id="E0005">        <logMessage>Employee [#_employee_id] has no access to [actionName].</logMessage>        <errorMessageKey>_no_privilege</errorMessageKey>        <flag>1</flag>    </errorCode>    ......    <!-- Common message -->    <errorCode id="W0001">        <logMessage>There is no data</logMessage>        <errorMessageKey>no_data</errorMessageKey>        <flag>0</flag>    </errorCode>    <!-- Course part exception -->    <errorCode id="W1001">        <logMessage>Failed to view detail course [#_course_id] that it is already deleted.</logMessage>        <errorMessageKey>_course_not_exist_error</errorMessageKey>        <flag>1</flag>    </errorCode>    </exception>

创建一个和其对应的DTO类存放每个异常信息

ErrorCode.java

public class ErrorCode {    private String errorCodeId;    private String flag;    private String errorMessage;    private String logMessage;    public String getLogMessage() {        return logMessage;    }    public void setLogMessage(String logMessage) {        this.logMessage = logMessage;    }    public String getFlag() {        return flag;    }    public void setFlag(String flag) {        this.flag = flag;    }    public String getErrorCodeId() {        return errorCodeId;    }    public void setErrorCodeId(String errorCodeId) {        this.errorCodeId = errorCodeId;    }    public String getErrorMessage() {        return errorMessage;    }    public void setErrorMessage(String errorMessage) {        this.errorMessage = errorMessage;    }}
定义一个常量类存放ErrorCodeId

ErrorCodeConstants.java

public class ErrorCodeConstants {    // Common Part    public static final String SERVER_ERROR = "E0001";    public static final String SERVER_VALIDATION_ERROR = "E0002";        public static final String ERROR = "E0004";        public static final String NO_ACCESS = "E0005";        ......    }


在启动项目的时候,写一个Servlet解析这些异常信息,并将其放入ServletContext中。

InitDataServlet.java

package com.augmentum.ot.initServlet;import java.util.Map;import javax.servlet.ServletContext;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import org.springframework.stereotype.Component;import com.augmentum.ot.dataObject.ErrorCode;import com.augmentum.ot.dataObject.constant.FlagConstants;import com.augmentum.ot.util.ReaderXmlUtils;@Componentpublic class InitDataServlet extends HttpServlet {    private static final long serialVersionUID = 2705746245967369017L;    @Override    public void init() throws ServletException {        super.init();        ServletContext servletContext = getServletContext();        try {            Map<String, ErrorCode> errorCodeMap = ReaderXmlUtils.getErrorCodes();  //自定义的解析xml的工具类            servletContext.setAttribute(FlagConstants.ERROR_CODE_MAP, errorCodeMap);        } catch (Exception e) {            e.printStackTrace();        }    }}

web.xml

    <servlet>        <display-name>InitDataServlet</display-name>        <servlet-name>InitDataServlet</servlet-name>        <servlet-class>com.augmentum.ot.initServlet.InitDataServlet</servlet-class>        <load-on-startup>1</load-on-startup>    </servlet>    <servlet-mapping>        <servlet-name>InitDataServlet</servlet-name>        <url-pattern>/InitDataServlet</url-pattern>    </servlet-mapping>

三、在service层和action层抛出异常

下面是service方法的一个方法

    @Override    public Course getDetailCourseById(Integer id) throws DataWarningException, ServerErrorException {        logger.debug(LogConstants.getDebugInput("courseId", id));        if (id == null || id <= 0) {            logger.error(LogConstants.objectIsNULLOrEmpty("id"));            throw new ServerErrorException(ErrorCodeConstants.SERVER_VALIDATION_ERROR);        }        Course course;        try {            course = courseDao.findByPrimaryKey(id);        } catch (Exception e) {            logger.error(e.getStackTrace(), e);            throw new ServerErrorException(ErrorCodeConstants.SERVER_ERROR);        }        if (course == null || course.getCourseIsDeleted() == FlagConstants.IS_DELETED) {            logger.warn(LogConstants.getLogCourseByErrorCode(ErrorCodeConstants.VIEW_COURSE_DELETED, id));            throw new DataWarningException(ErrorCodeConstants.VIEW_COURSE_DELETED);        }        ......        logger.debug(LogConstants.getDebugOutput("Course", course.toString()));        return course;    }

下面是action层的一个方法

    public String viewCourseDetail() throws DataWarningException, ServerErrorException {        ......        course = courseService.getDetailCourseById(courseId);        ......        return SUCCESS;    }

四、在Interceptor中处理异常

在我们系统中,每个Action类都继承一个BaseAction,在BaseAction中有个JSONObject对象,存放返回给前台的数据。所以错误数据我们可以存放到jsonObject中

ExceptionInterceptor.java

public class ExceptionInterceptor extends ExceptionMappingInterceptor {    private static final long serialVersionUID = -3837674457299306885L;    private static final Logger logger = Logger.getLogger(ExceptionInterceptor.class);    private BaseAction baseAction;            private boolean isAjaxRequest(HttpServletRequest request) {        String header = request.getHeader("X-Requested-With");        if (header != null && "XMLHttpRequest".equals(header))            return true;        else            return false;    }            private String handleExceptionByServerErrorException(Exception e, boolean isAjax) {        String errorCode = e.getMessage();        if (null == errorCode || "".equals(errorCode)) {            errorCode = ErrorCodeConstants.SERVER_ERROR;        }        ServletContext context = ServletActionContext.getServletContext();        @SuppressWarnings("unchecked")        Map<String, ErrorCode> errorCodeMap = (Map<String, ErrorCode>) context.getAttribute(FlagConstants.ERROR_CODE_MAP);        ErrorCode errorCodeEntity = errorCodeMap.get(errorCode);        logger.error(errorCodeEntity.getErrorMessage());                if (isAjax) {            // Make the JSON object.            baseAction.setJsonObject(JSONObject.fromObject(errorCodeEntity));            return FlagConstants.ERROR_JSON;   // "error_json"        } else {            baseAction.setErrorCode(errorCodeEntity);            return FlagConstants.ERROR_PAGE;  //"error_page"        }    }        private String handleDataWarningException(Exception e, boolean isAjax) {                String errorCode = e.getMessage();        ServletContext context = ServletActionContext.getServletContext();        @SuppressWarnings("unchecked")        Map<String, ErrorCode> errorCodeMap = (Map<String, ErrorCode>) context.getAttribute(FlagConstants.ERROR_CODE_MAP);        ErrorCode errorCodeEntity = errorCodeMap.get(errorCode);        errorCodeEntity.setErrorMessage(baseAction.getText(errorCodeEntity.getErrorMessageKey()));                if (isAjax == true) {            baseAction.setJsonObject(JSONObject.fromObject(errorCodeEntity));            return FlagConstants.ERROR_JSON;        } else {            baseAction.setErrorCode(errorCodeEntity);            return FlagConstants.ERROR_PAGE;        }    }        private String handleException(boolean isAjax) {        String errorCode = ErrorCodeConstants.SERVER_ERROR;        ServletContext context = ServletActionContext.getServletContext();        @SuppressWarnings("unchecked")        Map<String, ErrorCode> errorCodeMap = (Map<String, ErrorCode>) context.getAttribute(FlagConstants.ERROR_CODE_MAP);        ErrorCode errorCodeEntity = errorCodeMap.get(errorCode);                        if (isAjax) {            // Make the JSON object.            baseAction.setJsonObject(JSONObject.fromObject(errorCodeEntity));            return FlagConstants.ERROR_JSON;        } else {            baseAction.setErrorCode(errorCodeEntity);            return FlagConstants.ERROR_PAGE;        }    }        @Override    public String intercept(ActionInvocation invocation) throws Exception {        try {            return invocation.invoke();        } catch (Exception e) {                        baseAction = (BaseAction) invocation.getAction();            HttpServletRequest request = ServletActionContext.getRequest();            boolean isAjax = isAjaxRequest(request);            if (e instanceof ServerErrorException) {                return handleExceptionByServerErrorException(e, isAjax);            } else if (e instanceof DataWarningException) {                return handleDataWarningException(e, isAjax);            } else {                logger.error(e.getStackTrace(), e);                return handleException(isAjax);            }        }    }}

struts.xml

<global-results><result name="error_page" type="chain"><param name="actionName">handleError</param><param name="namespace">/error</param></result><result name="error_json" type="json"><param name="root">jsonObject</param></result></global-results>

其中handleError 是用于非ajax时的页面跳转的Action


五、前台处理

/*  data: 前台返回的数据  customUrl: 当发生异常要跳转页面时页面的URL  finalHandleFunc:弹出对话框后点击对话框后执行的函数  finalHandleFuncParam:上面函数所需参数*/function handleException(data, customUrl, finalHandleFunc, finalHandleFuncParam) {    if (data && data.errorCodeId) {        // 不跳转页面        if (data.flag == "0") {//先弹出对话框提示错误信息,当点击OK按钮时执行finalHandleFunc函数            initialErrorMsgBar(data.errorMessage, function() {                if(finalHandleFunc) {                    finalHandleFunc(finalHandleFuncParam);                }            });        }        // 跳转页面        if (data.flag == "1") {            if (data.errorCodeId == "E0001" || data.errorCodeId == "E0002") {//特殊情况,如无权限情况                window.onbeforeunload = null;                window.location.href = $("#basePath").val() + "error/handleError?errorCode.errorCodeId=" + data.errorCodeId;            } else if(customUrl){// 自定义跳转页面时,先弹出对话框提示错误信息,在跳错误页面                initialErrorMsgBar(data.errorMessage, function() {                    window.onbeforeunload = null;window.location = customUrl;                });            } else {                // 先弹出对话框提示错误信息,再跳到系统默认页面                initialErrorMsgBar(data.errorMessage, function() {                    window.onbeforeunload = null;                    window.location = $('#basePath').val() + 'dashboard/dashboard_dashboard';                });            }        }        return false;    }    return true;}


0 0