日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

带有Spring Boot和Spring Cloud的Java微服务

發布時間:2023/12/3 java 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 带有Spring Boot和Spring Cloud的Java微服务 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

朋友不允許朋友寫用戶身份驗證。 厭倦了管理自己的用戶? 立即嘗試Okta的API和Java SDK。 在幾分鐘之內即可對任何應用程序中的用戶進行身份驗證,管理和保護。

Java是開發微服務架構時使用的一種很棒的語言。 實際上,我們行業中的一些知名人士都在使用它。 您是否聽說過Netflix,Amazon或Google? 那eBay,Twitter和LinkedIn呢? 是的,處理不可思議流量的主要公司正在使用Java來實現。

在Java中實現微服務架構并不適合每個人。 因此,通常不需要實現微服務。 大多數公司這樣做都是為了擴展人員,而不是系統。 如果要擴大人員規模,雇用Java開發人員是做到這一點的最佳方法之一。 畢竟,比起其他大多數語言,流利的Java開發人員更多-盡管JavaScript似乎正在Swift趕上來!

Java生態系統具有一些完善的模式來開發微服務架構。 如果您熟悉Spring,則可以在家中使用Spring Boot和Spring Cloud進行開發。 由于這是上手最快的方法之一,所以我認為我將帶您快速入門。

使用Spring Cloud和Spring Boot創建Java微服務

在我的大多數教程中,我向您展示了如何從頭開始構建所有內容。 今天,我想采用一種不同的方法,并與您一起完成一個預先構建的示例。 希望這會更短并且更容易理解。

您可以從克隆@ oktadeveloper / java-microservices-examples存儲庫開始。

git clone https://github.com/oktadeveloper/java-microservices-examples.git cd java-microservices-examples/spring-boot+cloud

在spring-boot+cloud目錄中,有三個項目:

  • Discovery-service :Netflix Eureka服務器,用于服務發現。
  • car-service :一個簡單的Car Service,使用Spring Data REST來提供汽車的REST API。
  • api-gateway :具有/cool-cars端點的API網關,該端點與car-service進行對話并過濾出不涼爽的汽車(當然,在我看來)。

我使用start.spring.io的 REST API和HTTPie創建了所有這些應用程序。

http https://start.spring.io/starter.zip javaVersion==11 \artifactId==discovery-service name==eureka-service \dependencies==cloud-eureka-server baseDir==discovery-service | tar -xzvf -http https://start.spring.io/starter.zip \artifactId==car-service name==car-service baseDir==car-service \dependencies==actuator,cloud-eureka,data-jpa,h2,data-rest,web,devtools,lombok | tar -xzvf -http https://start.spring.io/starter.zip \artifactId==api-gateway name==api-gateway baseDir==api-gateway \dependencies==cloud-eureka,cloud-feign,data-rest,web,cloud-hystrix,lombok | tar -xzvf -

帶有Java 11+的Spring Microservices

為了使discovery-service在Java 11上運行,我必須添加對JAXB的依賴

<dependency><groupId>org.glassfish.jaxb</groupId><artifactId>jaxb-runtime</artifactId> </dependency>

其他兩個應用程序可以在Java 11上開箱即用地正常運行,而無需更改依賴項。

Netflix Eureka的Java服務發現

discovery-service的配置與大多數Eureka服務器相同。 它在其主類和設置其端口并關閉發現的屬性上作為@EnableEurekaServer批注。

server.port=8761 eureka.client.register-with-eureka=false

car-service和api-gateway項目以類似的方式配置。 兩者都定義了唯一的名稱,并且car-service配置為在端口8090上運行,因此它與8080不沖突。
汽車服務/src/main/resources/application.properties

server.port=8090 spring.application.name=car-service

api-gateway / src / main / resources / application.properties

spring.application.name=api-gateway

兩個項目中的主類都使用@EnableDiscoveryClient注釋。

使用Spring Data REST構建Java微服務

car-service提供了REST API,可讓您CRUD(創建,讀取,更新和刪除)汽車。 當應用程序使用ApplicationRunner bean加載時,它將創建一組默認的汽車。
car-service / src / main / java / com / example / carservice / CarServiceApplication.java

