Spring MVC异常统一处理(异常信息的国际化,日记记录)

电脑杂谈  发布时间:2019-08-15 09:01:41  来源:网络整理

springmvc日志处理_处理的日志时出错_springmvc aop 日志

JAVA EE项目中,还是是对上层的数据操作,不过业务层的处理过程,不过控制层的处理,都不可避免的会遇见这些可预知的(业务异常主动抛出)、不可预知的异常需要处理。一般dao层、service层的异常就会直接抛出,最终由controller统一进行处理,每位过程都单独处理异常,且要考虑到异常信息和后端的反馈,源码的耦合度高,不统一,中期维护的工作也多。

同样还必须考虑异常模块和日记系统、国际化的支持。

如果需要一种异常处理制度将异常处理解耦出来,如此确保相关处理过程的系统单一,和功能其他系统耦合,也实现了异常信息的统一处理和维护。

接下来以实际工作中Spring MVC实现异常的统一处理为例。

首先说说Spring MVC处理异常的3中手段,进行比较,最后选用一个比较恰当的手段。

Spring MVC提供的简单异常处理器SimpleMappingExceptionResolver; Spring MVC异常处理接口HandlerExceptionResolver自定义自己的异常处理器; @ExceptionHandler注解实现异常处理;

对于第一种方式来说,使用SimpleMappingExceptionResolver能够准确显示定义的异常处理按钮,进行异常处理,具备内置简单、有很好的扩展性,因为是基于配置的对已有的源码没有侵入性等长处。但是该原理仅仅希望获取到异常信息,对于这些数据的现象不适用。配置方式如下:

处理的日志时出错_springmvc aop 日志_springmvc日志处理

 error-businesserror-parameter

对于第二种方式,使用实现HandlerExceptionResolver接口的异常处理进行异常处理,具备内置简单、很好的扩展性、对已有代码没有侵入性等长处。同时因此自定义实现,我们可以在处理异常时进行额外的处理(日记的记录、异常信息的国际化等)。项目实际的研发中应该使用的这样内置方案,配置如下:

error/errorerror/error

对于第三种方式springmvc日志处理,通过@ExceptionHandler注解实现异常处理,毕竟特别灵巧,所以这样手段需要在每位controller上都需注解,解决方案是增强一个BaseController类,使用@ExceptionHandler注解声明异常处理,这些controller都承袭他。实现手段如下:

  public class BaseController {  
        /** 基于@ExceptionHandler异常处理 */  
        @ExceptionHandler  
        public String exp(HttpServletRequest request, Exception ex) {  
              
            request.setAttribute("ex", ex);  
              
            // 根据不同错误转向不同页面  
            if(ex instanceof BusinessException) {  
                return "error-business";  
            }else if(ex instanceof ParameterException) {  
                return "error-parameter";  
            } else {  
                return "error";  
            }  
        }  
    }  

使用这样原理存在侵入性springmvc日志处理,不过在异常处理时也不能获取异常以外的数据,且Ajax请求产生的异常信息无法反馈给后端。

综合权衡,使用第二种方式进行异常统一处理方案的设计。

处理的日志时出错_springmvc日志处理_springmvc aop 日志

首先判断下方案也是实现的需求。

出错页面跳转: 例如404页面。基于Spring MVC,后端访问某个列表跳转controller的时候出现异常的时候,跳转到错误列表。 Ajax异常反馈: 前端通过Ajax的手段访问controller获取JSON数据出现异常的时候,需要将异常信息反馈给后端。 异常信息的日记记录: 配合日志系统,实现异常日志的记录。 异常信息的国际化: 配合国际化设计实现异常信息的国际化。

1、 首先自定义异常解析器,源码清单如下:

package com.cisdi.ecis.common.exception;
import java.io.PrintWriter;
import java.io.StringWriter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
import com.cisdi.ecis.common.utils.ExceptionI18Message;
/**
 * 
 * @author LCore
 * 
 * 平台异常信息跳转、解析
 * 
 */
