Mengembalikan Data Gambar / Media dengan Spring MVC

1. Gambaran keseluruhan

Dalam tutorial ini, kami akan menggambarkan cara mengembalikan gambar dan media lain menggunakan rangka Spring MVC.

Kami akan membincangkan beberapa pendekatan, bermula dari memanipulasi HttpServletResponse secara langsung daripada beralih ke pendekatan yang mendapat manfaat daripada Penukaran Mesej, Rundingan Kandungan dan abstraksi Sumber Musim Semi . Kami akan melihat lebih dekat setiap perkara dan membincangkan kelebihan dan kekurangan mereka.

2. Menggunakan HttpServletResponse

Pendekatan paling mendasar dari muat turun gambar adalah secara langsung melawan objek respons dan meniru pelaksanaan Servlet yang murni , dan ditunjukkan dengan coretan berikut:

@RequestMapping(value = "/image-manual-response", method = RequestMethod.GET) public void getImageAsByteArray(HttpServletResponse response) throws IOException { InputStream in = servletContext.getResourceAsStream("/WEB-INF/images/image-example.jpg"); response.setContentType(MediaType.IMAGE_JPEG_VALUE); IOUtils.copy(in, response.getOutputStream()); }

Mengeluarkan permintaan berikut akan menjadikan gambar di penyemak imbas:

//localhost:8080/spring-mvc-xml/image-manual-response.jpg

Pelaksanaannya cukup mudah dan mudah kerana IOUtils dari pakej org.apache.commons.io . Walau bagaimanapun, kelemahan pendekatan ini adalah bahawa ia tidak kuat terhadap kemungkinan perubahan. Jenis mime dikodkan dengan ketat dan perubahan logik penukaran atau pengecualian lokasi gambar memerlukan perubahan pada kod.

Bahagian berikut membincangkan pendekatan yang lebih fleksibel.

3. Menggunakan HttpMessageConverter

Bahagian sebelumnya membincangkan pendekatan asas yang tidak memanfaatkan ciri Penukaran Mesej dan Rundingan Kandungan dari Spring MVC Framework. Untuk bootstrap ciri-ciri ini, kita perlu:

  • Nyatakan kaedah pengawal dengan anotasi @ResponseBody
  • Daftarkan penukar mesej yang sesuai berdasarkan jenis pengembalian kaedah pengawal ( ByteArrayHttpMessageConverter misalnya diperlukan untuk penukaran susunan bait yang betul ke fail gambar)

3.1. Konfigurasi

Untuk menunjukkan konfigurasi penukar, kita akan menggunakan ByteArrayHttpMessageConverter bawaan yang menukar mesej setiap kali kaedah mengembalikan jenis bait [] .

The ByteArrayHttpMessageConverter didaftarkan secara lalai, tetapi konfigurasi adalah mirip bagi apa-apa lain terbina dalam atau converter adat.

Menerapkan kacang penukar mesej memerlukan pendaftaran kacang MessageConverter yang sesuai dalam konteks Spring MVC dan menetapkan jenis media yang harus dikendalikannya. Anda boleh menentukannya melalui XML, menggunakanteg.

Teg ini harus ditentukan di dalam tag, seperti dalam contoh berikut:

     image/jpeg image/png     

Bahagian konfigurasi yang dinyatakan akan mendaftarkan ByteArrayHttpMessageConverter untuk jenis kandungan imej / jpeg dan imej / png . Sekiranya tag tidak terdapat dalam konfigurasi mvc, maka set penukar lalai akan didaftarkan.

Anda juga boleh mendaftarkan penukar mesej menggunakan konfigurasi Java :

@Override public void configureMessageConverters(List
    
      converters) { converters.add(byteArrayHttpMessageConverter()); } @Bean public ByteArrayHttpMessageConverter byteArrayHttpMessageConverter() { ByteArrayHttpMessageConverter arrayHttpMessageConverter = new ByteArrayHttpMessageConverter(); arrayHttpMessageConverter.setSupportedMediaTypes(getSupportedMediaTypes()); return arrayHttpMessageConverter; } private List getSupportedMediaTypes() { List list = new ArrayList(); list.add(MediaType.IMAGE_JPEG); list.add(MediaType.IMAGE_PNG); list.add(MediaType.APPLICATION_OCTET_STREAM); return list; }
    

3.2. Pelaksanaan

Sekarang kita dapat menerapkan kaedah kita yang akan menangani permintaan untuk media. Seperti yang dinyatakan di atas, anda perlu menandakan kaedah pengawal anda dengan anotasi @ResponseBody dan menggunakan bait [] sebagai jenis pengembalian:

@RequestMapping(value = "/image-byte-array", method = RequestMethod.GET) public @ResponseBody byte[] getImageAsByteArray() throws IOException { InputStream in = servletContext.getResourceAsStream("/WEB-INF/images/image-example.jpg"); return IOUtils.toByteArray(in); }

Untuk menguji kaedah, berikan permintaan berikut di penyemak imbas anda:

//localhost:8080/spring-mvc-xml/image-byte-array.jpg

