| | |
| | | package com.ard.tianyu.aspect; |
| | | |
| | | import com.ard.common.exception.NoPermissionException; |
| | | import com.ard.common.exception.ControlException; |
| | | import com.ard.common.utils.SecurityUtils; |
| | | import com.ard.tianyu.aspect.annotation.RequireUavControl; |
| | | import com.ard.tianyu.aspect.annotation.CheckTakeoffAltitude; |
| | | import com.ard.tianyu.aspect.annotation.CheckControlRight; |
| | | import com.ard.tianyu.domain.cache.UavTelemetryDataCache; |
| | | import com.ard.tianyu.domain.dto.telemetry.TelemetryData; |
| | | import com.ard.tianyu.service.control.UavControlService; |
| | | import com.ard.tianyu.websocket.domain.UavControlType; |
| | | import org.aspectj.lang.JoinPoint; |
| | |
| | | |
| | | /** |
| | | * AOP 切面:拦截 @RequireUavControl,检查用户是否拥有 UAV 控制权限 |
| | | * |
| | | * 注意切面顺序:同类方法注解按字母ABCD顺序,不同类注解按order(1)顺序 越小优先级越高 |
| | | */ |
| | | @Aspect |
| | | @Component |
| | |
| | | private UavControlService uavControlService; |
| | | |
| | | /** |
| | | * 拦截 @RequireUavControl 注解的方法 |
| | | * 前置通知:控制权检测 |
| | | */ |
| | | @Before("@annotation(requireUavControl)") |
| | | public void checkUavControl(JoinPoint joinPoint, RequireUavControl requireUavControl) { |
| | | @Before("@annotation(checkControlRight)") |
| | | public void checkUavControl(JoinPoint joinPoint, CheckControlRight checkControlRight) { |
| | | // 获取当前用户 ID |
| | | Long userId = SecurityUtils.getUserId(); |
| | | |
| | | // 获取控制类型 |
| | | UavControlType controlType = requireUavControl.value(); |
| | | UavControlType controlType = checkControlRight.value(); |
| | | |
| | | // 获取方法参数 |
| | | Object[] args = joinPoint.getArgs(); |
| | |
| | | Long currentController = uavControlService.getCurrentController(boxSn, |
| | | controlType.name().toLowerCase()); |
| | | if (currentController == null || !currentController.equals(userId)) { |
| | | throw new NoPermissionException("无权执行该操作,需要 " + controlType + " 控制权限"); |
| | | throw new ControlException("无权执行该操作,需要 " + controlType + " 控制权限"); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 前置通知:高度检查 |
| | | */ |
| | | @Before("@annotation(checkTakeoffAltitude)") |
| | | public void takeoffAltitudeCheck(JoinPoint joinPoint, CheckTakeoffAltitude checkTakeoffAltitude) { |
| | | // 获取最小高度 |
| | | double minAltitude = checkTakeoffAltitude.minAltitude(); |
| | | // 获取方法参数 |
| | | Object[] args = joinPoint.getArgs(); |
| | | |
| | | // 遍历参数,使用反射获取每个参数中的 boxSn |
| | | for (Object arg : args) { |
| | | String boxSn = getBoxSn(arg); // 调用之前实现的 getBoxSn 方法 |
| | | if (boxSn != null) { |
| | | TelemetryData uavTelemetryData = UavTelemetryDataCache.getUavTelemetryData(boxSn); |
| | | if (uavTelemetryData == null) { |
| | | throw new ControlException("遥测数据异常,无法执行!"); |
| | | } |
| | | // 检查高度 |
| | | if (uavTelemetryData.getAltitude() < minAltitude) { |
| | | throw new ControlException("高度太低,无法执行!最低高度: " + minAltitude); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 通过反射获取对象中的 boxSn 字段 |