html5中文学习网

您的位置: 首页 > 网络编程 > java教程 » 正文

java基于spring注解AOP的异常处理的方法_java_

[ ] 已经帮助:人解决问题

一、前言rtqHTML5中文学习网 - HTML5先行者学习网

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

二、基于@ControllerAdvice(加强的控制器)的异常处理rtqHTML5中文学习网 - HTML5先行者学习网
rtqHTML5中文学习网 - HTML5先行者学习网

@ControllerAdvice注解内部使用@ExceptionHandler、@InitBinder、@ModelAttribute注解的方法应用到所有的 @RequestMapping注解的方法。本例子中使用ExceptionHandler应用到所有@RequestMapping注解的方法,处理发生的异常。rtqHTML5中文学习网 - HTML5先行者学习网

示例代码:rtqHTML5中文学习网 - HTML5先行者学习网

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;@ResponseBodypublic 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的如下配置rtqHTML5中文学习网 - HTML5先行者学习网

<context:component-scan base-package="com.sishuok.es" 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> 

三、基于AOP的异常处理rtqHTML5中文学习网 - HTML5先行者学习网

1.处理controller层的异常 WebExceptionAspect.javartqHTML5中文学习网 - HTML5先行者学习网

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"/> */@Aspectpublic 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 .javartqHTML5中文学习网 - HTML5先行者学习网

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;@Aspectpublic 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的公共配置文件中加入如下配置:rtqHTML5中文学习网 - HTML5先行者学习网

<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注解rtqHTML5中文学习网 - HTML5先行者学习网

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 {}
@Aspect@Componentpublic class WebExceptionAspect { .......... }@Aspect@Componentpublic class ServiceExceptionAspect { .........}

四、疑惑rtqHTML5中文学习网 - HTML5先行者学习网

@within(org.springframework.stereotype.Service),拦截带有 @Service 注解的类的所有方法rtqHTML5中文学习网 - HTML5先行者学习网

@annotation(org.springframework.web.bind.annotation.RequestMapping),拦截带有@RquestMapping的注解方法rtqHTML5中文学习网 - HTML5先行者学习网

五、测试rtqHTML5中文学习网 - HTML5先行者学习网

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

完整项目下载地址:Spring-AOP_jb51.rarrtqHTML5中文学习网 - HTML5先行者学习网
rtqHTML5中文学习网 - HTML5先行者学习网

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。rtqHTML5中文学习网 - HTML5先行者学习网
rtqHTML5中文学习网 - HTML5先行者学习网

(责任编辑:)
推荐书籍
推荐资讯
关于HTML5先行者 - 联系我们 - 广告服务 - 友情链接 - 网站地图 - 版权声明 - 人才招聘 - 帮助