工厂模式+策略模式+AOP实现动态日志记录

文章描述了一个通过AOP切面编程监控HTTP调用第三方接口的日志记录系统。当接口返回不同状态或超时时,采用策略模式来处理不同的日志记录策略,如成功、失败或不记录。此外,还利用SpringBoot的组件和WebClient进行HTTP通信。
摘要由CSDN通过智能技术生成

场景:通过http调用第三方接口进行日志记录,第三方接口可能返回成功、可能返回失败(指调用成功,接口响应体为失败),也可能超时,甚至当不是期望的url时我们不进行日志记录。

1.依赖
<!-- aop 依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

<!-- http依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>

<!-- java 工具包 -->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.7.16</version>
        </dependency>

2.Htttutils编写

@Component
public class HttpUtils {

    // HTTP 前缀
    private static final String HTTP_PREFIX = "http://";

    
    public WebClient getWebClient(String ip, int port) {
        return WebClient.builder()
                .baseUrl(HTTP_PREFIX + ip + StrUtil.COLON + port)
                .defaultHeaders(heads -> {
                    heads.setExpires(1000);
                    heads.setContentType(MediaType.APPLICATION_JSON_UTF8);
                }).build();
    }

    
    public <T> T get(String ip, int port, String uri, Class<T> clazz) {
        WebClient webClient = getWebClient(ip, port);


        return webClient.get().uri(uri).retrieve().bodyToMono(clazz)
                .doOnError(ex -> {
                })
                .doOnSuccess(s -> {
                })
                .block();
    }
}

httpUtils上加@Component是将该实例放入Spring容器,为了给AOP拦截该实例的方法

3.AOP编写

@Component
@Aspect
public class LogAspect {

//    @Pointcut("")
//    public void logPoint() {
//    }

    private static final Map<Integer,String> statusMap = new HashMap<>();
    private static final List<String> urlList = new ArrayList<>();
    static {
        statusMap.put(200,"ok");
        statusMap.put(500,"error");
        urlList.add("/lundy/logs/communicationLogs/findCommunicationLog?id=");
        urlList.add("/lundy/logs/communicationLogs/retryCommunication?id=");
    }

    @Around("execution(* com.suzhouheart.utils.HttpUtils.get(..))")
    public Object aroundAop(ProceedingJoinPoint pj) {

        LinkedHashMap proceed = null;
        String str = "no_todo";
        Object[] args = pj.getArgs();
        try {
            proceed = (LinkedHashMap)pj.proceed();
            //httpUtils.get()的第三个参数为url
            if (urlList.contains(args[2])){

                str = statusMap.getOrDefault(proceed.get("status"),"error");
            }

        } catch (Throwable e) {
            str = "error";
        }
        LogHandle logHandle = UrlHandleFactory.getInvokeStrategy(str);
        logHandle.handle(args);
        return proceed;
    }
}

urlList中存放需要进行日志记录的url,当url不在这个集合里时,不进行日志记录。statusMap为状态转换map,根据http的响应状态,进行不同的处理。

4.策略模式编写

4.1编写策略接口


public interface LogHandle extends InitializingBean {

    void handle(Object[] args);
}

接口继承InitializingBean,其实现类要重写afterPropertiesSet()方法,该方法在加载这个bean的时候会调用,通过该方法可以将每个策略实现注册到工厂中。

4.2编写策略实现


@Component
public class SuccessHandle implements LogHandle{

    @Override
    public void handle(Object[] args) {
        System.out.println("成功");
        for (Object arg : args) {
            System.out.println(arg);
        }
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        UrlHandleFactory.register("ok", this);
    }
}

@Component
public class ErrorHandle implements LogHandle{

    @Override
    public void handle(Object[] args) {
        System.out.println("失败");
        for (Object arg : args) {
            System.out.println(arg);
        }
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        UrlHandleFactory.register("error", this);
    }
}

@Component
public class NoToDoHandle implements LogHandle{


    @Override
    public void handle(Object[] args) {
        System.out.println("不记录日志");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        UrlHandleFactory.register("no_todo",this);
    }
}

5.编写工厂模式

public class UrlHandleFactory {

    private static Map<String ,LogHandle> strategyMap = new HashMap<>();

    public static LogHandle getInvokeStrategy(String name){
        return strategyMap.get(name);
    }

    public static void register(String name, LogHandle logHandle){
        if (StringUtils.isEmpty(name) || null == logHandle){
            return;
        }
        strategyMap.put(name, logHandle);
    }
}

6.测试结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值