博客
关于我
Spring AOP 实战篇
阅读量:343 次
发布时间:2019-03-04

本文共 4692 字,大约阅读时间需要 15 分钟。

Spring AOP 实战指南

HTTP 接口鉴权

在实际开发中,HTTP RESTful服务的接口通常需要对调用方进行权限校验。直接在每个接口方法中进行权限验证虽然可行,但会导致代码冗余和潜在错误风险。为了更优雅地解决这个问题,我们可以使用Spring AOP来实现权限校验。

实现思路

  • 定制一个AuthChecker注解,用于标注需要权限校验的方法。
  • 使用Spring AOP的@Around注解,匹配标注了AuthChecker的方法。
  • 在advice中检查调用方的Cookie中是否存在合法的user_token,如果存在则允许访问,否则返回权限错误。
  • 代码示例

    @Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface AuthChecker {}@Component@Aspectpublic class HttpAopAdviseDefine {    @Pointcut("@annotation(com.xys.demo1.AuthChecker)")    public void pointcut() {}    @Around("pointcut()")    public Object checkAuth(ProceedingJoinPoint joinPoint) throws Throwable {        HttpServletRequest request = RequestContextHolder.getRequestAttributes().getRequest();        String token = getUserToken(request);        if (!token.equalsIgnoreCase("123456")) {            return "权限不合法!";        }        return joinPoint.proceed();    }    private String getUserToken(HttpServletRequest request) {        Cookie[] cookies = request.getCookies();        if (cookies == null) {            return "";        }        for (Cookie cookie : cookies) {            if (cookie.getName().equalsIgnoreCase("user_token")) {                return cookie.getValue();            }        }        return "";    }}

    使用示例

    @RestControllerpublic class DemoController {    @RequestMapping("/aop/http/alive")    public String alive() {        return "服务一切正常";    }    @AuthChecker    @RequestMapping("/aop/http/user_info")    public String callSomeInterface() {        return "调用了 user_info 接口。";    }}

    方法调用日志

    记录方法调用的日志是开发和维护服务的重要需求。我们可以使用Spring AOP的before、afterReturning和afterThrowing方法来实现日志记录。

    实现思路

  • 定义一个LogAopAdviseDefine类,使用@Before@AfterReturning@AfterThrowing注解。
  • 在before advice中记录方法调用参数。
  • 在afterReturning advice中记录方法返回结果。
  • 在afterThrowing advice中记录方法抛出的异常信息。
  • 代码示例

    @Component@Aspectpublic class LogAopAdviseDefine {    private Logger logger = LoggerFactory.getLogger(getClass());    @Pointcut("within(NeedLogService)")    public void pointcut() {}    @Before("pointcut()")    public void logMethodInvokeParam(JoinPoint joinPoint) {        logger.info("---Before method {} invoke, param: {}---", joinPoint.getSignature().toShortString(), joinPoint.getArgs());    }    @AfterReturning(pointcut = "pointcut()", returning = "retVal")    public void logMethodInvokeResult(JoinPoint joinPoint, Object retVal) {        logger.info("---After method {} invoke, result: {}---", joinPoint.getSignature().toShortString(), joinPoint.getArgs());    }    @AfterThrowing(pointcut = "pointcut()", throwing = "exception")    public void logMethodInvokeException(JoinPoint joinPoint, Exception exception) {        logger.info("---method {} invoke exception: {}---", joinPoint.getSignature().toShortString(), exception.getMessage());    }}

    使用示例

    @Servicepublic class NeedLogService {    private Logger logger = LoggerFactory.getLogger(getClass());    private Random random = new Random(System.currentTimeMillis());    public int logMethod(String someParam) {        logger.info("---NeedLogService: logMethod invoked, param: {}---", someParam);        return random.nextInt();    }    public void exceptionMethod() throws Exception {        logger.info("---NeedLogService: exceptionMethod invoked---");        throw new Exception("Something bad happened!");    }}

    方法耗时统计

    在服务监控中,记录方法调用耗时是非常重要的。我们可以使用Spring AOP的@Around注解来实现耗时统计。

    实现思路

  • 定义一个ExpiredAopAdviseDefine类,使用@Around注解。
  • 在advice中使用StopWatch记录方法执行时间。
  • 将方法执行时间上报到监控系统。
  • 代码示例

    @Component@Aspectpublic class ExpiredAopAdviseDefine {    private Logger logger = LoggerFactory.getLogger(getClass());    @Pointcut("within(SomeService)")    public void pointcut() {}    @Around("pointcut()")    public Object methodInvokeExpiredTime(ProceedingJoinPoint pjp) throws Throwable {        StopWatch stopWatch = new StopWatch();        stopWatch.start();        Object retVal = pjp.proceed();        stopWatch.stop();        reportToMonitorSystem(pjp.getSignature().toShortString(), stopWatch.getTotalTimeMillis());        return retVal;    }    private void reportToMonitorSystem(String methodName, long expiredTime) {        logger.info("---method {} invoked, expired time: {} ms---", methodName, expiredTime);    }}

    使用示例

    @Servicepublic class SomeService {    private Logger logger = LoggerFactory.getLogger(getClass());    private Random random = new Random(System.currentTimeMillis());    public void someMethod() {        logger.info("---SomeService: someMethod invoked---");        try {            Thread.sleep(random.nextInt(500));        } catch (InterruptedException e) {            e.printStackTrace();        }    }}

    总结

    通过以上几个实际场景的实现,我们可以看到Spring AOP的强大功能。无论是权限校验、日志记录还是耗时统计,Spring AOP都能以优雅的方式解决问题。如果你有更多的业务需求,可以根据实际需求灵活配置Spring AOP来实现更复杂的功能。

    转载地址:http://guie.baihongyu.com/

    你可能感兴趣的文章
    pip3 install PyQt5 --user 失败
    查看>>
    pip3命令全解析:Python3包管理工具的详细使用指南
    查看>>
    pip3安装命令重复创建文件‘/tmp/pip-install-xxxxx/package‘失败
    查看>>
    PIPE 接口信号列表
    查看>>
    pipeline配置与管理Job企业级实战
    查看>>
    pipeline项目配置实战
    查看>>
    Pipenv 与 Conda?
    查看>>
    QVGA/HVGA/WVGA/FWVGA分辨率屏含义及大小//Android虚拟机分辨率
    查看>>
    pipreqs : 无法将“pipreqs”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径 正确,然后再试一次。
    查看>>
    pipy国内镜像的网址
    查看>>
    quiver绘制python语言
    查看>>
    pip下载缓慢
    查看>>
    PIP使用SSH从BitBucket安装自定义软件包,无需输入SSH密码
    查看>>
    pip命令提示unknow or unsupported command install解决方法
    查看>>
    pip在安装模块时提示Read timed out
    查看>>
    pip更换源
    查看>>
    SpringBoot之Banner源码深度分解
    查看>>
    Pix2Pix如何工作?
    查看>>
    QuickBI助你成为分析师——搞定数据源
    查看>>
    pkl来存储python字典
    查看>>