博客
关于我
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/

    你可能感兴趣的文章
    python可视化matplotlib_如何使用Python中最强大的可视化工具Matplotlib?
    查看>>
    python可维护性_使用这7大神器,让你的Python 代码更容易于维护
    查看>>
    Python只运行一次while循环
    查看>>
    python变量的详细教程_Python零基础入门教程之语法入门[变量](第二期)
    查看>>
    Python变量命名方法-ChatGPT4o作答
    查看>>
    Python变量与运算符
    查看>>
    Python变量/运算符/函数/模块/string
    查看>>
    python发送邮件的时候出现 error (535, b‘5.7.3 Authentication unsuccessful‘) 解决方法
    查看>>
    python系列【仅供参考】:python flask框架 debug功能
    查看>>
    python发送notes邮件_使用python在Lotus Notes中发送邮件
    查看>>
    Python双版本下创建一个Scrapy(西瓜皮)项目
    查看>>
    Python双版本下No module named 'requests'
    查看>>
    python及pycharm2018软件安装教程
    查看>>
    python去重txt文本_Python实现的txt文件去重功能示例
    查看>>
    python去掉列表的逗号,从Python列表项中删除标点符号
    查看>>
    Python卸载所有包
    查看>>
    python单线程下实现多个socket并发
    查看>>
    Python单元测试框架介绍(超详细~)
    查看>>
    Python单元测试框架
    查看>>
    python单元测试之unittest
    查看>>