Rumah  >  Artikel  >  Java  >  Bagaimana untuk mereka bentuk pengecualian Java yang elegan?

Bagaimana untuk mereka bentuk pengecualian Java yang elegan?

王林
王林ke hadapan
2023-04-26 11:25:071140semak imbas

Bilakah anda perlu membuang pengecualian

Mula-mula kita perlu memahami soalan, bilakah kita perlu membuang pengecualian? Pengecualian direka untuk memudahkan penggunaan pembangun, tetapi tidak digunakan secara sembarangan. Sebenarnya, masalah ini sangat mudah Jika anda merasakan bahawa "masalah" tertentu tidak dapat diselesaikan, maka anda boleh membuang pengecualian. Sebagai contoh, jika anda menulis perkhidmatan, dan apabila anda menulis sekeping kod tertentu, anda mendapati bahawa masalah mungkin berlaku, maka sila buang pengecualian Percayalah, ini adalah masa terbaik untuk anda membuang pengecualian.

Apakah jenis pengecualian yang harus dilemparkan

Selepas memahami apabila kita perlu membuang pengecualian, mari kita fikirkan soalan lain Apabila kita benar-benar membuang pengecualian, apakah jenis pengecualian yang harus kita pilih? Adakah pengecualian yang diperiksa atau pengecualian yang tidak ditanda (RuntimeException)? Izinkan saya memberikan contoh untuk menggambarkan masalah ini, bermula dengan pengecualian yang diperiksa Contohnya, jika terdapat logik perniagaan sedemikian, data tertentu perlu dibaca dari fail tertentu Operasi membaca ini mungkin tidak dapat dilakukan kerana masalah lain seperti pemadaman fail. Jika ralat baca berlaku kerana pemerolehan, maka data mesti diperolehi daripada pangkalan data redis atau mysql Rujuk kod berikut (Integer) ialah program kemasukan awam String getKey(kunci Integer){

Nilai rentetan;

cuba {

InputStream inputStream = getFiles("/file/nofile");

//Seterusnya, baca nilai kunci daripada strim dan rujuk

nilai = ...;

} tangkapan (Pengecualian e) {

//Jika pengecualian dilemparkan, ia akan diambil dari mysql atau redis

nilai = ...;

}

}

InputStream awam getFiles(Laluan rentetan) membuang Exception {

Fail fail = Fail(laluan) baharu;

InputStream inputStream = batal;

cuba {

inputStream = BufferedInputStream baharu(FailInputStream(fail) baharu);

} tangkapan (FileNotFoundException e) {

buang Exception baru("Ralat baca I/O",e.getCause());

}

return inputStream;

}

Ok, selepas membaca kod di atas, anda mungkin mempunyai beberapa pemikiran dalam fikiran anda Ternyata pengecualian yang diperiksa boleh mengawal logik kewajipan Ya, betul, anda benar-benar boleh mengawal logik perniagaan melalui pengecualian yang diperiksa, tetapi ingat untuk tidak menggunakan Ia seperti ini. Kita harus bersikap munasabah kerana program itu sendiri adalah prosesnya digunakan dengan cara ini, ia menggunakan pengecualian Peranan yang diperluaskan akan membawa kepada peningkatan kerumitan kod, peningkatan gandingan dan mengurangkan kebolehbacaan kod. Jadi kita tidak boleh menggunakan pengecualian sedemikian? Sebenarnya, tidak, apabila benar-benar terdapat keperluan sedemikian, kita boleh menggunakannya dengan cara ini, tetapi ingat untuk tidak benar-benar menganggapnya sebagai alat atau cara untuk mengawal proses. Jadi bilakah pengecualian sedemikian perlu dibuang? Perlu dipertimbangkan bahawa jika pemanggil membuat ralat dalam panggilan, pemanggil mesti dibenarkan untuk mengendalikan ralat tersebut Hanya apabila keperluan tersebut dipenuhi, kami akan mempertimbangkan untuk menggunakan pengecualian yang diperiksa.

Seterusnya, mari kita lihat pengecualian yang tidak ditanda (RuntimeException). Kita sebenarnya melihat banyak pengecualian seperti RuntimeException, seperti java.lang.NullPointerException/java.lang.IllegalArgumentException, dll. Jadi bilakah kita membuang pengecualian seperti ini? Apabila kita menulis kaedah tertentu, kita mungkin mengalami ralat secara tidak sengaja RuntimeException dilemparkan pada masa ini Sebagai contoh, apabila laluan diluluskan, objek Fail yang sepadan dengan laluan perlu dikembalikan:

