0
点赞
收藏
分享

微信扫一扫

3.6 统一处理异常和使用AOP思想统一记录日志

文章目录



# 统一处理异常

SpringBoot 有统一处理异常的方法

把异常放到特定的路径下 只需要把错误页面放在templates/error下 错误页面的名称要和错误类型码一致

当出现对应类型错误的时候,springboot就会自动跳到相应的页面。

在这里插入图片描述

Spring处理异常 记录日志

在这里插入图片描述

记录日志后需要手动跳转到服务器发生错误页面

@RequestMapping(value = "/error",method = RequestMethod.GET)
public String getErrorPage()
{
    return "/error/500";
}

Spring处理Controller请求

不需要对某个Controller进行处理,可以处理所有Controller请求

//扫描包含Controller注解的方法
@ControllerAdvice(annotations = Controller.class)
public class ExceptionAdvice {
    //实例化日志
    private static final Logger logger = LoggerFactory.getLogger(ExceptionAdvice.class);

    //该方法会在Controller发生异常后被调用,用来捕获异常,记录日志
    //传入request和response对象。用于获取请求方式和返回信息
    @ExceptionHandler({Exception.class})
    public void handleException(Exception e, HttpServletRequest request, HttpServletResponse response) throws IOException {
        //遍历异常栈的信息
        logger.error("服务器发生异常: " + e.getMessage());
        for (StackTraceElement element : e.getStackTrace()) {
            logger.error(element.toString());
        }

        //判断浏览器请求的是页面还是异步请求返回,JSON字符串
        //固定技巧 通过reques获取
        String xRequestedWith = request.getHeader("x-requested-with");
        if ("XMLHttpRequest".equals(xRequestedWith)) {
            //响应返回普通字符串
            response.setContentType("application/plain;charset=utf-8");
            PrintWriter writer = response.getWriter();
            writer.write(CommunityUtil.getJSONString(1, "服务器异常!"));
        } else {
            response.sendRedirect(request.getContextPath() + "/error");
        }
    }
}

统一记录日志

AOP的术语

  • Target 处理需求的目标;
  • Aspect(方面,切面) 封装业务需求的组件 ;
  • 利用框架把Aspect织入到需要处理的需求目标上;
  • 编译时织入,程序运行效率高,但可能因为条件不足导致一些错误;运行时织入效率低
  • JoinPoint 织入到需求目标上的位置 (属性,方法);
  • Pointcut (切点) 表达式声明,声明织入的对象的位置;
  • Advice(通知) 具体的逻辑,和执行的位置

在这里插入图片描述

AOP的实现

AspectJ (一门新的语言,功能强大)

- AspectJ是语言级的实现,它扩展了Java语言,定义了AOP语法。

- AspectJ在编译期织入代码,它有一个专门的编译器,用来生成遵守Java字节码规范的class文件。

Spring AOP (大多数都是对方法进行织入)

- Spring AOP使用纯Java实现,它不需要专门的编译过程,也不需要特殊的类装载器。

- Spring AOP在运行时通过代理的方式织入代码,只支持方法类型的连接点。

- Spring支持对AspectJ的集成。

Spring AOP

代理:对象生成一个代理对象,调用的时候调用代理对象,而不是原始对象,代码织入到代理对象

JDK动态代理 (目标需要有接口)

- Java提供的动态代理技术,可以在运行时创建接口的代理实例。

- Spring AOP默认采用此种方式,在接口的代理实例中织入代码。

CGLib动态代理

- 采用底层的字节码技术,在运行时创建子类代理实例。

- 当目标对象不存在接口时,Spring AOP会采用此种方式,在子类实例中织入代码。

Spring AOP 应用和五类通知

–先设置切入点 表达式execution + 返回类型(*) +切入对象路径 + 对象方法 +(…)所有的参数

 @Pointcut("execution(* com.nowcoder.community.service.*.*(..))")

  public void pointcut() {

  }

//1、在连接点开始执行
 @Before("pointcut()")
//2、在连接点返回之后执行
 @AfterReturning("pointcut()")
//3、在连接点之后执行
 @After("pointcut()")
//4、在连接点抛异常之后执行
 @AfterThrowing("pointcut()")

//5、在连接点之前和之后执行
//ProceedingJoinPoint joinPoint  是连接点
//joinPoint.proceed();  调用原始对象方法
  @Around("pointcut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("around before");
        Object obj = joinPoint.proceed();
        System.out.println("around after");
        return obj;
    }

统一记录日志

@Component
@Aspect
public class ServiceLogAspect {
    private static final Logger logger= LoggerFactory.getLogger(ServiceLogAspect.class);

    //声明切点
    @Pointcut("execution(* com.js.community.service.*.*(..))")
    public void pointcut()
    {

    }

    //在连接点方法执行器执行
    @Before("pointcut()")
    public void before(JoinPoint joinPoint)
    {
        // 用户[1.2.3.4],在[xxx],访问了[com.js.community.service.xxx()].
        //获取用户ip 通过request工具类
        ServletRequestAttributes attributes =(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        String IP = request.getRemoteHost();
        String now = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        String target = joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName();
        logger.info(String.format("用户[%s],在[%s],访问了[%s].", IP, now, target));


    }
}

DEBUG

@Aspect 找不到该注解 导入依赖

<!--AOP依赖包-->
        <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.7</version>
        </dependency>
举报

相关推荐

0 条评论