Spring memberikan dukungan untuk integrasi aplikasi di seluruh kerangka kerja perusahaan dengan menggunakan ekstensi yang disebut Integrasi Musim Semi . Tujuan utamanya adalah untuk memfasilitasi aplikasi dengan domain bisnis yang beragam; teknologi bekerja menuju interoperabilitas horizontal di seluruh perusahaan. Ini menambahkan pesan ringan dan integrasi dengan sistem dan layanan eksternal menggunakan kerangka kerja adaptor. Artikel ini bertujuan untuk memberikan pemahaman dasar tentang Integrasi Pegas dan bagaimana hal itu meluas pada model pemrograman Pegas.
Ringkasan
Aplikasi komersial tidak lain adalah solusi untuk masalah yang ditimbulkan oleh unit bisnis. Besarnya dan kompleksitas masalah menentukan apakah solusinya berskala perusahaan atau hanya beberapa baris kode. Masalah dengan aplikasi perusahaan adalah, terkadang, sebagian dari solusi sudah tersedia menggunakan teknologi lama yang mungkin tidak hemat biaya untuk membangun kembali dari awal agar sesuai dengan teknologi yang lebih baru, baik itu perangkat keras atau perangkat lunak baru. Ini adalah masalah khas dengan aplikasi lawas. Oleh karena itu, yang bisa kita lakukan adalah membuat komponen baru yang saling beroperasi dengan sistem yang ada. Ini adalah integrasi aplikasi . Namun, masalahnya tidak berakhir di situ. Tidaklah mudah untuk membuat komponen yang bekerja secara mulus dengan komponen yang ada tanpa memaksakan batasan yang tidak perlu pada efisiensi satu sama lain. Ada pertimbangan serius yang harus ditangani untuk integrasi beberapa komponen tanpa batas. Spring Integration mempertimbangkan masalah ini dan menyediakan lingkungan bagi pengembang untuk membuat kode untuk integrasi yang mudah. Spring mengidentifikasi pola umum yang terlibat dan melakukan pekerjaan dengan sedikit campur tangan pengembang.
Kopling Longgar
Karena solusinya harus menggunakan banyak bagian, setiap bagian harus memiliki masalah terpisah sebanyak mungkin dengan cara yang longgar. Evolusi dari satu komponen tidak boleh menimbulkan implikasi desain dan pemeliharaan yang serius pada komponen lainnya. Situasi decoupled lengkap tidak cocok untuk integrasi, dan kopling ketat juga tidak dapat diterima. Oleh karena itu, permainannya adalah mendesain komponen dengan cara yang selonggar mungkin. Ada beberapa cara untuk mengurangi kopling dalam aplikasi Spring:injeksi ketergantungan atau arsitektur yang digerakkan oleh peristiwa . Arsitektur yang digerakkan oleh peristiwa adalah istilah yang luas dan memiliki perbedaan yang sangat tipis antara arsitektur yang digerakkan oleh pesan, atau MOM. Meskipun secara teknis tidak sama, untuk tujuan ini, kami dapat menggunakan istilah tersebut secara bergantian di sini. Hanya demi yang murni, perbedaan mendasar antara yang digerakkan oleh peristiwa dan yang digerakkan oleh pesan adalah bahwa pesan telah mengarahkan penerima sedangkan peristiwa tidak diarahkan; jika tidak, implementasinya hampir tidak memiliki demarkasi yang jelas. Mari kita tidak membahasnya di sini; sebagai gantinya, mari kita fokus pada bagaimana arsitektur berbasis peristiwa digunakan dengan Integrasi Musim Semi.
Integrasi Musim Semi yang Didorong oleh Peristiwa
Dalam arsitektur yang digerakkan oleh peristiwa, aplikasi yang kompleks dipecah menjadi beberapa komponen layanan. Komponen ini berinteraksi melalui peristiwa yang dihasilkan oleh komponen lain, yang disebut penerbit dari peristiwa. Komponen lain yang tertarik pada peristiwa tertentu berlangganan dan mengambil tindakan yang tepat sebagai tanggapan. Ini, pada dasarnya, adalah model penerbit-pelanggan dalam mengerjakan acara.
Perubahan spesifik dalam keadaan adalah suatu peristiwa. Seperti yang dinyatakan, acara dikirim ke pihak yang berkepentingan dan pelanggan acara dapat memilih untuk merespons dengan menyediakan layanan seperti menjalankan proses bisnis, menerbitkan acara lain atau, mungkin, mengabaikannya sama sekali. Itu berarti acara, setelah diterbitkan, tidak bertanggung jawab atas tanggapan pelanggan. Ini adalah skenario yang dipisahkan dan arsitektur yang digerakkan oleh peristiwa memanfaatkan skenario kopling longgar tersebut. Kopling longgar sangat cocok untuk melakukan alur kerja waktu nyata yang diperlukan Integrasi Pegas.
Komponen Integrasi Pegas
Sebagai perpanjangan dari kerangka Spring, Spring Integration pada dasarnya menambahkan tiga komponen:pesan, saluran pesan, dan titik akhir. Pengembang Spring Integration mengenali pola umum kesamaan untuk beroperasi di antara beragam arsitektur, domain, dan teknologi di arena perusahaan. Oleh karena itu, dengan memperkenalkan pesan melalui komponen menggunakan pipa dan filter, model ini menjadi dasar untuk integrasi aplikasi. Komponen filter mengkonsumsi atau menghasilkan pesan sementara pipa, disebut sebagai saluran di Spring Integration, menjelaskan aliran pesan antar filter.
Ada banyak seluk-beluk yang terlibat. Lihat tautan di bagian Referensi untuk lebih jelasnya. Di sini, mari kita fokus pada implementasi sederhana dengan DirectChannel .
Contoh Singkat
Contoh di Listing 1 adalah aplikasi Spring BOOT yang mengimplementasikan Integrasi Spring dengan DirectChannel . Di sini, saluran pesan digunakan untuk memisahkan titik akhir penerbit dan pelanggan. Saluran pesan digunakan untuk membuat koneksi dengan filter dan komponen adaptor. Contohnya cukup mudah dan menggunakan DirectChannel dengan penerbit-pelanggan dan model komunikasi point-to-point. Perhatikan bahwa kode ini belum sempurna dan implementasi sederhana untuk mengilustrasikan ide Integrasi Pegas.
<?xml version="1.0" encoding="UTF-8"?> <project xmlns_xsi="http://www.w3.org/2001/XMLSchema-instance" xsi_schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.mano.example</groupId> <artifactId>spring-integration</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>spring-integration</name> <description>Demo project for Spring BOOT</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.6.RELEASE</version> <relativePath/> <!-- look up parent from repository --> </parent> <properties> <project.build.sourceEncoding> UTF-8 </project.build.sourceEncoding> <project.reporting.outputEncoding> UTF-8 </project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId> spring-boot-starter-integration </artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId> spring-boot-starter-test </artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId> org.springframework.boot </groupId> <artifactId> spring-boot-maven-plugin </artifactId> </plugin> </plugins> </build> </project>
Cantuman 1: pom.xml, dependensi Spring BOOT untuk solusi Integrasi Pegas
package com.mano.example.springintegration.model; import java.util.Date; public class Tweet { private long tid; private String text; private Date time; private String hashTag; @Override public String toString() { return "Tweet{" + "tid=" + tid + ", text='" + text + ''' + ", time=" + time + ", hashTag='" + hashTag + ''' + '}'; } public long getTid() { return tid; } public void setTid(long tid) { this.tid = tid; } public String getText() { return text; } public void setText(String text) { this.text = text; } public Date getTime() { return time; } public void setTime(Date time) { this.time = time; } public String getUser() { return hashTag; } public void setUser(String hashTag) { this.hashTag = hashTag; } }
Cantuman 2: Tweet.java, kelas model
package com.mano.example.springintegration.repo; import com.mano.example.springintegration.model.Tweet; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.Date; import java.util.List; @Component public class TweetPublisher { private static long id; public List<Tweet> getTweets(){ List<Tweet> tweets = new ArrayList<>(); tweets.add(createTweet("Storms in Pacific","#weather")); tweets.add(createTweet("what's up developers?","#dev")); tweets.add(createTweet("Chinese delicacy in Amazon", "#traveller")); tweets.add(createTweet("inflation down by 2%","#stock")); tweets.add(createTweet("save river","#environment")); tweets.add(createTweet("New star found","#astronaut")); tweets.add(createTweet("Learn math quickly","#tutor")); tweets.add(createTweet("Save animals","#bovine")); tweets.add(createTweet("stars are favorable now", "#astro")); tweets.add(createTweet("social unrest in the world", "#concern")); return tweets; } Tweet createTweet(String text, String hashTag){ Tweet tweet = new Tweet(); tweet.setTid(id++); tweet.setUser(hashTag); tweet.setText(text); tweet.setTime(new Date()); return tweet; } }
Cantuman 3: TweetPublisher.java, mengisi data tweet
package com.mano.example.springintegration.pub; import com.mano.example.springintegration.model.Tweet; import org.springframework.beans.factory.annotation.Value; import org.springframework.integration.channel.DirectChannel; import org.springframework.integration.support .MessageBuilder; import org.springframework.stereotype.Component; @Component public class Tweeter { private DirectChannel channel; @Value("#{tweetChannel}") public void setChannel(DirectChannel channel) { this.channel = channel; } public void sendTweetReaders(Tweet tweet) { System.out.println("New Tweet - " + tweet.toString()); channel.send(MessageBuilder.withPayload(tweet) .build()); } }
Cantuman 4: Tweeter.java, kelas penerbit
package com.mano.example.springintegration.sub; import com.mano.example.springintegration.model.Tweet; import org.springframework.integration .MessageRejectedException; import org.springframework.messaging.Message; import org.springframework.messaging.MessageHandler; import org.springframework.messaging.MessagingException; import org.springframework.stereotype.Component; @Component public class TweetReader implements MessageHandler { @Override public void handleMessage(Message<?> message) throws MessagingException { Object payload = message.getPayload(); if (payload instanceof Tweet) { receiveAndAcknowledge((Tweet) payload); } else { throw new MessageRejectedException(message, "Unknown data type has been received."); } } void receiveAndAcknowledge(Tweet tweet) { System.out.println("Hi Tweeter, this is Reader #" + System.identityHashCode(this) + "." + "Received tweet - " + tweet.toString() + "n"); } }
Cantuman 5: TweetReader.java, kelas pelanggan
package com.mano.example.springintegration; import com.mano.example.springintegration.incoming .TweetPublisher; import com.mano.example.springintegration.model.Tweet; import com.mano.example.springintegration.pub.Tweeter; import com.mano.example.springintegration.sub.TweetReader; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure .SpringBootApplication; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.integration.channel.DirectChannel; import org.springframework.messaging.MessageChannel; import java.util.List; @SpringBootApplication @ComponentScan(basePackages = "com.mano.example.springintegration") public class SpringIntegrationApplication { @Autowired private TweetPublisher tweetPublisher; @Autowired private Tweeter tweeter; @Autowired private DirectChannel channel; @Bean public MessageChannel tweetChannel(){ return new DirectChannel(); } @Bean public CommandLineRunner commandLineRunner (ApplicationContext context){ return args -> { channel.subscribe(new TweetReader()); channel.subscribe(new TweetReader()); channel.subscribe(new TweetReader()); List<Tweet> tweets = tweetPublisher.getTweets(); for (Tweet tweet: tweets){ tweeter.sendTweetReaders(tweet); } }; } public static void main(String[] args) { SpringApplication.run(SpringIntegrationApplication .class, args); } }
Cantuman 6: SpringIntegrationApplication.java, kelas aplikasi utama
Kesimpulan
Perhatikan bahwa ada lebih banyak dengan Integrasi Musim Semi daripada yang diilustrasikan di sini. Ini hanyalah puncak gunung es. Detail penting dihilangkan. Lihat dokumentasi Spring untuk detail lebih lanjut tentang ini; link diberikan di bawah ini. Spring Integration memiliki kelebihan, seperti Inversion of Control (IoC), pemrograman berorientasi aspek untuk mengatasi masalah lintas sektoral, dan keunggulan inti lainnya dari Spring Framework yang tersedia. Integrasi Musim Semi membawanya lebih jauh. Pengembang Spring Integration tidak perlu tahu tentang bagaimana, kapan, dan keberadaan data. Kerangka kerja menangani bagaimana logika bisnis dijalankan dengan mengarahkan pesan melalui komponen yang sesuai. Terlepas dari skema konfigurasi XML biasa, starter Spring BOOT menyediakan dependensi yang diperlukan untuk memulai kode secara langsung dengan sedikit kekhawatiran tentang dependensi.
Referensi
- Ikhtisar Integrasi Musim Semi
- Integrasi Musim Semi