ujian kekosongan awam() {

myTest.getFiles("");

}

public File getFiles(Laluan rentetan) {

if(null == laluan || "".sama dengan(laluan)){

buang NullPointerException baharu("Laluan tidak boleh kosong!");

}

Fail fail = Fail(laluan);

kembalikan fail;

}

Contoh di atas menunjukkan bahawa jika laluan kosong apabila pemanggil memanggil getFiles(String), maka pengecualian penuding nol (yang merupakan subkelas RuntimeException) akan dilemparkan, dan pemanggil tidak perlu melakukan percubaan secara eksplisit... operasi tangkap... untuk pemprosesan paksa Ini memerlukan pemanggil untuk mengesahkan dahulu apabila memanggil kaedah sedemikian untuk mengelakkan RuntimeException Seperti berikut:

Pengecualian yang manakah harus digunakan

Melalui penerangan dan contoh di atas, kita boleh membuat kesimpulan Perbezaan antara RuntimeException dan pengecualian yang diperiksa ialah: sama ada pemanggil terpaksa mengendalikan pengecualian ini pilih pengecualian yang tidak ditanda (RuntimeException). Secara umumnya, jika tiada keperluan khas, kami mengesyorkan menggunakan RuntimeException.

Pengenalan senario dan pemilihan teknologi

Penerangan Seni Bina

Seperti yang kita ketahui, projek tradisional dibangunkan berdasarkan rangka kerja MVC Artikel ini menggunakan reka bentuk antara muka gaya tenang untuk mengalami keanggunan pengendalian pengecualian.

Kami menumpukan pada lapisan api yang tenang (serupa dengan lapisan pengawal dalam web) dan lapisan perkhidmatan, mengkaji cara pengecualian dilemparkan dalam perkhidmatan, dan kemudian cara lapisan api menangkap dan mengubah pengecualian.

Teknologi yang digunakan ialah: spring-boot, jpa (hibernate), mysql Jika anda tidak biasa dengan teknologi ini, pembaca perlu membaca sendiri bahan yang berkaitan.

Penerangan senario perniagaan

Pilih senario perniagaan yang agak mudah, mengambil pengurusan alamat penghantaran dalam e-dagang sebagai contoh Apabila pengguna membeli barang pada terminal mudah alih, mereka perlu mengurus alamat penghantaran Dalam projek, beberapa antara muka API disediakan untuk terminal mudah alih akses. , seperti: tambah alamat penghantaran, padamkan alamat penghantaran, tukar alamat penghantaran, tetapan alamat penghantaran lalai, pertanyaan senarai alamat penghantaran, pertanyaan alamat penghantaran tunggal dan antara muka lain.

Bina kekangan

ok, ini adalah senario perniagaan yang sangat asas yang telah ditetapkan, tidak kira apa jenis operasi API, ia mengandungi beberapa peraturan:

Tambahkan alamat penghantaran:

Bahan-bahan:

Id pengguna

Maklumat entiti alamat penghantaran

Kekangan:

Id pengguna tidak boleh kosong dan pengguna ini memang wujud

Medan yang diperlukan untuk alamat penghantaran tidak boleh kosong

Jika pengguna belum mempunyai alamat penghantaran, alamat penghantaran akan ditetapkan sebagai alamat penghantaran lalai apabila ia dibuat —

Padamkan alamat penghantaran:

Bahan-bahan:

Id pengguna

ID alamat penghantaran

Kekangan:

Id pengguna tidak boleh kosong dan pengguna ini memang wujud

Alamat penghantaran tidak boleh kosong, dan alamat penghantaran memang wujud

Tentukan sama ada alamat penghantaran ini ialah alamat penghantaran pengguna

Tentukan sama ada alamat penghantaran ini ialah alamat penghantaran lalai Jika ia adalah alamat penghantaran lalai, ia tidak boleh dipadamkan

Tukar alamat penghantaran:

Bahan-bahan:

Id pengguna

ID alamat penghantaran

Kekangan:

Id pengguna tidak boleh kosong dan pengguna ini memang wujud

Alamat penghantaran tidak boleh kosong, dan alamat penghantaran memang wujud

Tentukan sama ada alamat penghantaran ini ialah alamat penghantaran pengguna

Tetapan alamat lalai:

Bahan-bahan:

Id pengguna

ID alamat penghantaran

Kekangan:

