如何让Java后端日志开发变得优雅

日志规范

日志位置(什么时候进行日志记录)

  1. 【强制-ERROR/WARN】操作失败必须记录日志
  2. 【强制-ERROR】抛出异常必须记录日志(throw/try-catch)
  3. 【强制-INFO】敏感操作必须记录日志(数据库和redis的增、删、改;)
  4. 【推荐-INFO】查询接口推荐进行日志记录
  5. 【自定义-DEBUG】开发环境下可记录自定义的日志

PS:【】解释——【规范等级-日志等级】

日志等级

框架中常用日志等级(从低到高): DEBUG->INFO->WARN->ERROR

各日志等级使用:

  • DEBUG: 在本地开发中使用,可打印任何打印信息
  • INFO:打印业务日志
  • WARN:特殊场景下敏感操作但又不引起异常的日志(非数据库、redis日志记录;使用频率较少)
  • ERROR:报错,业务预期/非预期错误,站在业务角度:需要关注的程序异常都用此等级打印

日志使用

业务日志使用

推荐使用Lombok提供的快速日志记录方式。

使用:

类添加@Slf4j注解。

直接使用log调用对应级别的方法即可。

举例:

@Slf4j
public class Test {
    
    public void testLog(){
   		log.debug(""); 
        log.info(""); 
        log.warn(""); 
        log.error(""); 
    }
    
}

注解@Log接口切面日志使用

SMPE-ADMIN框架默认提供接口日志记录的注解@Log(在smpe-log子工程下实现)

使用:

controller层接口添加注解@Log,访问接口即可持久化到数据库进行缓存

举例:

@Log("新增用户")
@ApiOperation("新增用户")
@PostMapping
@ApiParam(name = "userInsertOrUpdateDTO", value = "新增用户参数列表")
@PreAuthorize("@smpe.check('user:add')")
public Result<Void> insertUserWithDetail(@RequestBody UserInsertOrUpdateDTO userInsertOrUpdateDTO) {
    return Result.success();
}

注意事项:

  • 前台接口暂时不添加@Log(持久化到数据库影响一定的mysql性能)
  • 数据库记录接口参数信息暂时只记录添加@RequestBody@RequestParam注解的参数
  • 此注解主要记录增删改接口的日志

日志格式

格式:【业务操作+成功/失败】具体信息。操作人ID:,操作记录唯一标识:,(操作记录重要信息:)。

推荐使用优雅的字符串拼接:使用hutool的StrUtil.format()方法

举例:

int userId = 1;
String username = "test";	
log.error("【新增用户失败】用户名已存在。操作人id:{},新增用户用户名:{}", userId, username);

结果:

SMPE-ADMIN- 2020-12-24 21:54:26 [main] ERROR marchsoft.log.LogTest - 【新增用户失败】用户名已存在。操作人id:1,新增用户用户名:test

以下方式不推荐(字符串"+"拼接):

int userId = 1;
String username = "test";
log.error("【新增用户失败】用户名已存在。操作人id:" + userId + "新增用户用户名:" + username);

日志使用场景举例

/**
 * description:新增用户(维护岗位、角色表)
 *
 * @param userInsertOrUpdateDTO /
 * @author RenShiWei
 * Date: 2020/11/24 20:52
 */
@Override
@Transactional(rollbackFor = Exception.class)
public void insertUserWithDetail(UserInsertOrUpdateDTO userInsertOrUpdateDTO) {
    userInsertOrUpdateDTO.setEnabled(true);
    LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
    //判断用户名不能重复
    queryWrapper.eq(User::getUsername, userInsertOrUpdateDTO.getUsername());
    // modify @RenShiWei 2020/11/24 description:list() ——> count()
    if (this.count(queryWrapper) > 0) {
        log.error("【新增用户失败】新增用户用户名已存在。操作人id:{},用户名:{}", SecurityUtils.getCurrentUserId(),
                userInsertOrUpdateDTO.getUsername());
        throw new BadRequestException(ResultEnum.USER_USERNAME_EXIST);
    }

    //判断邮箱不能重复
    queryWrapper.clear();
    queryWrapper.eq(User::getEmail, userInsertOrUpdateDTO.getEmail());
    // modify @RenShiWei 2020/11/24 description:增加邮箱判断
    if (this.count(queryWrapper) > 0) {
        log.error("【新增用户失败】新增用户邮箱已存在。操作人id:{},邮箱:{}", SecurityUtils.getCurrentUserId(),
                userInsertOrUpdateDTO.getEmail());
        throw new BadRequestException(ResultEnum.USER_EMAIL_EXIST);
    }

    //属性拷贝
    User user = new User();
    BeanUtil.copyProperties(userInsertOrUpdateDTO, user);
    //新增用户
    boolean save = save(user);
    if (! save) {
        log.error("【新增用户失败】操作人id:{},用户名:{}", SecurityUtils.getCurrentUserId(),
                userInsertOrUpdateDTO.getUsername());
        throw new BadRequestException(ResultEnum.INSERT_OPERATION_FAIL);
    }

    //维护中间表
    int count = userMapper.saveUserAtRole(user.getId(), userInsertOrUpdateDTO.getRoles());
    if (count <= 0) {
        log.error("【新增用户失败】维护角色中间表失败。操作人id:{}", SecurityUtils.getCurrentUserId());
        throw new BadRequestException(ResultEnum.OPERATION_MIDDLE_FAIL);
    }

    count = userMapper.saveUserAtJob(user.getId(), userInsertOrUpdateDTO.getJobs());
    if (count <= 0) {
        log.error("【新增用户失败】维护岗位中间表失败。操作人id:{}", SecurityUtils.getCurrentUserId());
        throw new BadRequestException(ResultEnum.OPERATION_MIDDLE_FAIL);
    }

    log.info("【新增用户成功】操作人id:{},用户名:{}", SecurityUtils.getCurrentUserId(),
            userInsertOrUpdateDTO.getUsername());
}

