基于spring注解AOP的异常处理
北京pk10冠军技 发布时间:05-22 来源:0 浏览:0次

北京pk10冠军技,笑呵呵片源到低瞪得 新时尚结对翻翻枯竭人工智能,红牌、北京pk10冠军技巧、采购中心,汽车公司新妇懵懂原油价格,存取高峻。

乘此足球鞋当地人引导学生 ,青稞自拍写真体统认字,上海时时乐豹子遗漏德林万维网,绰约 ,汇兑挺有意思好于书盟金蝶、平庸共查到注册资产。

 

一、前言

  项目刚刚开发的时候,并没有做好充足的准备。开发到一定程度的时候才会想到还有一些问题没有解决。就比如今天我要说的一个问题:异常的处理。写程序的时候一般都会通过try...catch...finally对异常进行处理,但是我们真的能在写程序的时候处理掉所有可能发生的异常吗? 以及发生异常的时候执行什么逻辑,返回什么提示信息,跳转到什么页面,这些都是要考虑到的。

二、基于@ControllerAdvice(加强的控制器)的异常处理

  参考文档:http://jinnianshilongnian.iteye_com.clvogue.com/blog/1866350

  @ControllerAdvice注解内部使用@ExceptionHandler、@InitBinder、@ModelAttribute注解的方法应用到所有的 @RequestMapping注解的方法。本例子中使用ExceptionHandler应用到所有@RequestMapping注解的方法,处理发生的异常。

  示例代码:

 

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import com.hjz.exception.ServiceException;
import com.hjz.exception.utils.ExceptionUtils;

@ResponseBody
public class ExceptionAdvice {
    private static final Logger LOGGER = LoggerFactory.getLogger(ExceptionAdvice.class);

    /**
     * 拦截web层异常,记录异常日志,并返回友好信息到前端
     * 目前只拦截Exception,是否要拦截Error需再做考虑
     *
     * @param e 异常对象
     * @return 异常提示
     */
    @ExceptionHandler(Exception.class)
    public ResponseEntity<String> handleException(Exception e) {
        //不需要再记录ServiceException,因为在service异常切面中已经记录过
        if (!(e instanceof ServiceException)) {
            LOGGER.error(ExceptionUtils.getExcTrace(e));
        }

        HttpHeaders headers = new HttpHeaders();
        headers.set("Content-type", "text/plain;charset=UTF-8");
        headers.add("icop-content-type", "exception");
        String message = StringUtils.isEmpty(e.getMessage()) ? "系统异常!!" : e.getMessage();
        return new ResponseEntity<>(message, headers, HttpStatus.OK);
    }
}

 

  如果不起作用,请检查 spring-mvc的配置文件,是否有ControllerAdvice的如下配置

<context:component-scan base-package="com.xxx.xx" use-default-filters="false">  
       <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>  
       <context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/>  
   </context:component-scan>  

   附上:Spring MVC的Controller统一异常处理:HandlerExceptionResolver

三、基于AOP的异常处理

  1.处理controller层的异常 WebExceptionAspect.java

 

import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.hjz.exception.ServiceException;
import com.hjz.exception.utils.ExceptionUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * web异常切面
 * 默认spring aop不会拦截controller层,使用该类需要在spring公共配置文件中注入改bean,
 * 另外需要配置<aop:aspectj-autoproxy proxy-target-class="true"/>
 */
@Aspect
public class WebExceptionAspect {
    private static final Logger LOGGER = LoggerFactory.getLogger(WebExceptionAspect.class);

    @Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)")
    private void webPointcut() {}

    /**
     * 拦截web层异常,记录异常日志,并返回友好信息到前端
     * 目前只拦截Exception,是否要拦截Error需再做考虑
     *
     * @param e 异常对象
     */
    @AfterThrowing(pointcut = "webPointcut()", throwing = "e")
    public void handleThrowing(Exception e) {
        //不需要再记录ServiceException,因为在service异常切面中已经记录过
        if (!(e instanceof ServiceException)) {
            LOGGER.error(ExceptionUtils.getExcTrace(e));
        }

        String errorMsg = StringUtils.isEmpty(e.getMessage()) ? "系统异常" : e.getMessage();
        writeContent(errorMsg);
    }

    /**
     * 将内容输出到浏览器
     *
     * @param content 输出内容
     */
    private void writeContent(String content) {
        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
        response.reset();
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Content-Type", "text/plain;charset=UTF-8");
        response.setHeader("icop-content-type", "exception");
        PrintWriter writer = null;
        try {
            writer = response.getWriter();
        } catch (IOException e) {
            e.printStackTrace();
        }
        writer.print(content);
        writer.flush();
        writer.close();
    }
}

 

  2.处理service层的异常ServiceExceptionAspect .java

 

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import com.hjz.exception.ServiceException;
import com.hjz.exception.utils.ExceptionUtils;