Id pengguna tidak boleh kosong dan pengguna ini memang wujud

Alamat penghantaran tidak boleh kosong, dan alamat penghantaran memang wujud

Tentukan sama ada alamat penghantaran ini ialah alamat penghantaran pengguna

Pertanyaan senarai alamat penghantaran:

Bahan-bahan:

Id pengguna

Kekangan:

Id pengguna tidak boleh kosong dan pengguna ini memang wujud

Pertanyaan alamat penghantaran tunggal:

Bahan-bahan:

Id pengguna

ID alamat penghantaran

Kekangan:

Id pengguna tidak boleh kosong dan pengguna ini memang wujud

Alamat penghantaran tidak boleh kosong, dan alamat penghantaran memang wujud

Tentukan sama ada alamat penghantaran ini ialah alamat penghantaran pengguna

Penghakiman kekangan dan pemilihan teknologi

Untuk kekangan dan senarai fungsi yang disenaraikan di atas, saya memilih beberapa senario pengendalian pengecualian biasa untuk analisis: menambah alamat penghantaran, memadamkan alamat penghantaran dan mendapatkan senarai alamat penghantaran.

Jadi apakah rizab pengetahuan yang perlu kita ada? Mari kita lihat fungsi alamat penghantaran:

Apabila menambah alamat penghantaran, ID pengguna dan maklumat entiti alamat penghantaran perlu disahkan Jadi bagaimana kita memilih alat untuk penghakiman tidak kosong? Penghakiman tradisional adalah seperti berikut:

/**

* Tambah alamat

* @param uid

* @param alamat

* @kembali

*/

public Address addAddress(Integer uid,Alamat alamat){

if(null != uid){

//Proses..

}

kembalikan null;

}

Dalam contoh di atas, jika anda hanya menilai bahawa uid kosong, tidak mengapa Jika anda menilai sama ada beberapa atribut yang diperlukan dalam entiti alamat kosong, ini akan menjadi bencana apabila terdapat banyak medan.

Jadi bagaimana kita harus membuat pertimbangan ini tentang memasukkan parameter Izinkan saya memperkenalkan dua mata pengetahuan kepada anda:

Kelas Prasyarat dalam Jambu Batu melaksanakan pertimbangan banyak kaedah input parameter

Spesifikasi pengesahan JSR 303 (pada masa ini pelaksanaan yang paling lengkap ialah hibernate-validator yang dilaksanakan oleh hibernate)

Jika kedua-dua teknologi cadangan ini digunakan, pertimbangan memasukkan parameter akan menjadi lebih mudah. Adalah disyorkan agar semua orang menggunakan teknologi matang dan kit alat balang ini, yang boleh mengurangkan banyak beban kerja yang tidak perlu. Kita hanya perlu fokus pada logik perniagaan. Daripada menangguhkan lebih banyak masa disebabkan pertimbangan input ini.

Bagaimana untuk mereka bentuk pengecualian java dengan elegan

pengenalan domain

Mengikut senario projek, dua model domain diperlukan, satu ialah entiti pengguna dan satu lagi ialah entiti alamat.

Domain alamat adalah seperti berikut:

@Entiti

@Data

Alamat kelas awam {

@Id

@GeneratedValue

id Integer peribadi;

wilayah String persendirian;//wilayah

bandar String persendirian;//bandar

daerah String persendirian;//Daerah

private Boolean isDefault;//Sama ada alamat lalai

@ManyToOne(cascade={CascadeType.ALL})

@JoinColumn(name="uid")

pengguna Pengguna peribadi;

}

Domain pengguna adalah seperti berikut:

@Entiti

@Data

Pengguna kelas awam {

@Id

@GeneratedValue

id Integer peribadi;

nama Rentetan peribadi;//Nama

@OneToMany(cascade= CascadeType.ALL,mappedBy="user",fetch = FetchType.LAZY)

set peribadi

}

Ok, di atas ialah hubungan model, dan hubungan antara pengguna dan alamat penghantaran ialah hubungan 1-n. @Data di atas menggunakan alat yang dipanggil lombok, yang menjana kaedah Setter dan Getter secara automatik, yang sangat mudah digunakan Pembaca yang berminat boleh mempelajarinya sendiri.

pengenalan dao

Untuk lapisan sambungan data, kami menggunakan rangka kerja spring-data-jpa, yang memerlukan kami hanya mewarisi antara muka yang disediakan oleh rangka kerja dan menamakan kaedah mengikut konvensyen untuk melengkapkan operasi pangkalan data yang kami inginkan.

