基於 Spring Cloud 的微服務腳手架

Grey Zeng發表於2022-12-18

基於 Spring Cloud 的微服務腳手架

作者: Grey

原文地址:

部落格園:基於 Spring Cloud 的微服務腳手架

CSDN:基於 Spring Cloud 的微服務腳手架

本文主要介紹了基於 Spring Cloud Finchley 和 Spring Boot 2.0.x 版本的微服務腳手架的搭建和關鍵程式碼說明,參考了重新定義 Spring Cloud 實戰

相關元件和版本

元件 版本 備註
Spring Boot 2.0.9.RELEASE -
Spring Cloud Finchley.SR4 -
JDK 1.8 高於JDK 1.8會有相容性問題
Eureka 基於 Spring Cloud F 版 註冊中心
Zuul 基於 Spring Cloud F 版 閘道器
hystrix 基於 Spring Cloud F 版 熔斷器
Spring Cloud Config 基於 Spring Cloud F 版 配置中心
Spring Cloud OpenFeign 基於 Spring Cloud F 版 用於服務之間的通訊,使用 HTTP 協議

架構圖如下

img

啟動方式,按如下順序啟動

  • skeleton-eureka-server

  • skeleton-config-server

  • skeleton-zuul-server

  • skeleton-hystrix-dashboard

  • skeleton-user-service

  • skeleton-data-service

測試三個請求,需要帶上x-customs-user引數,否則會被攔截器攔截提示無許可權。

GET http://localhost:7777/sc-user-service/getProviderData
Accept: application/json
x-customs-user: Spring

返回

HTTP/1.1 200 
Date: Sat, 17 Dec 2022 11:09:48 GMT
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked

[
  "Beijing Company",
  "Shanghai Company",
  "Shenzhen Company"
]
GET http://localhost:7777/sc-user-service/getContextUserId
Accept: application/json
x-customs-user: Spring

返回

HTTP/1.1 200 
Date: Sat, 17 Dec 2022 11:09:29 GMT
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked

Spring
GET http://localhost:7777/sc-user-service/getDefaultUser
Accept: application/json
x-customs-user: Spring

返回

HTTP/1.1 200 
Date: Sat, 17 Dec 2022 11:08:54 GMT
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked

zhudeming-dev

核心程式碼說明
上述三個方法在成功呼叫之前,都需要做鑑權邏輯

使用者鑑權部分,實現HandlerInterceptor即可,在preHandle中處理鑑權邏輯


public class UserContextInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse respone, Object arg2) throws Exception {
        User user = new User(HttpConvertUtil.httpRequestToMap(request));
        if (StringUtils.isEmpty(user.getUserId()) && StringUtils.isEmpty(user.getUserName())) {
            log.error("the user is null, please access from gateway or check user info");
            return false;
        }
        UserContextHolder.set(user);
        return true;
    }
……
}

上述三個請求分別代表三種不同的邏輯處理方式,第一個請求首先是到 sc-user-service 服務,sc-user-service 透過 RestTemplate 方式直接呼叫 data-service 服務,核心程式碼如下


@Component
public class UserService implements IUserService {
  ……
    @Override
    public List<String> getProviderData() {
        List<String> result = restTemplate.getForObject("http://sc-data-service/getProviderData", List.class);
        return result;
    }
}

第二個方法getContextUserId是獲取當前上下文使用者,使用的是 Spring Cloud 自帶的 Feign 客戶端,請求 data-service,Feign 請求會被攔截,並把當前使用者存在 ThreadLocal 中, data-service 從ThreadLocal 中拿到當前使用者資訊返回即可, 核心程式碼如下

public class UserContextInterceptor implements HandlerInterceptor {
    private static final Logger log = LoggerFactory.getLogger(UserContextInterceptor.class);

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse respone, Object arg2) throws Exception {
        User user = new User(HttpConvertUtil.httpRequestToMap(request));
        if (StringUtils.isEmpty(user.getUserId()) && StringUtils.isEmpty(user.getUserName())) {
            log.error("the user is null, please access from gateway or check user info");
            return false;
        }
        // 存當前使用者
        UserContextHolder.set(user);
        return true;
    }
}

其中UserContextHolder.set(user)就是把當前使用者存在ThreadLocal中。

public class UserContextHolder {
 
    public static ThreadLocal<User> context = new ThreadLocal<User>();

    public static User currentUser() {
        return context.get();
    }

    public static void set(User user) {
        context.set(user);
    }

    public static void shutdown() {
        context.remove();
    }

}

第三個方法getDefaultUser同樣是 sc-user-service 透過 Feign 客戶端訪問 data-service,但是使用者是透過配置中心來獲取(即:skeleton-config-server 專案作用)

@Component
@ConfigurationProperties(prefix = "cn.springcloud.book")
public class DataConfig {

    private String defaultUser;

 public String getDefaultUser() {
  return defaultUser;
 }

 public void setDefaultUser(String defaultUser) {
  this.defaultUser = defaultUser;
 }
    
}
server:
  port: 9090
spring:
  cloud:
    config:
      server:
        git:
          uri: https://gitee.com/zhudeming/spring-cloud-config.git
          #username:
          #password:
          search-paths: SC-BOOK-CONFIG
  application:
    name: sc-configserver

程式碼地址

microservice-skeleton, tag: finchley.sr4

參考資料

重新定義 Spring Cloud 實戰

相關文章