文章目录
# 统一处理异常
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>