Operasi pangkalan data pengguna adalah seperti berikut:

@Repositori

antara muka awam IUserDao memanjangkan JpaRepository {

}

Operasi alamat penghantaran adalah seperti berikut:

@Repositori

antara muka awam IAddressDao memanjangkan JpaRepository }

Seperti yang pembaca boleh lihat, DAO kami hanya perlu mewarisi JpaRepository, dan ia telah membantu kami menyelesaikan CURD asas dan operasi lain Jika anda ingin mengetahui lebih lanjut tentang projek spring-data, sila rujuk dokumentasi rasmi musim bunga penyelidikan tentang anomali.

Reka bentuk pengecualian perkhidmatan

ok, akhirnya kami telah mencapai tumpuan kami. Kami perlu menyelesaikan beberapa operasi perkhidmatan: tambah alamat penghantaran, padam alamat penghantaran dan dapatkan senarai alamat penghantaran Mula-mula lihat definisi antara muka perkhidmatan saya:

antara muka awam IAddressService {

/**

* Cipta alamat penghantaran

* @param uid

* @param alamat

* @kembali

*/

Alamat createAddress(Integer uid,Alamat alamat);

/**

* Padamkan alamat penghantaran

* @param uid

* @param bantuan

*/

void deleteAddress(Integer uid,Integer aid);

/**

* Tanya semua alamat penghantaran pengguna

* @param uid

* @kembali

*/

Senaraikan senaraikanAlamat(Integer uid);

}

Mari fokus pada pelaksanaan:

Tambahkan alamat penghantaran

Mula-mula, mari kita lihat kekangan yang disusun sebelum ini:

Bahan-bahan:

Id pengguna

Maklumat entiti alamat penghantaran

Kekangan:

Id pengguna tidak boleh kosong dan pengguna ini memang wujud

Medan yang diperlukan untuk alamat penghantaran tidak boleh kosong

Jika pengguna belum mempunyai alamat penghantaran, alamat penghantaran akan ditetapkan sebagai alamat penghantaran lalai apabila ia dibuat

Mari kita lihat pelaksanaan kod berikut dahulu:

@Override

public Address createAddress(Integer uid, Address address) {

//============ Berikut adalah kekangan ==============

//1. Id pengguna tidak boleh kosong dan pengguna ini wujud

Prasyarat.checkNotNull(uid);

Pengguna pengguna = userDao.findOne(uid);

if(null == pengguna){

buang RuntimeException baru("Pengguna semasa tidak ditemui!");

}

//2. Medan yang diperlukan untuk alamat penghantaran tidak boleh kosong

BeanValidators.validateWithException(validator, alamat);

//3. Jika pengguna belum mempunyai alamat penghantaran, tetapkannya sebagai alamat penghantaran lalai apabila alamat penghantaran dibuat

if(ObjectUtils.isEmpty(user.getAddresses())){

address.setIsDefault(true);

}

//============ Berikut ialah logik perniagaan yang biasa dilaksanakan ==============

address.setUser(pengguna);

Keputusan alamat = addressDao.save(alamat);

pulangkan hasil;

}

Antaranya, tiga kekangan yang diterangkan di atas telah selesai Apabila ketiga-tiga kekangan itu dipenuhi, logik perniagaan biasa boleh dijalankan, jika tidak pengecualian akan dilemparkan (biasanya disyorkan untuk membuang pengecualian runtime - RuntimeException di sini) .

Memperkenalkan teknologi berikut yang saya gunakan di atas:

Preconfitions.checkNotNull(T t) dinilai menggunakan com.google.common.base.Praconditions dalam Guava Oleh kerana banyak pengesahan digunakan dalam perkhidmatan, adalah disyorkan untuk menukar Prakonfigurasi kepada import statik:

. 1import statik com.google.common.base.Preconditions.checkNotNull;

Sudah tentu, arahan dalam github Guava juga mengesyorkan agar kami menggunakannya dengan cara ini.

BeanValidators.validateWithException(validator, alamat);

Ini dilakukan menggunakan spesifikasi jsr 303 yang dilaksanakan oleh hibernate Anda perlu lulus dalam validator dan entiti yang perlu disahkan Jadi bagaimana untuk mendapatkan validator, seperti berikut:

@Konfigurasi

kelas awam BeanConfigs {

@Kacang

public javax.validation.Validator getValidator(){

kembalikan LocalValidatorFactoryBean();

}

}

