سنة سعيدة متأخرة ، مجتمع الربيع!
مع بدء السنة المذهلة التالية من التطوير والتحسين في النظام البيئي Spring ، أود أن أشاطركم مثالًا محدثًا للتطبيق الذي يوضح جزءًا من التقدم المحرز في حافظة مشروع Spring فيما يتعلق بدعم نموذج البرمجة التفاعلي.
تم تحديث تطبيق BookStore Service Broker النموذجي لإظهار تكامل العديد من مشاريع Spring المختلفة ، بما في ذلك Spring Cloud Open Service Broker و Spring Data و Spring Security و Spring HATEOAS ، وبالطبع Spring WebFlux و Spring Boot. جميع هذه المشاريع لديها إصدارات من GA ، بما في ذلك الدعم التفاعلي وجاهز للإنتاج في التطبيقات والخدمات الخاصة بك.
ترجم بواسطة
middle_javaللبساطة ، يعمل التطبيق نفسه كسمسار وكمثيل للخدمة. على الرغم من أن الوسطاء أنفسهم يلتزمون بـ Open Service Broker API ، فإن الخدمات التي يقدمونها محددة بشكل أكثر تجريدية. الخدمات يمكن أن تفعل أو أن تكون أي شيء تقريبا. في حالة تطبيقنا ، يتم إنشاء مجموعة جديدة من بيانات الاعتماد لكل مثيل من الخدمة. يتم استخدام بيانات الاعتماد هذه في الطلبات إلى مثيل الخدمة. يتم تعيين عنوان URL لمثيل الخدمة الجديد على نفس المسار إلى الوسيط. وبالتالي ، يتم استخدام بيانات الاعتماد لفصل الطلبات إلى مثيلات خدمة مختلفة. كان الهدف هو تطوير مثال مجهز بالكامل يوضح أجزاء كثيرة من محفظة مشروع Spring.
Spring Cloud Open Service Broker 3.1
Spring Cloud Open Service Broker عبارة عن نظام أساسي لإنشاء تطبيقات Spring Boot التي تستخدم واجهة برمجة تطبيقات Open Service Broker ، وتتيح للمطورين توفير الخدمات للتطبيقات التي تعمل على الأنظمة الأساسية السحابية مثل Cloud Foundry و Kubernetes و OpenShift. بدءًا من الإصدار 3.0 ، يدعم Spring Cloud Open Service Broker إطارات الويب Spring WebFlux و Spring MVC باستخدام أنواع التفاعل في واجهات التحكم والخدمة.
للبدء في برنامج Spring Cloud Open Broker ، قم بتضمين مشغل Spring Boot في تطبيقك:
implementation('org.springframework.cloud:spring-cloud-starter-open-service-broker:3.1.0.RELEASE')
ثم نقوم بتطبيق
ServiceInstateService
و
ServiceInstateBindingService
. يوضح الكود التالي واجهة برمجة التطبيقات المطلوبة. انظر نموذج الطلب للحصول على التفاصيل الكاملة.
@Service public class BookStoreServiceInstanceService implements ServiceInstanceService { @Override public Mono < CreateServiceInstanceResponse > createServiceInstance( CreateServiceInstanceRequest request) { ... } @Override public Mono < GetServiceInstanceResponse > getServiceInstance( GetServiceInstanceRequest request) { ... } @Override public Mono < DeleteServiceInstanceResponse > deleteServiceInstance( DeleteServiceInstanceRequest request) { ... } }
ربيع مور البيانات
في عائلة مشروع
Spring Data ، تم تقديم الدعم التفاعلي في الأصل في
Spring Data Kay . أعلنت Spring Data R2DBC مؤخرًا عن إصدار GA ، لكن Spring Spring لم يصدر بعد إصدار GA يدمج مع Spring Data R2DBC. يستخدم هذا المثال MongoDB كمخزن بيانات النسخ الاحتياطي.
للبدء في Reactive MongoDB ، قم بتضمين بدء تشغيل Spring Boot في التطبيق الخاص بك:
implementation('org.springframework.boot:spring-boot-starter-data-mongodb-reactive')
لتوضيح ذلك ، أضف خادم MongoDB المدمج:
implementation('de.flapdoodle.embed:de.flapdoodle.embed.mongo')
ثم قم بإعداد مستودع تخزين Jet:
@Configuration @EnableReactiveMongoRepositories(basePackageClasses = { ServiceBrokerRepositoryPackageMarker.class, WebRepositoryPackageMarker.class }) public class ApplicationRepositoryConfiguration { }
أخيرًا ، حدد
ReactiveCrudRepository
. الواجهة التالية هي مثال واحد من نموذج التطبيق:
public interface ServiceInstanceRepository extends ReactiveCrudRepository < ServiceInstance, String > { }
أمن الربيع 5.2
تم تضمين الدعم التفاعلي في الأصل في برنامج
Security Security 5 ، واستمر التكامل مع Spring Boot و Spring Framework في التطور.
لاستخدام Spring Security ، قم ببدء تشغيل Spring Boot:
implementation('org.springframework.boot:spring-boot-starter-security')
بعد ذلك ، حدد تكوين الأمان باستخدام
@EnableWebCardingSecurity
. يوضح هذا الرمز كيف يحمي أحد التطبيقات نقاط النهاية للوسيط
/v2
و
/bookstars
التي تستجيب لطلبات مثيلات الخدمة:
@Configuration @EnableWebFluxSecurity public class SecurityConfiguration { @Bean public SecurityWebFilterChain securityWebFilterChain( ServerHttpSecurity http) { return http .csrf().disable() .httpBasic() .and().authorizeExchange() .pathMatchers("/bookstores/**").authenticated() .pathMatchers("/v2/**").hasAuthority( SecurityAuthorities.ADMIN) .matchers(EndpointRequest.to("info", "health")).permitAll() .matchers(EndpointRequest.toAnyEndpoint()).hasAuthority( SecurityAuthorities.ADMIN) .and().build(); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } }
بعد ذلك ، نقوم بتطبيق
ReactiveUserDetailsService
:
@Service public class RepositoryUserDetailsService implements ReactiveUserDetailsService { private final UserRepository userRepository; public RepositoryUserDetailsService(UserRepository userRepository) { this.userRepository = userRepository; } }
أخيرًا ، لا يتم دعم مقيِّمي الأذونات في وحدات تحكم WebFlux ، ولكن يمكننا تحقيق وظائف مماثلة عن طريق استدعاء وحدة الفول في تعبير SpEL وتمرير كائن المصادقة:
@GetMapping("/{bookStoreId}") @PreAuthorize("hasAnyRole('ROLE_FULL_ACCESS','ROLE_READ_ONLY') and @bookStoreIdEvaluator.canAccessBookstore(authentication, #bookStoreId)") public Mono<ResponseEntity<BookStoreResource>> getBooks( @PathVariable String bookStoreId) { return bookStoreService.getBookStore(bookStoreId) .flatMap(this::createResponse); }
يحلل هذا المثال الأذونات لتحديد ما إذا كان معرف مكتبة الكتب موجودًا:
public boolean canAccessBookstore(Authentication authentication, String bookStoreId) { return authentication.getAuthorities().stream() .filter(authority - > authority.getAuthority() .startsWith(BOOK_STORE_ID_PREFIX)) .map(authority - > { String serviceInstanceId = authority.getAuthority() .substring(BOOK_STORE_ID_PREFIX.length()); return serviceInstanceId.equals(bookStoreId); }) .findFirst() .orElse(true); }
ربيع هاتوس 1.0
تم إصدار Spring HATEOAS 1.0 GA مؤخرًا ويتضمن دعمًا تفاعليًا لربط طرق العرض والنمذجة.
إضافة Spring HATEOAS Starter لتنشيط تهيئة Spring Boot التلقائية. نظرًا لأننا نقوم بإنشاء تطبيق Spring WebFlux Reactive ، فإننا نحتاج إلى استبعاد تطبيق Spring Web starter:
implementation('org.springframework.boot:spring-boot-starter-hateoas') { exclude group: 'org.springframework.boot', module: 'spring-boot-starter-web' }
بعد ذلك ، يمكنك استخدام
WebFluxLinkBuilder
لإنشاء موارد Hypermedia:
public Mono < BookResource > toModel(Book book, String bookStoreId) { return Mono.just(new BookResource(book)) .flatMap(bookResource - > linkTo(methodOn( BookController.class).getBook(bookStoreId, book.getId())) .withSelfRel() .toMono() .flatMap(link - > Mono.just(bookResource.add(link))) .thenReturn(bookResource)); }
ثم يمكنك استخدام هذا المورد في نص استجابة وحدة التحكم:
return new BookStoreResourceAssembler().toModel(bookStore) .flatMap(bookStoreResource - > Mono.just(new ResponseEntity < > (bookStoreResource, HttpStatus.OK)));
إطار الربيع 5.2
عرض Spring Framework 5 دعمًا تفاعليًا في Spring WebFlux Web Framework الجديد. بالإضافة إلى ذلك ، يتضمن WebClient و WebTestClient الجديد دعمًا لاستخدام واختبار تطبيقات Spring WebFlux.
لاستخدامها ، ما عليك سوى إضافة مشغلات Spring Boot:
implementation('org.springframework.boot:spring-boot-starter-webflux') testImplementation('org.springframework.boot:spring-boot-starter-test') { exclude group: 'org.junit.vintage', module: 'junit-vintage-engine' }
على سبيل المثال ، استخدم
WebTestClient
لاختبار وظيفة جهاز التحكم:
this.client.get().uri("/bookstores/{bookStoreId}", bookStoreId) .accept(MediaType.APPLICATION_JSON) .exchange() .expectStatus().isEqualTo(HttpStatus.OK);
التمهيد الربيع 2.2
يقوم Spring Boot بدمج جميع هذه المشروعات ، حيث يوفر التكوين التلقائي للدعم التفاعلي في Spring WebFlux و Spring Data و Spring Security و Spring HATEOAS ، وكذلك في أدوات الاختبار. في كثير من الحالات ، لا يتطلب التطبيق سوى إضافة مشغلات Spring Boot معينة أو التبعيات ذات الصلة لتنشيط الوظيفة.
استنتاج
يتضمن هذا المنشور مقدمة موجزة عن الدعم التفاعلي في بعض مشاريع Spring. نظرًا لأن المزيد من مشاريع Spring تكيف وتدعم واجهات برمجة التطبيقات التفاعلية ، فسيكون للمطورين المزيد من الخيارات لاستخدام البرمجة الضرورية أو التفاعلية في تطبيقاتهم. بالإضافة إلى ذلك ، يوضح نموذج التطبيق هذا فقط بعض مشاريع Spring التي تقدم حاليًا الدعم التفاعلي. ابحث عن المزيد في المستقبل! إذا كانت لديك أسئلة أو مخاوف بشأن مشروع Spring معين ، فيرجى الاتصال بمشرفي المشروع على صفحة جيثب المقابلة.
ترجم بواسطة
middle_java