package com.example.carservice;import lombok.Data; import lombok.NoArgsConstructor; import lombok.NonNull; import org.springframework.boot.ApplicationRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.context.annotation.Bean; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.rest.core.annotation.RepositoryRestResource;import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import java.util.stream.Stream;@EnableDiscoveryClient @SpringBootApplication public class CarServiceApplication {public static void main(String[] args) {SpringApplication.run(CarServiceApplication.class, args);}@BeanApplicationRunner init(CarRepository repository) {return args -> {Stream.of("Ferrari", "Jaguar", "Porsche", "Lamborghini", "Bugatti","AMC Gremlin", "Triumph Stag", "Ford Pinto", "Yugo GV").forEach(name -> {repository.save(new Car(name));});repository.findAll().forEach(System.out::println);};} }@Data @NoArgsConstructor @Entity class Car {public Car(String name) {this.name = name;}@Id@GeneratedValueprivate Long id;@NonNullprivate String name; }@RepositoryRestResource interface CarRepository extends JpaRepository<Car, Long> { }

API網關中的Spring Cloud + Feign和Hystrix

Feign使編寫Java HTTP客戶端更加容易。 Spring Cloud使得僅需幾行代碼即可創建Feign客戶端。 Hystrix可以為您的Feign客戶端添加故障轉移功能,從而使它們更具彈性。

api-gateway使用Feign和Hystrix與下游car-service并在不可用時故障轉移到fallback()方法。 它還公開了一個/cool-cars終結點,該終結點過濾掉了您可能不想擁有的汽車。
api-gateway / src / main / java / com / example / apigateway / ApiGatewayApplication.java

package com.example.apigateway;import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; import lombok.Data; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.netflix.zuul.EnableZuulProxy; import org.springframework.cloud.openfeign.EnableFeignClients; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.hateoas.Resources; import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController;import java.util.ArrayList; import java.util.Collection; import java.util.stream.Collectors;@EnableFeignClients @EnableCircuitBreaker @EnableDiscoveryClient @EnableZuulProxy @SpringBootApplication public class ApiGatewayApplication {public static void main(String[] args) {SpringApplication.run(ApiGatewayApplication.class, args);} }@Data class Car {private String name; }@FeignClient("car-service") interface CarClient {@GetMapping("/cars")@CrossOriginResources<Car> readCars(); }@RestController class CoolCarController {private final CarClient carClient;public CoolCarController(CarClient carClient) {this.carClient = carClient;}private Collection<Car> fallback() {return new ArrayList<>();}@GetMapping("/cool-cars")@CrossOrigin@HystrixCommand(fallbackMethod = "fallback")public Collection<Car> goodCars() {return carClient.readCars().getContent().stream().filter(this::isCool).collect(Collectors.toList());}private boolean isCool(Car car) {return !car.getName().equals("AMC Gremlin") &&!car.getName().equals("Triumph Stag") &&!car.getName().equals("Ford Pinto") &&!car.getName().equals("Yugo GV");} }

運行Java微服務架構

如果您在單獨的終端窗口中使用./mvnw運行所有這些服務, ./mvnw可以導航至http://localhost:8761并查看它們是否已在Eureka中注冊。

如果您在瀏覽器中導航到http://localhost:8080/cool-bars ,您將被重定向到Okta。 什么啊

使用OAuth 2.0和OIDC保護Java微服務

我已經使用OAuth 2.0和OIDC在此微服務架構中配置了安全性。 兩者有什么區別? OIDC是提供身份的OAuth 2.0的擴展。 它還提供發現功能,因此可以從單個URL(稱為issuer )發現所有不同的OAuth 2.0端點。

如何為所有這些微服務配置安全性? 我很高興你問!

我在api-gateway和car-service的pom.xml中添加了Okta的Spring Boot啟動器:

<dependency><groupId>com.okta.spring</groupId><artifactId>okta-spring-boot-starter</artifactId><version>1.2.0</version> </dependency>

然后,我在Okta創建了一個新的OIDC應用,并配置了授權代碼流。 如果要查看運行中的所有內容,則需要完成以下步驟。

在Okta中創建Web應用程序