Ia akan mendapat objek Pengesah, dan kemudian kami boleh menyuntiknya dalam perkhidmatan dan menggunakannya:

@Autowired

pengesah Pengesah peribadi ;

Jadi bagaimanakah kelas BeanValidators dilaksanakan? Malah, pelaksanaannya sangat mudah. ​​Hanya menilai anotasi jsr 303 dan ia akan menjadi ok.

Jadi di manakah anotasi jsr 303 ditulis? Sudah tentu ia ditulis dalam kelas entiti alamat:

@Entiti

@Setter

@Getter

Alamat kelas awam {

@Id

@GeneratedValue

id Integer peribadi;

@NotNull

wilayah String persendirian;//wilayah

@NotNull

bandar String persendirian;//bandar

@NotNull

daerah String persendirian;//Daerah

private Boolean isDefault = false;//Adakah ia alamat lalai

@ManyToOne(cascade={CascadeType.ALL})

@JoinColumn(name="uid")

pengguna Pengguna peribadi;

}

Tulis kekangan yang anda perlukan untuk membuat pertimbangan Jika ia munasabah, anda boleh melaksanakan operasi perniagaan dan mengendalikan pangkalan data.

Pengesahan bahagian ini adalah perlu Salah satu sebab utama ialah pengesahan sedemikian boleh mengelakkan pemasukan data kotor. Jika pembaca mempunyai pengalaman dalam talian yang formal, mereka boleh memahami perkara seperti itu Sebarang ralat kod boleh diterima dan diubah suai, tetapi jika masalah data kotor berlaku, ia mungkin menjadi bencana yang dahsyat. Masalah program boleh dibetulkan, tetapi rupa data yang kotor mungkin tidak boleh dipulihkan. Jadi inilah sebabnya anda mesti menentukan kekangan dalam perkhidmatan sebelum melaksanakan operasi logik perniagaan.

Pertimbangan di sini ialah pertimbangan logik perniagaan, yang dibuat daripada perspektif perniagaan Selain itu, mungkin terdapat kekangan keadaan perniagaan yang berbeza dalam banyak senario, dan anda hanya perlu melakukannya mengikut keperluan.

Ringkasan kekangan adalah seperti berikut:

Kekangan pertimbangan asas (pertimbangan asas seperti nilai nol)

Kekangan atribut entiti (memenuhi pertimbangan asas seperti jsr 303)

Kekangan keadaan perniagaan (kekangan perniagaan yang berbeza yang dicadangkan oleh keperluan)

Apabila tiga mata ini berpuas hati, anda boleh meneruskan ke langkah seterusnya

ok, ini pada asasnya memperkenalkan cara membuat pertimbangan asas Mari kita kembali kepada isu reka bentuk pengecualian Kod di atas telah menerangkan dengan jelas cara menilai pengecualian di lokasi yang sesuai.

Adakah hanya membuang RuntimeException dikira sebagai membuang pengecualian dengan anggun? Sudah tentu tidak. Mengenai pengecualian yang dilemparkan dalam perkhidmatan, penulis percaya bahawa terdapat kira-kira dua kaedah membaling:

Melemparkan pengecualian dengan kod status RumtimeException

Melemparkan RuntimeException daripada jenis yang ditentukan

Berbanding dengan dua kaedah pengecualian, pengecualian pertama bermakna semua pengecualian saya membuang pengecualian RuntimeException, tetapi ia perlu mempunyai kod status Pemanggil boleh bertanya jenis perkara yang dilemparkan oleh perkhidmatan berdasarkan kod status.

Jenis pengecualian kedua merujuk kepada menyesuaikan ralat pengecualian yang ditentukan untuk sebarang pengecualian yang dilemparkan dalam perkhidmatan, dan kemudian membuang pengecualian.

Secara umumnya, jika sistem tidak mempunyai keperluan khas lain, adalah disyorkan untuk menggunakan kaedah kedua semasa pembangunan dan reka bentuk. Tetapi sebagai contoh, pengecualian penghakiman asas boleh dikendalikan sepenuhnya menggunakan perpustakaan kelas yang disediakan oleh jambu batu. Pengecualian JSR 303 juga boleh dikendalikan menggunakan kelas penghakiman pengecualian terkapsul mereka sendiri, kerana kedua-dua pengecualian ini adalah pertimbangan asas dan tidak perlu menentukan pengecualian khas untuk mereka. Tetapi untuk pengecualian yang dilemparkan oleh penghakiman kekangan syarat obligasi ketiga, anda perlu membuang pengecualian jenis yang ditentukan.

