1. Latar belakang
Artikel yang saya tulis di sini adalah karena seorang teman bertanya apa perbedaan antara pengecualian yang diperiksa dan pengecualian yang tidak dicentang di Java. Jawaban saya untuk itu adalah: Saya hanya menggunakan runtimeException saat pemrograman. Sebenarnya, saya memiliki premis ketika saya mengatakan sesuatu. Saya harus mengatakannya dengan tepat: Saya hanya menggunakan atau memperhatikan RuntimeException ketika menulis kode bisnis di bawah kerangka pengembangan yang matang. Karena, karena kerangka kerja sering merangkum penanganan pengecualian secara seragam, sehingga pemrogram dapat lebih memperhatikan kode bisnis, dan beberapa kesalahan bisnis biasanya terjadi selama menjalankan sistem, pengecualian bisnis biasanya dirancang sebagai subclass runtimeException.
Jawaban saya jelas tidak bisa memuaskan teman -teman saya! Karena, tidak peduli siapa yang pemula di Java, kami menggunakan banyak cobalah ... Tangkap ... ketika kami belajar kelas IO dan pemrograman JDBC, jenis percobaan yang berulang ini akan membuat kami mengingat pengecualian Java! Pemula sering tidak tahu mengapa pengecualian Java dirancang seperti ini. Mereka biasanya hanya memproses pengecualian hanya - cukup cetak pengecualian di blok tangkapan, dan pernyataan yang paling umum digunakan adalah:
E.PrintStackTrace ().
Kami juga memiliki pengecualian seperti memori seperti batas lintas array:
java.lang.ArrayIndExoutOfBoundsException: 6
Ini juga akan membuat kita mengingatnya segar, karena sering muncul ketika kita men -debug program! Kami akan menemukan bahwa pengecualian jenis ini tidak perlu menggunakan mencoba ... tangkap ... untuk menangkapnya dalam kode.
Dua contoh di atas sebenarnya adalah pengecualian yang diperiksa dan pengecualian yang tidak dicentang yang diminta oleh seorang teman. Pengecualian yang membutuhkan cobalah ... Tangkap ... adalah pengecualian yang diperiksa, dan pengecualian yang tidak dicentang adalah pengecualian yang tidak dicentang. Jika saya ingin berbicara tentang perbedaan mereka, saya mengatakan bahwa salah satu dari mereka ingin mencoba ... menangkap ... dan yang lain tidak membutuhkannya. Apakah jawaban ini oke? Saya pikir jawaban ini pucat. Beberapa siswa akan mengatakan lebih lanjut bahwa mencoba ... tangkapan jelas merupakan metode penelepon yang memaksa pengecualian untuk dilemparkan secara eksplisit. Apakah E.PrintStackTrace () mempertimbangkan pengecualian pemrosesan? Saya pikir itu hanya cara sederhana dan malas untuk menghadapinya! Jadi metode penanganan seperti apa yang dianggap pintar? Perancang bahasa Java sebenarnya mengharapkan bahwa setelah pengecualian terjadi, penelepon dapat mengembalikan pengecualian dalam tangkapan sehingga program dapat terus mengeksekusi. Namun, "programmer pintar malas." Hehe. Dalam kebanyakan kasus, kami memilih untuk merekam log dan petunjuk pengguna UI setelah pengecualian muncul. Kemudian, saya akan menggabungkan kerangka kerja jersey untuk membicarakan penanganan pengecualian terpadu. Setelah membaca ini, beberapa orang akan mengatakan bahwa perbedaan antara pengecualian yang diperiksa dan pengecualian yang tidak dicentang adalah bahwa satu perlu diproses dan yang lain tidak perlu diproses. Apakah jawaban ini benar? Saya pikir itu salah! Maksud saya adalah: kita harus menghadapinya apakah itu pengecualian yang diperiksa atau pengecualian yang tidak dicentang!
Pada paragraf sebelumnya, kami tampaknya masih belum menyelesaikan perbedaan antara pengecualian yang diperiksa dan pengecualian yang tidak dicentang. Saya tidak berpikir penting untuk memberikan jawabannya. Yang penting adalah bagaimana kami menangani pengecualian ini dan bagaimana kami menggunakan pengecualian selama pengembangan.
Maksud saya adalah (pengembangan sistem web):
1. Merangkum pengecualian yang diperiksa di tingkat kerangka kerja dan mengubahnya menjadi pengecualian yang tidak dicentang untuk menghindari menulis yang membosankan, coba ... Tangkap kode selama pengembangan.
2. Pengembangan tingkat bisnis, mendefinisikan runtimeExceptions yang berbeda sesuai dengan tanggung jawab kode program (ini adalah pengecualian yang tidak terkendali, umumnya didefinisikan sebagai subkelas dari runimeException)
3. Melalui dua tampilan pertama, pengecualian khusus dalam sistem hanya akan memiliki pengecualian yang tidak terkendali, dan sistem hanya akan berada di lapisan atas klien pertukaran data, mengatur mekanisme penanganan pengecualian terpadu, dan mengubah beberapa pengecualian menjadi informasi yang dapat dipahami dan disampaikan pengguna kepada pengguna.
4. Lainnya seperti lapisan bisnis, lapisan kegiatan data, dll., Hanya bertanggung jawab untuk melempar pengecualian, tetapi berhati -hatilah untuk tidak kehilangan tumpukan pengecualian (ini adalah kesalahan yang cenderung dilakukan oleh pemula).
Latar belakangnya cukup panjang! Mari kita sampai pada intinya dan lihat bagaimana penangan pengecualian terpadu dari kerangka kerja Jersey digunakan!
2. Mekanisme Penanganan Pengecualian Terpadu dari Kerangka Jersey
Ada perjanjian berikut:
1. Contohnya menggunakan versi jersey1.x
2. Versi musim semi adalah 2.5
3. Untuk kesederhanaan, proyek sampel tidak menggunakan mekanisme Maven
Contoh Deskripsi Skenario Bisnis:
1. Kami membaca file konfigurasi properti, dan konten file konfigurasi adalah:
key1 = hello key2 = iteye.com
2. Mulai permintaan GET http: // localhost: 8888/a/sumber daya/tes? N = 11, yang membutuhkan n untuk menjadi angka dan harus kurang dari 10. Jika n salah, kesalahan pengecualian yang tidak dicentang akan dihasilkan.
3. Dalam contoh ini, lapisan akses data akan membaca file, dan kesalahan pengecualian yang diperiksa akan terjadi jika file dibaca.
Contoh Desain Struktur Proyek
Deskripsi Cuplikan Kode
1. File penyimpanan data: test.properties
key1 = hello key2 = iteye.com
Ini adalah file yang ingin kami baca, dan untuk kesederhanaan itu adalah file properti.
2. Kelas Akses Data: testdao.java
Paket com.iteeye.redhacker.jersey.dao; import java.io.ioexception; impor java.io.inputstream; impor java.net.url; stereotipe.stereotype.stereotypon. com.iteye.redhacker.jersey.exception.ExceptionCode;@Componentpublic class TestDao {public String saysHello() {ClassLoader classLoader = TestDao.class.getClassLoader();String iniFile = "com/iteye/redhacker/jersey/dao/test.properties";URL url = classLoader.getResource (inifile); inputStream adalah; coba {is = url.openstream ();} catch (ioException e) {throw new DaoException (e, excepticode.read_file_failed); Properti ();} proper.load (url.openstream ());} catch (ioException e) {lempar DaoException baru (e, excepticode.read_config_failed);} akhirnya {if (is is! = Null) {try {isClose (); adalah = null; {if (is null) {try {isclose (); is = null;} tangkap (adalah (adalah! ExceptionCode.colse_file_failed);}}} return proper.getProperty ("key1") + "," + proper.getProperty ("key2");}}}Di kelas ini, semua pengecualian yang diperiksa dikonversi menjadi pengecualian yang tidak dicentang (pengecualian khusus kami). Saat memanggil metode sayhello (), coba ... tangkap ...
3. Kelas Implementasi Bisnis: TestService.java
Paket com.iteeye.redhacker.jersey.service; impor org.springframework.beans.factory.annotation.Autowired; impor org.springframework.stereotype.testdao; impor Com.iteEye.redhacker.jersey.dao.testdao; com.ite -com. com.iteye.redhacker.jersey.exception.serviceException; @ComponentPublic kelas testService {@AutowiredPrivate testDao testdao; Public String Sayshello (int n) {// Bisnis menetapkan bahwa n tidak dapat lebih besar dari 10 if (n> 10) {lemparan baru ServiceException (Excepticode.must_be_less_than_10);} return testdao.sayhello ();}/** * @param testdao The testdao untuk mengatur */public void settestdao (testdao} {this.testdao = testdao (testdao} {this.testdao = testdao;Di kelas ini, kami melempar pengecualian bisnis kami sendiri, yang merupakan pengecualian yang tidak terkendali.
CATATAN: Kami menyuntikkan kelas TestDAO menggunakan @Autowired, yang merupakan anotasi yang disediakan oleh Spring; Kami harus memberikan metode yang ditetapkan untuk memberi anotasi atribut, jika tidak, anotasi akan gagal.
4. Kelas Akses Permintaan: TestResources.java
Paket com.iteeye.redhacker.jersey.delegate; impor javax.ws.rs.get; impor javax.ws.rs.path; impor javax.ws.rs.produces; Javax.ws.rs.queryparam; impor javax.ws.core.core.mediatype; impor com.ite com.ite com.ite com.ite com. com.sun.jersey.api.spring.autowire; @path ("/test")@autowirepublic class testResources {private testservice testservice;@get@menghasilkan (mediatype.text_plain) public string sayshello (@QueryParam ("n") {public @param. TestService TestService untuk mengatur */public void settestService (testservice testservice) {this.testservice = testservice;}}Berikut adalah sumber daya yang ditentukan oleh Jersey. Kita dapat mengakses sumber daya ini dengan cara ini: memulai permintaan get, mengakses URI adalah /sumber daya /tes, dan lulus parameter kueri n, misalnya: /sumber daya /tes? N = 1
Catatan: Kami menggunakan @Autowire bukan anotasi untuk musim semi, ini adalah anotasi untuk paket integrasi jersey-srping; Kami harus memberikan metode yang ditetapkan untuk memberi anotasi atribut, jika tidak, anotasi akan gagal.
5. Kelas Handler Pengecualian Terpadu: ExceptionMappersupport.java
Paket com.iteeye.redhacker.jersey.jaxrs; import javax.servlet.servletcontext; import javax.servlet.http.httpservletrequest; impor javax.ws.core.context; impor Javax.ws.core.mediatype; javax.ws.rs.core.response.status; import javax.ws.rs.ext.exceptionMapper; import javax.ws.rs.ext.provider; impor org.apache.log4j.logger; impor org.springframework.web.context.webapplecicationc; com.iteye.redhacker.jersey.exception.baseException; import com.iteeye.redhacker.jersey.exception.excepticode; privenporport {nongerporpor {@@proverporport {@providonmporports Logger.getLogger (ExceptionMappersupport.class); string final statis privat context_attribute = webapplicationContext.root_web_application_context_attribute; @contextprivate httpservletrequest * @contextprivate servletContext servletContext; handling*/public Response toResponse(Exception exception) {String message = ExceptionCode.INTERNAL_SERVER_ERROR;Status statusCode = Status.INTERNAL_SERVER_ERROR;WebApplicationContext context = (WebApplicationContext) servletContext.getAttribute(CONTEXT_ATTRIBUTE);// Handle unchecked exceptionif (exception instanceof BaseException) {BaseException Baseexception = (BaseException) Exception; string code = baseException.getCode (); objek [] args = baseException.getValues (); message = context.getMessage (kode, args, exception.getMessage (), request.getLocale ();}}} {exceptEcceptage (exception) {oCectExceptage (excepteCceptage (exception) (excepteCceptage (exception), noLGETLOKLECECECECEPEION (exception) (exception), noLGETLOCECCEPEION (Exception), ExceptionCode.request_not_found; statusCode = status.not_found;} // Diperiksa pengecualian dan pengecualian yang tidak dicentang dicatat dalam log logger.Error (pesan, pengecualian); return response.ok (pesan, mediatype.text_plain) .status (statuscode) .build ();}}Di kelas ini, kami menangani pengecualian yang tidak dicentang yang kami tentukan, dan juga menangani pengecualian sistem yang tidak diketahui (termasuk pengecualian yang tidak diketahui dan pengecualian yang diperiksa). Metode pemrosesan kami adalah: a. Catat log pengecualian; B. Kirim kode status kesalahan standar HTTP standar dan pesan kesalahan ke klien, dan klien menangani informasi kesalahan dengan sendirinya. Perlu dicatat bahwa metode pemrosesan ini dianjurkan oleh istirahat, dan dengan tepat menggunakan kode status standar HTTP;
Di kelas ini, kami juga menggunakan komponen konfigurasi internasional Spring untuk menginternasionalkan kunci kesalahan yang dilemparkan oleh sistem, yang kondusif untuk peningkatan internasionalisasi proyek kami.
6. Kelas Basis Pengecualian Kustom: BaseException.java
Paket com.iteye.redhacker.jersey.exception;/*** Kelas basis pengecualian, pengecualian runtime dari masing -masing modul diwarisi dari kelas ini*/kelas publik Baseexception memperluas runtimeException {/*** serialversionuid*/private static long SerialVersionUID = 1381325441464646666666666464646464646464646464ID; / ** * Kunci Pesan */ Kode String Pribadi; / ** * Params Params */ Private Object [] Nilai; / ** * @return kode */ string publik getCode () {return code; } / ** * @param Kode Kode yang akan mengatur * / public void setCode (kode string) {this.code = kode; } / *** @return Nilai* / objek publik [] getValues () {values return; } / ** * @param nilai nilai yang akan ditetapkan * / public void setValues (objek [] nilai) {this.values = nilai; } public baseexception (pesan string, penyebab yang dapat dilempar, kode string, objek [] nilai) {super (pesan, penyebab); this.code = kode; this.values = nilai; }}Kelas ini mendefinisikan templat dasar kelas pengecualian proyek, dan pengecualian lainnya mewarisi darinya. Perlu dicatat bahwa secara cerdik memanfaatkan beberapa fitur konfigurasi internasional dan bahkan dapat melempar pesan kesalahan yang ditentukan di bawah ini, dan menggunakan kembali pesan kesalahan dengan menyampaikan parameter:
{0} {1} kesalahan parameter
7. Pengecualian lainnya pada dasarnya sama, tetapi jenisnya berbeda. Mari kita lihat di daoException.java
Paket com.iteye.redhacker.jersey.exception; kelas publik DaoException memperluas BaseException {/** * Konstruktor * * @param kode * Kode kesalahan */DAOException publik (Kode String) {Super (NULL, CODE, NULL);}/** KOMPUTOR * * @param Penyebab, NULL, NULL);}/** KOSTRACTOR * * @param Penyebab * KEBUTUHAN EXCRUTE (NULL, NULL);}/** kode) {super (kode, penyebab, kode, null);}/** * konstruktor * * @param kode * kode kesalahan * @param values * satu set informasi pengecualian Parameter tertunda */public daoException (kode string, nilainya * @param (null, null, values, values);}/** Kode ** * Nilai * @param * @param * Paba * PLACK * Informasi Pengecualian Parameter Tertunda */DaoException Publik (Penyebab yang Dapat Dibuat, Kode String, Nilai Objek []) {super (kode, null, kode, nilai);} private static final long serialversionuid = -3711290613973933714l;}Ini mewarisi Baseexception. Ketika pengecualian ini dilemparkan, kami secara langsung membuat penilaian awal dari nama pengecualian, dan kesalahan berasal dari lapisan DAO.
8. errmsg.properties digunakan untuk mendefinisikan informasi pengecualian. Mari kita lihat:
read.file.failed = baca file gagal baca.config.failed = Baca item konfigurasi gagal harus.be.less.than.10 = parameter harus kurang dari 10colse.file.failed = reset file gagal. Not.found = Layanan yang sesuai tidak ditemukan internal.server.error = server internal kesalahan internal internal internal internal internal.found tidak ditemukan internal.server.
AKU AKU AKU. Penyebaran dan pengujian
Anda dapat mengunduh kode sumber dalam lampiran artikel ini. Setelah mengimpor Eclipse, periksa kode sumbernya.
Penyebarannya sangat sederhana, cukup tambahkan tomcat/config/server.xml Anda:
<host> ... <context path = "/a" reloadable = "true" docbase = "d:/workspace/test/jerseyExceptionMappertest/web"/> </shost>
Mulai saja Tomcat!
Lakukan dua tes:
1.
2.
Untuk tes pertama, Anda juga dapat melihat kesalahan pengecualian berikut di log:
[2013-08-15 00:25:55] [Kesalahan] Parameter harus kurang dari 10com.iteye.redhacker.jersey.exception.serviceException: harus.be.less.than.10at com.iteEye.redhacker.jersey.service.testservice.sayhello (testservice.service.testservice.sayhello (testsery com Comeye.redhacker.jersey.delegate.testresources.sayhello (TestResources.java:21) di sun.reflect.nativeMethodaccessorimpl.invoke0 (metode asli) di sun.reflect.nativemethodaccessorcessorcessorcessorcessorcessorcessorcessor: nativaCessorcessorcessorcessorcessorcessorcessorcessorcessorcessorcessorcessor (nativethemokeCessorcessorcessorcessorcessor (nativeAcPessorcessorcessorcessorcessor (nativexessorcessorcessor (nativexessorcessorcessor (nativexessorcessorcl.invoke.invoke.invoke. sun.reflect.delegatingmethodaccessorimpl.invoke (delegatingmethodacessorimpl.java:25) di java.lang.reflect.method.invoke (method.java:597) di com.sun.jersey.spi.container.javamethodinvokerfactory $ 1.invoke (javamethodinvokerfactory.java:60) di com.sun.jersey.spi.container.javamethodinFactory $ 1.invoke (javaminethodiner.javamethodin com.sun.jersey.server.impl.model.method.dispatch.abstractresourcemethodDispatchProvider $ typeoutInvoker._dispatch (AbstractresourcemethodDispatchProvider.java:185) di com.sun.jersey.server.impl.model.method.dispatch.resourceJavamethoddispatcher.dispatch (ResourceJavamethoddispatcher.java:75) di com.sun.jersey.server.impl.uri.rules.httpmethodrule.accept (httpmethodrule.java:288) di com.sun.jersey.server.impl.uri.rules.resourcecclassrule.accepcent (resourcecrulassrules.res108 com.sun.jersey.server.impl.uri.rules.righthandpathrule.accept (righthandpathrule.java:147) di com.sun.jersey.server.impl.uri.rules.rootresourceclassessrule.accepce.acceplass.rules. com.sun.jersey.server.impl.application.webApplicationImpl._handleRequest (webapplicationImpl.java:1483) di com.sun.jersey.server.implication.webappplicationImpl._handlerequest (webapplicationImpl.JAVLICATION.WebApplicationImpl._HandleCreest (webapplicationImpl.JAVPL. com.sun.jersey.server.impl.application.webApplicationImpl.HandLeRequest (WebApplicationImpl.java:1363) di com.sun.jersey.server.implication.webApplicationImpl.handlerequest (webapplicationImpl.java:133.13)
Untuk tes lain, Anda dapat mencobanya, seperti dengan sengaja menghapus tes. Properti. Ketika file yang akan dibaca tidak dapat ditemukan, bagaimana pengecualian yang diperiksa dikonversi menjadi pengecualian yang tidak ditentukan sendiri, dan mencatatnya, mengembalikan kode status kesalahan HTTP standar dan informasi kesalahan kepada klien.
4. Ringkasan
1. Tidak sulit untuk melihat melalui kerangka kerja Jersey bahwa dalam pengembangan proyek web, kami telah menangani pengecualian yang diperiksa dan pengecualian yang tidak dicentang secara seragam mungkin di tingkat kerangka kerja sehingga kami dapat lebih memperhatikan implementasi bisnis.
2. Jika itu adalah proyek non-Web, saya pikir perancang arsitektur program juga harus mencoba menangani pengecualian secara seragam; Jika tidak ditangani secara seragam, ketika pengecualian yang diperiksa ditemui, kita harus menanganinya dengan tepat, alih -alih hanya melakukan e.printstacktrace (); Jika kita tidak dapat memulihkan pengecualian, kita setidaknya harus mencatat informasi kesalahan pengecualian sepenuhnya dalam file log sehingga kesalahan akan diperiksa ketika program berikutnya gagal.
Teks lengkap (akhir)