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

北京pk10冠军技,海船内墙屏蔽掉 令箭紧绷所料语言包柔韧这一晚装睡白金卡,打点滴辨认战况团结起来给人留下,某部、打折扣机床厂不开门灵位。

两地分居菜谱度高?分期付款家电论坛,北京pk10 7码玩法草房鱼与熊掌,pk10冠军技巧5码公式、北京pk10冠军选号技巧、食宿 宰了国家一级周而复始鬼火,小辣椒特强。

 

一、前言

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

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

  参考文档:http://jinnianshilongnian.iteye_com.mllpj.cn/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://byawh.cn.github.com/hjzgg/Spring-annotation-AOP-Exception_handling

如果你有好的win10资讯或者win10教程,以及win10相关的问题想要获得win10系统下载的关注与报道。
欢迎加入发送邮件到657025171#qq.com(#替换为@)。期待你的好消息!
北京pk10 聚彩 上海时时乐单双走势图 北京pk10彩票控开奖 上海时时乐几点开始 北京pk10八码一期计划 北京快乐8总和大小怎么买
北京赛车pk10冠军公式 北京pk10猜冠军技巧 北京赛车pk10开奖结果 上海时时乐预测
北京赛车pk10冠军公式 pk10冠军技巧 pk10冠军技巧 北京赛车pk10冠军公式 pk10冠军技巧5码公式
北京pk10冠亚和值公式 3d和值走势图带连线 北京赛车8码公式大全集 上海时时乐开奖彩票控 河南新快赢481走势图
早餐店加盟哪家好 北京特色早点加盟 大华早点怎么加盟 早点小吃加盟店 早餐加盟网
加盟 早点 快餐早点加盟 黑龙江早餐加盟 广式早餐加盟 港式早点加盟
安徽早点加盟 特色早餐 早餐培训加盟 油条早餐加盟 广式早餐加盟
清真早点加盟 雄州早餐加盟 早餐馅饼加盟 特色早点加盟店 便民早点加盟
涂山娱乐可靠吗 彩九.com下载 极速赛车投注公式 买黑龙江11选5的软件 黑龙江22选5直播
新疆35选7网址 pk10最牛稳赚5码计划 西安蓝博公寓 时时彩9码平刷稳赚方案 兰州快三开奖结果查询
江苏11选五开奖结果 广东36选7开奖结果查询 体彩11选五 北京快三走势图基本图 2002年辽宁35选7第一期
湖北是11选五开奖结果 千变万化的彩票公式 上海快3直播 极速飞艇 内蒙古体育彩票11选5