异常信息应统一进行处理. 程序员开发过程中,应尽量少用try..catch.避免因为catch造成的业务歧义.
而在web开发中,普通的页面提交动作,和ajax提交动作,处理方式不一样,因为跳转后直接显示响应数据,而ajax是通过error回调函数进行处理.

这里的处理思路,适用springmvc和struts2. 只是叫法不一样,一个是HandlerExceptionResolver ,一个是exceptioninterceptor.

下面是部分摘要,体现一下思路

首先定义异常拦截器:

@Component
public class MyExceptionHandler implements HandlerExceptionResolver {
protected Log log = LogFactory.getLog(this.getClass()); @Override
public ModelAndView resolveException(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex) {
log.error("异常捕获", ex);
String requestURI = request.getRequestURI();
String fileExtName = StringUtils.getFileExtName(requestURI);
boolean isajax = "ajax".equals(fileExtName);
Throwable parseException = parseException(ex);
return ExceptionHandlerFactory.createExceptionhandler(parseException)
.resolveException(request, response, handler, parseException, isajax);
}
  //这里要获取到最内层的异常
private static Throwable parseException(Throwable e){
Throwable tmp = e;
int breakPoint = ;
while(tmp.getCause()!=null){
if(tmp.equals(tmp.getCause())){
break;
}
tmp=tmp.getCause();
breakPoint++;
if(breakPoint>){
break;
}
}
return tmp;
}
}

然后是 ExceptionHandlerFactory 主要是用于生成 异常处理的具体类型

public class ExceptionHandlerFactory {

    /**
* 外挂的自定义处理器,用于外部扩展
*/
private static Map<String , ExceptionHandler> handlerList = null; public static ExceptionHandler createExceptionhandler(Throwable ex){
//这个是自定义的接口
ExceptionHandler exceptionHandler=null;
String packageName=ExceptionHandlerFactory.class.getName().replace(ExceptionHandlerFactory.class.getSimpleName(), "");
String className = ex.getClass().getSimpleName();
String classFullName = ex.getClass().getName(); if(handlerList==null){
handlerList = new HashMap<String, ExceptionHandler>();
}
if(handlerList.containsKey(classFullName)){
return handlerList.get(classFullName);
} //能走到这边,说明自定义的没有生效,走过之后,下面会将他缓存,也就是说,自定义的优先级永远大过系统自带的
try {
        //这里查找系统自带的,按照捕获的异常名称+ Handler进行查找,算是简单约定,因为框架开发中的内置我可以约定,扩展的使用配置文件进行
exceptionHandler = (ExceptionHandler)Class.forName(packageName+ className+"Handler").newInstance();
} catch (Exception e) {
e.printStackTrace();
}
if(exceptionHandler==null){
exceptionHandler = new SimpleExceptionHandler();
}
handlerList.put(classFullName, exceptionHandler); return exceptionHandler;
} public Map<String, ExceptionHandler> getHandlerList() {
return handlerList;
}
  //这里有getset,用于spring注入
public void setHandlerList(Map<String, ExceptionHandler> handlerList) {
ExceptionHandlerFactory.handlerList = handlerList;
} }

最后书写一个用于验证异常的处理类型

public class ConstraintViolationExceptionHandler  extends BaseExceptionHandler{

    @Override
public Object processException(HttpServletRequest request,
HttpServletResponse response, Object handler, Throwable ex,
boolean isajax) {
ConstraintViolationException e=(ConstraintViolationException)ex;
Set<ConstraintViolation<?>> constraintViolations = e.getConstraintViolations();
      //ValidateInfo包含当前出错的字段,错误信息,出错的字段所在的类型,等必要的信息
       // 在ajax特别是ajaxForm的提交中,只要前端约定好了命名规则,就可以根据返回的信息,进行界面提示,比如可渲染成和validate一样的风格
      // 也可以给出一个dialog提示,或者......
List<ValidateInfo> validateInfos =new ArrayList<ValidateInfo>();
if(constraintViolations!=null && !constraintViolations.isEmpty()){
for(ConstraintViolation<?> violation : constraintViolations){
ValidateInfo info = new ValidateInfo();
info.setField(violation.getPropertyPath().toString().replaceAll("\\.","_"));
info.setMessage(violation.getMessage());
Class<? extends Object> class1 = violation.getRootBean().getClass();
String simpleName =StringUtils.getSpringName(class1);
if(simpleName.indexOf("$pcsubclass")>-){ //这个判断是openjpa的代理类型,带$的不光是代理类型,内部类的名称同样有,所以编码上要约束
String[] ss = simpleName.split("\\$");
if(ss.length>){
simpleName = ss[ss.length-];
simpleName = simpleName.substring(,).toLowerCase()+simpleName.substring();
}
} info.setClassName(simpleName);
Object ov =violation.getInvalidValue();
if(ov==null){
info.setCurrentValue("");
}else{
info.setCurrentValue(ov.toString());
} validateInfos.add(info);
} }
return validateInfos; //返回经过封装的验证信息,用于jquery ajax error回调方法进行统一处理
}
}

