HPROSE for java 过滤器 filter + 重写session

须新
2023-12-01


       因为给手机app写接口,接口采用的hprose方式,故无法使用容器自带session。

       现在想重写session,当用户没有登录的时候,别的接口都不给调用直接返回自定义错误,小马哥说,一言不合就抛异常,抛了异常后面的代码就不执行了。

      可是无法满足返回自定义错误信息的需求。

      于是使用redis重写了session,并且使用匿名内部类实现了filter的效果。

     现在将代码分享出来给大家。

      首先是重写session的。 如果你只想知道怎么搞过滤器那么往后看。

      

@Service("pubSessionServiceImpl")
public class PubSessionServiceImpl implements PubSessionService,InitializingBean
{
    /*
     *用于存储所有类型Session类型的失效时间
     */
    public static List<ServiceSession> sessionTypeExpiraTiontimelist =  new ArrayList<ServiceSession>();
    @Autowired
    private RedisCacheService<PubSession> redisCacheService;
    
    @Autowired
    private RedisCacheService<String> sessionIdCacheService;
    
    @Autowired
    private RedisCacheService<HashSet<String>> pubsessionIdSetService;
    
    @Autowired
    private ServiceSessionDao serviceSessionDao;

    
    
    /**
     * 注册session
     * 
     * @param PubSession pubSession
     * @param int sessionType
     */
    @Override
    public void recordSession(PubSession pubSession, int sessionType)
    {
        pubSession.setAttribute("sessionType", sessionType);
        pubSession.setAttribute("lastOperationTime", new Date().getTime());
        
        HashSet<String> pubsessionIdSet = new HashSet<String>();
        if ((!CheckUtils.isNullOrEmpty(pubsessionIdSetService.get(EConstant.PUBSESSIONIDSET)))
            && pubsessionIdSetService.get(EConstant.PUBSESSIONIDSET).size() > 0)
        {
            pubsessionIdSet = pubsessionIdSetService.get(EConstant.PUBSESSIONIDSET);
        }
        pubsessionIdSet.add(pubSession.getSessionId());
        pubsessionIdSetService.put(EConstant.PUBSESSIONIDSET, pubsessionIdSet);
        
        redisCacheService.put("pmsservice:pubsession:" + pubSession.getSessionId(), pubSession);
    }
    /**
     * 获取session
     * 
     * @param String sessionId
     * @return PubSession
     */
    @Override
    public PubSession getPubSession(String sessionId)
    {
        PubSession pubSession = redisCacheService.get("pmsservice:pubsession:" + sessionId);
        if(!CheckUtils.isNullOrEmpty(pubSession)){
            pubSession.setAttribute("lastOperationTime", new Date().getTime());
            redisCacheService.put("pmsservice:pubsession:" + pubSession.getSessionId(), pubSession);
        }
        return pubSession;
    }
    /**
     * 更新session
     * 
     * @param PubSession pubSession
     */
    @Override
    public void updatePubSession(PubSession pubSession)
    {
        pubSession.setAttribute("lastOpoeratorTime", new Date().getTime());
        redisCacheService.put("pmsservice:pubsession:" + pubSession.getSessionId(), pubSession);
    }
    /**
     * 销毁session
     * 
     * @param String sessionId
     */
    @Override
    public void destroySession(String sessionId)
    {
        HashSet<String> pubsessionIdSet = pubsessionIdSetService.get(EConstant.PUBSESSIONIDSET);
        pubsessionIdSet.remove(sessionId);
        pubsessionIdSetService.put(EConstant.PUBSESSIONIDSET, pubsessionIdSet);
        redisCacheService.remove("pmsservice:pubsession:" + sessionId);
    }
    @Override
    public void afterPropertiesSet()
        throws Exception
    {
        this.init(new ServiceSession());
    }
    public void init(ServiceSession serviceSession)
    {
        sessionTypeExpiraTiontimelist = serviceSessionDao.findForList(serviceSession);
    }
    
}
        其中有一个redisCacheservice 也给大家共享出来。 这个写的不是太好,大家见笑了

    

@Service("redisCacheServiceImpl")
public class RedisCacheServiceImpl<E> implements RedisCacheService<E>
{
    /**
     * redisTemplate
     */
    @Resource(name = "jedisTemplate")
    private RedisTemplate<String, E> redisTemplate;
    
    @Resource(name = "stringRedisTemplate")
    private RedisTemplate<String, String> strRedisTemplate;
    
