您现在的位置是:首页 > 文章详情

SpringBoot系列之使用自定义注解校验用户是否登录

日期:2018-10-17点击:559

记得今年年初刚开始面试的时候,被问的最多的就是你知道Spring的两大核心嘛?那你说说什么是AOP,什么是IOC?我相信你可能也被问了很多次了。

1、到底是什么是AOP?

所谓AOP也就是面向切面编程,能够让我们在不影响原有业务功能的前提下,横切扩展新的功能。这里面有一个比较显眼的词我们需要注意一下,横切,它是基于横切面对程序进行扩展的。

2、AOP相关术语

在Spring的AOP中有很多的术语,而且容易混淆,大家一定要先搞清楚这几个概念:

  • 连接点(Joinpoint):在程序执行过程中某个特定的点,比如类初始化前、类初始化后,方法调用前,方法调用后;

  • 切点(Pointcut:所谓切点就是你所切取的类中的方法,比如你横切的这个类中有两个方法,那么这两个方法都是连接点,对这两个方法的定位就称之为切点;

  • 增强(Advice:增强是织入到连接点上的一段程序,另外它还拥有连接点的相关信息;

  • 目标对象(Target):增强逻辑的织入目标类,就是我的增强逻辑植入到什么位置;

  • 引介(Introduction:一种特殊的增强,它可以为类添加一些属性喝方法;

  • 织入(Weaving:织入就是讲增强逻辑添加到目标对象的过程;

  • 代理(Proxy:一个类被AOP织入增强后,就会产生一个结果类,他是融合了原类和增强逻辑的代理类;

  • 切面(Aspect:切面由切点和增强组成,他是横切逻辑定义和连接点定义的组成;

3、AOP功能实践

我们这里主要是学习SpringBoot中的一些功能,所以我们这里用的是SpringBoot工程,版本也是最新的2.0.5版本。

创建SpringBoot工程就不说了,我们直接引入Maven的依赖:

<parent>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-parent</artifactId>        <version>2.0.5.RELEASE</version>        <relativePath/> <!-- lookup parent from repository -->    </parent>    <properties>        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>        <java.version>1.8</java.version>    </properties>    <dependencies>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-web</artifactId>            <exclusions>                <exclusion>                    <groupId>org.springframework.boot</groupId>                    <artifactId>spring-boot-starter-tomcat</artifactId>                </exclusion>            </exclusions>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-jetty</artifactId>        </dependency>        <!-- 引入AOP -->        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-aop</artifactId>        </dependency>    </dependencies>    <build>        <plugins>            <plugin>                <groupId>org.apache.maven.plugins</groupId>                <artifactId>maven-compiler-plugin</artifactId>                <version>3.6.1</version>                <configuration>                    <source>1.8</source>                    <target>1.8</target>                </configuration>            </plugin>            <plugin>                <groupId>org.apache.maven.plugins</groupId>                <artifactId>maven-surefire-plugin</artifactId>                <version>2.20</version>                <configuration>                    <skip>true</skip>                </configuration>            </plugin>            <plugin>                <groupId>org.springframework.boot</groupId>                <artifactId>spring-boot-maven-plugin</artifactId>                <executions>                </executions>            </plugin>        </plugins>    </build>

 

首先我们来创建一个Controller类:

@RestController public class LoginController {    @GetMapping(value = "/username")    public String getLoginUserName(String userName, Integer age) {                return userName + " --- " + age;    } }

 

创建切面:

@Aspect @Component public class LogAspect {    /**     * 功能描述: 拦截对这个包下所有方法的访问     *     * @param:[]     * @return:void     **/    @Pointcut("execution(* com.example.springbootaop.controller.*.*(..))")    public void loginLog() {    }    // 前置通知    @Before("loginLog()")    public void loginBefore(JoinPoint joinPoint) {        // 我们从请求的上下文中获取request,记录请求的内容        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();        HttpServletRequest request = attributes.getRequest();        System.out.println("请求路径 : " + request.getRequestURL());        System.out.println("请求方式 : " + request.getMethod());        System.out.println("方法名 : " + joinPoint.getSignature().getName());        System.out.println("类路径 : " + joinPoint.getSignature().getDeclaringTypeName());        System.out.println("参数 : " + Arrays.toString(joinPoint.getArgs()));    }    @AfterReturning(returning = "object", pointcut = "loginLog()")    public void doAfterReturning(Object object) {        System.out.println("方法的返回值 : " + object);    }    // 方法发生异常时执行该方法    @AfterThrowing(throwing = "e",pointcut = "loginLog()")    public void throwsExecute(JoinPoint joinPoint, Exception e) {        System.err.println("方法执行异常 : " + e.getMessage());    }    // 后置通知    @After("loginLog()")    public void afterInform() {        System.out.println("后置通知结束");    }    // 环绕通知    @Around("loginLog()")    public Object surroundInform(ProceedingJoinPoint proceedingJoinPoint) {        System.out.println("环绕通知开始...");        try {            Object o =  proceedingJoinPoint.proceed();            System.out.println("方法环绕proceed,结果是 :" + o);            return o;        } catch (Throwable e) {            e.printStackTrace();            return null;        }    } }

 

注解概述:

  • @Apsect:将当前类标识为一个切面;

  • @Pointcut:定义切点,这里使用的是条件表达式;

  • @Before:前置增强,就是在目标方法执行之前执行;

  • @AfterReturning:后置增强,方法退出时执行;

  • @AfterThrowing:有异常时该方法执行;

  • @After:最终增强,无论什么情况都会执行;

  • @Afround:环绕增强;

测试:

异常测试:

 

4、定义自定义注解

应用场景:在我之前上个项目的时候,有这样一个注解,就是在访问其他接口的时候必须要登录,那么这个时候我们就定义一个注解,让它去对用户是否登录进行校验,那么基于这样的一个场景,我们来定义一个校验登录的注解。

创建一个注解:

@Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface Auth {    String desc() default "验证是否登录"; }

 

创建一个AOP切面:

@Aspect @Component public class LoginAspect {    @Pointcut(value = "@annotation(com.example.springbootaop.annotation.Auth)")    public void access() {    }    @Before("access()")    public void before() {        System.out.println("开始验证用户是否登录...");    }    @Around("@annotation(auth)")    public Object around(ProceedingJoinPoint pj, Auth auth) {        // 获取注解中的值        System.out.println("注解中的值 : " + auth.desc());        try {            // 检验是否登录 true 已经登录  false 未登录            Boolean flag = false;            if (flag == true) {                return "登录成功";            } else {                return "未登录";            }        } catch (Throwable throwable) {            return null;        }    } }

 

测试未登录:

测试登录:

这样我们就可以简单的实现了一个登录校验的注解。

通过今天的分享你会使用AOP和自定义注解了吗?我把源码的地址放在下面,有兴趣的朋友可以看看。

GitHub地址:https://github.com/liangbintao/SpringBootIntegration.git

原创不易,如果感觉不错,给个顺便扩散一下吧!

原文链接:https://my.oschina.net/u/3178270/blog/2248201
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章