Untuk

1buang RuntimeException baharu("Pengguna semasa tidak ditemui!");

Tentukan kelas pengecualian khusus untuk menilai pengecualian kewajipan ini:

kelas awam NotFindUserException memanjangkan RuntimeException {

awam NotFindUserException() {

super("Pengguna ini tidak dapat ditemui");

}

awam NotFindUserException(Mesej rentetan) {

super(mesej);

}

}

Kemudian tukar ini kepada:

1buang NotFindUserException baharu("Pengguna semasa tidak ditemui!");

atau

1buang NotFindUserException();

ok, melalui pengubahsuaian di atas pada lapisan perkhidmatan, perubahan kod adalah seperti berikut:

@Override

public Address createAddress(Integer uid, Address address) {

//============ Berikut adalah kekangan ==============

//1. Id pengguna tidak boleh kosong dan pengguna ini wujud

checkNotNull(uid);

Pengguna pengguna = userDao.findOne(uid);

if(null == pengguna){

buang NotFindUserException baharu("Pengguna semasa tidak ditemui!");

}

//2. Medan yang diperlukan untuk alamat penghantaran tidak boleh kosong

BeanValidators.validateWithException(validator, alamat);

//3. Jika pengguna belum mempunyai alamat penghantaran, tetapkannya sebagai alamat penghantaran lalai apabila alamat penghantaran dibuat

if(ObjectUtils.isEmpty(user.getAddresses())){

address.setIsDefault(true);

}

//============ Berikut ialah logik perniagaan yang biasa dilaksanakan ==============

address.setUser(pengguna);

Keputusan alamat = addressDao.save(alamat);

pulangkan hasil;

}

Perkhidmatan sedemikian nampaknya lebih stabil dan mudah difahami.

Padamkan alamat penghantaran:

Bahan-bahan:

Id pengguna

ID alamat penghantaran

Kekangan:

ID pengguna tidak boleh kosong dan pengguna ini memang wujud

Alamat penghantaran tidak boleh kosong, dan alamat penghantaran memang wujud

Tentukan sama ada alamat penghantaran ini ialah alamat penghantaran pengguna

Tentukan sama ada alamat penghantaran ini ialah alamat penghantaran lalai Jika ia adalah alamat penghantaran lalai, ia tidak boleh dipadamkan

Ia serupa dengan menambahkan alamat penghantaran di atas, jadi saya tidak akan menerangkan secara terperinci Reka bentuk perkhidmatan pemadaman adalah seperti berikut: @Override

public void deleteAddress(Integer uid, Integer aid) {

//============ Berikut adalah kekangan ==============

//1. Id pengguna tidak boleh kosong dan pengguna ini wujud

checkNotNull(uid);

Pengguna pengguna = userDao.findOne(uid);

if(null == pengguna){

buang NotFindUserException();

}

//2. Alamat penghantaran tidak boleh kosong, dan alamat penghantaran memang wujud

checkNotNull(bantuan);

Alamat alamat = addressDao.findOne(bantuan);

if(null == alamat){

buang NotFindAddressException();

}

//3. Tentukan sama ada alamat penghantaran ini ialah alamat penghantaran pengguna

if(!address.getUser().equals(user)){

buang NotMatchUserAddressException();

}

//4. Tentukan sama ada alamat penghantaran ini adalah alamat penghantaran lalai. Jika ia adalah alamat penghantaran lalai, ia tidak boleh dipadamkan

if(address.getIsDefault()){

buang DefaultAddressNotDeleteException();

}

//============ Berikut ialah logik perniagaan yang biasa dilaksanakan ==============

addressDao.delete(alamat);

}

Empat kelas pengecualian berkaitan direka: NotFindUserException, NotFindAddressException, NotMatchUserAddressException, DefaultAddressNotDeleteException Pengecualian yang berbeza dilemparkan mengikut keperluan perniagaan yang berbeza.

Dapatkan senarai alamat penghantaran:

Bahan-bahan:

Id pengguna

Kekangan:

Id pengguna tidak boleh kosong dan pengguna ini memang wujud

Kodnya adalah seperti berikut: @Override

