SpringAOP手写全局异常处理

1、使用@AfterThrowing异常通知:

注:使用异常通知,不会完全处理异常,异常会向上继续传递给调用者。

1.1自定义注解:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface ProcessException {
	Class[] value() default {};
}

1.2编写切面

@Component
@Aspect
public class UserAspect {
        @Pointcut("@within(org.springframework.stereotype.Controller)")
	private void exceptionProcesser() {}
    	@AfterThrowing(value = "exceptionProcesser()", throwing = "e")
	public void afterThrowingMethod(JoinPoint point, Throwable e) {
		Class clazz = point.getTarget().getClass();
		Method[] methods = clazz.getMethods();
		for (Method m : methods) {
			ProcessException anno = m.getAnnotation(ProcessException.class);
			if (anno != null) {
				Class[] exArr = anno.value();
				if (exArr.length == 0) {
					if (e instanceof RuntimeException) {
						try {
							m.invoke(clazz.newInstance(), e);
						} catch(Exception ex) {
							e.printStackTrace();
						}
					}
				} else {
					for (Class exClass : exArr) {
						if (exClass.isInstance(e)) {
							try {
								m.invoke(clazz.newInstance(), e);
							} catch(Exception ex) {
								e.printStackTrace();
							}
						}
					}
				}
				break;
			}
		}
	}
}

1.3写全局异常处理方法:

public abstract class BaseController {
    @ProcessException(ServiceException.class)
    public ResponseResult handleException(Throwable e) {
    	System.out.println(e.getMessage());
        ResponseResult result = new ResponseResult<>();
        result.setMessage(e.getMessage());
        if (e instanceof UsernameDuplicateKeyException) {
            result.setState(4001);
        } else if (e instanceof InsertException) {
            result.setState(4002);
        } else if (e instanceof UserNotFoundException) {
            result.setState(4003);
        } else if (e instanceof PasswordNotMatchException) {
            result.setState(4004);
        } else if (e instanceof UpdateException) {
            result.setState(4005);
        }
        return result;
    }
}
@Controller
@RequestMapping("/users")
public class UserController extends BaseController {
	
	@Autowired
	private IUserService userService;
	
	@PostMapping("/login")
	@ResponseBody
	public ResponseResult login(String username, String password, HttpSession session) {
		User user = userService.login(username, password);
		session.setAttribute("uid", user.getUid());
              session.setAttribute("username", user.getUsername());
		return new ResponseResult<>(SUCCESS);
	} 
	
}
@Data
public class ResponseResult implements Serializable {
    private static final long serialVersionUID = 8011176026667744133L;

    private Integer state;
    private String message;
    private T data;

    public ResponseResult() {
    }

    public ResponseResult(Integer state) {
        this.state = state;
    }
    public ResponseResult(Integer state, T data) {
        this.state = state;
        this.data = data;
    }
}

2、使用Around环绕通知:

1.1自定义注解:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface ProcessException {
	Class[] value() default {};
}

1.2编写切面

@Component
@Aspect
public class UserAspect {
        @Pointcut("@within(org.springframework.stereotype.Controller)")
	private void exceptionProcesser() {}
        @Around(value="exceptionProcesser()")
	public Object around(ProceedingJoinPoint jp) throws Throwable {
		try {
			return jp.proceed();
		} catch (Throwable e) {
			try {
				Class clazz = jp.getTarget().getClass();
				Method[] methods = clazz.getMethods();
				for (Method m : methods) {
					ProcessException anno = m.getAnnotation(ProcessException.class);
					if (anno != null) {
						Class[] exArr = anno.value();
						if (exArr.length == 0) {
							if (e instanceof RuntimeException) {
								return m.invoke(clazz.newInstance(), e);
							}
						} else {
							for (Class exClass : exArr) {
								if (exClass.isInstance(e)) {
									return m.invoke(clazz.newInstance(), e);
								}
							}
						}
					}
				}
				throw e;
			} catch (Exception ex) {
				throw ex;
			}
		}
	}
}

1.3写全局异常处理方法:

public abstract class BaseController {
    @ProcessException(ServiceException.class)
    public ResponseResult handleException(Throwable e) {
    	System.out.println(e.getMessage());
        ResponseResult result = new ResponseResult<>();
        result.setMessage(e.getMessage());
        if (e instanceof UsernameDuplicateKeyException) {
            result.setState(4001);
        } else if (e instanceof InsertException) {
            result.setState(4002);
        } else if (e instanceof UserNotFoundException) {
            result.setState(4003);
        } else if (e instanceof PasswordNotMatchException) {
            result.setState(4004);
        } else if (e instanceof UpdateException) {
            result.setState(4005);
        }
        return result;
    }
}
@Controller
@RequestMapping("/users")
public class UserController extends BaseController {
	
	@Autowired
	private IUserService userService;
	
	@PostMapping("/login")
	@ResponseBody
	public ResponseResult login(String username, String password, HttpSession session) {
		User user = userService.login(username, password);
		session.setAttribute("uid", user.getUid());
              session.setAttribute("username", user.getUsername());
		return new ResponseResult<>(SUCCESS);
	} 
	
}
@Data
public class ResponseResult implements Serializable {
    private static final long serialVersionUID = 8011176026667744133L;

    private Integer state;
    private String message;
    private T data;

    public ResponseResult() {
    }

    public ResponseResult(Integer state) {
        this.state = state;
    }
    public ResponseResult(Integer state, T data) {
        this.state = state;
        this.data = data;
    }
}

你可能感兴趣的:(SpringBoot,SpringMVC,spring,SpringAOP)