项目异常处理

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

一、自定义异常

首先,我们自定义了两种类型的异常: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;

@Component
public 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Spring Boot项目中,可以通过异常处理来处理应用程序中出现的异常。Spring Boot提供了多种处理异常的方式,下面介绍两种常用的方式:全局异常处理和自定义异常处理。 1. 全局异常处理: 在Spring Boot项目中,可以通过定义一个全局异常处理器来统一处理应用程序中的异常。可以使用@ControllerAdvice注解和@ExceptionHandler注解来实现全局异常处理。 首先,在项目中创建一个类,使用@ControllerAdvice注解标记该类为全局异常处理器。然后,在该类中定义一个或多个方法,使用@ExceptionHandler注解标记这些方法来处理具体的异常。例如: ```java @ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(Exception.class) public ResponseEntity<String> handleException(Exception ex) { // 处理异常逻辑... return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Internal Server Error"); } } ``` 上述代码中,handleException方法用于处理所有的Exception类型的异常,当应用程序中出现Exception类型的异常时,会执行该方法,并返回一个包含错误信息的ResponseEntity对象。 2. 自定义异常处理: 除了全局异常处理外,还可以自定义异常处理来处理特定的异常。可以通过创建自定义的异常类,并在需要抛出异常的地方抛出该异常,然后通过@ControllerAdvice注解和@ExceptionHandler注解来处理该异常。 首先,创建一个自定义的异常类,继承自Exception或其子类。例如: ```java public class MyCustomException extends Exception { public MyCustomException(String message) { super(message); } } ``` 然后,在需要抛出异常的地方抛出该异常。例如: ```java public void myMethod() throws MyCustomException { // 发生异常的逻辑... throw new MyCustomException("Something went wrong"); } ``` 最后,在全局异常处理器中使用@ExceptionHandler注解来处理该自定义异常。例如: ```java @ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(MyCustomException.class) public ResponseEntity<String> handleMyCustomException(MyCustomException ex) { // 处理自定义异常逻辑... return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(ex.getMessage()); } } ``` 上述代码中,handleMyCustomException方法用于处理MyCustomException类型的异常,当应用程序中出现MyCustomException类型的异常时,会执行该方法,并返回一个包含错误信息的ResponseEntity对象。 使用全局异常处理和自定义异常处理可以使得Spring Boot项目异常处理更加灵活和统一。根据具体需求,可以选择适合自己项目异常处理方式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值