LswlApi.java
package com.uustop.framework.aspectj.lang.annotation;
import org.springframework.http.HttpMethod;
import java.lang.annotation.*;
/**
* 自定义出入参记录注解
*
* @author uustop
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LswlApi {
/**
* 描述信息
*/
public String description() default "";
/**
* 自定义请求路径(覆盖默认方法名路径)
*/
String customPath() default "";
/**
* HTTP请求方法(默认为POST)
*/
HttpMethod method() default HttpMethod.POST;
}
LswlApiInvokerAspect.java
package com.uustop.framework.aspectj;
import cn.hutool.core.lang.TypeReference;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONConfig;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.uustop.framework.aspectj.lang.annotation.ApiClass;
import com.uustop.framework.aspectj.lang.annotation.LswlApi;
import com.uustop.framework.web.domain.RespEntity;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import java.io.IOException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Proxy;
import java.lang.reflect.Type;
@Aspect
@Component
public class LswlApiInvokerAspect {
// 使用注入的RestTemplate(确保在配置中配置)
private final RestTemplate restTemplate;
private static final ObjectMapper mapper = new ObjectMapper();
// 基础URL从配置读取(示例值)
private final String baseUrl;
public LswlApiInvokerAspect(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
this.baseUrl = "http://127.0.0.1:6087/business/api"; // 实际应从@Value注入
}
/**
* 核心拦截逻辑
*/
@Around("@annotation(com.uustop.framework.aspectj.lang.annotation.LswlApi)")
public Object remoteMethodInvocation(ProceedingJoinPoint pjp) {
// 1. 获取方法元数据
MethodSignature signature = (MethodSignature) pjp.getSignature();
Method method = signature.getMethod();
LswlApi apiAnnotation = method.getAnnotation(LswlApi.class);
// 2. 获取目标类信息(关键修改点)
Class<?> targetClass = getTargetClass(pjp);
// 3. 获取类上的注解
ApiClass apiClassAnnotation = targetClass.getAnnotation(ApiClass.class);
// 2. 构建目标URL
String url = buildTargetUrl(method.getName(), apiAnnotation.customPath(), apiClassAnnotation);
// 3. 准备请求实体
HttpEntity<Object> requestEntity = prepareRequestEntity(pjp.getArgs());
// 4. 获取返回类型信息
// Class<?> returnType = signature.getReturnType();
Type genericReturnType = method.getGenericReturnType();
// 5. 执行远程调用并转换类型
return executeRemoteCall(url, apiAnnotation.method(), requestEntity, genericReturnType);
}
/**
* 获取目标类(处理代理类情况)
*/
private Class<?> getTargetClass(ProceedingJoinPoint pjp) {
Object target = pjp.getTarget();
// 处理Spring代理类(CGLIB)
if (target.getClass().getName().contains("$$")) {
return target.getClass().getSuperclass();
}
// 处理JDK动态代理
if (Proxy.isProxyClass(target.getClass())) {
// 获取代理实现的接口
Class<?>[] interfaces = target.getClass().getInterfaces();
if (interfaces.length > 0) {
return interfaces[0]; // 返回第一个接口
}
}
// 普通类
return target.getClass();
}
/**
* 构建目标URL
*/
private String buildTargetUrl(String methodName, String customPath, ApiClass apiClassAnnotation) {
StringBuilder urlBuilder = new StringBuilder(baseUrl);
// 添加类注解路径(如果存在)
if (apiClassAnnotation != null && !apiClassAnnotation.path().isEmpty()) {
String classPath = apiClassAnnotation.path();
if (!classPath.startsWith("/")) {
urlBuilder.append('/');
}
urlBuilder.append(classPath);
}
if (!customPath.isEmpty()) {
urlBuilder.append(customPath.startsWith("/") ? customPath : "/" + customPath);
} else {
urlBuilder.append("/").append(methodName);
}
return urlBuilder.toString();
}
/**
* 准备请求实体
*/
private HttpEntity<Object> prepareRequestEntity(Object[] args) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
// 智能选择请求体:
// - 无参数: null
// - 单参数: 直接作为body
// - 多参数: 封装为数组
Object requestBody = null;
if (args.length == 1) {
requestBody = args[0];
} else if (args.length > 1) {
requestBody = args;
}
return new HttpEntity<>(requestBody, headers);
}
/**
* 准备请求实体
*/
// private HttpEntity<Object> prepareRequestEntity(Method method, Object[] args) {
// HttpHeaders headers = new HttpHeaders();
// headers.setContentType(MediaType.APPLICATION_JSON);
//
// // 获取方法的参数名
// java.lang.reflect.Parameter[] parameters = method.getParameters();
//
// // 创建一个Map来存储参数名和值
// Map<String, Object> requestBodyMap = new HashMap<>();
// for (int i = 0; i < parameters.length; i++) {
// requestBodyMap.put(parameters[i].getName(), args[i]);
// }
//
// // 智能选择请求体:
// // - 无参数: null
// // - 单参数: 直接作为body
// // - 多参数: 封装为数组
// Object requestBody = null;
// try {
// // 使用ObjectMapper将Map转换为JSON字符串
// ObjectMapper objectMapper = new ObjectMapper();
// requestBody = objectMapper.writeValueAsString(requestBodyMap);
// } catch (Exception e) {
// // 处理JSON转换异常
// throw new RuntimeException("Failed to convert request body to JSON", e);
// }
//
// return new HttpEntity<>(requestBody, headers);
// }
/**
* 执行远程调用并处理响应
*/
private <T> T executeRemoteCall(String url, HttpMethod httpMethod,
HttpEntity<?> requestEntity,
Type genericType) {
// 处理泛型类型(如List<User>)
ResponseEntity<String> response = restTemplate.exchange(url, httpMethod, requestEntity, String.class);
try {
return handleResponse(response, genericType);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 将JSON字符串转换为RespEntity<T>类型,支持嵌套泛型
*/
public static <T> Object convertJsonToRespEntity(String json, Type genericReturnType) throws Exception {
// 构建包含完整泛型信息的JavaType
JavaType javaType = buildRespEntityType(genericReturnType);
// 执行转换
return mapper.readValue(json, javaType);
}
public static Object deserializeFromType(String jsonString, Type genericReturnType) throws IOException {
// 1. 创建 ObjectMapper 实例
ObjectMapper objectMapper = new ObjectMapper();
// 2. 将 Type 转换为 JavaType
JavaType javaType = objectMapper.getTypeFactory().constructType(genericReturnType);
// 3. 反序列化 JSON 字符串
return objectMapper.readValue(jsonString, javaType);
}
public static Object parseJsonToType(String jsonString, Type targetType) {
// 1. 创建自定义JSON配置(解决日期格式问题)
JSONConfig config = JSONConfig.create()
// 设置日期格式为 "yyyy-MM-dd HH:mm:ss"
.setDateFormat("yyyy-MM-dd HH:mm:ss")
// 自动忽略不存在的字段
.setIgnoreCase(true);
// 2. 使用 Hutool 的强大解析能力
JSON json = JSONUtil.parse(jsonString, config); // 关键:直接解析为通用JSON类型
// 3. 转换为目标类型(通过动态TypeReference)
return json.toBean(new TypeReference<Object>() {
@Override
public Type getType() {
return targetType; // 使用反射获取的泛型类型
}
});
}
/**
* 处理HTTP响应
*/
private <T> T handleResponse(ResponseEntity<String> response, Type genericType) throws Exception {
if (response.getStatusCode().is2xxSuccessful()) {
return (T) parseJsonToType(response.getBody(), genericType);
}
// 自定义异常处理(根据实际需求扩展)
throw new RemoteApiException(
"Remote API call failed: " + response.getStatusCode() +
" - " + response.getBody()
);
}
/**
* 构建RespEntity<T>的JavaType,处理嵌套泛型
*/
private static JavaType buildRespEntityType(Type genericType) {
if (!(genericType instanceof ParameterizedType)) {
// 非泛型类型,使用原始类型
return mapper.getTypeFactory().constructType(RespEntity.class);
}
ParameterizedType paramType = (ParameterizedType) genericType;
Type[] typeArgs = paramType.getActualTypeArguments();
if (typeArgs.length == 0) {
// 无泛型参数,使用原始类型
return mapper.getTypeFactory().constructType(RespEntity.class);
}
// 处理泛型参数(例如List<Project>)
JavaType genericTypeArg = mapper.getTypeFactory().constructType(typeArgs[0]);
// 构建RespEntity<T>类型
return mapper.getTypeFactory().constructParametricType(
RespEntity.class,
genericTypeArg
);
}
/**
* 自定义异常类
*/
public static class RemoteApiException extends RuntimeException {
public RemoteApiException(String message) {
super(message);
}
}
}