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 Set
onLineUsers = 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 Set
onLineUsers = 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 拼写有没有错误

上一篇:阿里云内容管理图片校验简单使用
下一篇:基于DFA算法实现文章敏感词过滤

发表评论

最新留言

哈哈,博客排版真的漂亮呢~
[***.90.31.176]2025年03月23日 15时13分01秒