    @Override
    public void put(String key, E obj)
    {
        ValueOperations<String, E> valueOper = redisTemplate.opsForValue();
        valueOper.set(key, obj);
    }
    
    @Override
    public E get(String key)
    {
        ValueOperations<String, E> valueOper = redisTemplate.opsForValue();
        return valueOper.get(key);
    }
    
    @Override
    public List<E> getList(String key)
    {
        ListOperations<String, E> valueOper = redisTemplate.opsForList();
        return valueOper.range(key, 0, -1);
    }
    
    @Override
    public Long remove(final String key)
    {
        if (!exists(key))
        {
            return 0l;
        }
        return redisTemplate.execute(new RedisCallback<Long>()
        {
            @Override
            public Long doInRedis(RedisConnection connection)
                throws DataAccessException
            {
                long result = 0;
                result = connection.del(key.getBytes());
                return result;
            }
        });
    }
    
    @Override
    public boolean exists(final String key)
    {
        return redisTemplate.execute(new RedisCallback<Boolean>()
        {
            public Boolean doInRedis(RedisConnection connection)
                throws DataAccessException
            {
                return connection.exists(key.getBytes());
            }
        });
    }
    
    @Override
    public void addSet(String key, E[] objs)
    {
        ListOperations<String, E> list = redisTemplate.opsForList();
        for(E obj : objs)
        {
            list.leftPush(key, obj);
        }
    }
    
    @SuppressWarnings("unchecked")
    @Override
    public void addSet(String key, Set<E> list)
    {
        this.addSet(key, (E[])list.toArray());
    }
    
    @SuppressWarnings("unchecked")
    @Override
    public void addSet(String key, List<E> objSet)
    {
        this.addSet(key, (E[])objSet.toArray());
    }
    
   
    
    @Override
    public boolean addStr(final String key, final String value)
    {
        boolean result = strRedisTemplate.execute(new RedisCallback<Boolean>()
        {
            public Boolean doInRedis(RedisConnection connection)
                throws DataAccessException
            {
                RedisSerializer<String> serializer = getRedisSerializer();
                byte[] keys = serializer.serialize(key);
                byte[] values = serializer.serialize(value);
                return connection.setNX(keys, values);
            }
        });
        return result;
    }
    
    @Override
    public boolean updateStr(final String key, final String value)
    {
        if (!this.exists(key))
        {
            return this.addStr(key, value);
        }
        return strRedisTemplate.execute(new RedisCallback<Boolean>()
        {
            public Boolean doInRedis(RedisConnection connection)
                throws DataAccessException
            {
                RedisSerializer<String> serializer = getRedisSerializer();
                byte[] keys = serializer.serialize(key);
                byte[] values = serializer.serialize(value);
                connection.set(keys, values);
                return true;
            }
        });
    }
    
    @Override
    public String getStr(final String key)
    {
        String result = strRedisTemplate.execute(new RedisCallback<String>()
        {
            public String doInRedis(RedisConnection connection)
                throws DataAccessException
            {
                RedisSerializer<String> serializer = getRedisSerializer();
                byte[] keys = serializer.serialize(key);
                byte[] values = connection.get(keys);
                if (values == null)
                {
                    return null;
                }
                String value = serializer.deserialize(values);
                return value;
            }
        });
        return result == null ? EConstant.EMPTY : result;
    }
    
    /**
     * 获取 RedisSerializer
     * 
     * @return RedisSerializer
     */
    private RedisSerializer<String> getRedisSerializer()
    {
        return strRedisTemplate.getStringSerializer();
    }

    @Override
    public Long removeFuzzy(final String key)
    {
        return redisTemplate.execute(new RedisCallback<Long>()
        {
            @Override
            public Long doInRedis(RedisConnection connection)
                throws DataAccessException
            {
                long result = 0;
                Set<byte[]> keys = connection.keys(key.getBytes());
                for(byte[] keySet : keys){
                    result += connection.del(keySet);
                }
                return result;
            }
        });
    }

    @Override
    public Set<E> getSet(String key)
    {
        // TODO Auto-generated method stub
        return null;
    }
}

我这里有一个用户是否绑定房间的判断,和ssoid(有的叫token或者sessionId)是否能查到对应的用户。

来判断是否往下执行业务方法,如果没登录ssoid查询到的session里面的user为null,直接返回错误。

用以下的类来接收用户信息和错误信息。

