Das Backend bietet Dienste an, gibt normalerweise die JSON -Zeichenfolge zurück, aber in einigen Szenarien kann es erforderlich sein, den Binärstrom direkt zurückzugeben, z. B. eine Bildbearbeitungsschnittstelle, in der Hoffnung, den Bildstrom direkt an den Frontend zurückzugeben. Was kann zu diesem Zeitpunkt getan werden?
Die Hauptverwendung ist das HTTPServletResponse -Objekt, und der Fall wird wie folgt implementiert
@RequestMapping(value = {"/img/render"}, method = {RequestMethod.GET, RequestMethod.POST, RequestMethod.OPTIONS})@CrossOrigin(origins = "*")@ResponseBodypublic String execute(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) { // IMG ist der binäre Strom des Bild Byte [] img = xxx; httpServletResponse.setContentType ("Bild/png"); OutputStream os = httpServletResponse.getOutputStream (); OS.Write (IMG); os.flush (); os.close (); zurück "Erfolg";}Dinge zu beachten
Im Allgemeinen gibt die von einem Backend bereitgestellte Serviceschnittstelle häufig JSON -Daten zurück. Wie bereits erwähnt, sind die Szene der direkten Rückgabe von Bildern. Was sind also die allgemeinen Möglichkeiten, Bilder zurückzugeben?
Wie soll ein Controller gleichzeitig die oben genannten drei Nutzungshaltungen unterstützen?
Da es verschiedene Möglichkeiten gibt, zurückzukehren, wie man es auswählt, wird es natürlich vom Front-End angegeben, sodass Sie ein Bean-Objekt definieren können, das Parameter anfordert.
@Datapublic Class BasieRequest {private statische endgültige lange Serialversionuid = 1146303518394712013L; / ** * Ausgabebildmethode: * * URL: HTTP -Adresse (Standardmethode) * Base64: Base64 Codierung * Stream: Direct Return Image * */ private String Outtype; /*** Bildtyp zurückgeben* JPG | png | webp | GIF */ private String mediType; public returnTypeenum returnType () {return returnTypeenum.getenum (Outtype); } public in MediTypeenum mediType () {return mediTypeenum.getenum (mediateType); }}Um das Urteil zu vereinfachen, wurden zwei Annotationen definiert, ein Rückkehrtypen und das andere in MediaPeenum. Natürlich ist die Notwendigkeit nicht besonders groß. Das Folgende ist die Definition von beiden.
public enum returnTypeenum {url ("url"), stream ("stream"), base64 ("base"); privater String -Typ; ReturnTypeenum (String -Typ) {this.type = type; } private statische Karte <String, ReturnTypeenum> Karte; static {map = new HashMap <> (3); für (returnTyPeenum e: returnTyPeenum.Values ()) {map.put (E.Type, e); }} public static returnTypeenum getenum (String -Typ) {if (type == null) {return url; } ReturnTypeenum e = map.get (type.tolowerCase ()); E == NULL zurückgeben? URL: E; }} @Datapublic enum in minytypeenum {ImageJPG ("JPG", "Image/JPEG", "ffd8ff"), ImageGif ("Gif", "Image/Gif", "47494638"), ImagePng ("Png", Image/png "," 895047 "," WebPP ("," 895047 ",", "png", "895047"), Imagew ("," png ". "Image/Webp", "52494646"), private endgültige Zeichenfolge ext; private endgültige Stringmime; private endgültige Stringmagie; Mediitypeenum (String ext, String mime, String Magic) {this.ext = ext; this.mime = mime; this.magic = Magic; } private statische Karte <String, mediTypeenum> Karte; static {map = new HashMap <> (4); für (minytypeenum e: values ()) {map.put (e.getEXT (), e); }} public static in MediTypeenum getenum (String -Typ) {if (type == null) {return imageJpg; } MinyTypeenum e = map.get (type.tolowerCase ()); E == NULL zurückgeben? ImageJPG: E; }}Das obige ist die mit dem Anforderungsparameter eingekapselte Bean. Natürlich gibt es auch eine entsprechende Bohne zurückzukehren.
@Datapublic Class BaserePonse { / *** Gibt den relativen Pfad des Bildes zurück* / private String -Pfad; / *** Gibt das HTTPS -Format des Bildes zurück*/ private String -URL; / *** Bild im Basis64 -Format*/ private String -Basis;}veranschaulichen:
In der tatsächlichen Projektumgebung sind Anforderungsparameter und Rückgabe definitiv nicht so einfach wie oben, sodass Sie sie implementieren können, indem Sie die obige Bean erben oder das entsprechende Format selbst definieren.
Da das Ziel klar ist, ist die Verpackung der klarste Schritt darin
Protected void BuildResponse (Baserequest -Anforderung, BaserePonse -Antwort, Byte [] Bytes) löst Selferror {Switch (Request.ReturnType ()) {case url: Upload (Bytes, Antwort) aus; brechen; Case Base64: Base64 (Bytes, Antwort); brechen; Fallstream: Stream (Bytes, Anfrage); }} private void Upload (Byte [] Bytes, BaserePonse -Antwort) löst Selferror {try {// hochladen auf den Bildserver und ersetzen Sie String path = uploadutil.Upload (Bytes); if (Stringutils.isblank (Pfad)) {// fehlgeschlagenes Neuladungsfehler Neue InternalError (NULL); } response.setPath (Pfad); Antwort.Seturl (cdnutil.img (Pfad)); } catch (ioException e) {// CDN -Ausnahme -log.Error ("auf CDN -Fehler hochladen! E: {}", e); neue cDnUploadError (e.getMessage ()) werfen; }} // return base64Private void base64 (byte [] bytes, BaserePon -Antwort) {String base = base64.getEncoder (). CodetoString (bytes); response.setBase (Basis);} // Rückgabe des Binary Image private void Stream (Byte [] Bytes, Baserequest -Anforderung) löst SelfError {try {mediateTypeenum mediType = request.mediatype () aus; HttpServletResponse ServletResponse = ((ServletRequestAttributes) RequestContexTHolder.getRequestAttributes ()). GetResponse (); servletResponse.setContentType (minyType.getMime ()); OutputStream os = servletResponse.getOutputStream (); OS.Write (Bytes); os.flush (); os.close (); } catch (Ausnahme e) {log.Error ("Allgemeiner Rückgabe -Stream -IMG -Fehler! Req: {}, e: {}", request, e); if (Stringutils.isnotblank (e.getMessage ())) {neue InternalError werfen (e.getMessage ()); } else {neue interneError werfen (null); }}}veranschaulichen:
Bitte ignorieren Sie die oben genannten maßgefertigten Ausnahmemethoden. Wenn Sie sie verwenden müssen, können Sie diese benutzerdefinierten Ausnahmen vollständig beseitigen. Hier spreche ich kurz darüber, warum diese benutzerdefinierte Ausnahmemethode in tatsächlichen Projekten verwendet wird, hauptsächlich aufgrund der folgenden Vorteile
In Verbindung mit globaler Ausnahmebetapikat (ControllerAdvie) ist es sehr bequem und einfach zu bedienen
Alle Ausnahmen werden zentral behandelt, um Informationsstatistiken und Alarm zu erleichtern
Wenn Sie beispielsweise eine Ausnahmeanzahl an einem einheitlichen Ort ausführen und dann eine bestimmte Schwelle überschreiten, rufen Sie die verantwortliche Person an, sodass die Stelle nicht aktiv die Stelle an jedem Ort begraben müssen, an dem ein Ausnahmefall auftritt.
Vermeiden Sie die Übertragung von Fehlerstatuscodes von Fehler für die Schicht für Schicht
- Dies gilt hauptsächlich für Webdienste. Im Allgemeinen enthält es den entsprechenden Fehlerstatuscode und die Fehlermeldung in der zurückgegebenen JSON -Zeichenfolge.
- Ausnahmefall kann überall erscheinen. Um diese Ausnahmeinformationen beizubehalten, werden entweder die Daten an die Controller -Schicht für Schicht übergeben. oder es wird in ThreadLocal gefunden; Offensichtlich ist keiner dieser Methoden bequem zu verwenden
Natürlich gibt es Nachteile:
Ausnahmemethode, zusätzlicher Leistungsaufwand. Bei benutzerdefinierten Ausnahmen habe ich die folgende Methode abgedeckt, keinen vollständigen Stapel
@OverridePublic Synchronisierte Throwable FillinStacktrace () {return this;}Einige Leute mögen diese Methode der Codierungsgewohnheiten möglicherweise nicht
Es scheint nicht interessant zu sein, nur zu sagen, dass Sie nicht üben. Das obige Design spiegelt sich voll im Open-Source-Projekt Quick-Media wider, das ich aufrechterhalten habe. Natürlich gibt es einige Unterschiede zu den oben genannten. Schließlich hängt es mehr mit dem Geschäft zusammen. Wenn Sie interessiert sind, können Sie sich darauf verweisen.
QuickMedia: https://github.com/liuyueyi/quick-media:
BASACTION: com.hust.hui.quickmedia.web.wxapi.wxBaseaction#BuildReturn
Das obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, es wird für das Lernen aller hilfreich sein und ich hoffe, jeder wird Wulin.com mehr unterstützen.