El backend proporciona servicios, generalmente devuelve la cadena JSON, pero en algunos escenarios, puede ser necesario devolver directamente la transmisión binaria, como una interfaz de edición de imágenes, con la esperanza de devolver directamente la transmisión de la imagen al interfaz. ¿Qué se puede hacer en este momento?
El uso principal es el objeto httpservletResponse, y el caso se implementa de la siguiente manera
@RequestMapping (valor = {"/img/render"}, método = {requestMethod.get, requestmethod.post, requestMethod.options})@Crossorigin (orígenes = "*")@ResponseBodyPublic String Execute (httpServletRequest httpServeResquest, httpServletResponse HttpseCte Execute) la secuencia binaria del byte de imagen [] img = xxx; httpservletResponse.setContentType ("Image/Png"); OutputStream OS = httpservletResponse.getOutputStream (); OS.Write (IMG); OS.Flush (); os.close (); devolver "éxito";}Cosas a tener en cuenta
En términos generales, la interfaz de servicio proporcionada por un backend a menudo devuelve datos JSON. Como se mencionó anteriormente, la escena de devolver directamente las imágenes, entonces, ¿cuáles son las formas comunes de devolver las imágenes?
Entonces, ¿cómo debería un controlador que brindamos soporte para las tres posturas de uso anteriores al mismo tiempo?
Debido a que hay varias formas diferentes de regresar, ya que para elegir, por supuesto, es especificada por el front-end, por lo que puede definir un objeto de frijoles que solicite parámetros.
@Datapublic Class Baserequest {private estático final Long SerialVersionUid = 1146303518394712013l; / ** * Método de imagen de salida: * * URL: Dirección Http (método predeterminado) * Base64: Base64 Codificación * Stream: Imagen de retorno directo * */ private String outType; /*** Tipo de imagen de retorno* JPG | PNG | webp | gif */ private string mediatype; public returnTypeenum returntype () {return returnTypeenum.getenum (outType); } public Mediatypeenum Mediatype () {return Mediatypeenum.getenum (mediatype); }}Para simplificar el juicio, se definieron dos anotaciones, un retornado de retorno y el otro mediatypeenum. Por supuesto, la necesidad no es particularmente grande. La siguiente es la definición de ambos.
public enum returnTypeenum {url ("url"), stream ("stream"), base64 ("base"); tipo de cadena privada; ReturnTypeenum (tipo de cadena) {this.type = type; } mapa estático privado <string, returntypeenum> map; static {map = new HashMap <> (3); para (returnTypeenum e: returntypeenum.values ()) {map.put (e.type, e); }} public static returnTypeenum getenum (tipo de cadena) {if (type == null) {return url; } Returntypeenum e = map.get (type.tolowercase ()); return e == null? URL: E; }} @Datapublic enum MediaTypeEnum { ImageJpg("jpg", "image/jpeg", "FFD8FF"), ImageGif("gif", "image/gif", "47494638"), ImagePng("png", "image/png", "89504E47"), ImageWebp("webp", "image/webp", "52494646"), cadena final privada ext; Cadena final privada mime; Magia de cadena final privada; MediATypeenum (String Ext, String Mime, String Magic) {this.ext = ext; this.mime = mime; this.magic = Magic; } mapa estático privado <cadena, mediAtypeenum> map; static {map = new HashMap <> (4); para (mediAtypeenum e: value ()) {map.put (e.getext (), e); }} public static static mediAtypeenum getenum (tipo de cadena) {if (type == null) {return imageJpg; } Mediatypeenum e = map.get (type.tolowercase ()); return e == null? ImageJpg: E; }}Lo anterior es el bean encapsulado con el parámetro de solicitud. Por supuesto, también hay un frijol correspondiente para regresar.
@Datapublic Class BaseSponse { / *** Devuelve la ruta relativa de la ruta de la imagen* / privada de cadena; / *** Devuelve el formato HTTPS de la imagen*/ URL de cadena privada; / *** Imagen en formato base64*/ base de cadena privada;}ilustrar:
En el entorno de proyecto real, los parámetros de solicitud y la retorno definitivamente no serán tan simples como anteriormente, por lo que puede implementarlo heredando el frijol anterior o definiendo el formato correspondiente usted mismo.
Dado que el objetivo es claro, el embalaje es el paso más claro en este
buildResponse de building protegido (solicitud de Basequest, respuesta de respuesta base, byte [] bytes) arroja selfEror {switch (request.returnType ()) {case url: upload (bytes, respuesta); romper; Case Base64: Base64 (bytes, respuesta); romper; Case Stream: Stream (bytes, solicitud); }} private void upload (byte [] bytes, respuesta base -respuesta) arroja selfEror {try {// cargar en el servidor de imágenes y reemplazar string ruta = uploadUtil.upload (bytes); if (stringUtils.isblank (ruta)) {// cargar fallido lanzar new GonalError (nulo); } respuesta.setPath (ruta); Response.SetUrl (cdNutil.img (ruta)); } catch (ioException e) {// CDN Exception log.error ("Cargar al error CDN! E: {}", e); arrojar nuevos cdnuploaderror (e.getMessage ()); }} // return Base64Private void base64 (byte [] bytes, respuesta base -ponse) {string base = base64.getEncoder (). Encodetostring (bytes); Response.setBase (base);} // Devuelve la imagen binaria privada void stream (byte [] bytes, solicitud de baseequest) arroja selfEror {try {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 ("Error de transmisión de retorno general img! Req: {}, e: {}", request, e); if (stringUtils.isNotBlank (e.getMessage ())) {lanzar new GonalErRor (e.getMessage ()); } else {tirar nueva internalSor (nulo); }}}ilustrar:
Ignore los métodos de excepción personalizados anteriores. Cuando necesite usarlos, puede eliminar por completo estas excepciones personalizadas; Aquí hablo brevemente sobre por qué este método de excepción personalizada se usa en proyectos reales, principalmente debido a las siguientes ventajas
Junto con la captura de excepción global (controlerAdvie), es muy conveniente y simple de usar
Todas las excepciones se manejan centralmente para facilitar las estadísticas de información y la alarma
Por ejemplo, después de realizar un recuento de excepciones en un lugar unificado, y luego exceder un cierto umbral, llame a la persona a cargo, por lo que no es necesario enterrar activamente el lugar en cada lugar donde ocurre un caso de excepción.
Evite la transmisión de la capa por capa de los códigos de estado de error
- Esto es principalmente para servicios web. En general, contiene el código de estado de error correspondiente y el mensaje de error en la cadena JSON devuelta.
- El caso de excepción puede aparecer en cualquier lugar. Para mantener esta información de excepción, los datos se pasan a la capa del controlador por capa; o se encuentra en ThreadLocal; obviamente ninguno de estos métodos es conveniente de usar
Por supuesto, hay desventajas:
Método de excepción, sobrecarga de rendimiento adicional, por lo que en excepciones personalizadas, he cubierto el siguiente método, no tengo una pila completa
@OverridePublic Synchronized Throwable FillInStackTrace () {return this;}Es posible que a algunas personas no les guste este método de codificación.
No parece interesante decir que no practicas. El diseño anterior se refleja completamente en el proyecto de código abierto, medios rápidos que he estado manteniendo. Por supuesto, hay algunas diferencias con respecto a lo anterior. Después de todo, está más relacionado con el negocio. Si está interesado, puede consultarlo.
Quickmedia: https://github.com/liuyueyi/quick-media:
Baseaction: com.hust.hui.quickmedia.web.wxapi.wxbaseaction#buildreturn
Lo anterior es todo el contenido de este artículo. Espero que sea útil para el aprendizaje de todos y espero que todos apoyen más a Wulin.com.