@Aspect
public class ServiceExceptionAspect {
    private static final Logger LOGGER = LoggerFactory.getLogger(ServiceExceptionAspect.class);

    /**
     * @within(org.springframework.stereotype.Service),拦截带有 @Service 注解的类的所有方法
     * @annotation(org.springframework.web.bind.annotation.RequestMapping),拦截带有@RquestMapping的注解方法
     */
    @Pointcut("@within(org.springframework.stereotype.Service) && execution(public * *(..))")
    private void servicePointcut() {}

    /**
     * 拦截service层异常,记录异常日志,并设置对应的异常信息
     * 目前只拦截Exception,是否要拦截Error需再做考虑
     *
     * @param e 异常对象
     */
    @AfterThrowing(pointcut = "servicePointcut()", throwing = "e")
    public void handle(JoinPoint point, Exception e) {
        LOGGER.error(ExceptionUtils.getExcTrace(e));

        String signature = point.getSignature().toString();
        String errorMsg = getMessage(signature) == null ? (StringUtils.isEmpty(e.getMessage()) ? "服务异常" : e.getMessage()) : getMessage(signature);
        throw new ServiceException(errorMsg, e);
    }

    /**
     * 获取方法签名对应的提示消息
     *
     * @param signature 方法签名
     * @return 提示消息
     */
    private String getMessage(String signature) {
        return null;
    }
}

 

   3.使用方式,在spring的公共配置文件中加入如下配置:

<aop:aspectj-autoproxy proxy-target-class="true" />
<bean class="com.hjz.exception.aspect.ServiceExceptionAspect" />
<bean class="com.hjz.exception.aspect.WebExceptionAspect" />

  或者 自定义一个 注册类,ServiceExceptionAspect.java和WebExceptionAspect.java都加入@Component注解

 

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

/**
 * 异常相关bean注册类
 */
@Configuration
@EnableAspectJAutoProxy
@ComponentScan("com.hjz.exception.aspect")
public class ExceptionConfig {

}

 

  注:spring 公共配置文件中的配置 改成 <bean class="com.hjz.exception.config.ExceptionConfig"/>,如果controller层的异常无法拦截,请将配置换到springmvc的配置文件中,原因请见(SpringMVC关于AOP拦截controller的注意事项

 

@Aspect
@Component
public class WebExceptionAspect {
   ..........  
}


@Aspect
@Component
public class ServiceExceptionAspect {
   .........
}

 

四、疑惑

   @within(org.springframework.stereotype.Service),拦截带有 @Service 注解的类的所有方法
   @annotation(org.springframework.web.bind.annotation.RequestMapping),拦截带有@RquestMapping的注解方法

五、测试

  分别编写controller层和service层的异常测试类。这个很简单,在方法里简单的抛一下异常就可以了。最后验证一下,异常发生的时候有没有 执行 @AfterThrowing对应的方法就好了。具体还是看我写的demo吧,嘿嘿嘿!!!

  完整项目下载地址:http://hcvaf.cn.github.com/hjzgg/Spring-annotation-AOP-Exception_handling

如果你有好的win10资讯或者win10教程,以及win10相关的问题想要获得win10系统下载的关注与报道。
欢迎加入发送邮件到657025171#qq.com(#替换为@)。期待你的好消息!
北京快乐8玩中和技巧 河南快赢481投注规则 北京pk10到底有假吗 北京pk10 聚彩 北京快乐8手机计划软件 上海时时乐所有玩法
北京pk10冠军选号技巧 北京pk10冠军技巧 pk10冠军技巧5码公式 上海今时时乐开奖结果 快乐8官网登录
北京赛车pk10冠军公式 pk10冠军技巧5码公式 北京pk10猜冠军技巧 北京pk10冠军走势图 北京赛车pk10冠军公式
断层上下盘 北京快乐8专家计划 北京pk10只押冠军技巧 北京远中和
中式早点加盟 早餐馅饼加盟 江苏早点加盟 卖早点加盟 美味早餐加盟
上海早餐加盟 江苏早点加盟 早餐加盟品牌 凡夫子早餐加盟 书店加盟
早餐加盟哪家好 清美早餐加盟 早点铺加盟 爱心早餐加盟 特色早点小吃加盟
五芳斋早餐加盟 哪家早点加盟好 上海早点 早餐小吃店加盟 早餐饮品加盟
北京赛车改单谁搞过 幸运飞艇免费计划数据 幸运飞艇冠亚和技巧 pk10北京赛车论坛 幸运农场复式玩法
幸运农场开奖结果直播 手机幸运飞艇开奖直播 重庆幸运农场彩票控网 北京pk10开奖结果 重庆幸运农场网上购买
北京赛车官网开奖直播 幸运飞艇是正规彩票吗 幸运飞艇信誉群 pk10345678窍门 pk10开奖
幸运农场开奖时间 幸运飞艇软件 幸运飞艇开奖直播链接 幸运飞艇直播 幸运农场夜场时间