Le backend fournit des services, renvoie généralement la chaîne JSON, mais dans certains scénarios, il peut être nécessaire de renvoyer directement le flux binaire, tel qu'une interface d'édition d'image, dans l'espoir de renvoyer directement le flux d'image en frontend. Que peut-on faire pour le moment?
L'utilisation principale est l'objet httpservletResponse, et le cas est implémenté comme suit
@Requestmapping (value = {"/ img / render"}, méthode = {requestMethod.get, requestMethod.post, requestMethod.options}) @ crossorigin (origins = "*") @ réponse, httServleRsserSerSerSerSerSERSERSPER IMG est le flux binaire de l'octet d'image [] img = xxx; httpservletResponse.setContentType ("image / png"); OutputStream os = httpservletResponse.getOutputStream (); OS.Write (IMG); os.flush (); os.close (); retourner "succès";}Choses à noter
D'une manière générale, l'interface de service fournie par un backend renvoie souvent les données JSON. Comme mentionné précédemment, la scène des images de retour directement, alors quelles sont les moyens courants de retourner des images?
Alors, comment un contrôleur devrions-nous fournir un soutien aux trois postures d'utilisation ci-dessus en même temps?
Parce qu'il existe plusieurs façons de revenir, pour laquelle choisir, bien sûr, il est spécifié par le front-end, vous pouvez donc définir un objet bean qui demande des paramètres.
@Datapublic classe BaseRequest {private statique final long serialversionUID = 1146303518394712013l; / ** * Méthode d'image de sortie: * * URL: Adresse HTTP (méthode par défaut) * Base64: Base64 Encodage * Stream: Image de retour directe * * / String privé OutType; / ** * RETOUR le type d'image * JPG | PNG | webp | gif * / private string mediaType; public returnTypeenum returnType () {return returnTypeem.getEnum (outType); } public mediaTypeenum mediaType () {return mediaTypeenum.getEnum (mediaType); }}Afin de simplifier le jugement, deux annotations ont été définies, l'une de retour et l'autre MediaTypeenum. Bien sûr, la nécessité n'est pas particulièrement grande. Ce qui suit est la définition des deux.
public Enum returnTypeenum {url ("url"), stream ("stream"), base64 ("base"); type de chaîne privé; ReturnTypeEnum (string type) {this.type = type; } Carte statique privée <String, retourneypeenum> map; statique {map = new hashmap <> (3); for (returnTypeeNum e: returnTypeem.values ()) {map.put (e.type, e); }} public static returnTypeenum GETENUM (String Type) {if (type == null) {return url; } ReturnTypeenum e = map.get (type.tolowercase ()); Retour E == NULL? URL: e; }} @Datapublic enum mediaTypeeNum {imagejpg ("jpg", "image / jpeg", "ffd8ff"), imagegif ("gif", "image / gif", "47494638"), imagepng ("png", "image / png" "52494646"), chaîne finale privée ext; String final privé mime; magie de cordes finales privées; MediaTypeeNum (String ext, String MIME, String Magic) {this.ext = ext; this.mime = mime; this.magic = magie; } Carte statique privée <String, MediaTypeeNUM> MAP; statique {map = new hashmap <> (4); for (mediaTypeenum e: valeurs ()) {map.put (e.getExt (), e); }} public static mediaTypeenum GETENUM (String Type) {if (type == null) {return imagejpg; } MediaTypeenum e = map.get (type.tolowercase ()); Retour E == NULL? Imagejpg: e; }}Ce qui précède est le haricot encapsulé avec le paramètre de demande. Bien sûr, il y a aussi un haricot correspondant à retourner.
@Datapublic Class BaseResponse {/ ** * Renvoie le chemin relatif de l'image * / PROWAT PRIVATE STRING; / ** * Renvoie le format HTTPS de l'image * / URL de chaîne privée; / ** * Image au format Base64 * / base de chaîne privée;}illustrer:
Dans l'environnement du projet réel, les paramètres de demande et le retour ne seront certainement pas aussi simples que ci-dessus, vous pouvez donc le mettre en œuvre en héritant du bean ci-dessus ou en définissant le format correspondant vous-même.
Étant donné que l'objectif est clair, l'emballage est l'étape la plus claire dans ce
Protected void buildResponse (BaseRequest Request, BaseResponse Response, Byte [] octets) lève Ségétroite {switch (request.returnType ()) {URL de cas: upload (bytes, réponse); casser; Case Base64: Base64 (octets, réponse); casser; Case Stream: Stream (octets, demande); }} Private void upload (byte [] octets, BaseResponse Response) lève l'auto-orientation {try {// télécharger sur le serveur d'image et remplacer la chaîne path = uploadUtil.upload (bytes); if (stringUtils.isblank (path)) {// upload a échoué lancer un nouveau Internerror (null); } réponse.setPath (path); Response.SetUrl (cdnutil.img (path)); } catch (ioException e) {// cdn exception log.Error ("Télécharger vers CDN error! e: {}", e); lancer un nouveau cdnuploadError (e.getMessage ()); }} // return Base64Private void Base64 (byte [] octets, BaseResponse Response) {String Base = Base64.GetEncoder (). EncodeToString (Bytes); Response.SetBase (base);} // Renvoie l'image binaire privé void Stream (byte [] octets, BasErequest request) lève l'auto-orientation {try {mediaTypeenum mediaType = request.mediaType (); HttpServletResponse servLetResponse = ((servLetRequestAttributes) requestContexTholder.getRequestAttributes ()). GetResponse (); servletResponse.setContentType (mediaType.getMime ()); OutputStream os = servletResponse.getOutputStream (); OS.Write (octets); os.flush (); os.close (); } catch (exception e) {Log.Error ("Erreur générale du flux de retour IMG! req: {}, e: {}", request, e); if (stringUtils.isnotblank (e.getMessage ())) {throw new internerror (e.getMessage ()); } else {lance un nouveau Internerror (null); }}}illustrer:
Veuillez ignorer les méthodes d'exception personnalisées ci-dessus. Lorsque vous devez les utiliser, vous pouvez complètement éliminer ces exceptions personnalisées; Ici, je explique brièvement pourquoi cette méthode d'exception personnalisée est utilisée dans les projets réels, principalement en raison des avantages suivants
En conjonction avec la capture d'exception globale (ControllerAdvie), il est très pratique et simple à utiliser
Toutes les exceptions sont gérées de manière centralisée pour faciliter les statistiques et l'alarmage de l'information
Par exemple, après avoir effectué un nombre d'exceptions dans un endroit unifié, puis dépasser un certain seuil, appelez la personne responsable, il n'est donc pas nécessaire d'enterrer activement l'endroit à chaque endroit où un cas d'exception se produit.
Évitez la transmission couche par couche des codes d'état d'erreur
- C'est principalement pour les services Web. Généralement, il contient le code d'état d'erreur et le message d'erreur correspondant dans la chaîne JSON renvoyée.
- Le cas d'exception peut apparaître n'importe où. Afin de maintenir ces informations d'exception, les données sont transmises à la couche de contrôleur par couche; ou il se trouve en threadlocal; De toute évidence, aucune de ces méthodes n'est commode à utiliser
Bien sûr, il y a des inconvénients:
Méthode d'exception, sur -charge de performances supplémentaires, donc dans les exceptions personnalisées, j'ai couvert la méthode suivante, je n'ai pas de pile complète
@OverridePublic Synchronisé Throwable FillinstackTrace () {Renvoie ceci;}Certaines personnes peuvent ne pas aimer cette méthode de codage
Il ne semble pas intéressant de dire que vous ne vous entraînez pas. La conception ci-dessus se reflète entièrement dans les médias rapides du projet open source que je maintenais. Bien sûr, il existe quelques différences par rapport à ce qui précède. Après tout, il est plus lié à l'entreprise. Si vous êtes intéressé, vous pouvez vous y référer.
QuickMedia: https://github.com/liuyueyi/quick-media:
Baseaction: com.hust.hui.quickmedia.web.wxapi.wxbaseAction # BuildReturn
Ce qui précède est tout le contenu de cet article. J'espère que cela sera utile à l'apprentissage de tous et j'espère que tout le monde soutiendra davantage Wulin.com.