Halo, Habr! Saya mempersembahkan kepada Anda terjemahan dari artikel
“10 Kerangka Kerangka Kerja Pegas Paling Umum” oleh Toni Kukurin.
Musim semi mungkin merupakan salah satu kerangka kerja Java yang paling populer, juga binatang yang kuat untuk dijinakkan. Meskipun konsep dasarnya cukup mudah dimengerti, perlu waktu dan upaya untuk menjadi pengembang Spring yang kuat.
Pada artikel ini, kita akan melihat beberapa kesalahan paling umum di Spring, terutama yang berhubungan dengan aplikasi web dan Spring Boot. Seperti yang dinyatakan di
situs web Spring Boot , itu memaksakan ide tentang bagaimana aplikasi industri harus dibangun, jadi dalam artikel ini kami akan mencoba untuk menunjukkan ide ini dan memberikan ikhtisar dari beberapa tips yang cocok dengan proses pengembangan aplikasi web Spring Boot standar.
Jika Anda tidak terlalu mengenal Spring Boot, tetapi masih ingin mencoba beberapa hal yang disebutkan, saya membuat
repositori GitHub yang menyertai artikel ini . Jika Anda merasa bahwa Anda kehilangan bagian mana pun dalam artikel ini, saya sarankan kloning repositori ke komputer lokal Anda dan bermain dengan kodenya.
Kesalahan Umum # 1: Turun Terlalu Rendah
Kami menemukan kesalahan umum ini karena sindrom
"tidak ditemukan di sini" cukup umum di dunia pengembangan perangkat lunak. Gejalanya meliputi penulisan ulang fragmen kode yang sering digunakan secara teratur, dan banyak pengembang tampaknya menderita karenanya.
Meskipun memahami bagian dalam perpustakaan tertentu dan implementasinya untuk sebagian besar adalah baik dan perlu (dan bisa menjadi proses pembelajaran yang sangat baik), terus-menerus menyelesaikan detail implementasi tingkat rendah yang sama berbahaya bagi pengembangan Anda sebagai insinyur perangkat lunak. Ada alasan mengapa abstraksi dan kerangka kerja seperti Spring ada yang benar-benar memisahkan Anda dari kerajinan berulang dan memungkinkan Anda untuk fokus pada detail tingkat yang lebih tinggi - objek domain dan logika bisnis Anda.
Oleh karena itu, gunakan abstraksi - lain kali Anda menemukan masalah tertentu, pertama-tama lakukan pencarian cepat dan tentukan apakah perpustakaan yang memecahkan masalah ini terintegrasi ke dalam Spring. Saat ini, Anda kemungkinan besar akan menemukan solusi yang sesuai yang ada. Sebagai contoh perpustakaan yang bermanfaat, dalam contoh-contoh sisa artikel ini, saya akan menggunakan anotasi
proyek Lombok . Lombok digunakan sebagai generator kode templat dan pengembang malas di dalam Anda, semoga tidak memiliki masalah dengan gagasan perpustakaan ini. Sebagai contoh, lihat seperti apa
“kacang Jawa standar” dengan Lombok:
@Getter @Setter @NoArgsConstructor public class Bean implements Serializable { int firstBeanProperty; String secondBeanProperty; }
Seperti yang dapat Anda bayangkan, kode di atas mengkompilasi menjadi:
public class Bean implements Serializable { private int firstBeanProperty; private String secondBeanProperty; public int getFirstBeanProperty() { return this.firstBeanProperty; } public String getSecondBeanProperty() { return this.secondBeanProperty; } public void setFirstBeanProperty(int firstBeanProperty) { this.firstBeanProperty = firstBeanProperty; } public void setSecondBeanProperty(String secondBeanProperty) { this.secondBeanProperty = secondBeanProperty; } public Bean() { } }
Namun, perhatikan bahwa Anda kemungkinan besar harus menginstal plugin jika Anda bermaksud menggunakan Lombok dengan IDE Anda. Versi plugin untuk IntelliJ IDEA dapat ditemukan di
sini .
Kesalahan Umum # 2: Membocorkan Konten Internal
Mengungkap struktur internal Anda selalu merupakan ide yang buruk, karena itu menciptakan fleksibilitas dalam desain layanan dan, oleh karena itu, berkontribusi terhadap praktik pengkodean yang buruk. "Kebocoran" konten internal terwujud dalam kenyataan bahwa struktur database dapat diakses dari titik akhir API tertentu. Sebagai contoh, anggap POJO berikut ("Plain Java Object") mewakili tabel dalam database Anda:
@Entity @NoArgsConstructor @Getter public class TopTalentEntity { @Id @GeneratedValue private Integer id; @Column private String name; public TopTalentEntity(String name) { this.name = name; } }
Misalkan ada titik akhir yang perlu mengakses data TopTalentEntity. Tidak peduli seberapa menggoda untuk mengembalikan instance TopTalentEntity, solusi yang lebih fleksibel adalah membuat kelas baru untuk menampilkan data TopTalentEntity pada titik akhir API:
@AllArgsConstructor @NoArgsConstructor @Getter public class TopTalentData { private String name; }
Dengan demikian, membuat perubahan pada backend database tidak akan memerlukan perubahan tambahan pada lapisan layanan. Pikirkan tentang apa yang terjadi jika Anda menambahkan bidang kata sandi ke TopTalentEntity untuk menyimpan hash kata sandi pengguna dalam basis data - tanpa konektor seperti TopTalentData, jika Anda lupa mengubah layanan, frontend tidak sengaja akan menampilkan beberapa informasi rahasia yang sangat tidak diinginkan!
Kesalahan Umum # 3: Kurangnya Pemisahan Tugas
Ketika aplikasi Anda tumbuh, mengatur kode Anda menjadi masalah yang semakin penting. Ironisnya, sebagian besar prinsip pengembangan perangkat lunak mulai dilanggar di mana-mana - terutama dalam kasus-kasus di mana sedikit perhatian diberikan untuk merancang arsitektur aplikasi. Salah satu kesalahan paling umum yang dihadapi pengembang adalah mencampur tanggung jawab kode, dan itu sangat mudah dilakukan!
Apa yang biasanya melanggar prinsip
pemisahan tugas hanyalah "menambahkan" fungsi baru ke kelas yang ada. Ini, tentu saja, adalah solusi jangka pendek yang sangat baik (untuk permulaan, ini membutuhkan lebih sedikit pengetikan), tetapi pasti akan menjadi masalah di masa depan, apakah selama pengujian, pemeliharaan, atau di suatu tempat di antaranya. Pertimbangkan pengontrol berikut, yang mengembalikan TopTalentData dari repositori-nya:
@RestController public class TopTalentController { private final TopTalentRepository topTalentRepository; @RequestMapping("/toptal/get") public List<TopTalentData> getTopTalent() { return topTalentRepository.findAll() .stream() .map(this::entityToData) .collect(Collectors.toList()); } private TopTalentData entityToData(TopTalentEntity topTalentEntity) { return new TopTalentData(topTalentEntity.getName()); } }
Pada awalnya, tidak terlihat ada sesuatu yang salah dengan potongan kode ini. Ini memberikan daftar TopTalentData yang diambil dari instance TopTalentEntity. Namun, jika Anda melihat lebih dekat, kita akan melihat bahwa sebenarnya TopTalentController melakukan beberapa hal di sini. Yaitu: memetakan permintaan untuk titik akhir tertentu, mengambil data dari repositori dan mengubah entitas yang diperoleh dari TopTalentRepository ke dalam format lain. Solusi "bersih" adalah dengan membagi tanggung jawab ini ke dalam kelas mereka sendiri. Mungkin terlihat seperti ini:
@RestController @RequestMapping("/toptal") @AllArgsConstructor public class TopTalentController { private final TopTalentService topTalentService; @RequestMapping("/get") public List<TopTalentData> getTopTalent() { return topTalentService.getTopTalent(); } } @AllArgsConstructor @Service public class TopTalentService { private final TopTalentRepository topTalentRepository; private final TopTalentEntityConverter topTalentEntityConverter; public List<TopTalentData> getTopTalent() { return topTalentRepository.findAll() .stream() .map(topTalentEntityConverter::toResponse) .collect(Collectors.toList()); } } @Component public class TopTalentEntityConverter { public TopTalentData toResponse(TopTalentEntity topTalentEntity) { return new TopTalentData(topTalentEntity.getName()); } }
Manfaat tambahan dari hierarki ini adalah memungkinkan kita untuk menentukan di mana fungsionalitas berada dengan hanya memeriksa nama kelas. Selain itu, selama pengujian, kami dapat dengan mudah mengganti kelas dengan implementasi tiruan, jika perlu.
Kesalahan Umum # 4: Inkonsistensi dan Penanganan Kesalahan yang Buruk
Topik konsistensi belum tentu eksklusif untuk Spring (atau Jawa, dalam hal ini), tetapi masih merupakan aspek penting untuk dipertimbangkan ketika bekerja pada proyek Spring. Sementara gaya penulisan kode dapat menjadi subjek diskusi (dan biasanya itu adalah masalah kesepakatan pada tim atau seluruh perusahaan), keberadaan standar bersama sangat membantu dalam kinerja. Ini terutama berlaku untuk tim yang terdiri dari beberapa orang. Konsistensi memungkinkan kode untuk ditransmisikan tanpa biaya sumber daya untuk pemeliharaan atau penyediaan penjelasan terperinci mengenai tanggung jawab berbagai kelas.
Pertimbangkan proyek Pegas dengan berbagai file konfigurasi, layanan, dan pengontrol. Menjadi semantik konsisten dalam penamaan mereka, struktur yang mudah dicari dibuat di mana setiap pengembang baru dapat mengontrol cara bekerja dengan kode: misalnya, akhiran Config ditambahkan ke kelas konfigurasi, akhiran Layanan untuk layanan dan akhiran pengontrol untuk pengontrol.
Terkait erat dengan topik konsistensi, penanganan kesalahan sisi server patut mendapat perhatian khusus. Jika Anda pernah harus menangani jawaban pengecualian dari API yang ditulis dengan buruk, Anda mungkin tahu mengapa bisa menyakitkan untuk menguraikan pengecualian, dan bahkan lebih sulit untuk menentukan alasan mengapa pengecualian ini awalnya terjadi.
Sebagai pengembang API, idealnya Anda ingin mencakup semua titik akhir pengguna dan menerjemahkannya ke dalam format kesalahan umum. Ini biasanya berarti bahwa Anda memiliki kode kesalahan umum dan deskripsi, dan bukan hanya alasan dalam bentuk: a) mengembalikan pesan "500 Internal Server Error" atau b) hanya menyetel ulang jejak tumpukan ke pengguna (yang harus dihindari dengan cara apa pun, karena itu menunjukkan bagian dalam Anda selain kompleksitas pemrosesan di sisi klien).
Contoh format respons kesalahan umum mungkin:
@Value public class ErrorResponse { private Integer errorCode; private String errorMessage; }
Sesuatu yang serupa biasanya ditemukan di sebagian besar API populer dan biasanya berfungsi dengan baik, karena dapat dengan mudah dan sistematis didokumentasikan. Anda dapat menerjemahkan pengecualian ke dalam format ini dengan memberikan metode dengan anotasi @ExceptionHandler (contoh anotasi diberikan dalam Kesalahan Umum # 6).
Kesalahan Umum # 5: Multithreading yang salah
Terlepas dari apakah itu ditemukan di aplikasi desktop atau web, di Spring atau tidak di Spring, multithreading dapat menjadi tugas yang menakutkan. Masalah yang disebabkan oleh menjalankan program paralel sulit dipahami dan seringkali sangat sulit untuk di-debug - pada kenyataannya, karena sifat masalahnya, setelah Anda memahami bahwa Anda berurusan dengan masalah eksekusi paralel, Anda mungkin harus sepenuhnya meninggalkan debugger dan mulai periksa kode Anda secara manual sampai Anda menemukan penyebab kesalahan. Sayangnya, untuk mengatasi masalah seperti itu tidak ada solusi template. Bergantung pada kasus tertentu, Anda harus menilai situasi dan kemudian menyerang masalah dari sudut yang Anda anggap terbaik.
Idealnya, tentu saja, Anda ingin sepenuhnya menghindari bug multithreading. Sekali lagi, tidak ada pendekatan tunggal untuk ini, tetapi berikut adalah beberapa pertimbangan praktis untuk debugging dan mencegah kesalahan multithreading:
Hindari Status Global
Pertama, selalu ingat masalah "negara global". Jika Anda membuat aplikasi multi-utas, segala hal yang dapat diubah secara global harus dipantau dengan cermat dan, jika mungkin, dihapus sepenuhnya. Jika ada alasan variabel global harus tetap bisa berubah, gunakan
sinkronisasi dengan hati-hati dan pantau kinerja aplikasi Anda untuk mengonfirmasi bahwa itu tidak melambat karena masa tunggu yang baru.
Hindari Mutabilitas
Ini mengikuti langsung dari
pemrograman fungsional dan, menurut OOP, menyatakan bahwa volatilitas kelas dan perubahan status harus dihindari. Singkatnya, hal tersebut di atas berarti keberadaan setter dan bidang akhir pribadi di semua kelas model. Nilai-nilai mereka hanya berubah selama konstruksi. Dengan demikian, Anda dapat yakin bahwa tidak akan ada masalah dalam perlombaan untuk sumber daya dan bahwa mengakses properti dari objek akan selalu memberikan nilai yang benar.
Catat data penting
Evaluasi di mana aplikasi Anda dapat menyebabkan masalah, dan pra-log semua data penting. Jika terjadi kesalahan, Anda akan berterima kasih atas informasi tentang permintaan apa yang diterima dan Anda dapat lebih memahami mengapa aplikasi Anda berperilaku buruk. Sekali lagi, perlu dicatat bahwa logging meningkatkan file I / O, jadi Anda tidak boleh menyalahgunakannya, karena ini dapat secara serius mempengaruhi kinerja aplikasi Anda.
Gunakan kembali implementasi yang ada
Kapan pun Anda perlu membuat utas sendiri (misalnya, untuk melakukan permintaan asinkron ke berbagai layanan), gunakan kembali implementasi aman yang ada, daripada buat solusi Anda sendiri. Sebagian besar, ini berarti menggunakan
ExecutorServices dan
CompletableFutures dengan gaya fungsional Java 8 yang rapi untuk membuat utas. Spring juga memungkinkan pemrosesan permintaan tidak sinkron melalui kelas
DeferredResult .
Kesalahan umum # 6: tidak menggunakan validasi berbasis anotasi
Mari kita bayangkan bahwa layanan TopTalent kami, yang disebutkan di atas, membutuhkan titik akhir untuk menambahkan Super Talents baru. Selain itu, anggap bahwa untuk alasan yang sangat bagus, setiap nama baru harus memiliki panjang 10 karakter. Salah satu cara untuk melakukan ini adalah sebagai berikut:
@RequestMapping("/put") public void addTopTalent(@RequestBody TopTalentData topTalentData) { boolean nameNonExistentOrHasInvalidLength = Optional.ofNullable(topTalentData) .map(TopTalentData::getName) .map(name -> name.length() == 10) .orElse(true); if (nameNonExistentOrInvalidLength) {
Namun, hal di atas (selain dirancang dengan buruk) sebenarnya bukan solusi "bersih". Kami memeriksa lebih dari satu jenis validitas (yaitu, bahwa TopTalentData bukan nol, dan TopTalentData.name tidak nol, dan TopTalentData.name panjangnya 10 karakter), dan juga memberikan pengecualian jika data tidak valid.
Ini dapat dilakukan dengan lebih bersih menggunakan
validator Hibernate dengan Spring. Pertama, kami menulis ulang metode addTopTalent untuk mendukung validasi:
@RequestMapping("/put") public void addTopTalent(@Valid @NotNull @RequestBody TopTalentData topTalentData) { topTalentService.addTopTalent(topTalentData); } @ExceptionHandler @ResponseStatus(HttpStatus.BAD_REQUEST) public ErrorResponse handleInvalidTopTalentDataException(MethodArgumentNotValidException methodArgumentNotValidException) {
Selain itu, kita harus menunjukkan properti mana yang ingin kita periksa di kelas TopTalentData:
public class TopTalentData { @Length(min = 10, max = 10) @NotNull private String name; }
Spring sekarang akan memotong permintaan dan memverifikasinya sebelum memanggil metode - tidak perlu menggunakan tes manual tambahan.
Cara lain kita dapat mencapai hal yang sama adalah dengan membuat anotasi kita sendiri. Meskipun anotasi khusus biasanya digunakan hanya ketika kebutuhan Anda melebihi
konstanta bawaan Hibernate , untuk contoh ini, mari kita bayangkan bahwa anotasi
Panjang tidak ada. Anda harus membuat validator yang memeriksa panjang string dengan membuat dua kelas tambahan, satu untuk memeriksa dan satu untuk properti anotasi:
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @Documented @Constraint(validatedBy = { MyAnnotationValidator.class }) public @interface MyAnnotation { String message() default "String length does not match expected"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; int value(); } @Component public class MyAnnotationValidator implements ConstraintValidator<MyAnnotation, String> { private int expectedLength; @Override public void initialize(MyAnnotation myAnnotation) { this.expectedLength = myAnnotation.value(); } @Override public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) { return s == null || s.length() == this.expectedLength; } }
Perhatikan bahwa dalam kasus ini, praktik terbaik untuk pemisahan tugas mengharuskan Anda menandai properti sebagai valid jika itu nol (s == null dalam metode isValid), dan kemudian menggunakan anotasi
NotNull jika ini merupakan persyaratan tambahan untuk properti:
public class TopTalentData { @MyAnnotation(value = 10) @NotNull private String name; }
Kesalahan Umum # 7: Menggunakan Konfigurasi XML (Diam)
Meskipun XML diperlukan untuk versi Spring sebelumnya, saat ini sebagian besar konfigurasi dapat dilakukan secara eksklusif dengan kode Java / anotasi. Konfigurasi XML hanya mewakili boilerplate tambahan dan tidak perlu.
Artikel ini (dan repositori GitHub yang menyertainya) menggunakan anotasi untuk mengonfigurasi Spring dan Spring tahu kacang mana yang harus disambungkan karena paket root dianotasi menggunakan anotasi senyawa @SpringBootApplication, misalnya:
@SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
Anotasi komposit ini (Anda dapat mempelajari lebih lanjut tentang hal itu dalam dokumentasi
Spring ) hanya memberi Spring petunjuk tentang paket mana yang harus dipindai untuk mengekstrak kacang. Dalam kasus khusus kami, ini berarti bahwa kelas-kelas berikut akan digunakan untuk menghubungkan kacang, dimulai dengan paket tingkat atas (co.kukurin):
@Component (TopTalentConverter, MyAnnotationValidator) @RestController (TopTalentController) @Repository (TopTalentRepository) @Service (TopTalentService)
@Component (TopTalentConverter, MyAnnotationValidator) @RestController (TopTalentController) @Repository (TopTalentRepository) @Service (TopTalentService)
@Component (TopTalentConverter, MyAnnotationValidator) @RestController (TopTalentController) @Repository (TopTalentRepository) @Service (TopTalentService)
@Component (TopTalentConverter, MyAnnotationValidator) @RestController (TopTalentController) @Repository (TopTalentRepository) @Service (TopTalentService)
Jika kita memiliki kelas tambahan yang dijelaskan dengan @Configuration, mereka juga akan diperiksa untuk konfigurasi Java.
Kesalahan umum nomor 8: lupakan profil
Masalah yang sering dihadapi ketika mengembangkan server adalah perbedaan antara berbagai jenis konfigurasi, biasanya konfigurasi industri dan pengembangan. Alih-alih mengubah berbagai parameter konfigurasi secara manual setiap kali Anda beralih dari pengujian ke penerapan aplikasi, cara yang lebih efisien adalah dengan menggunakan profil.
Pertimbangkan kasus ini saat Anda menggunakan basis data dalam memori untuk pengembangan lokal dan basis data MySQL di PROM. Intinya, ini berarti Anda akan menggunakan URL yang berbeda dan (semoga) kredensial yang berbeda untuk mengaksesnya masing-masing. Mari kita lihat bagaimana hal ini dapat dilakukan dengan dua file konfigurasi yang berbeda:
APLIKASI FILE.YAML
# set default profile to 'dev' spring.profiles.active: dev # production database details spring.datasource.url: 'jdbc:mysql://localhost:3306/toptal' spring.datasource.username: root spring.datasource.password:
APLIKASI FILE-DEV.YAML
spring.datasource.url: 'jdbc:h2:mem:' spring.datasource.platform: h2
Tampaknya, Anda tidak ingin secara tidak sengaja melakukan tindakan apa pun pada basis data industri Anda saat Anda mengacaukan kode, jadi masuk akal untuk mengatur profil default di dev. Kemudian di server, Anda dapat secara manual mengganti profil konfigurasi dengan menentukan parameter -Dspring.profiles.active = prod untuk JVM. Selain itu, Anda juga dapat mengatur variabel lingkungan OS ke profil default yang diinginkan.
Kesalahan Umum # 9: Ketidakmampuan untuk Menerima Injeksi Ketergantungan
Penggunaan injeksi dependensi yang tepat di Spring berarti memungkinkan Anda untuk mengikat semua objek Anda bersama dengan memindai semua kelas konfigurasi yang diperlukan; ini berguna untuk memisahkan hubungan, dan juga membuat pengujian lebih mudah. Alih-alih kelas yang menghubungkan keras, dengan melakukan sesuatu seperti ini:
public class TopTalentController { private final TopTalentService topTalentService; public TopTalentController() { this.topTalentService = new TopTalentService(); } }
Kami membiarkan Spring melakukan pengikatan untuk kami:
public class TopTalentController { private final TopTalentService topTalentService; public TopTalentController(TopTalentService topTalentService) { this.topTalentService = topTalentService; } }
Misko Hevery dari Google talk menjelaskan secara rinci "alasan" untuk injeksi ketergantungan, jadi mari kita lihat bagaimana ini digunakan dalam praktik. Dalam pembagian tanggung jawab (Kesalahan Umum # 3), kami menciptakan kelas layanan dan pengontrol. Misalkan kita ingin menguji controller dengan asumsi bahwa TopTalentService berperilaku dengan benar. Kami dapat menyisipkan objek tiruan alih-alih implementasi layanan yang sebenarnya, memberikan kelas konfigurasi terpisah:
@Configuration public class SampleUnitTestConfig { @Bean public TopTalentService topTalentService() { TopTalentService topTalentService = Mockito.mock(TopTalentService.class); Mockito.when(topTalentService.getTopTalent()).thenReturn( Stream.of("Mary", "Joel") .map(TopTalentData::new).collect(Collectors.toList())); return topTalentService; } }
Kemudian kita bisa menyematkan objek tiruan dengan memberi tahu Spring untuk menggunakan SampleUnitTestConfig sebagai penyedia konfigurasi:
@ContextConfiguration(classes = { SampleUnitTestConfig.class })
Maka ini akan memungkinkan kita untuk menggunakan konfigurasi konteks untuk menanamkan kacang kustom dalam pengujian unit.
Kesalahan umum # 10: kurangnya pengujian atau pengujian yang salah
Terlepas dari kenyataan bahwa ide pengujian unit telah bersama kami untuk waktu yang lama, banyak pengembang tampaknya "lupa" untuk melakukan ini (terutama jika ini tidak perlu), atau cukup tinggalkan untuk nanti. Jelas, ini tidak diinginkan, karena tes tidak hanya memverifikasi kebenaran kode Anda, tetapi juga berfungsi sebagai dokumentasi tentang bagaimana aplikasi harus berperilaku dalam situasi yang berbeda.
Saat menguji layanan web, Anda jarang melakukan tes unit "bersih" yang luar biasa, karena interaksi melalui HTTP biasanya memerlukan panggilan DispatcherServlet Spring dan melihat apa yang terjadi ketika HttpServletRequest yang sebenarnya diterima (yang menjadikannya uji integrasi, dengan menggunakan validasi, serialisasi, dll.).
REST Assured - Java DSL untuk dengan mudah menguji layanan REST di atas MockMVC telah terbukti menjadi solusi yang sangat elegan.
Pertimbangkan fragmen kode berikut dengan injeksi dependensi: @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = { Application.class, SampleUnitTestConfig.class }) public class RestAssuredTestDemonstration { @Autowired private TopTalentController topTalentController; @Test public void shouldGetMaryAndJoel() throws Exception {
SampleUnitTestConfig memungkinkan implementasi tiruan TopTalentService di TopTalentController, sementara semua kelas lainnya terhubung menggunakan konfigurasi standar yang diperoleh dengan memindai paket yang berakar pada paket kelas aplikasi. RestAssuredMockMvc hanya digunakan untuk menciptakan lingkungan yang ringan dan mengirim permintaan GET ke / toptal / get endpoint.Menjadi Master Musim Semi
Musim semi adalah kerangka kerja yang kuat yang mudah untuk memulai, tetapi membutuhkan dedikasi dan waktu untuk mencapai penguasaan penuh. Jika Anda menghabiskan waktu untuk mengenal kerangka kerja, itu pasti akan meningkatkan produktivitas Anda dalam jangka panjang dan pada akhirnya membantu Anda menulis kode yang lebih bersih dan menjadi pengembang yang lebih baik.Jika Anda mencari sumber daya tambahan, Spring In Action adalah buku praktik bagus yang mencakup banyak topik inti Spring.TAGSJava SpringFrameworkKomentar
Timothy SchimandlePada # 2, saya berpikir bahwa mengembalikan objek domain lebih disukai dalam banyak kasus. Contoh objek kustom Anda adalah salah satu dari beberapa kelas yang memiliki bidang yang ingin kami sembunyikan. Tetapi sebagian besar objek yang saya kerjakan tidak memiliki batasan seperti itu, dan menambahkan kelas dto hanya kode yang tidak perlu.Semua dalam semua artikel yang bagus. Kerja bagusSPIRITED ke Timothy Schimandle,saya sepenuhnya setuju. Sepertinya lapisan kode tambahan yang tidak perlu telah ditambahkan, saya pikir @JsonIgnore akan membantu untuk mengabaikan bidang (walaupun dengan kelemahan dalam strategi deteksi repositori default), tetapi secara keseluruhan ini adalah posting blog yang bagus. Bangga tersandung ...Arokiadoss AsirvathamBung, kesalahan pemula yang umum lainnya adalah: 1) Ketergantungan Siklik, dan 2) ketidakpatuhan terhadap doktrin deklarasi Kelas Singleton dasar, seperti menggunakan variabel instan dalam kacang dengan cakupan singleton.HlodowigMengenai nomor 8, saya percaya bahwa pendekatan ke profil sangat tidak memuaskan. Mari kita lihat:- Keamanan: beberapa orang mengatakan: jika repositori Anda bersifat publik, apakah akan ada kunci / kata sandi rahasia? Kemungkinan besar, akan begitu, mengikuti pendekatan ini. Kecuali, tentu saja, Anda menambahkan file config ke .gitignore, tetapi ini bukan opsi yang serius.
- Duplikasi: setiap kali saya memiliki pengaturan yang berbeda, saya harus membuat file properti baru, yang sangat mengganggu.
- Portabilitas: Saya tahu ini hanya satu argumen JVM, tetapi nol lebih baik dari satu. Kesalahan cenderung jauh lebih kecil.
Saya mencoba menemukan cara untuk menggunakan variabel lingkungan dalam file konfigurasi saya daripada "hard coding" nilai-nilai, tetapi sejauh ini saya belum berhasil, saya pikir saya perlu melakukan penelitian lebih lanjut.Artikel bagus Tony, terus bekerja dengan baik!Terjemahan selesai: tele.gg/middle_java