Senarai awam senaraikanAlamat(Integer uid) {

//============ Berikut adalah kekangan ==============

//1. Id pengguna tidak boleh kosong dan pengguna ini wujud

checkNotNull(uid);

Pengguna pengguna = userDao.findOne(uid);

if(null == pengguna){

buang NotFindUserException();

}

//============ Berikut ialah logik perniagaan yang biasa dilaksanakan ==============

Keputusan pengguna = userDao.findOne(uid);

return result.getAddresses();

}

Reka bentuk luar biasa API

Terdapat lebih kurang dua kaedah melontar:

Melemparkan pengecualian dengan kod status RumtimeException

Melemparkan RuntimeException daripada jenis yang ditentukan

Ini disebut semasa mereka bentuk pengecualian lapisan perkhidmatan Melalui pengenalan lapisan perkhidmatan, kami memilih kaedah lontaran kedua apabila lapisan perkhidmatan melontar pengecualian, kita perlu menggunakan Terdapat dua cara untuk membuang: anda perlu menentukan jenis pengecualian API dan kod status yang berkaitan sebelum melontar pengecualian Inti reka bentuk pengecualian ini adalah untuk membolehkan pengguna yang memanggil API untuk memahami dengan lebih jelas pengecualian, kami juga perlu membuat jadual yang sepadan untuk memaparkan maklumat terperinci pengecualian yang sepadan dengan kod status dan kemungkinan masalah yang mungkin berlaku dengan pengecualian kepada pengguna untuk memudahkan pertanyaan pengguna. (seperti dokumentasi api yang disediakan oleh github, dokumentasi api yang disediakan oleh WeChat, dsb.), terdapat faedah lain: jika pengguna perlu menyesuaikan mesej gesaan, gesaan boleh diubah suai berdasarkan kod status yang dikembalikan.

kekangan pengesahan api

Pertama sekali, untuk reka bentuk API, perlu ada objek dto Objek ini bertanggungjawab untuk berkomunikasi dan memindahkan data dengan pemanggil, dan kemudian domain dto-> diserahkan kepada perkhidmatan untuk operasi Kedua, Point, sebagai tambahan kepada perkhidmatan yang disebutkan memerlukan pertimbangan asas (penghakiman batal) dan pengesahan jsr 303, lapisan api juga perlu melakukan pengesahan yang berkaitan Jika pengesahan gagal, ia akan dikembalikan terus kepada pemanggil maklumkan panggilan itu gagal dan tidak sepatutnya Jika anda mengakses perkhidmatan dengan data haram, pembaca mungkin sedikit keliru Jika perkhidmatan itu belum disahkan, mengapa lapisan API masih perlu disahkan? Konsep direka di sini: Undang-undang Murphy dalam pengaturcaraan Jika pengesahan data pada lapisan API diabaikan, maka data yang tidak sah boleh dibawa ke lapisan perkhidmatan, dan kemudian data kotor boleh disimpan ke pangkalan data.

Jadi teras pengaturcaraan yang ketat ialah: jangan sekali-kali percaya bahawa data yang diterima adalah sah.

Reka bentuk luar biasa API

Apabila mereka bentuk pengecualian lapisan API, seperti yang kami katakan di atas, anda perlu menyediakan kod ralat dan maklumat ralat Kemudian anda boleh mereka bentuknya seperti ini untuk menyediakan pengecualian kelas super API yang lain yang diwarisi daripada kelas super ini:

ApiException kelas awam memanjangkan RuntimeException {

dilindungi Kod ralat Panjang ;

data Objek dilindungi ;

ApiException awam(Kod ralat panjang, Mesej rentetan, Data objek, Boleh Lempar e){

super(mesej,e);

this.errorCode = errorCode ;

this.data = data ;

}

ApiException awam(Kod ralat panjang, Mesej rentetan, data Objek){

ini(Kod ralat,mesej,data,null);

}

ApiException awam(Kod ralat panjang, Mesej rentetan){

ini(Kod ralat,mesej,null,null);

}

ApiException awam(Mesej rentetan, Boleh Lempar e){

ini(null,mesej,null,e);

}

awam ApiException(){

}

ApiException awam(Boleh Lempar e){

super(e);

}

awam Long getErrorCode() {

pulangkan kod ralat;

}

public void setErrorCode(Long errorCode) {

this.errorCode = errorCode;

}

public Object getData() {

pulangkan data;

}

public void setData(data objek) {

this.data = data;

}

}

然后分别定义api层异常:ApiDefaultAddressNotDeleteException,ApiNotFindAddressException,ApiNotFindUserException,ApiNotMatchUserAddressException。

