日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

spring boot 使用AOP實現是否已登錄檢測

作者:ganyuanmen 更新時間: 2024-03-23 編程語言

? ? ? ? 前后端分離的開發中,用戶http請求應用服務的接口時, 如果要求檢測該用戶是否已登錄。可以實現的方法有多種, 本示例是通過aop 的方式實現,簡單有效。

? ? ? ? 約定:前端http的post?請求

export async function request(url,data) {
    const config = {
      method: 'POST',
      headers: {'Content-Type': 'application/json'},
    }
	//每個請求的參數要求附加sessionid, 該sessionid 是登錄時生成的
	const paramsData = Object.assign(data,{sessionid:globalData.sessionID || ''})
    config.body = JSON.stringify(paramsData)

    try {
      const res = await window.fetch(url, config)
      if(res.status!==200){
        return {
          status: res.status,
          data:{},
          headers: res.headers,
          url: res.url,
          statusText:res.statusText
        }
      }
    
      return {
        status: res.status,
        data:await res.json(),
        headers: res.headers,
        url: res.url,
      }
    
    } catch (err) {
      return {
        status: 404,
        data:{},
        headers: res.headers,
        url: res.url,
        statusText:'fetch error:'+err.toString()
      }
    }
  }
  

1、在pom.xml 引用

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-aop</artifactId>
		</dependency>

2、創建插入標記


@Target({ElementType.METHOD}) // 只在對象方法上標記
@Retention(RetentionPolicy.RUNTIME) //運行時反射
public @interface Interceptor {
    String additionalMessage() default "";
}

3、實現切入類


@Aspect
@Component
@Slf4j
public class LoggingAspect {

    @Autowired
    public StringRedisTemplate redisTemplatelocate;

    private  <T> T getSessionID(Object postData,Class<T> clazz){
        return (T)postData;
    }

    @Around("@annotation(Interceptor)") //有標記的地方將實現以下和切入
    public Object logExecutionTime(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        //獲取切入方法的參數,就是前部請求的json數據
        Object[] args = proceedingJoinPoint.getArgs();

        //獲取其中的sessionid
        // requestBase 實體類只有一個參sessionid , 做為其它實體類的父類,用于接收接口上傳的參數。
        RequestBase requestBase=getSessionID(args[0],RequestBase.class);
        log.info("sessionid:{}",requestBase.getSessionid());

        //檢測該sessionid 是否存在(redis)
        if (requestBase.getSessionid()==null || !redisTemplatelocate.hasKey(requestBase.getSessionid())) {
            //用戶未登陸
            throw new Exception("用戶未登陸");
        }

        //獲取  request 和 response
        ServletRequestAttributes servletRequestAttributes = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes());
        log.info("request:{}",servletRequestAttributes.getRequest());
        log.info("response:{}",servletRequestAttributes.getResponse());

        MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();
        String className = methodSignature.getDeclaringType().getSimpleName();
        String methodName = methodSignature.getMethod().getName();
        Instant startTime = Instant.now();
         //實行被切入的方法
        Object result = proceedingJoinPoint.proceed();
        
        String additionalMessage = methodSignature.getMethod().getAnnotation(Interceptor.class).additionalMessage();
        long elapsedTime = Duration.between(startTime, Instant.now()).toMillis();
        log.info("Class Name: {}, Method Name: {}, Additional Message: {}, Elapsed Time: {}ms",
                className, methodName, additionalMessage, elapsedTime);
        log.info("Result: {}", result);
        return result;
    }
}

4 建立api接口,在需要檢測的方法上加入@Interceptor 就完成切入的檢測。


@RestController
@Slf4j
public class ExampleController {

    @PostMapping("/t1")
    @Interceptor(additionalMessage = "要求檢測登錄")
    @ResponseBody
    public ResponseEntity<RequestBase> getData(@RequestBody DataRequest req) {
        try {
            return new ResponseEntity<>(req, HttpStatus.OK);
        } catch (Exception e) {
            return new ResponseEntity<>(null, HttpStatus.BAD_REQUEST);
        }
    }
}

5 實體類


@Data
public class DataRequest extends RequestBase {
    private  String name;
}


@Data
public class RequestBase{
    private String sessionid;
}

? ?該方法只適用于少部分需要檢測,而大部份不需要檢測的情況下,如果整個包都需要檢測的,利用execution方?法實現

 @Pointcut("execution(public * com.example.myapp..*.*(..))")

@Aspect
@Component
@Slf4j
public class LoginExecution {

    @Autowired
    public StringRedisTemplate redisTemplatelocate;

    private  <T> T getSessionID(Object postData,Class<T> clazz){
        return (T)postData;
    }

    //切入點: com.aop.ttt 下的所有public 方法
    @Pointcut("execution(public * com.aop.ttt..*.*(..))")
    public void publicMethods() {}

    @Around("publicMethods()")
    public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
        //獲取切入方法的參數,就是前部請求的json數據
        Object[] args = joinPoint.getArgs();

        //獲取其中的sessionid
        // requestBase 實體類只有一個參sessionid , 做為其它實體類的父類,用于接收接口上傳的參數。
        RequestBase requestBase=getSessionID(args[0],RequestBase.class);
        log.info("sessionid:{}",requestBase.getSessionid());

        //檢測該sessionid 是否存在(redis)
        if (requestBase.getSessionid()==null || !redisTemplatelocate.hasKey(requestBase.getSessionid())) {
            //用戶未登陸
            throw new Exception("用戶未登陸");
        }

        //獲取  request 和 response
        ServletRequestAttributes servletRequestAttributes = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes());
        log.info("request:{}",servletRequestAttributes.getRequest());
        log.info("response:{}",servletRequestAttributes.getResponse());


        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        String className = methodSignature.getDeclaringType().getSimpleName();
        String methodName = methodSignature.getMethod().getName();
        Instant startTime = Instant.now();
        //實行被切入的方法
        Object result = joinPoint.proceed();


        long elapsedTime = Duration.between(startTime, Instant.now()).toMillis();
        log.info("Class Name: {}, Method Name: {}, Elapsed Time: {}ms",
                className, methodName, elapsedTime);
        log.info("Result: {}", result);
        return result;
    }
}

原文鏈接:https://blog.csdn.net/ganyuanmen/article/details/136129364

  • 上一篇:沒有了
  • 下一篇:沒有了
欄目分類
最近更新