Idea+maven+spring-cloud项目搭建系列--11-2 dubbo鉴权&日志记录&数据统一封装

前言:使用dubbo做为通信组件,如果接口需要鉴权,和日志记录需要怎样处理;

1 鉴权:

1.1 在bootstrap.yml 中定义过滤器:
dubbo.provider.filter: 过滤器的名字:
在这里插入图片描述
1.2 resources 目录下创建配置文件:
1) resources 创建目录:/META-INF/dubbo
2) 创建文件名字为org.apache.dubbo.rpc.Filter 的纯文本文件:
在这里插入图片描述
3) 定义过滤器:
过滤器名字=过滤器路径地址
在这里插入图片描述
4)服务提供端:DubboTokenFilter:

package org.lgx.bluegrass.bluegrasses.dubbofilter;

import org.apache.dubbo.rpc.*;
import org.apache.dubbo.rpc.filter.TokenFilter;
import org.lgx.bluegrass.api.common.dto.ResponseDTO;
import org.lgx.bluegrass.bluegrasses.util.ApplicationContextUtils;
import org.lgx.bluegrass.bluegrasses.util.RedisUtil;
import org.springframework.util.StringUtils;

/**
 * @Description TODO
 * @Date 2023/3/7 15:38
 * @Author lgx
 * @Version 1.0
 */
public class DubboTokenFilter extends TokenFilter {
    
    
    private RedisUtil redisUtil;
    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
    
    
        String isNeedToken = invoker.getUrl().getParameter(Constants.TOKEN_KEY);
        // 是否需要进行token 验证
        if (StringUtils.hasText(isNeedToken)) {
    
    
        	// 获取消费端传入的token
            String clientToken1 = invocation.getAttachment("dubbo_accesstoken");
            // 获取服务端的token
            String serverToken = getServerToken();
            //  token验证并且统一封装返回结果
            if (!serverToken.equals(clientToken1)) {
    
    
                // token 异常则直接封装ResponseDTO 并返回
                return AsyncRpcResult.newDefaultAsyncResult(ResponseDTO.defaultResponse("token illegal"), invocation);
                // 也可以抛出异常
                // Class<?> serviceType = invoker.getInterface();
                // throw new RpcException("Invalid token! Forbid invoke remote service " + serviceType + " method " + invocation.getMethodName() + "() from consumer " + RpcContext.getContext().getRemoteHost() + " to provider " + RpcContext.getContext().getLocalHost());

            }
        }
        return invoker.invoke(invocation);
    }
	// 从redis 中获取token 业务自行实现
    private String getServerToken() {
    
    
        if (null == redisUtil) {
    
    
            redisUtil = (RedisUtil) ApplicationContextUtils.getBean("redisUtil");
        }
        String accessToken = redisUtil.get("dubbo_accesstoken");
        return "1234";
    }
}

ResponseDTO 封装类:

// loomback 插件
@Data
@Accessors(chain = true)
public class ResponseDTO<T> implements Serializable {
    
    

    private static final long serialVersionUID = 3918877423924837166L;

    private int code = 200;
    private T body;
    private String msg;
    private boolean redirect = true;
    private List<ResponseMessage> messages;
    private List<String> message = new ArrayList<>();
    private int errNum;
    private String errorMsg;
    private Object errorObject;

    private boolean success = true;
    public static <T> ResponseDTO defaultResponse(T t) {
    
    
        return new ResponseDTO().setCode(BizHttpStatus.HTTP_STATUS_200.getStatus()).setBody(t);
    }
}

RedisUtil 封装类:stringRedisTemplate bean 自行配置实现

@Component
public class RedisUtil {
    
    

    @Autowired
    @Qualifier("stringRedisTemplate")
    private StringRedisTemplate redisTemplate;

    public void setRedisTemplate(StringRedisTemplate redisTemplate) {
    
    
        this.redisTemplate = redisTemplate;
    }

    public StringRedisTemplate getRedisTemplate() {
    
    
        return this.redisTemplate;
    }
    /**
     * 获取指定 key 的值
     *
     * @param key
     * @return
     */
    public String get(String key) {
    
    
        return redisTemplate.opsForValue().get(key);
    }
      /**
     * 设置指定 key 的值
     *
     * @param key
     * @param value
     */
    public void set(String key, String value) {
    
    
        redisTemplate.opsForValue().set(key, value);
    }
}

服务业务类提供者:
DubboTestServiceImpl:

import org.apache.dubbo.config.annotation.DubboService;
import org.lgx.bluegrass.api.common.dto.ResponseDTO;
import org.lgx.bluegrass.api.service.DubboTestService;

/**
 * @Description TODO
 * @Date 2023/2/23 15:50
 * @Author lgx
 * @Version 1.0
 */
// dubbo 服务暴露标识,token = "1234" 定义token验证标识
@DubboService(token = "1234")
public class DubboTestServiceImpl implements DubboTestService {
    
    
    @Override
    public ResponseDTO test(String token) {
    
    
        return ResponseDTO.defaultResponse("hello es"+ token);
    }
}

