吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 652|回复: 4
收起左侧

[求助] java回调请教

[复制链接]
ppgjx 发表于 2022-5-21 23:08
本帖最后由 ppgjx 于 2022-5-21 23:09 编辑

我现在在做一个用户系统,基于token认证的,现在想建立一个websocket服务所有登录的用户都链接这个websocket服务器 ,但是websocket如何实时踢人下线这个问题困扰了我很久

这是我的登录校验代码,可以到看到每次请求都去检测用户带来的uid和token是否和redis里面的匹配
[Asm] 纯文本查看 复制代码
package com.ppgjx.app.interceptor;

import com.ppgjx.app.annotation.PxCheckLogin;
import com.ppgjx.app.annotation.PxCheckRole;
import com.ppgjx.app.common.user.ans.common.UserInfo;
import com.ppgjx.app.common.user.ans.common.UserRoleInfo;
import com.ppgjx.app.common.user.ans.common.UserRolePermissionInfo;
import com.ppgjx.app.constant.RedisKey;
import com.ppgjx.app.constant.ResultCode;
import com.ppgjx.app.execption.ResRunException;
import com.ppgjx.app.util.MyUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 *
 * 用户登录拦截器
 *
 */
@Slf4j
public class UserLoginInterceptor extends HandlerInterceptorAdapter {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    //过滤未登录用户
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        this.hasPermission(handler,request);
        return  true;
    }

    //判断是否登录
    private void isLogin(HttpServletRequest request){
        String uid =  request.getHeader("uid");
        String token =  request.getHeader("token");
        if(null != uid && null != token){
            String redisUid = stringRedisTemplate.opsForValue().get(String.format(RedisKey.LOGIN_USER_TOKEN,uid ));
            if(!token.equals(redisUid)){
                throw new ResRunException(ResultCode.OTHER_LOGIN_ERR);
            }
        }else {
            throw new ResRunException(ResultCode.NOT_LOGIN_ERR);
        }
    }


    /**
     * 是否有权限
     */
    private boolean hasPermission(Object handler,HttpServletRequest request) {
        if (handler instanceof HandlerMethod) {


            HandlerMethod handlerMethod = (HandlerMethod) handler;
            //获取类上的注解
            PxCheckLogin pxCheckLoginClass =  handlerMethod.getMethod().getDeclaringClass().getAnnotation(PxCheckLogin.class);
            // 获取方法上的注解
            PxCheckLogin pxCheckLogin = handlerMethod.getMethod().getAnnotation(PxCheckLogin.class);
            //如果类上加了注解进行拦截
            if(null != pxCheckLoginClass){
                //如果这个方法有注解 且 设置了为不登录则通过 否则检验
                if(null != pxCheckLogin && !pxCheckLogin.value()){
                    return true;
                }else {
                    this.isLogin(request);
                }
            }else {
                //如果类上没注册则检查方法
                if(null != pxCheckLogin && pxCheckLogin.value()){
                    this.isLogin(request);
                }
            }
        }
        return true;
    }
}


这是我的websockert服务器代码 只是做了简单的逻辑 没有做登录 我现在想的是 怎么才能让用户校验类 如果判断用户下线了 会给websocket一个回调 这样就完美的解决及时下线的问题 但是我实在不知道这个回调改怎么写 希望有大佬帮帮我

[Asm] 纯文本查看 复制代码
package com.ppgjx.app.netty.user;


import com.ppgjx.app.service.PxUserService;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.concurrent.GlobalEventExecutor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

@Component
@Slf4j
public class UserChannelHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {


    private static StringRedisTemplate redisTemplate;

    private static PxUserService pxUserService;


    @Resource
    public void setStringRedisTemplate(StringRedisTemplate redisTemplate) {
        UserChannelHandler.redisTemplate = redisTemplate;
    }



    @Resource
    public void setPxUserService(PxUserService pxUserService) {
        UserChannelHandler.pxUserService = pxUserService;
    }


    //用户id=>channel示例
    //可以通过用户的唯一标识保存用户的channel
    //这样就可以发送给指定的用户
    public static ChannelGroup clients = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);


    //客户端断开链接
    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        System.out.println("客户端断开连接 --- " + ctx.channel().id() );
        clients.remove(ctx.channel());
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println("channelRead");
        super.channelRead(ctx, msg);
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
        //获取客户端消息
        String context = msg.text();
        log.info(ctx.channel().id().asShortText() + " 测试数据 ---" + context + " -- 当前客户数量 --- " + clients.size());
 
        pushAllUser( "用户: " + ctx.channel().id().asShortText() + " 消息: " + context + " 当前客户数量: " + clients.size());
    }

    /**
     * 推送所有
     * [url=home.php?mod=space&uid=952169]@Param[/url] text
     */
    public void pushAllUser(String text){
        clients.writeAndFlush(new TextWebSocketFrame(text));
    }


    /**
     * 推送所有除了自己
     * @param text
     * @param ctx
     */
    public void pushOtherUser(String text,ChannelHandlerContext ctx){
        clients.forEach(ch ->{
            if(ctx.channel() != ch){
                ch.writeAndFlush(new TextWebSocketFrame(text));
            }
        });
    }

    //客户端建立连接
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws  Exception{

        System.out.println("客户端建立连接 --- " + ctx.channel().id() );
        //添加channels
        clients.add(ctx.channel());
    }


    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        System.out.println("异常 --- " + ctx.channel().id());
        ctx.channel().close();
        clients.remove(ctx.channel());
    }



}

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

Kuronoks 发表于 2022-5-22 02:47
保存Session,open的时候保存对应用户的Session,close的时候删除
unmask 发表于 2022-5-22 09:13
用户下线,netty不是会触发handlerRemoved的吗?我还是不太懂你的具体需求...
头像被屏蔽
cmbslgn 发表于 2022-5-22 09:27
头像被屏蔽
xiadongming 发表于 2022-5-22 15:20
提示: 作者被禁止或删除 内容自动屏蔽
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-25 11:49

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表