登錄到您的1563開發者帳戶(或者注冊 ,如果你沒有一個帳戶)。

  • 在“ 應用程序”頁面上,選擇添加應用程序
  • 在“創建新應用程序”頁面上,選擇“ Web”
  • 為您的應用提供一個令人難忘的名稱,將http://localhost:8080/login/oauth2/code/okta為登錄重定向URI,選擇刷新令牌 (除了授權代碼 ),然后點擊完成
  • 將發行者(位于API > 授權服務器下 ),客戶端ID和客戶端密鑰復制到兩個項目的application.properties中。

    okta.oauth2.issuer=$issuer okta.oauth2.client-id=$clientId okta.oauth2.client-secret=$clientSecret

    下一節中的Java代碼已經存在,但是我認為我已經對其進行了解釋,以便您了解正在發生的事情。

    為OAuth 2.0登錄和資源服務器配置Spring Security

    在ApiGatewayApplication.java ,我添加了Spring Security配置以啟用OAuth 2.0登錄并將網關作為資源服務器。

    @Configuration static class OktaOAuth2WebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {// @formatter:offhttp.authorizeRequests().anyRequest().authenticated().and().oauth2Login().and().oauth2ResourceServer().jwt();// @formatter:on} }

    在此示例中未使用資源服務器配置,但是我添加了它,以防您想將移動應用程序或SPA連接到此網關。 如果您使用的是SPA,則還需要添加一個bean來配置CORS。

    @Bean public FilterRegistrationBean<CorsFilter> simpleCorsFilter() {UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();CorsConfiguration config = new CorsConfiguration();config.setAllowCredentials(true);config.setAllowedOrigins(Collections.singletonList("*"));config.setAllowedMethods(Collections.singletonList("*"));config.setAllowedHeaders(Collections.singletonList("*"));source.registerCorsConfiguration("/**", config);FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>(new CorsFilter(source));bean.setOrder(Ordered.HIGHEST_PRECEDENCE);return bean; }

    如果確實使用像這樣的CORS過濾器,建議您將源,方法和標頭更改為更具體,以提高安全性。

    CarServiceApplication.java僅配置為資源服務器,因為不希望直接訪問它。

    @Configuration static class OktaOAuth2WebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {// @formatter:offhttp.authorizeRequests().anyRequest().authenticated().and().oauth2ResourceServer().jwt();// @formatter:on} }

    為了使API網關能夠訪問Car Service,我在API網關項目中創建了UserFeignClientInterceptor.java 。
    > api-gateway / src / main / java / com / example / apigateway / UserFeignClientInterceptor.java

    package com.example.apigateway;import feign.RequestInterceptor; import feign.RequestTemplate; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService; import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; import org.springframework.security.oauth2.core.OAuth2AccessToken; import org.springframework.stereotype.Component;@Component public class UserFeignClientInterceptor implements RequestInterceptor {private static final String AUTHORIZATION_HEADER = "Authorization";private static final String BEARER_TOKEN_TYPE = "Bearer";private final OAuth2AuthorizedClientService clientService;public UserFeignClientInterceptor(OAuth2AuthorizedClientService clientService) {this.clientService = clientService;}@Overridepublic void apply(RequestTemplate template) {Authentication authentication = SecurityContextHolder.getContext().getAuthentication();OAuth2AuthenticationToken oauthToken = (OAuth2AuthenticationToken) authentication;OAuth2AuthorizedClient client = clientService.loadAuthorizedClient(oauthToken.getAuthorizedClientRegistrationId(),oauthToken.getName());OAuth2AccessToken accessToken = client.getAccessToken();template.header(AUTHORIZATION_HEADER, String.format("%s %s", BEARER_TOKEN_TYPE, accessToken.getTokenValue()));} }

    我在ApiGatewayApplication.java其配置為RequestInterceptor :

    @Bean public RequestInterceptor getUserFeignClientInterceptor(OAuth2AuthorizedClientService clientService) {return new UserFeignClientInterceptor(clientService); }

    并且,我在api-gateway/src/main/resources/application.properties添加了兩個屬性,因此Feign支持Spring Security。

    feign.hystrix.enabled=true hystrix.shareSecurityContext=true

    請參閱在啟用安全性的情況下運行的Java微服務

    使用./mvnw在單獨的終端窗口中運行所有應用程序,或者根據需要在您的IDE中運行。

    為了簡化在IDE中的運行,根目錄中有一個聚合器pom.xml 。 如果安裝了IntelliJ IDEA的命令行啟動器 , idea pom.xml需要運行idea pom.xml 。

    導航到http://localhost:8080/cool-cars ,您將被重定向到Okta進行登錄。

    輸入您的Okta開發人員帳戶的用戶名和密碼,您應該會看到涼爽的汽車清單。

    如果您到此為止并成功運行了示例應用程序,那么恭喜! 你真酷! 😎

    使用Netflix Zuul和Spring Cloud代理路由

    Netflix Zuul是您可能希望在微服務體系結構中使用的另一個便捷功能。 Zuul是一項網關服務,可提供動態路由,監視,彈性等。

    為了添加Zuul,我將其作為依賴項添加到api-gateway/pom.xml :

    <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-zuul</artifactId> </dependency>

    然后,我將@EnableZuulProxy添加到ApiGatewayApplication類。

    import org.springframework.cloud.netflix.zuul.EnableZuulProxy;@EnableZuulProxy @SpringBootApplication public class ApiGatewayApplication {... }

    為了將訪問令牌傳遞到代理路由,我創建了一個AuthorizationHeaderFilter類,該類擴展了ZuulFilter 。

    package com.example.apigateway;import com.netflix.zuul.ZuulFilter; import com.netflix.zuul.context.RequestContext; import org.springframework.core.Ordered; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService; import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; import org.springframework.security.oauth2.core.OAuth2AccessToken; import org.springframework.security.oauth2.core.oidc.OidcUserInfo;import java.util.Optional;import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;public class AuthorizationHeaderFilter extends ZuulFilter {private final OAuth2AuthorizedClientService clientService;public AuthorizationHeaderFilter(OAuth2AuthorizedClientService clientService) {this.clientService = clientService;}@Overridepublic String filterType() {return PRE_TYPE;}@Overridepublic int filterOrder() {return Ordered.LOWEST_PRECEDENCE;}@Overridepublic boolean shouldFilter() {return true;}@Overridepublic Object run() {RequestContext ctx = RequestContext.getCurrentContext();Optional<String> authorizationHeader = getAuthorizationHeader();authorizationHeader.ifPresent(s -> ctx.addZuulRequestHeader("Authorization", s));return null;}private Optional<String> getAuthorizationHeader() {Authentication authentication = SecurityContextHolder.getContext().getAuthentication();OAuth2AuthenticationToken oauthToken = (OAuth2AuthenticationToken) authentication;OAuth2AuthorizedClient client = clientService.loadAuthorizedClient(oauthToken.getAuthorizedClientRegistrationId(),oauthToken.getName());OAuth2AccessToken accessToken = client.getAccessToken();if (accessToken == null) {return Optional.empty();} else {String tokenType = accessToken.getTokenType().getValue();String authorizationHeaderValue = String.format("%s %s", tokenType, accessToken.getTokenValue());return Optional.of(authorizationHeaderValue);}} }

    您可能會注意到, getAuthorizationHeader()方法中的代碼與UserFeignClientInterceptor的代碼非常相似。 由于只有幾行,因此我選擇不將其移至實用程序類。 Feign攔截器用于@FeignClient ,而Zuul過濾器用于Zuul代理的請求。

    為了使Spring Boot和Zuul知道此過濾器,我在主應用程序類中將其注冊為Bean。

    public AuthorizationHeaderFilter authHeaderFilter(OAuth2AuthorizedClientService clientService) {return new AuthorizationHeaderFilter(clientService); }

    為了將請求從API網關代理到汽車服務,我添加了到api-gateway/src/main/resources/application.properties路由。

    zuul.routes.car-service.path=/cars zuul.routes.car-service.url=http://localhost:8090zuul.routes.home.path=/home zuul.routes.home.url=http://localhost:8090zuul.sensitive-headers=Cookie,Set-Cookie

    我在/home路線的car-service項目中添加了HomeController 。

    package com.example.carservice;import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController;import java.security.Principal;@RestController public class HomeController {private final static Logger log = LoggerFactory.getLogger(HomeController.class);@GetMapping("/home")public String howdy(Principal principal) {String username = principal.getName();JwtAuthenticationToken token = (JwtAuthenticationToken) principal;log.info("claims: " + token.getTokenAttributes());return "Hello, " + username;} }

    確認您的Zuul路線工作

    由于這些更改已經在您克隆的項目中,因此您應該能夠在瀏覽器中查看https://localhost:8080/cars和http://localhost:8080/home 。

    Spring Cloud Config呢?

    在此示例中您可能已經注意到的一件事是,您必須在每個應用程序中配置OIDC屬性。 如果您有500個微服務,這可能是一個真正的痛苦。 是的,您可以將它們定義為環境變量,這樣就可以解決問題。 但是,如果您具有使用不同OIDC客戶端ID的不同微服務堆棧,則此方法將很困難。

    Spring Cloud Config是一個為分布式系統提供外部化配置的項目。 與其在本示例中添加它,不如在以后的教程中介紹它。

    那Kotlin呢?

    我用Java寫這篇文章是因為它是Java生態系統中最受歡迎的語言。 然而,根據RedMonk從2019年1月開始的編程語言排名, Kotlin呈上升趨勢 。

    至少在本季度,Kotlin大幅增長,而所有三個基于JVM的同行均下降。 實際上,Kotlin跳了這么遠,以至于它最終進入了第20名的前20名,并在此同時超越了Clojure(#24)和Groovy(#24)。 它仍然遠遠落后于Scala(#13),但在這些排名的歷史上,Kotlin的增長僅次于Swift,因此很有趣的發現下一輪還是接下來的比賽。

    Spring對Kotlin有很好的支持,您可以在start.spring.io上選擇它作為語言。 如果您希望我們使用Kotlin寫更多帖子,請在評論中告訴我們!

    刷新令牌的已知問題

    默認情況下,Okta的訪問令牌在一小時后過期。 這是預期的,并且在使用OAuth 2.0時建議使用短期訪問令牌。 刷新令牌的壽命通常更長(思考幾天或幾個月),并且可用于獲取新的訪問令牌。 使用Okta的Spring Boot啟動器時,這應該會自動發生,但事實并非如此。

    我配置了Okta組織,使其訪問令牌在五分鐘內到期。 您可以通過以下方法執行此操作:轉到“ API” >“ 授權服務器” >“ 訪問策略” ,單擊“ 默認策略” ,然后編輯其規則。 然后將訪問令牌的生存期從1小時更改為5分鐘。

    在瀏覽器中點擊http://localhost:8080/cool-cars ,您將被重定向到Okta進行登錄。 登錄后,您應該會看到汽車的JSON字符串。

    去做其他事情超過5分鐘。

    回來,刷新瀏覽器,您會看到[]而不是所有的汽車。

    我仍在努力解決此問題,一旦找到我將更新此帖子。 如果您碰巧知道解決方案,請告訴我!

    更新: Spring Security 5.1尚未自動刷新OAuth訪問令牌。 它應該在Spring Security 5.2中可用 。

    通過Spring Boot,Spring Cloud和微服務獲得更多樂趣

    我希望您喜歡這個關于如何使用Spring Boot和Spring Cloud構建Java微服務架構的教程。 您學習了如何以最少的代碼構建所有內容,然后使用Spring Security,OAuth 2.0和Okta將其配置為安全。

    您可以在GitHub上找到本教程中顯示的所有代碼。

    我們是此博客上的Spring Boot,Spring Cloud和微服務的忠實擁護者。 這是您可能會發現有趣的其他幾篇文章:

    • 帶有Spring Cloud Config和JHipster的Java微服務
    • Angular 8 + Spring Boot 2.2:立即構建一個CRUD應用程序!
    • Spring Boot登錄選項快速指南
    • 使用Spring Boot和Kubernetes構建微服務架構
    • 使用HTTPS和OAuth 2.0保護服務到服務的Spring微服務
    • 構建Spring微服務并對其進行Dockerize生產

    請在Twitter @oktadev上關注我們,并訂閱我們的YouTube頻道,以了解更多有關Spring Boot和微服務的知識。

    “帶有Spring Boot和Spring Cloud的Java微服務”最初于2019年5月22日發布在Okta開發者博客上

    朋友不允許朋友寫用戶身份驗證。 厭倦了管理自己的用戶? 立即嘗試Okta的API和Java SDK。 在幾分鐘之內即可對任何應用程序中的用戶進行身份驗證,管理和保護。

    翻譯自: https://www.javacodegeeks.com/2019/06/java-microservices-spring-boot-spring-cloud.html

    創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

    總結

    以上是生活随笔為你收集整理的带有Spring Boot和Spring Cloud的Java微服务的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。