服务定义:DubboThreeService:

public interface DubboThreeService {
    
    
    ResponseDTO testOne(String token);
}

5) 消费端:同服务提供端1),2),3),相同 ,定义好过滤器
定义消费端token 填充:
DubboTokenFilter

public class DubboTokenFilter implements Filter {
    
    
    private RedisUtil redisUtil;

    @Override
    public Result invoke(Invoker<?> invoker, Invocation inv) throws RpcException {
    
    
        if (null == redisUtil) {
    
    
            Object obj = ApplicationContextUtils.getBean("redisUtil");
            if (null != obj){
    
    
                redisUtil = (RedisUtil) obj;
            }

        }
        String isNeedToken = invoker.getUrl().getParameter(Constants.TOKEN_KEY);
        // 是否需要进行token 验证
        if (StringUtils.hasText(isNeedToken)) {
    
    
        	// Constants.TOKEN_KEY, "1234", 便于跳过duboo 内置的token 验证
        	// "1234" 对应服务提供端业务实现类中定义的token @DubboService(token = "1234")
            inv.setAttachment(Constants.TOKEN_KEY, "1234");
            // 设置本次真正需要验证的token
            inv.setAttachment("dubbo_accesstoken", "1234qazwsxedc");
        }
        // 远程接口调用
        return invoker.invoke(inv);
    }
}

6 ) 消费端测试:

@RestController
public class DubboRpcController {
    
    
	 @DubboReference
    private DubboTestService  dubboTestService;
    @RequestMapping(value = "/dubbo-test", method = RequestMethod.GET)
    public String index(@RequestParam("token") String token) {
    
    
        return dubboTestService.test(token).toString();
    }
}

在这里插入图片描述

2 日志记录:

DubboAccessLogFilter:

import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.utils.ConfigUtils;
import org.apache.dubbo.rpc.*;
import org.apache.dubbo.rpc.support.AccessLogData;

import java.util.Date;

/**
 * @Description TODO
 * @Date 2023/3/8 16:48
 * @Author lgx
 * @Version 1.0
 */
public class DubboAccessLogFilter implements Filter {
    
    
    private static final Logger logger = LoggerFactory.getLogger(DubboAccessLogFilter.class);
    @Override
    public Result invoke(Invoker<?> invoker, Invocation inv) throws RpcException {
    
    
        try {
    
    
        	// 是否需要对改接口进行日志记录
            String accessLogKey = invoker.getUrl().getParameter("accesslog");
            if (ConfigUtils.isNotEmpty(accessLogKey)) {
    
    
            	// 请求的数据
                AccessLogData logData = this.buildAccessLogData(invoker, inv);
               // save log
                saveLog(logData);
            }
        } catch (Throwable var5) {
    
    
            logger.warn("Exception in AccessLogFilter of service(" + invoker + " -> " + inv + ")", var5);
        }

        return invoker.invoke(inv);
    }
	// 自行实现数据的保存
    private void saveLog(AccessLogData logData) {
    
    
	
    }

    private AccessLogData buildAccessLogData(Invoker<?> invoker, Invocation inv) {
    
    
        AccessLogData logData = AccessLogData.newLogData();
        logData.setServiceName(invoker.getInterface().getName());
        logData.setMethodName(inv.getMethodName());
        logData.setVersion(invoker.getUrl().getParameter("version"));
        logData.setGroup(invoker.getUrl().getParameter("group"));
        logData.setInvocationTime(new Date());
        logData.setTypes(inv.getParameterTypes());
        logData.setArguments(inv.getArguments());
        return logData;
    }
}

服务业务提供端:

// accesslog  日志记录标识
@DubboService(accesslog = "123")
public class DubboTestServiceTwoImpl implements DubboTestTwoService {
    
    
    @Override
    public ResponseDTO sayHello() {
    
    
        Map<String,Object> result = new HashMap<>(1<<2);
        result.put("data","Hello !");
        result.put("success",true);
        result.put("code",200);
        return ResponseDTO.defaultResponse(result);
    }
}

3 数据统一封装:

AppendedFilter:

import org.apache.dubbo.rpc.*;
import org.lgx.bluegrass.api.common.dto.ResponseDTO;

/**
 * @Description TODO
 * @Date 2023/3/7 11:00
 * @Author lgx
 * @Version 1.0
 */
public class AppendedFilter implements Filter {
    
    
    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
    
    
        Result result = invoker.invoke(invocation);
        Result appResponse = ((AsyncRpcResult) result).getAppResponse();
        Object data = appResponse.getValue();
        if (data instanceof ResponseDTO) {
    
    
            return result;
        }
        // 统一进行ResponseDTO 格式数据封装返回
        appResponse.setValue(ResponseDTO.defaultResponse(data));
        return result;
    }
}

参考:
1 调用拦截扩展;

猜你喜欢

转载自blog.csdn.net/l123lgx/article/details/129425686