登录统计功能总结

我爱海鲸 2025-03-03 14:54:01 暂无标签

简介当前(今天、今日)日期查询

1、我们的需求是需要做一个登录的统计:

全年登录人次(人次)

今日登录人次(人次)

今日登录人数(人)

2、我们在mysql中创建两张表:

t_login_statistic(登录统计表)、t_login_statistic_day(登录统计天表)

CREATE TABLE
  `t_login_statistic` (
    `id` bigint(20) NOT NULL AUTO_INCREMENT,
    `login_type` tinyint(2) NOT NULL COMMENT '登录方式:1:第一种登录,2:第二种登录,3:第三种登录',
    `user_id` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '用户id',
    `login_time` timestamp NULL DEFAULT NULL COMMENT '登录时间',
    PRIMARY KEY (`id`)
  ) ENGINE = InnoDB AUTO_INCREMENT = 1008 DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '登录统计表'
  


  CREATE TABLE
  `t_login_statistic_day` (
    `day` varchar(20) NOT NULL COMMENT '日期',
    `login_count` int(11) DEFAULT '0' COMMENT '登录人次',
    `login_user_count` int(11) DEFAULT '0' COMMENT '登录人数',
    `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
    PRIMARY KEY (`day`)
  ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '登录统计天表'



思路:登录事件-检查登录统计天表中是否存在记录(t_login_statistic_day)-如果存在记录-查询当天统计表是否存在数据 (t_login_statistic)-如果存在记录-当天的登录次数加1 (t_login_statistic_day)-如果不存在记录-当天的登录次数加1,当天的登录人次加1 (t_login_statistic_day)-如果统计天表不存在记录-直接当天的登录次数和登录人数插入一条数据

service:

/**
 * @author haijin
 * @description: 登录统计相关业务
 * @date 2025/1/13 15:18
 */
@Slf4j
@Service
public class LoginStatisticService {

    @Autowired
    private LoginStatisticDao loginStatisticDao;

    @Transactional( value = "msbTxManager",rollbackFor = Exception.class)
    public ResponseModel addStatics(LoginSuccessEventPara loginSuccessEventPara) {
        String userId = UserContextHolder.getContext().getUserId();
        log.info("当前用户id【{}】",userId);
        LoginStatisticVo loginStatisticVo = LoginStatisticVo.builder()
                .loginTime(new Date())
                .userId(userId)
                .build();
        // 事件id
        Integer eventId = loginSuccessEventPara.getEventId();
        LoginTypeEnum loginTypeEnum = LoginTypeEnum.getInstance(eventId);
        if (LoginTypeEnum.LOGIN_4A_EVENT == loginTypeEnum) {
            // 4a登录事件
            loginStatisticVo.setLoginType(LoginTypeEnum.LOGIN_4A_EVENT.getCode());
        } else if (LoginTypeEnum.LOGIN_LOGIN_EVENT == loginTypeEnum) {
            // 本地登录
            loginStatisticVo.setLoginType(LoginTypeEnum.LOGIN_LOGIN_EVENT.getCode());
        } else if (LoginTypeEnum.LOGIN_SSO_EVENT == loginTypeEnum) {
            // sso登录
            loginStatisticVo.setLoginType(LoginTypeEnum.LOGIN_SSO_EVENT.getCode());
        } else {
            throw MsbException.logic("登录统计-登录方式异常【{}】",eventId);
        }
        // 查询当天统计表是否存在数据 (t_login_statistic)
        boolean existsByUserIdAndLoginTimeOfDay = loginStatisticDao.existsByUserIdAndLoginTimeOfDay(userId);
        // 记录登录统计表 (t_login_statistic)
        loginStatisticDao.insertLoginStatistic(loginStatisticVo);
        log.info("existsByUserIdAndLoginTimeOfDay【{}】",existsByUserIdAndLoginTimeOfDay);
        // 检查登录统计天表中是否存在记录 (t_login_statistic_day)
        String curDateStr = DateUtil.date2Str("yyyyMMdd", new Date());
        boolean existsByDay = loginStatisticDao.existsByDay(curDateStr);
        if (existsByDay) {
            // 天表中已经存在了当天的记录了 (t_login_statistic_day)
            if (existsByUserIdAndLoginTimeOfDay) {
                // 统计表中已经当前userid的数据存在了
                // 当天的登录次数加1 (t_login_statistic_day)
                loginStatisticDao.incrementLoginCountByDay(curDateStr);
            } else {
                // 当天的登录次数加1,当天的登录人次加1 (t_login_statistic_day)
                loginStatisticDao.incrementLoginUserCountByDay(curDateStr);
            }
        } else {
            // 天表中不存在当天的记录,直接当天的登录次数和登录人数插入一条数据
            loginStatisticDao.insertLoginStatisticDay(curDateStr,1,1);
        }
        return ResponseModel.success();
    }

    /**
     * 登录统计天表查询
     * @return igonre
     */
    public LoginStatisticResponseVo query() {
        // 当前日期
        String curDate = DateUtil.date2Str("yyyyMMdd", new Date());
        LoginStatisticDayVo loginStatisticDayVo = loginStatisticDao.findByDay(curDate);
        Long countCurrentYear = loginStatisticDao.sumLoginCountCurrentYear();
        if (loginStatisticDayVo == null) {
            countCurrentYear = countCurrentYear == null ? 0L : countCurrentYear;
            return LoginStatisticResponseVo.builder()
                    // 今日登录次数
                    .loginCount(0L)
                    // 年登录人次
                    .yearLoginCount(countCurrentYear)
                    // 今日登录人数
                    .loginUserCount(0L)
                    .build();
        }
        return LoginStatisticResponseVo.builder()
                // 今日登录次数
                .loginCount(loginStatisticDayVo.getLoginCount())
                // 年登录人次
                .yearLoginCount(countCurrentYear)
                // 今日登录人数
                .loginUserCount(loginStatisticDayVo.getLoginUserCount())
                .build();
    }
}

dao:

/**
 * @author haijin
 * @description: 登录统计
 * @date 2025/1/13 15:38
 */
@Mapper
@Repository
public interface LoginStatisticDao {

    /**
     * 插入登录统计表数据
     * @param loginStatisticVo 登录统计数据
     */
    void insertLoginStatistic(@Param("loginStatisticVo") LoginStatisticVo loginStatisticVo);

    /**
     * 根据用户ID和当天的登录时间检查是否存在记录
     * @param userId 用户ID
     * @return ignore
     */
    boolean existsByUserIdAndLoginTimeOfDay(@Param("userId") String userId);

    /**
     * 根据日期(格式:yyyyMMdd)检查登录统计天表中是否存在记录
     * @param day 日期字符串,格式为 yyyyMMdd
     * @return ignore
     */
    boolean existsByDay(@Param("day") String day);


    /**
     * 向登录统计天表插入或更新数据
     * @param day 日期字符串,格式为 yyyyMMdd
     * @param loginCount 登录人次
     * @param loginUserCount 登录人数
     */
    void insertLoginStatisticDay(@Param("day")String day,@Param("loginCount") int loginCount,@Param("loginUserCount") int loginUserCount);


    /**
     * 根据日期对登录统计天表的 login_count 进行加1操作并更新 update_time
     * @param day 日期字符串,格式为 yyyyMMdd
     */
    void incrementLoginCountByDay(String day);

    /**
     * 根据日期对登录统计天表的 login_user_count 进行加1操作并更新 update_time
     * @param day 日期字符串,格式为 yyyyMMdd
     */
    void incrementLoginUserCountByDay(String day);

    /**
     * 根据日期查询登录统计天表中的记录
     * @param day 日期字符串,格式为 yyyyMMdd
     * @return ignore
     */
    LoginStatisticDayVo findByDay(String day);

    /**
     * 查询当前年份的 login_count 总和
     * @return ignore
     */
    Long sumLoginCountCurrentYear();
}

dao-xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="xyz.haijin.dao.login.LoginStatisticDao">

    <insert id="insertLoginStatistic" parameterType="xyz.haijin.vo.statistic.login.LoginStatisticVo">
        INSERT INTO t_login_statistic (
            login_type,
            user_id,
            login_time
        ) VALUES (
                     #{loginStatisticVo.loginType},
                     #{loginStatisticVo.userId},
                     #{loginStatisticVo.loginTime}
                 )
    </insert>

    <select id="existsByUserIdAndLoginTimeOfDay" parameterType="map" resultType="boolean">
        SELECT EXISTS (
                       SELECT 1
                       FROM t_login_statistic
                       WHERE user_id = #{userId}
// 日期在当天内
            <![CDATA[ AND login_time BETWEEN CURDATE() AND CURDATE() + INTERVAL 1 DAY - INTERVAL 1 SECOND]]>
                   )
    </select>

    <select id="existsByDay" parameterType="string" resultType="boolean">
        SELECT EXISTS (
                       SELECT 1
                       FROM t_login_statistic_day
                       WHERE `day` = #{day}
                   )
    </select>

    <insert id="insertLoginStatisticDay" parameterType="map">
        INSERT INTO t_login_statistic_day (
            `day`,
            `login_count`,
            `login_user_count`,
            `update_time`
        ) VALUES (
                     #{day},
                     #{loginCount},
                     #{loginUserCount},
                     NOW()
                 )
    </insert>

    <update id="incrementLoginCountByDay" parameterType="string">
        UPDATE t_login_statistic_day
        SET login_count = login_count + 1,
            update_time = NOW()
        WHERE `day` = #{day}
    </update>

    <update id="incrementLoginUserCountByDay" parameterType="string">
        UPDATE t_login_statistic_day
        SET login_user_count = login_user_count + 1
            ,login_count = login_count + 1,
            update_time = NOW()
        WHERE `day` = #{day}
    </update>


    <select id="findByDay" parameterType="string" resultType="xyz.haijin.login.LoginStatisticDayVo">
        SELECT
            `day`,
            `login_count` as loginCount,
            `login_user_count` as loginUserCount,
            `update_time` as updateTime
        FROM t_login_statistic_day
        WHERE `day` = #{day}
    </select>

    <select id="sumLoginCountCurrentYear" resultType="Long">
        SELECT SUM(login_count) AS totalLoginCount
        FROM t_login_statistic_day
        WHERE YEAR(STR_TO_DATE(`day`, '%Y%m%d')) = YEAR(CURRENT_DATE)
    </select>
</mapper>

feigin调用:

/**
 * @author haijin
 * @description: 登录统计微服务接口
 * @date 2025/1/14 9:39
 */
@FeignClient(value ="loginStatisticClient", url = "localhost:8080" , path = "/loginStatistic")
public interface LoginStatisticClient {


    /**
     * 登录统计添加
     * @param loginSuccessEventPara 登录统计参数
     * @return ignore
     */
    @PostMapping("/add")
    ResponseModel addStatics(@RequestHeader("Authorization") String authorization, @RequestBody LoginSuccessEventPara loginSuccessEventPara);

    /**
     * 登录统计查询
     * @return ignore
     */
    @PostMapping("/query")
    ItemResponseModel<LoginStatisticResponseVo> query();
}

 

你好:我的2025