BaseExceptionHandler 只是对最后响应代码做一个判断

public abstract class BaseExceptionHandler implements ExceptionHandler{

    /**
* 用于传递到页面的值
*/
protected Map<String, Object> data = new HashMap<String, Object>(); /**
* 写到输出流
*/
protected ModelAndView write(HttpServletRequest request,
HttpServletResponse response, Object handler, Throwable ex,
boolean isajax,Object dt){
int responseCode=;
if(ex instanceof BaseRuntimeException){
responseCode=((BaseRuntimeException)ex).getResponseCode();
}
if(ex instanceof ConstraintViolationException){
responseCode=;
}
response.setStatus(responseCode);
if(!isajax){//非ajax,直接跳转的,这里的是否ajax很简单,我们约定,ajax请求全部使用.ajax扩展.当然通过httpheader也能,jquery还支持preFilter,可以在这里统一加参数
ModelAndView modelAndView = new ModelAndView("/error/error");
modelAndView.addObject("__exception__", ex);
modelAndView.addAllObjects(data);
if(dt!=null){
modelAndView.addObject(dt);
}
return modelAndView;
}
//这个是封装的标准返回值模版,包含相应code,错误信息和响应数据等字段
ResultTemplate createFailResult = ResultTemplate.createFailResult(ex.getMessage());
createFailResult.setData(dt);
WebUtils.renderJson(createFailResult);
return null;
} public abstract Object processException(HttpServletRequest request,
HttpServletResponse response, Object handler, Throwable ex,
boolean isajax); @Override
public ModelAndView resolveException(HttpServletRequest request,
HttpServletResponse response, Object handler, Throwable ex,
boolean isajax) {
Object d = processException(request, response, handler, ex, isajax);
return write(request,
response, handler, ex,
isajax,d);
} }

xml 配置

<bean class="com.core.web.interceptor.exceptionhandler.ExceptionHandlerFactory">
<property name="handlerList">
<map>
<entry key="javax.validation.ConstraintViolationException" > <!-- jpa验证异常,这里可以不配置,系统内置,也可以配置自己的,替换系统自带的 -->
<bean class="com.core.web.interceptor.exceptionhandler.ConstraintViolationExceptionHandler"/>
</entry> </map>
</property>
</bean>

