UE4 定义一个全局工程可以使用的日志类名

Posted Suozhiyuan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UE4 定义一个全局工程可以使用的日志类名相关的知识,希望对你有一定的参考价值。

使用宏封装了一个文本输出窗口打印

NewTypes.h

 // Fill out your copyright notice in the Description page of Project Settings.
 
 #pragma once
 
 #include "CoreMinimal.h"
 
 // 定义一个全局工程可以使用的日志类名, 通常在头文件中声明,并在源文件中与 DEFINE_LOG_CATEGORY 配对。所有包含头文件的文件都可以访问。
 // @param CategoryName,类别名
 // @param DefaultVerbosity,样式类型
 // @param CompileTimeVerbosity,覆盖范围
 DECLARE_LOG_CATEGORY_EXTERN(SZYLog, Log, All);
 
 
 #ifndef BREAK_IF
 #define BREAK_IF(x) if(x) break
 #endif // !BREAK_IF
 
 #ifndef BREAK_IF_WARNING
 #define BREAK_IF_WARNING(x, Format, ...) if (x)UE_LOG(SZYLog, Warning, Format, ##__VA_ARGS__); break;
 #endif // !BREAK_IF_WARRING
 
 #ifndef BREAK_IF_ERROR
 #define BREAK_IF_ERROR(x, Format, ...) if (x)UE_LOG(SZYLog, Error, Format, ##__VA_ARGS__); break;
 #endif // !BREAK_IF_ERROR

NewTypes.cpp

 // Fill out your copyright notice in the Description page of Project Settings.
 
 
 #include "NewTypes.h"
 
 
 DEFINE_LOG_CATEGORY(SZYLog)            // 定义日志类别的宏,通常与头文件中的 DECLARE_LOG_CATEGORY_EXTERN 配对。 @param类别名,类别定义

 

调用:

BREAK_IF_WARNING(条件为真, 输出内容)

如果不加 do while 会报错 非法 brank

     do 
     
         MyScene = CreateDefaultSubobject<USceneComponent>(FName("MyRoot"));
         BREAK_IF_WARNING(!SetRootComponent(MyScene), TEXT("Set root component error!"))
         BREAK_IF_WARNING(RootComponent == nullptr, TEXT("Root is nullptr!!!"));
 
      while (false);

 

 

封装了一个屏幕打印

 namespace DemoHelper
 
 
     FORCEINLINE void Debug(FString Message, float Duration = 3.f)
     
         if (GEngine) 
         
             GEngine->AddOnScreenDebugMessage(-1, Duration, FColor::Yellow, Message);
         
     
 

调用:DemoHelper::Debug(FString("TEST!!!"));   

 

springboot-使用AOP日志拦截实现

一 前言

借助spring的AOP功能,我们可以将AOP应用至全局异常处理,全局请求拦截等,本篇文章的核心功能就是使用AOP实现日志记录,比如哪些用户进行了哪些操作,对于一个成功的项目这是必须记录的,故知识追寻者这边给出一个简单模型应用;

二 定义枚举

枚举定义的类型就是实现日志的哪些操作,如下所示,有些是登陆日志,有些是增删改查日志,不同的系统可以定义不同的日志,读者可以自由选择;

public enum LogEnum {

    UNOPERATE(0,"未定义操作"),
    SELECT(1,"查询"),
    INSERT(2,"添加"),
    UPDATE(3,"更新"),
    DELETE(4,"删除"),
    EXPORT(5,"excel导出"),
    LOGIN(6,"登陆"),
    LOGOUT(7,"登出"),
    ;

    LogEnum( Integer code, String operate) {
        this.operate = operate;
        this.code = code;
    }

    LogEnum(){

    }

    // 操作
    private String operate;
    // 操作码
    private Integer code;

    public String getOperate() {
        return operate;
    }

    public void setOperate(String operate) {
        this.operate = operate;
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }
}

三 注解

使用注解的目的就是在哪些方法上使用注解,也就是标记这属于哪些操作,通过注解操作类型结合已经定义的枚举就可以简单的实现哪些方法上进行了哪些操作;

@Documented
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MonitorLog {

    /* *
     * @Author lsc
     * <p>日志内容 </p>
     * @Param []
     * @Return java.lang.String
     */
    String value() default "";

    /* *
     * @Author lsc
     * <p>日志操作类型 </p>
     * @Param []
     * @Return int
     */
    LogEnum operateType() default LogEnum.UNOPERATE;


}

四 AOP切面

将注解设置为切点。将切点织入切面后使用环绕通知增强已经被注解标注的方法,此时就可以获得所有的注解操作,然后将日志记录入库,就可以简单实现用户的日志操作监控,当前提是在AOP中获得用户名,常见的shiro框架就有getSubject的方法获得用户名,当然根据不同的读者使用的技术不同进行获取,知识追寻者这边为了简单实现功能就没有使用一堆繁琐的方法去实现一个用户登陆认证系统;

/**
 * @Author lsc
 * <p>日志aop切面 </p>
 */

@Aspect
@Component
public class LogAsp {

    /* *
     * @Author lsc
     * <p> 设置切点</p>
     * @Param []
     * @Return void
     */
    @Pointcut("@annotation(com.zszxz.annotation.MonitorLog)")
    public void logPointCut() {

    }

    // 环绕通知
    @Around("logPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        // 开始时间
        LocalDateTime beginTime = LocalDateTime.now();
        // 执行方法
        Object result = point.proceed();
        // 结束时间
        LocalDateTime endTime = LocalDateTime.now();
        Duration duration = Duration.between(beginTime, endTime);
        // 操作时长
        long seconds = duration.getSeconds();
        // 保存日志
        saveLog(point,seconds);
        return result;
    }

    private void  saveLog(ProceedingJoinPoint point, long seconds){
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        // 获得注解
        MonitorLog monitorLog = method.getAnnotation(MonitorLog.class);
        if (monitorLog!=null){
            // 获得操作类型
            LogEnum operateType = monitorLog.operateType();
            // 获得操作内容
            String value = monitorLog.value();
            System.out.printf("获得操作类型: %s , 获得操作内容: %s ",operateType.getCode(),value);

            //请求的参数
            Object[] args = point.getArgs();
            try{
                List<Object> objects = Arrays.asList(args);
                System.out.println(objects);
            }catch (Exception e){

            }

        }
    }
}

五表现层

controller 所示,模拟进行查询用户操作的方法,并且在方法上标明注解这是个查询用户的方法,当访问此API时就会被AOP拦截;

/**
 * @Author lsc
 * <p> </p>
 */
@RestController
public class UserController {


    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @MonitorLog(value="查询用户",operateType = LogEnum.SELECT)
    @GetMapping("zszxz")
    public String getUser(String user){
        return "zszxz";
    }


}

如果哪些不懂可以参照一下知识追寻者的源码(专栏说明或者公主号都要知识追寻者github地址),

以上是关于UE4 定义一个全局工程可以使用的日志类名的主要内容,如果未能解决你的问题,请参考以下文章

C++ 怎么定义一个全局函数,能够在一个工程的所有文件中使用!

UE4打包失败求助!!!

UE4 C++ UDataAssetUPrimaryDataAsset 的简单使用

ue4 material custom node - global function and method

离线成员函数定义是不是需要完全限定的类名到全局范围?

通过AOP实现全局日志打印