提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
目录
一、项目背景
项目里使用的S3的域名换了,存量的历史数据有提供对外的查询,要求进行兼容。
二、思路
2.1 逐一替换
最笨的办法,工作量比较大,容易漏掉,找到所有的地方,然后用replaceAll进行替换,记住,不是replace,是replaceAll,这是为了防止有的信息中保存多个图片的信息。
2.2 切面AOP
2.2.1 @AfterReturning
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
* @Author: 计科0706
* @Date: 2023/09/05/17:47
* @Description:
*/
@Component
@Aspect
@Slf4j
public class S3UrlReplaceInterceptor {
@Value("${s3.oldshowpoint}")
private String oldshowpoint;
@Value("${s3.showpoint}")
private String showPoint;
private final ObjectMapper objectMapper = new ObjectMapper();
// 定义一个切点,匹配所有Controller层的方法
@Pointcut("execution(* com.XXX.controller.*.*(..))")
public void controllerPointcut() {}
// 定义一个通知,对所有Controller层方法的返回值进行处理
@AfterReturning(value = "controllerPointcut()", returning = "result")
public Object afterController(JoinPoint joinPoint, Object result) throws Throwable {
if (result != null) {
try {
// 将对象转换为JSON字符串
String jsonResult = objectMapper.writeValueAsString(result);
// 执行替换操作
jsonResult = jsonResult.replaceAll(oldshowpoint, showPoint);
// 将JSON字符串还原为原始对象
return objectMapper.readValue(jsonResult, result.getClass());
} catch (JsonProcessingException e) {
// 处理JSON序列化和反序列化异常
log.error(e.getMessage(), e);
// 返回原始结果
return result;
}
}
return result;
}
}
乍一看没毛病,打断点,也能进来,也确实执行了替换。
但是问题来了,最终客户端拿到的结果没有被替换,依旧是原值,尴尬了.......
2.2.2 @Around
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
* @Author: 计科0706
* @Date: 2023/09/05/17:47
* @Description:
*/
@Component
@Aspect
@Slf4j
public class S3UrlReplaceInterceptor {
@Value("${s3.oldshowpoint}")
private String oldshowpoint;
@Value("${s3.showpoint}")
private String showPoint;
private final ObjectMapper objectMapper = new ObjectMapper();
// 定义一个切点,匹配所有Controller层的方法
@Pointcut("execution(* com.XXX.controller.*.*(..))")
public void controllerPointcut() {}
// 定义一个通知,对所有Controller层方法的返回值进行处理
@Around(value = "controllerPointcut()")
public Object afterController(ProceedingJoinPoint joinPoint) throws Throwable {
// 执行目标方法
Object result = joinPoint.proceed();
if (result != null) {
try {
// 将对象转换为JSON字符串
String jsonResult = objectMapper.writeValueAsString(result);
// 执行替换操作
jsonResult = jsonResult.replaceAll(oldshowpoint, showPoint);
// 将JSON字符串还原为原始对象
return objectMapper.readValue(jsonResult, result.getClass());
} catch (JsonProcessingException e) {
// 处理JSON序列化和反序列化异常
log.error(e.getMessage(), e);
// 返回原始结果
return result;
}
}
return result;
}
}
这下经过测试,客户端也的确拿到了预期的值。
你以为这就完了吗,另一个服务从这个服务查信息,其中就有一些日期格式的,该服务向外输出的日期格式为LocalDateTime类型。
2.2.3 罪魁祸首ObjectMapper
该类会将时间格式的信息,转换为ISO 8601格式
"createTime": {
"month": "SEPTEMBER",
"year": 2023,
"dayOfMonth": 4,
"dayOfWeek": "MONDAY",
"dayOfYear": 247,
"hour": 11,
"minute": 22,
"monthValue": 9,
"nano": 0,
"second": 47,
"chronology": {
"id": "ISO",
"calendarType": "iso8601"
}
}
用JSON调整,调整后的代码为下边的:
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
* @Author: 计科0706
* @Date: 2023/09/05/17:47
* @Description:
*/
@Component
@Aspect
@Slf4j
public class S3UrlReplaceInterceptor {
@Value("${s3.oldshowpoint}")
private String oldshowpoint;
@Value("${s3.showpoint}")
private String showPoint;
private final ObjectMapper objectMapper = new ObjectMapper();
// 定义一个切点,匹配所有Controller层的方法
@Pointcut("execution(* com.XXX.controller.*.*(..))")
public void controllerPointcut() {}
// 定义一个通知,对所有Controller层方法的返回值进行处理
@Around(value = "controllerPointcut()")
public Object afterController(ProceedingJoinPoint joinPoint) throws Throwable {
// 执行目标方法
Object result = joinPoint.proceed();
if (result != null) {
try {
// 将对象转换为JSON字符串
String jsonResult = JSON.toJSONString(result);
// 执行替换操作
jsonResult = jsonResult.replaceAll(oldshowpoint, showPoint);
// 将JSON字符串还原为原始对象
return JSON.parseObject(jsonResult, result.getClass());
} catch (JsonProcessingException e) {
// 处理JSON序列化和反序列化异常
log.error(e.getMessage(), e);
// 返回原始结果
return result;
}
}
return result;
}
}
所有问题解决