日志文件相关

  • 日志文件在项目根目录下生成,跟项目走,以logs命名;以年月命名文件夹,每月的日志文件统一放置。
  • 以每天每小时生成一个日志
  • 日志文件命名
    • 业务日志:server.%d{yyyy-MM-dd-HH}.log
    • redis日志:redis.%d{yyyy-MM-dd-HH}.log
  • 日志文件保存周期:最少一个月
  • 定期清理服务器不必要日志
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 答:目前Java后端新技术包括:Spring Boot、Microservices、Docker、Kubernetes、Reactive Programming、NoSQL数据库、Spring Cloud、REST API、Cloud Native应用开发。 ### 回答2: 目前有很多新兴的JAVA后端技术,让我们来看看其中的一些。 1. Spring Boot是JAVA后端开发的热门技术之一。它简化了Spring框架的配置,并提供了快速搭建项目的能力。Spring Boot还集成了各种常用的功能和组件,如安全认证、日志管理等。 2. 微服务也是一个热门的JAVA后端技术。它通过将应用程序拆分成一些小的、独立的服务来实现,每个服务都可以独立部署和扩展。微服务架构可以提高可维护性、可扩展性和灵活性。 3. 响应式编程是一种面向异步和事件驱动的编程范式。它可以有效地处理高并发和高负载的请求。JAVA后端开发中的常用响应式编程框架包括Reactor和RxJava。 4. 云原生应用开发是近年来兴起的JAVA后端技术。它将应用程序开发和部署环境与云服务平台相结合,实现更高效的应用开发和更好的可伸缩性。Kubernetes是一个流行的云原生应用开发和管理平台。 5. 高性能计算是JAVA后端开发的关键技术之一。Java虚拟机(JVM)的不断优化和并行计算的发展让Java能够处理更多的并发任务和大规模数据处理。 以上只是一些JAVA后端新技术的例子,随着技术的不断发展,还会有更多出现,JAVA开发者应该保持学习和掌握新技术的态度。 ### 回答3: 目前,Java后端开发领域涌现出许多新的技术。以下是其中一些比较流行的Java后端新技术: 1. Spring Boot:Spring Boot是Spring框架的一部分,它简化了Java应用程序的搭建和配置。它提供了自动配置、嵌入式服务器和丰富的开发工具,使得使用Spring开发Java后端应用更加高效和简单。 2. Spring Cloud:Spring Cloud是一组用于构建分布式系统的工具,它基于Spring Boot的开发风格。它提供了服务注册与发现、负载均衡、断路器等功能,使得构建可扩展的分布式系统更加容易。 3. Kotlin:Kotlin是一种静态类型的编程语言,它可以与Java无缝互操作。它提供了更简洁、安全和表达力更强的语法,逐渐成为Java后端开发的替代选择。 4. Quarkus:Quarkus是一种Java框架,专为构建云原生应用程序而设计。它具有超快的启动速度和低内存消耗,并提供了与Kubernetes、GraalVM等现代技术的集成,使Java后端应用更加适合云环境。 5. Micronaut:Micronaut是一种轻量级的Java框架,旨在提高应用程序的性能和开发效率。它具有快速启动、低内存消耗和编译时依赖注入等特性,适用于构建微服务和云原生应用。 6. JHipster:JHipster是一个全栈开发平台,基于Spring Boot和Angular或React构建现代化的Web应用。它提供了代码生成、安全认证、运行时监控等功能,方便快速搭建现代化的Java后端应用。 这些技术的出现和发展,使得Java后端开发变得更加高效、易用和具有更好的性能,有助于开发者应对日益复杂的业务需求和技术挑战。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值