рдирдпрд╛ рд╕рд╛рд▓ рдореБрдмрд╛рд░рдХ рд╣реЛ, рд╡рд╕рдВрдд рд╕рдореБрджрд╛рдп!
рдЬреИрд╕рд╛ рдХрд┐ рд╕реНрдкреНрд░рд┐рдВрдЧ рдЗрдХреЛрд╕рд┐рд╕реНрдЯрдо рдореЗрдВ рд╡рд┐рдХрд╛рд╕ рдФрд░ рд╕реБрдзрд╛рд░ рдХрд╛ рдЕрдЧрд▓рд╛ рдЕрджреНрднреБрдд рд╡рд░реНрд╖ рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИ, рдореИрдВ рдЖрдкрдХреЗ рд╕рд╛рде рдПрдХ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рдПрдХ рдЕрджреНрдпрддрди рдЙрджрд╛рд╣рд░рдг рдХреЛ рд╕рд╛рдЭрд╛ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдЬреЛ рдХрд┐ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рд╢реАрд▓ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рдореЙрдбрд▓ рдХреЗ рд╕рдорд░реНрдерди рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реНрдкреНрд░рд┐рдВрдЧ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдкреЛрд░реНрдЯрдлреЛрд▓рд┐рдпреЛ рдореЗрдВ рдХреА рдЧрдИ рдкреНрд░рдЧрддрд┐ рдХреЗ рд╣рд┐рд╕реНрд╕реЗ рдХреЛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддрд╛ рд╣реИред
рдмреБрдХрд╕реНрдЯреЙрд░ рд╕рд░реНрд╡рд┐рд╕ рдмреНрд░реЛрдХрд░ рдПрдкреНрд▓рд┐рдХреЗрд╢рди
рдХреЛ рдХрдИ рдЕрд▓рдЧ-рдЕрд▓рдЧ рд╕реНрдкреНрд░рд┐рдВрдЧ рдкреНрд░реЛрдЬреЗрдХреНрдЯреНрд╕ рдХреЗ рдПрдХреАрдХрд░рдг рдХреЛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдкрдбреЗрдЯ
рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рд╕реНрдкреНрд░рд┐рдВрдЧ рдХреНрд▓рд╛рдЙрдб рдУрдкрди рд╕рд░реНрд╡рд┐рд╕ рдмреНрд░реЛрдХрд░, рд╕реНрдкреНрд░рд┐рдВрдЧ рдбреЗрдЯрд╛, рд╕реНрдкреНрд░рд┐рдВрдЧ рд╕рд┐рдХреНрдпреЛрд░рд┐рдЯреА, рд╕реНрдкреНрд░рд┐рдВрдЧ рд╣реЗрдЯреЛрд╕ рдФрд░ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рд╕реНрдкреНрд░рд┐рдВрдЧ рд╡реЗрдмрдлреНрд▓рдХреНрд╕ рдФрд░ рд╕реНрдкреНрд░рд┐рдВрдЧ рдмреВрдЯ рд╢рд╛рдорд┐рд▓ рд╣реИрдВред рдЗрди рд╕рднреА рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдореЗрдВ GA рдХреЗ рд╕рдВрд╕реНрдХрд░рдг рд╣реИрдВ, рдЬрд┐рдирдореЗрдВ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рддреНрдордХ рд╕рдорд░реНрдерди рдФрд░ рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдФрд░ рд╕реЗрд╡рд╛рдУрдВ рдореЗрдВ рдЙрддреНрдкрд╛рджрди рдХреЗ рд▓рд┐рдП рддреИрдпрд╛рд░ рд╣реИрдВред
@Middle_java рджреНрд╡рд╛рд░рд╛
рдЕрдиреБрд╡рд╛рджрд┐рддрд╕рд╛рджрдЧреА рдХреЗ рд▓рд┐рдП, рдЖрд╡реЗрджрди рд╕реНрд╡рдпрдВ рдПрдХ рджрд▓рд╛рд▓ рдФрд░ рдПрдХ рд╕реЗрд╡рд╛ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд░реВрдк рдореЗрдВ рдХрд╛рд░реНрдп рдХрд░рддрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдВрдХрд┐ рдмреНрд░реЛрдХрд░ рдЦреБрдж рдУрдкрди рд╕рд░реНрд╡рд┐рд╕ рдмреНрд░реЛрдХрд░ рдПрдкреАрдЖрдИ рдХрд╛ рдкрд╛рд▓рди рдХрд░рддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рд╡реЗ рдЬреЛ рд╕реЗрд╡рд╛рдПрдВ рдкреНрд░рджрд╛рди рдХрд░рддреЗ рд╣реИрдВ рд╡реЗ рдЕрдзрд┐рдХ рд╕рд╛рд░рдЧрд░реНрднрд┐рдд рд░реВрдк рд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рд╣реЛрддреА рд╣реИрдВред рд╕реЗрд╡рд╛рдПрдБ рд▓рдЧрднрдЧ рдХреБрдЫ рднреА рдХрд░ рд╕рдХрддреА рд╣реИрдВ рдпрд╛ рд╣реЛ рд╕рдХрддреА рд╣реИрдВред рд╣рдорд╛рд░реЗ рдЖрд╡реЗрджрди рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рд╕реЗрд╡рд╛ рдХреЗ рдкреНрд░рддреНрдпреЗрдХ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рдХреНрд░реЗрдбреЗрдВрд╢рд┐рдпрд▓реНрд╕ рдХрд╛ рдПрдХ рдирдпрд╛ рд╕реЗрдЯ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИред рдпреЗ рдХреНрд░реЗрдбреЗрдВрд╢рд┐рдпрд▓ рд╕реЗрд╡рд╛ рдХреЗ рдЕрдиреБрд░реЛрдз рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВред рдирдИ рд╕реЗрд╡рд╛ рдЖрд╡реГрддреНрддрд┐ рдХрд╛ URL рдмреНрд░реЛрдХрд░ рдХреЗ рд░реВрдЯ рдХреЗ рд╕рдорд╛рди рд╣реИред рдЗрд╕ рдкреНрд░рдХрд╛рд░, рдХреНрд░реЗрдбреЗрдВрд╢рд┐рдпрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рд╡рд┐рднрд┐рдиреНрди рд╕реЗрд╡рд╛ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреЗ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рдЕрд▓рдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд▓рдХреНрд╖реНрдп рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╕реБрд╕рдЬреНрдЬрд┐рдд рдЙрджрд╛рд╣рд░рдг рд╡рд┐рдХрд╕рд┐рдд рдХрд░рдирд╛ рдерд╛ рдЬреЛ рд╕реНрдкреНрд░рд┐рдВрдЧ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдкреЛрд░реНрдЯрдлреЛрд▓рд┐рдпреЛ рдХреЗ рдХрдИ рд╣рд┐рд╕реНрд╕реЛрдВ рдХреЛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддрд╛ рд╣реИред
рд╕реНрдкреНрд░рд┐рдВрдЧ рдХреНрд▓рд╛рдЙрдб рдУрдкрди рд╕рд░реНрд╡рд┐рд╕ рдмреНрд░реЛрдХрд░ 3.1
рд╕реНрдкреНрд░рд┐рдВрдЧ рдХреНрд▓рд╛рдЙрдб рдУрдкрди рд╕рд░реНрд╡рд┐рд╕ рдмреНрд░реЛрдХрд░ рд╕реНрдкреНрд░рд┐рдВрдЧ рдмреВрдЯ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рдирд┐рд░реНрдорд╛рдг рдХреЗ рд▓рд┐рдП рдПрдХ рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо рд╣реИ рдЬреЛ рдУрдкрди рд╕рд░реНрд╡рд┐рд╕ рдмреНрд░реЛрдХрд░ рдПрдкреАрдЖрдИ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреЛ рдХреНрд▓рд╛рдЙрдб рдлрд╛рдЙрдВрдбреНрд░реА, рдХреБрдмреЗрд░рдиреЗрдЯреНрд╕ рдФрд░ рдУрдкрдирд╢рд┐рдлреНрдЯ рдЬреИрд╕реЗ рдХреНрд▓рд╛рдЙрдб рдкреНрд▓реЗрдЯрдлрд╛рд░реНрдореЛрдВ рдкрд░ рдЪрд▓рдиреЗ рд╡рд╛рд▓реЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛ рд╕реЗрд╡рд╛рдПрдВ рдкреНрд░рджрд╛рди рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рд╕рдВрд╕реНрдХрд░рдг 3.0 рд╕реЗ рд╢реБрд░реВ рд╣реЛрдХрд░, рд╕реНрдкреНрд░рд┐рдВрдЧ рдХреНрд▓рд╛рдЙрдб рдУрдкрди рд╕рд░реНрд╡рд┐рд╕ рдмреНрд░реЛрдХрд░ рдирд┐рдпрдВрддреНрд░рдХ рдФрд░ рд╕реЗрд╡рд╛ рдЗрдВрдЯрд░рдлреЗрд╕ рдореЗрдВ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рд╢реАрд▓ рдкреНрд░рдХрд╛рд░реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕реНрдкреНрд░рд┐рдВрдЧ рд╡реЗрдмрдлреНрд▓рдХреНрд╕ рдФрд░ рд╕реНрдкреНрд░рд┐рдВрдЧ рдПрдорд╡реАрд╕реА рд╡реЗрдм рдлреНрд░реЗрдорд╡рд░реНрдХ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИред
рд╕реНрдкреНрд░рд┐рдВрдЧ рдХреНрд▓рд╛рдЙрдб рдУрдкрди рд╕рд░реНрд╡рд┐рд╕ рдмреНрд░реЛрдХрд░ рдХреЗ рд╕рд╛рде рд╢реБрд░реБрдЖрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЕрдкрдиреЗ рдЖрд╡реЗрджрди рдореЗрдВ рд╕реНрдкреНрд░рд┐рдВрдЧ рдмреВрдЯ рд╕реНрдЯрд╛рд░реНрдЯрд░ рд╢рд╛рдорд┐рд▓ рдХрд░реЗрдВ:
implementation('org.springframework.cloud:spring-cloud-starter-open-service-broker:3.1.0.RELEASE')
рдлрд┐рд░ рд╣рдо
ServiceInstateService
рдФрд░
ServiceInstateBindingService
рд▓рд╛рдЧреВ
ServiceInstateBindingService
ред рдирд┐рдореНрди рдХреЛрдб рдЖрд╡рд╢реНрдпрдХ API рджрд┐рдЦрд╛рддрд╛ рд╣реИред рдкреВрд░реНрдг рд╡рд┐рд╡рд░рдг рдХреЗ рд▓рд┐рдП рдирдореВрдирд╛ рдЖрд╡реЗрджрди рджреЗрдЦреЗрдВред
@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) { ... } }
рд╕реНрдкреНрд░рд┐рдВрдЧ рдбреЗрдЯрд╛ рдореВрд░
рд╕реНрдкреНрд░рд┐рдВрдЧ рдбреЗрдЯрд╛ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдкрд░рд┐рд╡рд╛рд░ рдореЗрдВ, рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рддреНрдордХ рд╕рдорд░реНрдерди рдореВрд▓ рд░реВрдк рд╕реЗ
рд╕реНрдкреНрд░рд┐рдВрдЧ рдбреЗрдЯрд╛ Kay рдореЗрдВ рдкреЗрд╢ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рд╕реНрдкреНрд░рд┐рдВрдЧ рдбреЗрдЯрд╛ R2DBC рдиреЗ рд╣рд╛рд▓ рд╣реА рдореЗрдВ GA рд░рд┐рд▓реАрдЬрд╝ рдХреА рдШреЛрд╖рдгрд╛ рдХреА рд╣реИ, рд▓реЗрдХрд┐рди рд╕реНрдкреНрд░рд┐рдВрдЧ рдмреВрдЯ рдореЗрдВ рдЕрднреА рддрдХ рд╕реНрдкреНрд░рд┐рдВрдЧ рдбреЗрдЯрд╛ R2DBC рдХреЗ рд╕рд╛рде GA рд░рд┐рд▓реАрдЬрд╝ рдПрдХреАрдХреГрдд рдирд╣реАрдВ рд╣реИред рдпрд╣ рдЙрджрд╛рд╣рд░рдг рдмреИрдХрдЕрдк рдбреЗрдЯрд╛ рд╕реНрдЯреЛрд░ рдХреЗ рд░реВрдк рдореЗрдВ MongoDB рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред
рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рд╢реАрд▓ MongoDB рдХреЗ рд╕рд╛рде рдЖрд░рдВрдн рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЕрдкрдиреЗ рдЖрд╡реЗрджрди рдореЗрдВ рд╕реНрдкреНрд░рд┐рдВрдЧ рдмреВрдЯ рд╕реНрдЯрд╛рд░реНрдЯрд░ рд╢рд╛рдорд┐рд▓ рдХрд░реЗрдВ:
implementation('org.springframework.boot:spring-boot-starter-data-mongodb-reactive')
рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд MongoDB рд╕рд░реНрд╡рд░ рдЬреЛрдбрд╝реЗрдВ:
implementation('de.flapdoodle.embed:de.flapdoodle.embed.mongo')
рдлрд┐рд░ рдЬреЗрдЯ рд░рд┐рдкреЛрдЬрд┐рдЯрд░реА рдХреА рд╕реНрдерд╛рдкрдирд╛ рдХрд░реЗрдВ:
@Configuration @EnableReactiveMongoRepositories(basePackageClasses = { ServiceBrokerRepositoryPackageMarker.class, WebRepositoryPackageMarker.class }) public class ApplicationRepositoryConfiguration { }
рдЕрдВрдд рдореЗрдВ,
ReactiveCrudRepository
рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░реЗрдВред рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдПрдХ рдирдореВрдирд╛ рдЕрдиреБрдкреНрд░рдпреЛрдЧ рд╕реЗ рдПрдХ рдЙрджрд╛рд╣рд░рдг рд╣реИ:
public interface ServiceInstanceRepository extends ReactiveCrudRepository < ServiceInstance, String > { }
рд╡рд╕рдВрдд рд╕реБрд░рдХреНрд╖рд╛ 5.2
рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рддреНрдордХ рд╕рдорд░реНрдерди рдореВрд▓ рд░реВрдк рд╕реЗ
рд╕реНрдкреНрд░рд┐рдВрдЧ рд╕реБрд░рдХреНрд╖рд╛ 5 рдореЗрдВ рд╢рд╛рдорд┐рд▓ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛
, рдФрд░ рд╕реНрдкреНрд░рд┐рдВрдЧ рдмреВрдЯ рдХреЗ рд╕рд╛рде рдПрдХреАрдХрд░рдг рдФрд░ рд╕реНрдкреНрд░рд┐рдВрдЧ рдлреНрд░реЗрдорд╡рд░реНрдХ рд╡рд┐рдХрд╕рд┐рдд рдХрд░рдирд╛ рдЬрд╛рд░реА рд╣реИред
рд╕реНрдкреНрд░рд┐рдВрдЧ рд╕реБрд░рдХреНрд╖рд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╕реНрдкреНрд░рд┐рдВрдЧ рдмреВрдЯ рд╕реНрдЯрд╛рд░реНрдЯрд░ рдЬреЛрдбрд╝реЗрдВ:
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 рдирд┐рдпрдВрддреНрд░рдХреЛрдВ рдореЗрдВ рдЕрдиреБрдорддрд┐ рдореВрд▓реНрдпрд╛рдВрдХрдирдХрд░реНрддрд╛рдУрдВ рдХрд╛ рд╕рдорд░реНрдерди рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╣рдо рд╕реНрдкреЗрд▓ рдПрдХреНрд╕рдкреНрд░реЗрд╢рди рдореЗрдВ рдмреАрди рдХреЛ рдХреЙрд▓ рдХрд░рдХреЗ рдФрд░ рдСрдереЗрдВрдЯрд┐рдХреЗрд╢рди рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рдкрд╛рд╕ рдХрд░рдХреЗ рд╕рдорд╛рди рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
@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
рд╕реНрдкреНрд░рд┐рдВрдЧ рд╣реЗрдЯреЛрд╕ 1.0 рдЬреАрдП рд╣рд╛рд▓ рд╣реА рдореЗрдВ рдЬрд╛рд░реА рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ рдФрд░ рдЗрд╕рдореЗрдВ рд▓рд┐рдВрдХрд┐рдВрдЧ рдФрд░ рдореЙрдбрд▓рд┐рдВрдЧ рд╡рд┐рдЪрд╛рд░реЛрдВ рдХреЗ рд▓рд┐рдП рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рддреНрдордХ рд╕рдорд░реНрдерди рд╢рд╛рдорд┐рд▓ рд╣реИред
рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд╕реНрдкреНрд░рд┐рдВрдЧ рдмреВрдЯ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдХреЛ рд╕рдХреНрд░рд┐рдп рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реНрдкреНрд░рд┐рдВрдЧ рд╣реЗрдЯреЛрд╕ рд╕реНрдЯрд╛рд░реНрдЯрд░ рдЬреЛрдбрд╝реЗрдВред рдЪреВрдВрдХрд┐ рд╣рдо рд╕реНрдкреНрд░рд┐рдВрдЧ рд╡реЗрдмрдлреНрд▓рдХреНрд╕ рд░рд┐рдПрдХреНрдЯрд┐рд╡ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдмрдирд╛ рд░рд╣реЗ рд╣реИрдВ, рд╣рдореЗрдВ рд╕реНрдкреНрд░рд┐рдВрдЧ рд╡реЗрдм рд╕реНрдЯрд╛рд░реНрдЯрд░ рдХреЛ рдмрд╛рд╣рд░ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:
implementation('org.springframework.boot:spring-boot-starter-hateoas') { exclude group: 'org.springframework.boot', module: 'spring-boot-starter-web' }
рдЕрдЧрд▓рд╛, рдЖрдк рд╣рд╛рдЗрдкрд░рдореАрдбрд┐рдпрд╛ рд╕рдВрд╕рд╛рдзрдиреЛрдВ рдХреЗ рдирд┐рд░реНрдорд╛рдг рдХреЗ рд▓рд┐рдП
WebFluxLinkBuilder
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
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
рд╕реНрдкреНрд░рд┐рдВрдЧ рдлреНрд░реЗрдорд╡рд░реНрдХ 5 рдиреЗ рдореВрд▓ рд░реВрдк рд╕реЗ рдирдП рд╕реНрдкреНрд░рд┐рдВрдЧ рд╡реЗрдмрдлреНрд▓рдХреНрд╕ рд╡реЗрдм рдлреНрд░реЗрдорд╡рд░реНрдХ рдореЗрдВ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рддреНрдордХ рд╕рд╣рд╛рдпрддрд╛ рдХреА рдкреЗрд╢рдХрд╢ рдХреАред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдирдП WebClient рдФрд░ WebTestClient рдореЗрдВ рд╕реНрдкреНрд░рд┐рдВрдЧ рд╡реЗрдмрдлреНрд▓рдХреНрд╕ рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдХреЗ рдЙрдкрдпреЛрдЧ рдФрд░ рдкрд░реАрдХреНрд╖рдг рдХреЗ рд▓рд┐рдП рд╕рдорд░реНрдерди рд╢рд╛рдорд┐рд▓ рд╣реИред
рдЙрдирдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдмрд╕ рд╕реНрдкреНрд░рд┐рдВрдЧ рдмреВрдЯ рд╢реБрд░реБрдЖрдд рдЬреЛрдбрд╝реЗрдВ:
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
рд╕реНрдкреНрд░рд┐рдВрдЧ рдмреВрдЯ рдЗрди рд╕рднреА рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдХреЛ рдПрдХреАрдХреГрдд рдХрд░рддрд╛ рд╣реИ, рд╕реНрдкреНрд░рд┐рдВрдЧ рд╡реЗрдмрдлреНрд▓рдХреНрд╕, рд╕реНрдкреНрд░рд┐рдВрдЧ рдбреЗрдЯрд╛, рд╕реНрдкреНрд░рд┐рдВрдЧ рд╕рд┐рдХреНрдпреЛрд░рд┐рдЯреА, рд╕реНрдкреНрд░рд┐рдВрдЧ рд╣реЗрдЯреЛрд╕ рдореЗрдВ рд░рд┐рдПрдХреНрдЯрд┐рд╡ рд╕рдкреЛрд░реНрдЯ рдХреЗ рдСрдЯреЛ-рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдХреЗ рд╕рд╛рде-рд╕рд╛рде рдкрд░реАрдХреНрд╖рдг рдЙрдкрдХрд░рдгреЛрдВ рдХреА рдкреЗрд╢рдХрд╢ рдХрд░рддрд╛ рд╣реИред рдХрдИ рдорд╛рдорд▓реЛрдВ рдореЗрдВ, рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЛ рд╕рдХреНрд░рд┐рдп рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рдХреЗрд╡рд▓ рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╕реНрдкреНрд░рд┐рдВрдЧ рдмреВрдЯ рд╢реБрд░реБрдЖрдд рдпрд╛ рд╕рдВрдмрдВрдзрд┐рдд рдирд┐рд░реНрднрд░рддрд╛ рдХреЗ рдЕрддрд┐рд░рд┐рдХреНрдд рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред
рдирд┐рд╖реНрдХрд░реНрд╖
рдЗрд╕ рдкреЛрд╕реНрдЯ рдореЗрдВ рдХреБрдЫ рд╕реНрдкреНрд░рд┐рдВрдЧ рдкреНрд░реЛрдЬреЗрдХреНрдЯреНрд╕ рдореЗрдВ рд░рд┐рдПрдХреНрдЯрд┐рд╡ рд╕рдкреЛрд░реНрдЯ рдХрд╛ рдПрдХ рд╕рдВрдХреНрд╖рд┐рдкреНрдд рдкрд░рд┐рдЪрдп рд╢рд╛рдорд┐рд▓ рд╣реИред рдЕрдзрд┐рдХ рд╕реЗ рдЕрдзрд┐рдХ рд╕реНрдкреНрд░рд┐рдВрдЧ рдкреНрд░реЛрдЬреЗрдХреНрдЯреНрд╕ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рд╢реАрд▓ рдПрдкреАрдЖрдИ рдХрд╛ рдЕрдиреБрдХреВрд▓рди рдФрд░ рд╕рдорд░реНрдерди рдХрд░рддреЗ рд╣реИрдВ, рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреЗ рдкрд╛рд╕ рдЕрдкрдиреЗ рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдореЗрдВ рдЖрд╡рд╢реНрдпрдХ рдпрд╛ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рд╢реАрд▓ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдзрд┐рдХ рд╡рд┐рдХрд▓реНрдк рд╣реЛрдВрдЧреЗред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдпрд╣ рдирдореВрдирд╛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗрд╡рд▓ рдХреБрдЫ рд╕реНрдкреНрд░рд┐рдВрдЧ рдкреНрд░реЛрдЬреЗрдХреНрдЯреНрд╕ рдХреЛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддрд╛ рд╣реИ рдЬреЛ рд╡рд░реНрддрдорд╛рди рдореЗрдВ рд░рд┐рдПрдХреНрдЯрд┐рд╡ рд╕рдкреЛрд░реНрдЯ рдкреНрд░рджрд╛рди рдХрд░рддреЗ рд╣реИрдВред рднрд╡рд┐рд╖реНрдп рдореЗрдВ рдФрд░ рджреЗрдЦреЗрдВ! рдпрджрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ рдХрд┐рд╕реА рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╕реНрдкреНрд░рд┐рдВрдЧ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдкреНрд░рд╢реНрди рдпрд╛ рдЪрд┐рдВрддрд╛рдПрдБ рд╣реИрдВ, рддреЛ рдХреГрдкрдпрд╛ рд╕рдВрдмрдВрдзрд┐рдд GitHub рдкреГрд╖реНрда рдкрд░ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдЕрдиреБрд░рдХреНрд╖рдХреЛрдВ рд╕реЗ рд╕рдВрдкрд░реНрдХ рдХрд░реЗрдВред
@Middle_java рджреНрд╡рд╛рд░рд╛
рдЕрдиреБрд╡рд╛рджрд┐рдд