SpringMVC对异常进行全局处理,并区分对待ajax和普通请求的更多相关文章

  1. springmvc处理局部异常和全局异常

    springmvc通过HandlerExceptionResolver(是一个接口,在spring-webmvc依赖下)处理程序异常,包括处理器异常.数据绑定异常以及处理器执行时发生的异常.Handl ...

  2. SpringMVC 处理异常的4种方式

    springmvc处理异常有三种方式: 1.在一个controller中定义一个方法,用@ExceptionHandler注解标注.(优先级最高) @ExceptionHandler public M ...

  3. springmvc全局异常处理ControllerAdvice区分返回响应类型是页面还是JSON

    思路: 加一个拦截器,在preHandler中取得HandlerMethod,判断其方法的返回类型,以及方法的注解和类的注解. 如果返回是json,收到异常则返回默认的异常包装类型. 如果返回是页面, ...

  4. springmvc 通过异常增强返回给客户端统一格式

    在springmvc开发中,我们经常遇到这样的问题:逻辑正常执行时返回客户端指定格式的数据,比如json,但是遇NullPointerException空指针异常,NoSuchMethodExcept ...

  5. springmvc、 springboot 项目全局异常处理

    异常在项目中那是不可避免的,通常情况下,我们需要对全局异常进行处理,下面介绍两种比较常用的情况. 准备工作: 在捕获到异常的时候,我们通常需要返回给前端错误码,错误信息等,所以我们需要手动封装一个js ...

  6. Xamarin.Android-捕获未处理异常(全局异常)

    一.前言 android中如果出现了未处理的异常,程序会闪退,这是非常不好的用户体验,很多用户会因此卸载APP,因此未处理的异常是应该尽力避免的. 有些很难避免的异常(如:IO.网络等),应在代码中进 ...

  7. SpringMVC学习--异常处理器

    简介 springmvc在处理请求过程中出现异常信息交由异常处理器进行处理,自定义异常处理器可以实现一个系统的异常处理逻辑. 异常处理思路 系统中异常包括两类:预期异常和运行时异常RuntimeExc ...

  8. SpringMVC接口测试异常:Can not deserialize instance of int out of START_OBJECT token

    之前使用springmvc搭建了restful风格的接口服务,在使用mockmvc进行集成测试的时候出现了异常:Can not deserialize instance of int out of S ...

  9. Struts局部异常与全局异常处理

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAowAAAG3CAIAAACxBJNyAAAgAElEQVR4nOy9z6tk15Ymdv4B0eRU8O

随机推荐

  1. 基础连接已经关闭: 未能为 SSL/TLS 安全通道建立信任关系。

    (转自:http://blog.sina.com.cn/s/blog_5eca668b01018949.html)定义一个类,来对远程X.509证书的验证,进行处理,返回为true.我们要自己定义一个 ...

  2. Spring 事务处理

    Spring 默认执行事务回滚:当开启事务的类中对数据库的操作的异常没有任何处理时,才会主动触发事务回滚. 而很多时候业务都需要对抛出的异常进行处理,所以如果try,catch了操作数据库的方法,事务 ...

  3. Linux Runlevel 启动 脚本

    Linux 操作系统自从开始启动至启动完毕需要经历几个不同的阶段,这几个阶段就叫做 Runlevel,同样,当Linux操作系统关闭时也要经历另外几个不同的 Runlevel,下面详细介绍一下 Run ...

  4. ReactJS学习笔记(二)

    1.Ajax: componentDidMount 方法设置 Ajax 请求,等到请求成功,再用 this.setState 方法重新渲染 UI. /*demo1*/ var Demo1Box=Rea ...

  5. java学习第14天(集合的框架和基本遍历)

    今天主要是接触了集合的概念,集合简单意义上来说就是类对象的集合,我们一般用Collection 这个接口来表示,集合主要体系为: Collection |--List |--ArrayList |-- ...

  6. RabbitMQ学习: 介绍

    1. 介绍 RabbitMQ是一个由erlang开发的基于AMQP(Advanced Message Queue )协议的开源实现.用于在分布式系统中存储转发消息,在易用性.扩展性.高可用性等方面都非 ...

  7. HTTP权威协议笔记-6.代理

    6.1 Web的中间实体 Http的代理服务器即是客户端的服务器又是服务器的客户端. 它介于服务器与客户端之间,当客户端发送请求报文经过它时,它会像服务器一样正确的处理请求和返回响应,同时,代理服务器 ...

  8. 查询数据库最大id加1

    SELECT ISNULL(MAX(id),0)+1 AS MaxId FROM TABLE ISNULL(MAX(id),0) 就是如果id为空 就返回0,然后再加1

  9. DataSnap 2009 系列之三 (生命周期篇)

    DataSnap 2009 系列之三 (生命周期篇) DataSnap 2009的服务器对象的生命周期依赖于DSServerClass组件的设置 当DSServer启动时从DSServerClass组 ...

  10. UE3 ExampleGame Android版无法运行解决方案

    首先将 UE3\UnrealEngine3\UDKGame\Build\Android 文件夹 拷贝到 ExampleGame\Build下面.里面有相应的android 配置文件.xml 若果此时 ...