dubbo服务之间传递用户信息

公司的服务需要拆分了,调研过后采用决定采用dubbo进行分布式服务拆分,在分布式的环境下,用户信息或者链路日志id需要在不同分布式服务之间传递,这里记录下实现方式:

首先导入依赖,pom如下

        
        
            org.apache.dubbo
            dubbo-spring-boot-starter
            2.7.12
        
        
        
            org.springframework.boot
            spring-boot-starter-web
            2.3.0.RELEASE
        
        
            org.projectlombok
            lombok
        
        
            com.alibaba
            fastjson
            1.2.70
        

其次创建全局用户对象

package com.example.demo.entity;

import lombok.Data;

import java.io.Serializable;

/**
 * 登录用户对象
 *
 * @author charles
 */
@Data
public class LoginUser implements Serializable {

    private static final long serialVersionUID = 1599282604110237521L;

    /**
     * 用户id
     */
    private Integer id;
    /**
     * 用户号码
     */
    private String userTel;
    /**
     * 用户名
     */
    private String userName;

}

创建保存用户信息对象的上下文

import com.example.demo.context;

import com.example.demo.entity.LoginUser;

public class UserContext {
    private static ThreadLocal userHolder = new ThreadLocal();

    public static void setUser(LoginUser loginUser) {
        userHolder.set(loginUser);
    }

    public static LoginUser getUser() {
        return userHolder.get();
    }

    public static void clear() {
        userHolder.remove();
    }
}

创建请求拦截器,获取用户信息填充进入上下文,这里我使用的是自己的方法,可以根据个人不同的情况进行调整

package com.example.demo.handle.interceptor;

import com.alibaba.fastjson.JSONObject;
import com.example.demo.context.UserContext;
import com.example.demo.entity.LoginUser;
import com.example.demo.util.TicketUtil;
import com.example.demo.util.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import redis.clients.jedis.JedisPool;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 拦截请求,获取用户信息填充上下文
 */
@Slf4j
public class UserInterceptor extends HandlerInterceptorAdapter {

    @Resource
    private JedisPool jedisPool;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        LoginUser user = new LoginUser();
        //注意这里是我自己的获取用户信息的方式,可以根据个人不同的情况进行调整
        // 获取ticket
        String ticket = TicketUtil.getTicketValue(request);
        // 不需要强制登录, 取当前用户信息有就返回无则不返回 不进行拦截
        if (StringUtils.isNotBlank(ticket)) {
            String jsonUserBo = RedisUtil.get(jedisPool, ticket);
            if (StringUtils.isNotBlank(jsonUserBo)) {
                LoginUser tmpUserBo = JSONObject.parseObject(jsonUserBo, LoginUser.class);
                BeanUtils.copyProperties(tmpUserBo, user);
            }
        }
        UserContext.setUser(user);
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        UserContext.clear();
    }

}

拦截器生效

package com.example.demo.config;

import  com.example.demo.interceptor.UserInterceptor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * @author charles
 */
@Slf4j
@Configuration
public class UserInfoConfiguration implements WebMvcConfigurer {


    @Bean
    public UserInterceptor userInterceptor() {
        return new UserInterceptor();
    }


    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 拦截器
      registry.addInterceptor(this.userInterceptor());
    }
}

接下来就是重点了,dubbo拦截器获取用户信息

首先是消费方拦截器

package com.example.demo.filter;

import com.alibaba.dubbo.common.extension.Activate;
import com.alibaba.dubbo.rpc.*;
import com.alibaba.fastjson.JSON;
import com.example.demo.context.UserContext;
import com.example.demo.entity.LoginUser;
import com.example.demo.constants.Constant;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

@Slf4j
@Activate(group = {Constant.CONSUMER})
public class UserInfoConsumerFilter implements Filter {

    @Override
    public Result invoke(Invoker invoker, Invocation invocation) throws RpcException {
        LoginUser user = UserContext.getUser();
        String userInfo;
        if (user != null) {
            userInfo = JSON.toJSONString(user);
        } else {
            userInfo = RpcContext.getContext().getAttachment(Constant.DUBBO_USER_KEY);
        }
        invocation.getAttachments().put(Constant.DUBBO_USER_KEY, StringUtils.isBlank(userInfo) ? JSON.toJSONString(new LoginUser()) : userInfo);
        return invoker.invoke(invocation);
    }
}

再然后是提供方拦截器

package com.example.demo.filter;

import com.alibaba.dubbo.common.extension.Activate;
import com.alibaba.dubbo.rpc.*;
import com.alibaba.fastjson.JSON;
import com.example.demo.context.UserContext;
import com.example.demo.entity.LoginUser;
import com.example.demo.constants.Constant;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

@Slf4j
@Activate(group = {Constant.PROVIDER})
public class UserInfoProviderFilter implements Filter {

    @Override
    public Result invoke(Invoker invoker, Invocation invocation) throws RpcException {
        String userInfo = RpcContext.getContext().getAttachment(Constant.DUBBO_USER_KEY);
        if (StringUtils.isBlank(userInfo)) {
            return invoker.invoke(invocation);
        }
        try {
            LoginUser user = JSON.parseObject(userInfo, LoginUser.class);
            UserContext.setUser(user);
            return invoker.invoke(invocation);
        } finally {
            UserContext.clear();
        }
    }
}

最后最最重要的一部,添加拦截器生效配置

 在如上图所示中添加如下所示配置使拦截器生效

userInfoConsumerFilter=com.example.demo.filter.UserInfoConsumerFilter
userInfoProviderFilter=com.example.demo.filter.UserInfoProviderFilter

你可能感兴趣的:(dubbo,java,dubbo)