O back -end fornece serviços, geralmente retorna a string json, mas em alguns cenários, pode ser necessário retornar diretamente o fluxo binário, como uma interface de edição de imagem, na esperança de retornar diretamente o fluxo de imagem ao front -end. O que pode ser feito neste momento?
O uso principal é o objeto HttpServletResponse, e o caso é implementado da seguinte maneira
@RequestMapping (value = {"/img/render"}, métod = {requestmethod.get, requestmethod.post, requestmethod.options})@crossorigin (origens = "*")@ResponsBodyPublic String Execute (httpSertLeSTEONSTERSERTSERTTSVEL IMG é o fluxo binário do byte de imagem [] img = xxx; httpServletResponse.setContentType ("Image/png"); OutputStream OS = httpServletResponse.getOutputStream (); OS.WRITE (IMG); os.flush (); os.close (); retornar "sucesso";}Coisas a serem observadas
De um modo geral, a interface de serviço fornecida por um back -end geralmente retorna dados JSON. Como mencionado anteriormente, a cena de retornar diretamente as fotos, então quais são as maneiras comuns de devolver fotos?
Então, como um controlador deve fornecer suporte para as três posturas de uso acima ao mesmo tempo?
Como existem várias maneiras diferentes de retornar, como a que se escolher, é claro que é especificada pelo front-end, para que você possa definir um objeto de feijão que solicite parâmetros.
@Datapublic Classe basequest {private estático final serialversionuid = 1146303518394712013L; / ** * Método da imagem de saída: * * URL: Endereço HTTP (método padrão) * Base64: Base64 Encoding * Stream: Imagem de retorno direto * */ String privada Outtype; /*** Retornar Tipo de imagem* jpg | png | webp | GIF */ String privada MediaType; public ReturnTypeenum ReturnType () {return ReturnTypeenum.getenum (UTTYPE); } public MediaTypeenum MediaType () {return MediaTypeenum.getenum (MediaType); }}Para simplificar o julgamento, duas anotações foram definidas, um retorno -Typeenum e o outro MediaTypeenum. Claro, a necessidade não é particularmente grande. O seguinte é a definição de ambos.
public Enum ReturnTypeenum {url ("url"), stream ("stream"), base64 ("base"); tipo de sequência privada; ReturnTypeenum (tipo de string) {this.type = type; } mapa estático privado <string, returnTypeenum> mapa; estático {map = new Hashmap <> (3); para (returnTypeenum E: returnTypeenum.Values ()) {map.put (e.type, e); }} public static retornypeenum getenum (string tipo) {if (type == null) {return url; } ReturnTypeenum e = map.get (type.TolowerCase ()); retornar e == nulo? Url: e; }} @Datapublic enum mediatypeenum {imagejpg ("jpg", "image/jpeg", "ffd8ff"), imagegif ("gif", "imagem/gif", "47494638"), imagepng ("png", "imagem/png", "8504"), imagepng ("png", "image/png", "8504"), "segmapng "w "w)," imagem "," e imagem. "Image/Webp", "52494646"), String final privada Ext; MIME DE String final privado; Magia de cordas finais privadas; MediaTypeenum (String ext, String MIME, String Magic) {this.ext = ext; this.mime = MIME; this.Magic = Magic; } mapa estático privado <string, mediaTypeenum> mapa; estático {map = new Hashmap <> (4); for (MediaTypeenum e: valores ()) {map.put (por exemplo, (), e); }} public static mediaTypeenum getenum (string type) {if (type == null) {return imagejpg; } Mediatypeenum e = map.get (type.TolowerCase ()); retornar e == nulo? Imagejpg: e; }}O acima é o feijão encapsulado com o parâmetro de solicitação. Obviamente, há também um feijão correspondente para retornar.
@Datapublic Class BaseSponse { / *** Retorne o caminho relativo da imagem* / Path String Private; / *** Retorne o formato HTTPS da imagem*/ private String url; / *** imagem no formato base64*/ base de string privada;}ilustrar:
No ambiente real do projeto, os parâmetros de solicitação e o retorno definitivamente não serão tão simples quanto acima, para que você possa implementá -lo herdando o feijão acima ou definindo o formato correspondente.
Como o objetivo é claro, a embalagem é a etapa mais clara neste
Protected void BuildResponse (Solicitação Basequest, Resposta BaseResponse, Byte [] bytes) lança Selferror {switch (request.returnType ()) {case url: upload (bytes, resposta); quebrar; base base64: base64 (bytes, resposta); quebrar; fluxo de casos: stream (bytes, solicitação); }} upload privado void (byte [] bytes, resposta de resposta BaseRespo) lança Selferror {try {// Faça o upload no servidor de imagens e substitua o caminho da string = uploadUtil.upload (bytes); if (stringutils.isblank (path)) {// upload falhou, lança novo internalError (null); } Response.SetPath (Path); Response.seturl (cdnutil.img (caminho)); } catch (ioexception e) {// CDN Exception Log.error ("Carregue para CDN Error! E: {}", e); lançar novo cdNuploaderror (E.GetMessage ()); }} // retorna base64Private void base64 (byte [] bytes, resposta de resposta BaseRespo) {string base = base64.getEncoder (). CodetoString (bytes); Response.setBase (base);} // retorna a imagem binária private void stream (byte [] bytes, solicitação BasEQuest) lança Selferror {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 (Exceção e) {log.error ("General Return Stream IMG Error! Req: {}, e: {}", solicitação, e); if (stringUtils.isnotblank (e.getMessage ())) {tiro o novo internalError (e.getMessage ()); } else {lança o novo internalError (nulo); }}}ilustrar:
Por favor, ignore os métodos de exceção personalizada acima. Quando você precisa usá -los, pode eliminar completamente essas exceções personalizadas; Aqui falo brevemente sobre por que esse método de exceção personalizado é usado em projetos reais, principalmente por causa das seguintes vantagens
Em conjunto com a captura de exceção global (controleradvie), é muito conveniente e simples de usar
Todas as exceções são tratadas centralmente para facilitar as estatísticas de informação e alarme
Por exemplo, depois de realizar uma contagem de exceção em um local unificado e, em seguida, excedendo um certo limite, ligue para a pessoa responsável; portanto, não há necessidade de enterrar ativamente o local em cada local onde ocorre um caso de exceção.
Evite a transmissão de camada por camada dos códigos de status de erro
- Isso é principalmente para serviços da Web. Geralmente, ele contém o código de status de erro correspondente e a mensagem de erro na sequência JSON retornada.
- O caso de exceção pode aparecer em qualquer lugar. Para manter essas informações de exceção, os dados são passados para a camada do controlador por camada; ou é encontrado no Threadlocal; Obviamente, nenhum desses métodos é conveniente para usar
Claro, existem desvantagens:
Método de exceção, sobrecarga de desempenho adicional; portanto, em exceções personalizadas, eu cobri o seguinte método, não tenho uma pilha completa
@OverridePublic Sincronizou Throwable FillInstackTrace () {return This;}Algumas pessoas podem não gostar desse método de hábitos de codificação
Não parece interessante apenas dizer que você não pratica. O design acima é totalmente refletido no projeto de código aberto, mídia rápida que eu mantenho. Obviamente, existem algumas diferenças em relação ao exposto. Afinal, está mais relacionado ao negócio. Se você estiver interessado, pode se referir a ele.
QuickMedia: https://github.com/liuyueyi/quick-media:
Baseaction: com.hust.hui.quickmedia.web.wxapi.wxbaseAction#Buildreturn
O exposto acima é todo o conteúdo deste artigo. Espero que seja útil para o aprendizado de todos e espero que todos apoiem mais o wulin.com.