
springboot利用切面记录在线人数
发布日期:2021-05-06 19:32:58
浏览次数:17
分类:技术文章
本文共 4727 字,大约阅读时间需要 15 分钟。
众所周知springboot两大特性,ioc和aop即控制反转和面向切面编程。
aop的用处主要是横向截取公有功能。比如管理事务,处理异常等 目前在做一个论坛系统,需要统计在线人数。 有两个方案: 1、就是利用Session会话机制,通过监听器判断是否有新的会话生成,这种的好处是即使参数中没有用户信息也可以正常收集信息,缺点是如果同一个用户打开多个会话,那么会重复记录。 2、就是利用一个Set集合。每次有用户触发接口,记录用户ID,最后Set.size()即是在线人数 springboot集成aop的注解实现主要有两种 一种是正常的切点注入 首先pom文件添加依赖org.springframework.boot spring-boot-starter-aop
然后是切面类package com.hqjl.communityserv.aspect;import com.hqjl.communityserv.request.RequestParamInfo;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Pointcut;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.stereotype.Component;import java.util.HashSet;import java.util.Set;/** * @author chunying * @Date: 2019/11/6 0006 */@Aspect@Componentpublic class UserLine { private final Logger LOG = LoggerFactory.getLogger(UserLine.class); private static SetonLineUsers = new HashSet<>(); @Pointcut("execution(* com.hqjl.communityserv.controller..*(..))") public void addOnlineUser(){ } @Around(addOnlineUser()) public Object interceptor(ProceedingJoinPoint point) { Object result = null; Object[] args = point.getArgs(); if (args != null && args.length > 0) { RequestParamInfo arg = (RequestParamInfo)args[0]; String userID = arg.getUserID(); if (!onLineUsers.contains(userID)) { onLineUsers.add(userID); } } try { result = point.proceed(); }catch(Throwable e) { LOG.error(e.getMessage(), e); } return result; } public static Integer getOnlineCount() { return onLineUsers.size(); }}Aspect注解:表明这是一个切面类Component注解:不用多说吧 注入到spring中Pointcut注解:切点配置 我这里配置的表示 controller包下的所有类会被这个切面影响。具体写法可查切面表达式Around注解:和我们用xml配置文件一样 表示advice。还有Before After等参数ProceedingJoinPoint 这个是必须的 这个类继承了JoinPoint其中proceed()方法表示执行方法。这个里面有许多方法大概列一下//拦截的实体类Object target = point.getTarget();//拦截的方法名称String methodName = point.getSignature().getName();//拦截的方法参数Object[] args = point.getArgs();//拦截的放参数类型Class[] parameterTypes = ((MethodSignature)point.getSignature()).getMethod().getParameterTypes();Method m = null;try { //通过反射获得拦截的methodm = target.getClass().getMethod(methodName, parameterTypes);//如果是桥则要获得实际拦截的methodif(m.isBridge()){ for(int i = 0; i < args.length; i++){ //获得泛型类型 Class genClazz = GenericsUtils.getSuperClassGenricType(target.getClass()); //根据实际参数类型替换parameterType中的类型 if(args[i].getClass().isAssignableFrom(genClazz)){ parameterTypes[i] = genClazz; }} //获得parameterType参数类型的方法 m = target.getClass().getMethod(methodName, parameterTypes); }} catch (SecurityException e) { e.printStackTrace();} catch (NoSuchMethodException e) { e.printStackTrace(); }}
这是第一种方法
如果觉得不够灵活 我们可以用第二种 基于注解的配置 首先创建注解package com.hqjl.communityserv.annotation;import java.lang.annotation.*;/** * @author chunying * @Date: 2019/11/6 0006 */@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)@Documentedpublic @interface UserOnline { }
然后配置切面类
package com.hqjl.communityserv.aspect;import com.hqjl.communityserv.request.RequestParamInfo;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Pointcut;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.stereotype.Component;import java.util.HashSet;import java.util.Set;/** * @author chunying * @Date: 2019/11/6 0006 */@Aspect@Componentpublic class UserLine { private final Logger LOG = LoggerFactory.getLogger(UserLine.class); private static SetonLineUsers = new HashSet<>(); @Around(value = "@annotation(com.hqjl.communityserv.annotation.UserOnline)") public Object interceptor(ProceedingJoinPoint point) { Object result = null; Object[] args = point.getArgs(); if (args != null && args.length > 0) { RequestParamInfo arg = (RequestParamInfo)args[0]; String userID = arg.getUserID(); if (!onLineUsers.contains(userID)) { onLineUsers.add(userID); } } try { result = point.proceed(); }catch(Throwable e) { LOG.error(e.getMessage(), e); } return result; } public static Integer getOnlineCount() { return onLineUsers.size(); }}
把这个注解配置到方法上 就会被切面注入了。
另外如果报了这个错
Caused by: java.lang.IllegalArgumentException: error at ::0 can’t find referenced pointcut 有两种可能 一种jdk版本与aop不兼容 第二种 请检查你得pointcut 和 around 拼写有没有错误发表评论
最新留言
哈哈,博客排版真的漂亮呢~
[***.90.31.176]2025年03月23日 15时13分01秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
SVM多类识别
2019-03-03
svn 撤销已提交的错误修改
2019-03-03
算法工程师数学理论提高札记(improving)
2019-03-03
Android网络优化--精准获取流量消耗
2019-03-03
VTK:IO之WriteVTI
2019-03-03
VTK:图片之ImageExport
2019-03-03
VTK:图片之ImageMathematics
2019-03-03
VTK:图片之ImageOrientation
2019-03-03
VTK:图片之ImageToPolyDataFilter
2019-03-03
VTK:图片之ImageToStructuredPoints
2019-03-03
VTK:图片之ImageValueRange
2019-03-03
VTK:图片之PickPixel
2019-03-03
VTK:图片之RGBToHSV
2019-03-03
VTK:隐式函数之ImplicitQuadric
2019-03-03
VTK:隐式函数之ImplicitSphere
2019-03-03
VTK:InfoVis之DelimitedTextReader
2019-03-03
数据结构与算法学习1-----稀疏数组
2019-03-03
Java转换xml格式时间 (yyyy-MM-ddTHH:mm:ss.SSSZ)
2019-03-03
Python 使用 __getstate__ 和 __setstate__ 魔法方法
2019-03-03
关于json
2019-03-03