以默认地址不能删除为例:

kelas awam ApiDefaultAddressNotDeleteException memanjangkan ApiException {

awam ApiDefaultAddressNotDeleteException(Mesej rentetan) {

super(AddressErrorCode.DefaultAddressNotDeleteErrorCode, mesej, null);

}

}

AddressErrorCode.DefaultAddressNotDeleteErrorCode就是需要提供给调用者的错误码。错误码类如下:

kelas abstrak awam AddressErrorCode {

awam statik akhir Long DefaultAddressNotDeleteErrorCode = 10001L;//默认地址不能删除

akhir statik awam Long NotFindAddressErrorCode = 10002L;//找不到此收货地址

akhir statik awam Long NotFindUserErrorCode = 10003L;//找不到此用户

akhir statik awam Long NotMatchUserAddressErrorCode = 10004L;//用户与收货地址不匹配

}

ok,那么api层的异常就已经设计完了,在此多说一句,AddressErrorCode错误码类存放了可耶说的话做法是把他放到配置文件中进行管理。

api处理异常

api层会调用service层,然后来处理service中出现的所有异常,首先,需要保证一点,一定要论一定要讝一定市讚了一个转发的功能就好(接口参数,传递给service参数,返回给调用者数据,这三个基本功能),然后就要在传递给service参数的那个方法调用。 🎜>

此处仅以添加地址为例:

@Autowired

alamat IAddressService peribadiService;

/**

* Tambahkan alamat penghantaran

* @param addressDTO

* @kembali

*/

@RequestMapping(method = RequestMethod.POST)

public AddressDTO add(@Valid @RequestBody AddressDTO addressDTO){

Alamat alamat = Alamat baru();

BeanUtils.copyProperties(alamatDTO,alamat);

Keputusan alamat;

cuba {

result = addressService.createAddress(addressDTO.getUid(), address);

}tangkap (NotFindUserException e){

buang ApiNotFindUserException baharu("找不到该用户");

}tangkap (Pengecualian e){//未知错误

buang ApiException(e) baharu;

}

AddressDTO resultDTO = new AddressDTO();

BeanUtils.copyProperties(result,resultDTO);

resultDTO.setUid(result.getUser().getId());

pulangkan hasilDTO;

}

layanan常用的一种异常转化方式。相似删除收货地址和获取收货地址也类似这样处理,在此,不在赘述。

api异常转化

已经讲解了如何抛出异常和何如将service异常转化为api异常,那么转化成api异常更小异常处理呢? 答案是否定的,当抛出api异常后,我们需要把api异常返回的数据(json atau xml)让用户看懂,那么需要把api异常转化成dto对象(ErrorDTO),看如下下代玜: kelas ApiExceptionHandlerAdvice {

/**

* Tangani pengecualian yang dilemparkan oleh pengendali.

*/

@ExceptionHandler(value = Exception.class)

@ResponseBody

Public ResponseEntity exception(Exception exception,HttpServletResponse response) {

ErrorDTO errorDTO = new ErrorDTO();

if(exception instanceof ApiException){//api异常

ApiException apiException = (ApiException)exception;

errorDTO.setErrorCode(apiException.getErrorCode());

}else{//未知异常

errorDTO.setErrorCode(0L);

}

errorDTO.setTip(exception.getMessage());

ResponseEntity responseEntity = ResponseEntity baharu<>(errorDTO,HttpStatus.valueOf(response.getStatus()));

return responseEntity;

}

@Setter

@Getter

kelas ErrorDTO{

Kod ralat Panjang peribadi;

petua Rentetan peribadi;

}

}

ok, 这样就完成了api异常转化成用户可以读懂的DTO对象了,代码中用到了@ControllerAdvice用户可以读懂的DTO对象了,代码中用到了@ControllerAdvice用户可以读懂的DTO对象了,代码中用到了@ControllerAdvice用我曾更新了中文切面处理。

Apabila pengecualian berlaku semasa memanggil antara muka API, pengguna juga boleh menerima format data biasa Contohnya, apabila tiada pengguna (uid ialah 2), tetapi alamat penghantaran ditambahkan untuk pengguna ini, posmen (pemalam Google digunakan. untuk mensimulasikan permintaan http) Data:

{

"Kod ralat": 10003,

"tip": "Pengguna tidak dapat ditemui"

}

Atas ialah kandungan terperinci Bagaimana untuk mereka bentuk pengecualian Java yang elegan?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:yisu.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam