注解类:
package com.ruoyi.framework.aspectj.lang.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD) //注解放置的目标位置,METHOD是可注解在方法级别上
@Retention(RetentionPolicy.RUNTIME) //注解在哪个阶段执
public @interface LoginCheck {
Class<?>[] value() default {};//传入泛型对象
}
AOP拦截类
package com.ruoyi.framework.aspectj;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.aspectj.lang.annotation.LoginCheck;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.project.api.domain.RequestVo;
import com.ruoyi.project.user.user.service.IMctUserService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Map;
/**
* @author dushisen
* @Title: LoginCheckAspect
* @Description: 验证登录token
* @date 2021/01/20 10:00
*/
@Aspect
@Component
public class LoginCheckAspect {
private static final Logger log = LoggerFactory.getLogger(LoginCheckAspect.class);
@Autowired
private IMctUserService mctUserService;
// 配置织入点(添加注解的方法都会进入)
@Pointcut("@annotation(com.ruoyi.framework.aspectj.lang.annotation.LoginCheck)")
public void logPointCut()
{
}
//@Around注解为添加@LoginCheck的方法执行之前和执行之后都会运行此方法体。此注解可以修改传入的参数,返回方法体中继续执行方法
//@Before注解会在方法体执行前执行
//@AfterReturning注解会在方法体执行后执行
@Around("logPointCut()")
public Object aspectAroundMethond(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
// 获得注解
LoginCheck controllerLoginCheck = getAnnotationLoginCheck(proceedingJoinPoint);
if (controllerLoginCheck == null)
{
return AjaxResult.error();
}
//请求RequestMapping地址
String requestURI = ServletUtils.getRequest().getRequestURI();
//方法名称
String className = proceedingJoinPoint.getTarget().getClass().getName();
String methodName = proceedingJoinPoint.getSignature().getName();
String method = className + "." + methodName + "()";
//泛型类
Class<?>[] value = controllerLoginCheck.value();//获取注解中传入的参数
//请求的参数方法中请求栏的第一个参数(args[0]为添加注解方法中的第一个参数以此类推)
Object[] args = proceedingJoinPoint.getArgs();
//将参数所在的数组转换成json
String params = JSON.toJSONString(args[0]);
JSONObject paramJson = JSONObject.parseObject(params);
System.out.println("---------------------------------params---------------------------------"+params);
System.out.println("获取连接点对象开始");
if(StringUtils.isNotEmpty(paramJson.getString("userId"))){
//此处修改请求参数修改后转换类型再放回去
paramJson.put("userId","123");
//拦截处理业务逻辑后设置回参,注意回参的类型要和添加注解的方法中参数的类型一致(args[0]为添加注解方法中的第一个参数以此类推)
args[0]=JSONStringToObject(paramJson.toJSONString(),RequestVo.class, value);
//如果添加这句话就会返回到添加注解的方法体中继续执行方法,这个o就是添加注解的方法的返回值
Object o = proceedingJoinPoint.proceed(args);
return o;
}else{
//如果不加就会直接返回到前端
return AjaxResult.error("aspectAroundMethond返回");
}
}
/**
* 泛型json转换(比如转换成RequestVo<MchUser>类型)
* @param str json串
* @param collectionClass
* @param elementClasses
* @param <T>
* @return
* @throws IOException
*/
public static <T> T JSONStringToObject(String str, Class<?> collectionClass, Class<?>... elementClasses) throws IOException {
ObjectMapper mapper = new ObjectMapper();
JavaType javaType = mapper.getTypeFactory().constructParametricType(collectionClass, elementClasses);
return mapper.readValue(str, javaType);
}
/**
* 是否存在注解,如果存在就获取
*/
private LoginCheck getAnnotationLoginCheck(JoinPoint joinPoint) throws Exception
{
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
if (method != null)
{
return method.getAnnotation(LoginCheck.class);
}
return null;
}
}
controller中方法:
package com.ruoyi.project.api.controller.user;
import com.ruoyi.framework.aspectj.lang.annotation.LoginCheck;
import com.ruoyi.framework.web.controller.BaseController;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.project.api.domain.RequestVo;
import com.ruoyi.project.user.user.domain.MctUser;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
/**
* 客户信息Controller
*
* @author ruoyi
* @date 2020-12-18
*/
@Controller
@RequestMapping("api/user/user")
public class ApiUserController extends BaseController
{
@RequestMapping(value = "/test", method = { RequestMethod.GET, RequestMethod.POST })
@ResponseBody
//自定义注解传入的为需要返回时转为RequestVo<MctUser>的泛型
@LoginCheck(MctUser.class)
public AjaxResult test(@RequestBody RequestVo<MctUser> requestVo) {
MctUser data = requestVo.getData();
System.out.println(data.getUserName());
return AjaxResult.success("方法返回");
}
}
RequestVo类:
package com.ruoyi.project.api.domain;
public class RequestVo<T> {
private String userId;
private String userToken;
private T data;
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getUserToken() {
return userToken;
}
public void setUserToken(String userToken) {
this.userToken = userToken;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}