JavaWeb
2025.03.03 javaWeb学习日记
今天主要是完成了黑马给的文档里面day13的作业,熟悉了AOP的使用方法。同时也进入到了前端关于Vue的方面,主要是认识一个简单的vue项目开发流程,学习选项式API和组合式API,知道了两者如何进行转化,在什么场景下用更好。
前端页面今天学习的部分较为简单,只是一个简单的转化,就不记录了。
记录下黑马day14里面的作业4
题目:基于springAOP技术完成如下需求。
**需求:**记录当前 tlias 智能学习辅助系统中所有员工的登录操作 (切入点:execution(…); 通知类型:@Around) ,无论登录成功还是失败,都需要记录日志。
日志信息包含如下信息:
- 用户名 (登录时,输入的用户名) ----- 【提示:用户名在原始方法执行时的参数中 – 获取到参数可以强转】
- 密码 (登录时,输入的密码) -------- 【提示:密码在原始方法执行时的参数中 – 获取到参数可以强转 】
- 操作时间 (什么时间,员工登录的)
- 登录是否成功 ------ 【提示:在原始方法执行后的返回值中,可以通过Result来获取code从而判断成功还是失败 – 可以强转】
- 登录成功后,下发的jwt令牌 ------ 【提示:jwt在原始方法执行后的返回值中 – 可以强转】
- 登录操作耗时
创建表结构和实体类有对应的代码,这里就不展示了
解题思路:
其实只要理解了AOP的作用,这道题也是比较简单的。
一开始,自己对AOP的作用没有理解正确,以为是在代码里面调用了目标对象的方法后,才能获取对应的值。但其实在参数传入到对应的方法的时候,该方法就被@Around通知拦截了。拦截器就会立即获取到确定的参数。所以整个过程其实是三个顺序。
- 前置处理:首先获取传入的参数,在用户登陆的时候,就会传入对应的emp参数,这个时候获取到用户输入的对应的username和password的值
- 调用目标方法:通过
joinPoint.proceed()
执行实际的登录逻辑.调用目标方,获得对应的返回值。 - 根据返回值来判断登录是否成功,登陆成功了,就再获取token的值,登陆失败了,就设置success为失败。同时需要捕获异常,如果发生了异常,那么也是登录失败了。但要先在数据库中记录对应的值,再抛出异常。
代码示例:
package com.itheima.aop;
import com.itheima.mapper.EmpLoginLogMapper;
import com.itheima.pojo.Emp;
import com.itheima.pojo.EmpLoginLog;
import com.itheima.pojo.LoginInfo;
import com.itheima.pojo.Result;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
@Slf4j
@Component
@Aspect
public class OperationLoginLogAspect {
@Autowired
private EmpLoginLogMapper empLoginLogMapper;
@Around("@annotation(com.itheima.anno.LoginOperation)")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
long startTime = System.currentTimeMillis();
//获取传入的参数
Object[] args = joinPoint.getArgs();
Emp emp = null;
if(args!=null&&args.length >0 && args[0] instanceof Emp){
emp=(Emp)args[0];
}
EmpLoginLog loginLog = new EmpLoginLog();
if (emp!=null){
loginLog.setUsername(emp.getUsername());
loginLog.setPassword(emp.getPassword());
}
loginLog.setLoginTime(LocalDateTime.now());
Object result = null;
try {
result=joinPoint.proceed();
if(result instanceof Result){
Result res=(Result) result;
if(res.getCode()==1){
loginLog.setIsSuccess((short)1);
if(res.getData() instanceof LoginInfo){
LoginInfo info=(LoginInfo) res.getData();
loginLog.setJwt(info.getToken());
}
}else {
loginLog.setIsSuccess((short)0);
}
}else {loginLog.setIsSuccess((short)0);}
}catch (Exception e){
log.info("登录异常",e);
loginLog.setIsSuccess((short)0);
long endTime=System.currentTimeMillis();
loginLog.setCostTime(endTime-startTime);
empLoginLogMapper.insert(loginLog);
//插入日志操作后,再处理异常
throw e;
}
long endTime=System.currentTimeMillis();
loginLog.setCostTime(endTime-startTime);
empLoginLogMapper.insert(loginLog);
return result;
}
}
整个流程没有很困难,但要注意对应的细节。记得加上@Aspect
注解
这个是自定义的接口的示例,将接口添加在需要通知的方法和类上,添加到登录逻辑的控制层即可。
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LoginOperation {
}
总的来说没有很难,就是对传入的参数进行前置处理,对调用完目标方法后的结果进行后置处理!
今天算法花费的事件较长,学习项目的时间较短,但也是有对应的收获的,希望后续也有时间写写总结,巩固当天所学习的知识。