/**
 * 用户基础数据校验结果
 * 
 * @author wanglei
 * @version [版本号, 2016年10月20日]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
class UserCheckInfo
{
    /**
     * 检查结果
     */
    private boolean checkResult;
    
    /**
     * 错误信息
     */
    private String resultMsg;
    
    /**
     * 用户中心的用户
     */
    private UCenterUser centerUser;
    
    public UserCheckInfo(boolean checkResult, String resultMsg, UCenterUser centerUser)
    {
        this.checkResult = checkResult;
        this.resultMsg = resultMsg;
        this.centerUser = centerUser;
    }
    
    public boolean isCheckResult()
    {
        return checkResult;
    }
    
    public String getResultMsg()
    {
        return resultMsg;
    }
    
    public UCenterUser getCenterUser()
    {
        return centerUser;
    }
}
用以下方法来做检查
/**
     * 获取usercheck信息 主要是检查是否绑定了房间和是否登陆
     * 
     * @param ssoId ssoId
     * @param isCheckBindUnit 是否检查绑定房间, true检查 false不检查
     * @return 如果ssoId在用户中心验证m欸有登陆用户,则返回错误,如果isCheckBindUnit=true 并且没有绑定房间会返回false 其他情况返回true
     */
    private UserCheckInfo getUserCheckInfo(String ssoId, boolean isCheckBindUnit)
    {
        UCenterUser centerUser = this.getUserInfo(ssoId);
        
        if (!CheckUtils.isNullOrEmpty(centerUser))
        {
            if (isCheckBindUnit && CheckUtils.isNullOrEmpty(centerUser.getSysBindingUnit()))
            {
                return new UserCheckInfo(false, this.getErrorJson("该用户没有绑定默认房间"), centerUser);
            }
        }
        else
        {
            return new UserCheckInfo(false, this.getErrorJson("ssoid验证失败"), null);
        }
        return new UserCheckInfo(true, null, centerUser);
    }

最后是业务接口

interface WYServiceFun
{
    String service(Map<String, Object> paramMap, UCenterUser centerUser, String ssoId);
}<span style="white-space:pre">																											</span>

然后是充当filter的方法,这个方法没有使用到usercheckinfo的错误信息我一会修复下。

/**
     * 执行业务方法,如果验证出了问题,出了异常 直接返回code 300
     * 
     * @param paramMap 参数map
     * @param isCheckBindUnit 是否检查绑定房间
     * @param serviceFun WYServiceFun实现类,里面只有一个服务接口
     * @return 直接返回此数据即可
     */
    private String exeService(Map<String, Object> paramMap, boolean isCheckBindUnit, WYServiceFun serviceFun)
    {
        String ssoId = StringUtil.toString(paramMap.get("sso_sid"));
        // 获取用户信息
        UserCheckInfo checkInfo = this.getUserCheckInfo(ssoId, false);
        try
        {
            
            if (checkInfo.isCheckResult())
            {
                return serviceFun.service(paramMap, checkInfo.getCenterUser(), ssoId);
            }
        }
        catch (Exception e)
        {
            e.getStackTrace();
            LOG.error(null, e);
            return getReturnClientJson(EConstant.ERROR_CODE, new HashMap<String, Object>());
        }
        return getReturnClientJson(EConstant.ERROR_CODE, new HashMap<String, Object>());
    }

写业务的时候这么写

如果用户没有登录exeService方法可以直接返回错误。

有没有感觉像是在写js的回调方法。

 /**
     * 发送验证码
     * @param paramMap sso_sid phone 房主的手机号 identity 绑定类型
     * @return state 300代表输入的手机号没有查询到他底下有相关的房间 200代表验证码发送成功
     */
    public String sendVCode(Map<String, Object> paramMap)
    {
        return exeService(paramMap, false, new WYServiceFun()
        {
            public String service(Map<String, Object> paramMap, UCenterUser centerUser, String ssoId)
            {
                PubSession pubSession = pubSessionService.getPubSession(ssoId);
                List<Map<String, Object>> unitInfoList = getUserUnitInfoList(paramMap,null);
                // 如果这个手机号没有找到
                if (unitInfoList.isEmpty())
                {
                    return getReturnClientJson(EConstant.ERROR_CODE, (Map<String, Object>)MapUtils.getMapFromArgs(new Object[]{"data","notFindUnit"}));
                }
                pubSession.setAttribute("unitInfoList", unitInfoList);
                // 还没写完,将就着看吧,写着代码突然想写博客的
                return getReturnClientJson(EConstant.SUCCESS_CODE, list2Map(unitInfoList));
            }
        });
        
    }


 类似资料: