HeartBeatController.java 4.9 KB
package com.tianbo.warehouse.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.tianbo.warehouse.controller.response.ResultJson;
import com.tianbo.warehouse.dao.KakoUserMapper;
import com.tianbo.warehouse.model.KakoUser;
import com.tianbo.warehouse.util.RedisUtils;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;

@RestController()
@Slf4j
public class HeartBeatController {

    @Autowired
    private RedisUtils redisUtils;

    @Resource
    private KakoUserMapper kakoUserMapper;

    //token头部标识类型,Bearer代表Bearer TOKEN
    static final String AUTHORIZATION_HEADER = "Bearer ";

    //检查token时效是否低于标准线
    static final long TOKEN_TTL_CHECK_MIN= 36000L;

    //重置token时效为标准线
    static final long TOKEN_TTL_ADD= 86400L;

    //心跳每次续费时长
    static final long HEARTBEAT_TOKEN_TTL_ADD= 10L;

    @ApiOperation(value = "用户心跳接口", notes = "心跳续期")
    @PostMapping("/heartbeat")
    public ResultJson heartbeat(HttpServletRequest request, HttpServletResponse response){
        try {

            //1. 获取客户端IP,因为有反向代理所以要从头部获取代理过来的头部IP
            String clientIP =null;
            clientIP  = request.getRemoteAddr();
            String header_forwarded = request.getHeader("x-forwarded-for");
            if (StringUtils.isNotBlank(header_forwarded)) {
                clientIP = request.getHeader("x-forwarded-for");
                // 多次反向代理后会有多个ip值,第一个ip才是真实ip
                if (clientIP.contains(",")) {
                    clientIP = clientIP.split(",")[0];
                }
            }

            //2.获取token
            String token = request.getHeader("Authorization");
            /**
             * key样式
             * accessToken:token
             */
            if (token!=null && !token.isEmpty() && token.startsWith(AUTHORIZATION_HEADER)){
                token = token.substring(AUTHORIZATION_HEADER.length());
                String accessToken = token;
                String userDetailStr = redisUtils.get(accessToken);


                //4. 更新用户心跳时间及在线状态IP等资料
                if (StringUtils.isNotBlank(userDetailStr)){

                    JSONObject u = JSON.parseObject(userDetailStr);
                    String userId= u.getString("id");
                    String userInfo = u.getString("name");
                    String username = u.getString("username");
//                userDetailStr = userDetailStr.replace("@","");

                    /**3.续期token过期时间
                     * 增加过期时间,考虑到程序及网络传输中间的时间损耗,
                     * 每10秒一个的心跳直接续费10秒的话,token的过期时间还是会随着时间逐步减少
                     */
                    long  tokenExpireTime= redisUtils.getExpire(accessToken);
                    if(tokenExpireTime < TOKEN_TTL_CHECK_MIN){
                        redisUtils.expire(accessToken, TOKEN_TTL_ADD);
                        redisUtils.expire(username, TOKEN_TTL_ADD);
                    }else{
                        redisUtils.expire(accessToken,tokenExpireTime+HEARTBEAT_TOKEN_TTL_ADD);
                        redisUtils.expire(username, tokenExpireTime+HEARTBEAT_TOKEN_TTL_ADD);
                    }

                    /**
                     * 多式联运用户表
                     */
//                Integer dsly_userId = u.getInteger("id");
//                USER user = new USER();
//                user.setId(dsly_userId);
//                user.setLoginip(clientIP);
//                user.setLogintime(new Date());
//                user.setOnline(true);
//                int ii = userMapper.updateByPrimaryKeySelective(user);

                    KakoUser kakoUser = new KakoUser();
                    kakoUser.setId(userId);
                    kakoUser.setLoginIp(clientIP);
                    kakoUser.setLoginDate(new Date());
                    kakoUser.setOnline(true);
                    int i  = kakoUserMapper.updateByPrimaryKeySelective(kakoUser);

                    return i > 0 ?  new ResultJson("200","心跳成功"): new ResultJson("400","心跳失败");
                }

            }
            return  new ResultJson("400","心跳失败");

        }catch (Exception e){
            log.error("[HEART-BEAT-ERROR]-",e);
            return  new ResultJson("400","心跳失败");
        }
    }
}