Backend menyediakan layanan, biasanya mengembalikan string JSON, tetapi dalam beberapa skenario, mungkin perlu untuk secara langsung mengembalikan aliran biner, seperti antarmuka pengeditan gambar, berharap untuk secara langsung mengembalikan aliran gambar ke frontend. Apa yang bisa dilakukan saat ini?
Penggunaan utama adalah objek httpservletResponse, dan kasus ini diimplementasikan sebagai berikut
@RequestMapping(value = {"/img/render"}, method = {RequestMethod.GET, RequestMethod.POST, RequestMethod.OPTIONS})@CrossOrigin(origins = "*")@ResponseBodypublic String execute(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) { // IMG adalah aliran biner byte gambar [] img = xxx; httpservletResponse.setContentType ("gambar/png"); OutputStream os = httpservletResponse.getoutputStream (); os.write (img); os.flush (); os.close (); mengembalikan "sukses";}Hal -hal yang perlu diperhatikan
Secara umum, antarmuka layanan yang disediakan oleh backend sering mengembalikan data JSON. Seperti yang disebutkan sebelumnya, adegan gambar yang secara langsung, jadi apa cara umum untuk mengembalikan gambar?
Jadi bagaimana seharusnya pengontrol yang kami berikan dukungan untuk tiga postur penggunaan di atas secara bersamaan?
Karena ada beberapa cara berbeda untuk kembali, seperti yang harus dipilih, tentu saja itu ditentukan oleh front-end, sehingga Anda dapat mendefinisikan objek kacang yang meminta parameter.
@DataPublic Class BaseRequest {private static final long serialversionuid = 1146303518394712013l; / ** * Metode gambar output: * * URL: Alamat http (metode default) * base64: base64 encoding * Stream: Direct Return Image * */ Private String OutType; /*** Mengembalikan tipe gambar* jpg | png | Webp | gif */ mediatype string pribadi; public returnTypeenum returnType () {return returnTypeenum.getEnum (outType); } mediatypeenum mediatype () {return mediatypeenum.getenum (mediatype); }}Untuk menyederhanakan penilaian, dua anotasi didefinisikan, satu returntypeenum dan yang lainnya mediatypeenum. Tentu saja, kebutuhan itu tidak terlalu bagus. Berikut ini adalah definisi keduanya.
public enum returntypeenum {url ("url"), stream ("stream"), base64 ("base"); tipe string pribadi; ReturnTypeenum (string type) {this.type = type; } peta statis pribadi <string, returnTypeenum> peta; static {peta = hashmap baru <> (3); untuk (returntypeenum e: returnTypeenum.values ()) {map.put (e.type, e); }} public static returnTypeenum getEnum (string type) {if (type == null) {return url; } ReturnTypeenum e = map.get (type.tolowercase ()); mengembalikan E == NULL? URL: E; }} @DataPublic enum mediatypeenum {imageJpg ("jpg", "image/jpeg", "ffd8ff"), imageGif ("gif", "image/gif", "47494638"), imagepng ("png", "gambar/png", "89504." Png "," png "," 89504), "png", "png", "89504)," png "," png "," 89504. " "Image/Webp", "52494646"), string final pribadi ext; Private Final String Mime; sihir string final pribadi; Mediatypeenum (string ext, string mime, string magic) {this.ext = ext; this.Mime = mime; this.magic = sihir; } peta statis pribadi <string, mediatypeenum> peta; static {peta = hashmap baru <> (4); untuk (mediatypeenum e: values ()) {map.put (e.getext (), e); }} public static mediatypeenum getEnum (string type) {if (type == null) {return imageJpg; } Mediatypeenum e = Map.get (type.tolowercase ()); mengembalikan E == NULL? ImageJPG: E; }}Di atas adalah kacang yang dienkapsulasi dengan parameter permintaan. Tentu saja, ada juga kacang yang sesuai untuk kembali.
@DataPublic Class Baseresponse { / *** Mengembalikan jalur relatif gambar* / jalur string privat; / *** Mengembalikan format https dari gambar*/ private string url; / *** Gambar dalam format base64*/ private string base;}menjelaskan:
Dalam lingkungan proyek yang sebenarnya, permintaan parameter dan pengembalian pasti tidak akan sesederhana di atas, sehingga Anda dapat mengimplementasikannya dengan mewarisi kacang di atas atau mendefinisikan format yang sesuai sendiri.
Karena tujuannya jelas, pengemasan adalah langkah yang paling jelas dalam hal ini
Void BuildResponse yang dilindungi (permintaan Baserequest, respons Baseresponse, byte [] byte) melempar selferror {switch (request.ReturnType ()) {case url: unggah (byte, respons); merusak; base case64: base64 (byte, response); merusak; aliran kasus: stream (byte, permintaan); }} private void unggah (byte [] bytes, respons Baseresponse) melempar selferror {coba {// unggah ke server gambar dan ganti path string = unggahutil.upload (bytes); if (stringutils.isblank (path)) {// unggah gagal melempar internalerror baru (null); } response.setPath (path); response.setUrl (cdnutil.img (path)); } catch (ioException e) {// cdn exception log.error ("Unggah ke cdn error! e: {}", e); lempar cdnuploadError baru (e.getMessage ()); }} // return base64private void base64 (byte [] byte, respons Baseresponse) {string base = base64.getEncoder (). EncodeToString (bytes); response.setBase (base);} // kembalikan gambar biner batal private void (byte [] byte, permintaan basequest) melempar selferror {coba {mediatypeenum mediatype = request.mediatype (); HttpservletResponse servletResponse = ((servletRequestAttributes) requestContextholder.getRequestAttributes ()). GetResponse (); servletResponse.setContentType (mediatype.getMime ()); OutputStream os = servletResponse.getoutputStream (); os.write (bytes); os.flush (); os.close (); } catch (Exception e) {log.error ("General Return Stream IMG error! Req: {}, e: {}", request, e); if (stringutils.isnotblank (e.getMessage ())) {lempar internalError baru (e.getMessage ()); } else {throw new internalError (null); }}}menjelaskan:
Harap abaikan metode pengecualian khusus di atas. Ketika Anda perlu menggunakannya, Anda dapat sepenuhnya menghilangkan pengecualian khusus ini; Di sini saya secara singkat berbicara tentang mengapa metode pengecualian khusus ini digunakan dalam proyek aktual, terutama karena keunggulan berikut
Sehubungan dengan Pengecualian Pengecualian Global (ControllerAdvie), sangat nyaman dan mudah digunakan
Semua pengecualian ditangani secara terpusat untuk memfasilitasi statistik informasi dan alarm
Misalnya, setelah melakukan jumlah pengecualian di tempat yang disatukan, dan kemudian melebihi ambang batas tertentu, panggil orang yang bertanggung jawab, sehingga tidak perlu secara aktif mengubur tempat di setiap tempat di mana kasus pengecualian terjadi.
Hindari transmisi kode status kesalahan lapisan demi lapis
- Ini terutama untuk layanan web. Secara umum, ini berisi kode status kesalahan yang sesuai dan pesan kesalahan dalam string JSON yang dikembalikan.
- Kasus pengecualian mungkin muncul di mana saja. Untuk mempertahankan informasi pengecualian ini, baik data diteruskan ke lapisan pengontrol demi lapisan; atau ditemukan di Threadlocal; Jelas tidak satu pun dari metode ini yang nyaman digunakan
Tentu saja, ada kelemahan:
Metode pengecualian, overhead kinerja tambahan, jadi dalam pengecualian khusus, saya telah membahas metode berikut, tidak memiliki tumpukan lengkap
@Overridepublic Sinkronisasi lemparan yang dapat dilempar ke dalam () {return this;}Beberapa orang mungkin tidak menyukai metode pengkodean ini
Tampaknya tidak menarik untuk hanya mengatakan bahwa Anda tidak berlatih. Desain di atas sepenuhnya tercermin dalam Proyek Open Source Quick-media yang telah saya pertahankan. Tentu saja, ada beberapa perbedaan dari yang di atas. Bagaimanapun, ini lebih terkait dengan bisnis. Jika Anda tertarik, Anda dapat merujuknya.
QuickMedia: https://github.com/liuyueyi/quick-media:
Basa: com.hust.hui.quickmedia.web.wxapi.wxbaseAction#buildreturn
Di atas adalah semua konten artikel ini. Saya berharap ini akan membantu untuk pembelajaran semua orang dan saya harap semua orang akan lebih mendukung wulin.com.