Java:对请求结果进行拦截替换

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

目录

一、项目背景

二、思路

2.1 逐一替换

2.2 切面AOP


一、项目背景

项目里使用的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;
    }

}

 所有问题解决

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java中,可以使用拦截器来拦截后端的返回结果,并使用数据库中的模拟报文进行替换。具体步骤如下: 1. 创建一个拦截器类,实现HandlerInterceptor接口,并重写preHandle、postHandle和afterCompletion方法。其中,preHandle方法用于在处理请求之前拦截请求,postHandle方法用于在处理请求之后拦截请求,而afterCompletion方法用于在请求完成之后拦截请求。 2. 在拦截器类中,使用AOP技术,拦截Controller层的方法,获取返回结果。 3. 将返回结果与数据库中的模拟报文进行比较,如果匹配成功,则使用模拟报文进行替换。 4. 最后,将替换后的结果返回给前端。 下面是一个示例代码: ``` public class MockInterceptor implements HandlerInterceptor { @Autowired private MockMessageService mockMessageService; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 在请求处理之前拦截请求 return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { // 在请求处理之后拦截请求,获取返回结果 if (modelAndView != null && !StringUtils.isEmpty(modelAndView.getViewName())) { String viewName = modelAndView.getViewName(); String mockMessage = mockMessageService.getMockMessage(viewName); if (!StringUtils.isEmpty(mockMessage)) { // 如果匹配成功,则使用模拟报文进行替换 modelAndView.setViewName("mock"); modelAndView.addObject("mockMessage", mockMessage); } } } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // 在请求完成之后拦截请求 } } ``` 在上面的代码中,MockMessageService是一个用于获取模拟报文的服务类。在postHandle方法中,我们获取了返回结果的视图名称,并调用MockMessageService的getMockMessage方法获取对应的模拟报文。如果匹配成功,则将返回结果的视图名称设置为"mock",并将模拟报文添加到modelAndView中。最终,返回给前端的结果就是模拟报文
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值