public class PlatformMappingExceptionResolver extends
		SimpleMappingExceptionResolver {
	static Logger logger = LoggerFactory.getLogger(PlatformMappingExceptionResolver.class);
	@Override
	protected ModelAndView doResolveException(HttpServletRequest request,
			HttpServletResponse response, Object handler, Exception ex) {
		String viewName = determineViewName(ex, request);
		// vm方式返回
		if (viewName != null) {
			if (!( request.getHeader("accept").indexOf("application/json") > -1 || ( request
					.getHeader("X-Requested-With") != null && request
					.getHeader("X-Requested-With").indexOf("XMLHttpRequest") > -1 ) )) {
				// 非异步方式返回
				Integer statusCode = determineStatusCode(request, viewName);
				if (statusCode != null) {
					applyStatusCodeIfPossible(request, response, statusCode);
				}
				// 跳转到提示页面
				return getModelAndView(viewName, ex, request);
			} else {
				// 异步方式返回
				try {
					PrintWriter writer = response.getWriter();
					writer.write(ExceptionI18Message.getLocaleMessage(ex.getMessage()));
					response.setStatus(404, ExceptionI18Message.getLocaleMessage(ex.getMessage()));
				        //将异常栈信息记录到日志中
                                        logger.error(getTrace(ex)); 
					writer.flush();
				} catch ( Exception e ) {
					
					e.printStackTrace();
				}
				// 不进行页面跳转
				return null;
			}
		} else {
			return null;
		}
	}
	public static String getTrace(Throwable t) {
        StringWriter stringWriter= new StringWriter();
        PrintWriter writer= new PrintWriter(stringWriter);
        t.printStackTrace(writer);
        StringBuffer buffer= stringWriter.getBuffer();
        return buffer.toString();
    }
}

2、以后在Spring MVC配置文档中配置异常解析器映射路径。


error/errorerror/error

3、 异常信息的国际化

springmvc aop 日志_处理的日志时出错_springmvc日志处理

通过上述配置同样就已然满足了方案需求中的大部分需求,还仅剩一个需求:异常信息的国际化。上述代码中有一段代码:

ExceptionI18Message.getLocaleMessage(ex.getMessage()

ExceptionI18Message就是根据目前的修辞环境得到异常信息,实现细则如下:

package com.cisdi.ecis.common.utils;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.support.RequestContext;
public class ExceptionI18Message{
   
    public static String getLocaleMessage(String key){
    	HttpServletRequest request =  ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
    	RequestContext requestContext = new RequestContext(request);
    	return requestContext.getMessage(key);
    }
}

关于国际化:

后端程序员在编码时,可以直接抛出业务异常,反而压入的message应该是国际化文件中的"key",自己在去国际化文件中编写多套语言的key的value。例如:

##Exception
pbs.exception.copyNode=The Exceptioninfo I18n

springmvc aop 日志_处理的日志时出错_springmvc日志处理

以后我们压入的异常信息为pbs.exception.copyNode:

throw new Exception("pbs.exception.copyNode");

到此为止,方案已经设计完毕,简单的试验下是否满足我们的需求吧,对于列表跳转的异常这里就不在测试了,主要在于前端Ajax请求controller抛出业务异常的时候前端是否希望收到反馈。

前端代码:

$.ajax({
                url: "${basePath}/doc/addDocMaterials",
                type: "post",
                dataType: "json",
                data: obj,
                complete: function(xhr) {
                    console.log(xhr);
                    if (xhr.status == 200 && xhr.responseText != null) {} else {
                        $.messager.alert('#springMessage("message.tip")', xhr.responseText);
                        displayLoad();
                    }
                }
});

以后后端主动抛出业务异常的时候,后端获取到的反馈结果如下:(这儿我们就以下面的抛出异常的源码为例)。

到此为止,关于Spring MVC异常的统一处理方案(国际化、Ajax反馈)结束。


本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-119309-1.html

    相关阅读
      发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

      热点图片
      拼命载入中...