Di sisi kelebihannya, kaedah ini tidak mengetahui apa-apa mengenai HttpServletResponse, proses penukaran sangat dapat dikonfigurasi, mulai dari menggunakan penukar yang tersedia hingga menentukan yang disesuaikan. Jenis kandungan respons tidak harus dikodkan keras tetapi akan dirundingkan berdasarkan akhiran jalur permintaan .jpg .

Kelemahan pendekatan ini ialah anda perlu menerapkan logik secara eksplisit untuk mengambil gambar dari sumber data (fail tempatan, penyimpanan luaran, dll.) Dan anda tidak mempunyai kawalan ke atas tajuk atau kod status respons.

4. Menggunakan Kelas ResponseEntity

Anda boleh mengembalikan gambar sebagai bait [] yang dibungkus dalam Entiti Respons . Spring MVC ResponseEntity membolehkan kawalan bukan sahaja pada badan Respons HTTP tetapi juga tajuk dan kod status respons. Mengikuti pendekatan ini, anda perlu menentukan jenis kaedah kembali sebagai ResponseEntity dan membuat objek ResponseEntity yang dikembalikan dalam badan kaedah.

@RequestMapping(value = "/image-response-entity", method = RequestMethod.GET) public ResponseEntity getImageAsResponseEntity() { HttpHeaders headers = new HttpHeaders(); InputStream in = servletContext.getResourceAsStream("/WEB-INF/images/image-example.jpg"); byte[] media = IOUtils.toByteArray(in); headers.setCacheControl(CacheControl.noCache().getHeaderValue()); ResponseEntity responseEntity = new ResponseEntity(media, headers, HttpStatus.OK); return responseEntity; }

Menggunakan ResponseEntity membolehkan anda mengkonfigurasi kod respons untuk permintaan tertentu.

Menetapkan kod respons secara terang-terangan sangat berguna dalam menghadapi peristiwa luar biasa misalnya jika gambar tidak dijumpai ( FileNotFoundException ) atau rosak ( IOException) . Dalam kes ini, semua yang diperlukan adalah menetapkan kod respons misalnya ResponseEntity baru (null, header, HttpStatus.NOT_FOUND), di blok tangkapan yang mencukupi.

Selain itu, jika anda perlu menetapkan beberapa tajuk khusus dalam respons anda, pendekatan ini lebih mudah daripada menetapkan tajuk dengan menggunakan objek HttpServletResponse yang diterima oleh kaedah sebagai parameter. Ini menjadikan tandatangan kaedah jelas dan fokus.

5. Mengembalikan Imej Menggunakan Kelas Sumber

Akhirnya, anda boleh mengembalikan gambar dalam bentuk objek Sumber .

Antara muka Sumber adalah antara muka untuk mengaburkan akses ke sumber rendah. Ia diperkenalkan pada musim bunga sebagai pengganti yang lebih mampu untuk kelas java.net.URL standard . Ini membolehkan akses mudah ke pelbagai jenis sumber (fail tempatan, fail jauh, sumber jalan kelas) tanpa perlu menulis kod yang mengambilnya secara eksplisit.

Untuk menggunakan pendekatan ini, jenis kaedah pengembalian harus ditetapkan ke Sumber dan anda perlu memberi penjelasan kaedah dengan anotasi @ResponseBody .

5.1. Pelaksanaan

@ResponseBody @RequestMapping(value = "/image-resource", method = RequestMethod.GET) public Resource getImageAsResource() { return new ServletContextResource(servletContext, "/WEB-INF/images/image-example.jpg"); }

atau, jika kita mahukan lebih banyak kawalan ke atas tajuk respons:

@RequestMapping(value = "/image-resource", method = RequestMethod.GET) @ResponseBody public ResponseEntity getImageAsResource() { HttpHeaders headers = new HttpHeaders(); Resource resource = new ServletContextResource(servletContext, "/WEB-INF/images/image-example.jpg"); return new ResponseEntity(resource, headers, HttpStatus.OK); }

Dengan menggunakan pendekatan ini, anda menganggap gambar sebagai sumber yang dapat dimuat menggunakan pelaksanaan antara muka ResourceLoader . Dalam kes sedemikian, anda abstrak dari lokasi tepat gambar anda dan ResourceLoader memutuskan dari mana ia dimuat.

Ini menyediakan pendekatan umum untuk mengendalikan lokasi gambar menggunakan konfigurasi, dan menghilangkan keperluan untuk menulis kod pemuatan fail.

6. Kesimpulannya

Di antara pendekatan yang disebutkan di atas, kami bermula dari pendekatan asas, kemudian menggunakan pendekatan yang mendapat manfaat dari ciri penukaran mesej kerangka. Kami juga membincangkan cara mendapatkan kod respons dan tajuk respons tanpa menyerahkan objek respons secara langsung.

Akhirnya, kami menambahkan fleksibiliti dari sudut pandang lokasi gambar, kerana dari mana untuk mendapatkan gambar, ditentukan dalam konfigurasi yang lebih mudah diubah dengan cepat.

Muat turun Imej atau Fail dengan Spring menerangkan cara mencapai perkara yang sama menggunakan Spring Boot.

Contoh kod yang mengikuti tutorial boleh didapati di GitHub.