? ? ? ? 前后端分離的開發(fā)中,用戶http請(qǐng)求應(yīng)用服務(wù)的接口時(shí), 如果要求檢測(cè)該用戶是否已登錄。可以實(shí)現(xiàn)的方法有多種, 本示例是通過(guò)aop 的方式實(shí)現(xiàn),簡(jiǎn)單有效。
? ? ? ? 約定:前端http的post?請(qǐng)求
export async function request(url,data) {
const config = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
}
//每個(gè)請(qǐng)求的參數(shù)要求附加sessionid, 該sessionid 是登錄時(shí)生成的
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、創(chuàng)建插入標(biāo)記
@Target({ElementType.METHOD}) // 只在對(duì)象方法上標(biāo)記
@Retention(RetentionPolicy.RUNTIME) //運(yùn)行時(shí)反射
public @interface Interceptor {
String additionalMessage() default "";
}
3、實(shí)現(xiàn)切入類
@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)") //有標(biāo)記的地方將實(shí)現(xiàn)以下和切入
public Object logExecutionTime(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
//獲取切入方法的參數(shù),就是前部請(qǐng)求的json數(shù)據(jù)
Object[] args = proceedingJoinPoint.getArgs();
//獲取其中的sessionid
// requestBase 實(shí)體類只有一個(gè)參sessionid , 做為其它實(shí)體類的父類,用于接收接口上傳的參數(shù)。
RequestBase requestBase=getSessionID(args[0],RequestBase.class);
log.info("sessionid:{}",requestBase.getSessionid());
//檢測(cè)該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();
//實(shí)行被切入的方法
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接口,在需要檢測(cè)的方法上加入@Interceptor 就完成切入的檢測(cè)。
@RestController
@Slf4j
public class ExampleController {
@PostMapping("/t1")
@Interceptor(additionalMessage = "要求檢測(cè)登錄")
@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 實(shí)體類文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-830392.html
@Data
public class DataRequest extends RequestBase {
private String name;
}
@Data
public class RequestBase{
private String sessionid;
}
? ?該方法只適用于少部分需要檢測(cè),而大部份不需要檢測(cè)的情況下,如果整個(gè)包都需要檢測(cè)的,利用execution方?法實(shí)現(xiàn)文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-830392.html
@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;
}
//切入點(diǎn): com.aop.ttt 下的所有public 方法
@Pointcut("execution(public * com.aop.ttt..*.*(..))")
public void publicMethods() {}
@Around("publicMethods()")
public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
//獲取切入方法的參數(shù),就是前部請(qǐng)求的json數(shù)據(jù)
Object[] args = joinPoint.getArgs();
//獲取其中的sessionid
// requestBase 實(shí)體類只有一個(gè)參sessionid , 做為其它實(shí)體類的父類,用于接收接口上傳的參數(shù)。
RequestBase requestBase=getSessionID(args[0],RequestBase.class);
log.info("sessionid:{}",requestBase.getSessionid());
//檢測(cè)該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();
//實(shí)行被切入的方法
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;
}
}
到了這里,關(guān)于spring boot 使用AOP實(shí)現(xiàn)是否已登錄檢測(cè)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!