Бэкэнд предоставляет услуги, обычно возвращает строку JSON, но в некоторых сценариях может потребоваться непосредственно вернуть двоичный поток, такой как интерфейс редактирования изображений, надеясь напрямую вернуть поток изображения на фронт. Что можно сделать в это время?
Основное использование - это объект httpservletresponse, и дело реализовано следующим образом
@RequestMapping(value = {"/img/render"}, method = {RequestMethod.GET, RequestMethod.POST, RequestMethod.OPTIONS})@CrossOrigin(origins = "*")@ResponseBodypublic String execute(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) { // img это двоичный поток байта изображения [] img = xxx; httpservletresponse.setContentType ("Image/png"); OutputStream OS = httpservletresponse.getOutputStream (); Os.Write (IMG); os.flush (); os.close (); вернуть "успех";}Что следует отметить
Вообще говоря, интерфейс сервиса, предоставляемый бэкэнд, часто возвращает данные JSON. Как упоминалось ранее, сцена непосредственно возвращающегося картинок, так каковы общие способы вернуть картинки?
Итак, как контроллер мы должны одновременно поддержать три вышеуказанные позы использования?
Поскольку существует несколько разных способов вернуть, так как вы выбираете, конечно, это указано на переднем конце, так что вы можете определить объект из бобов, который запрашивает параметры.
@Datapublic class baserequest {private static final long serialversionuid = 1146303518394712013L; / ** * Метод вывода изображения: * * URL: HTTP -адрес (метод по умолчанию) * BASE64: BASE64 ENCODING * Stream: прямое возвращение изображения * */ Private String Outtype; /*** Возвращение типа изображения* JPG | Png | webp | GIF */ Private String MediaType; public returntypeenum returntype () {return returntypeenum.getenum (outtype); } public MediaTypeenum mediaType () {return mediaTypeenum.getEnum (mediaType); }}Чтобы упростить суждение, были определены две аннотации, один returntypeenum, а другой MediaTypeenum. Конечно, необходимость не особенно велика. Ниже приведено определение обоих.
public enum returntypeenum {url ("url"), stream ("stream"), base64 ("base"); частная строка типа; Returntypeenum (type string) {this.type = type; } частная статическая карта <строка, returntypeenum> map; static {map = new Hashmap <> (3); for (returntypeenum e: returntypeenum.values ()) {map.put (e.type, e); }} public static returntypeenum getEnum (type) {if (type == null) {return url; } Returntypeenum e = map.get (type.tolowercase ()); вернуть e == null? URL: E; }} @Datapublic enum mediatypeenum {imagejpg ("jpg", "image/jpeg", "ffd8ff"), ImageGif ("GIF", "Image/GIF", "47494638"), ImagePng («PNG», «Image/Png», «WebP», «WebP», «WebP», «WebP», «WebBP», «WebBP», «Image», «WebBP», «Image/Png», «Image», «Image/Png». "52494646"), частная финальная строка ext; частная финальная строка Mime; частная финальная строка магия; MediaTyPeenum (String Ext, String Mime, String Magic) {this.ext = ext; this.mime = mime; this.magic = магия; } частная статическая карта <строка, mediaTypeenum> map; static {map = new Hashmap <> (4); for (mediaTypeenum e: values ()) {map.put (e.getext (), e); }} public Static MediaTypeenum getEnum (тип строки) {if (type == null) {return imageJpg; } MediaTypeenum e = map.get (type.tolowercase ()); вернуть e == null? ImageJpg: E; }}Выше приведено бобовый, инкапсулированный с параметром запроса. Конечно, есть также соответствующий боб для возвращения.
@Datapublic class baseresponse { / *** Возвращает относительный путь изображения* / private String Path; / *** вернуть формат HTTPS изображения*/ private String URL; / *** Изображение в Base64 Format*/ Private String Base;}иллюстрировать:
В фактической среде проекта запрос параметров и возврата, безусловно, будут не такими простыми, как выше, поэтому вы можете реализовать его, унаследовав приведенный выше фасоль или определяя соответствующий формат самостоятельно.
Поскольку цель ясна, упаковка является самым чистым шагом в этом
Защищенный void buildresponse (запрос baserequest, ответ Baseresponse, байт [] байты) бросает Selferror {switch (request.returntype ()) {case url: upload (bytes, response); перерыв; База корпуса64: base64 (байты, ответ); перерыв; поток корпуса: поток (байты, запрос); }} private void upload (byte [] bytes, baser -response) бросает Selferror {try {// загружать на сервер изображения и заменить path = uploadutil.upload (bytes); if (stringUtils.isblank (path)) {// upload Не удалось бросить новый InternalError (null); } response.setPath (path); response.seturl (cdnutil.img (path)); } catch (ioException e) {// cdn exception log.error ("upload to cdn error! e: {}", e); бросить новый cdnuploaderror (e.getmessage ()); }} // return base64private void base64 (byte [] bytes, baseresponse response) {string base = base64.getencoder (). EncodetoString (bytes); response.setbase (base);} // возвращает двоичное изображение Private void -поток (Byte [] Bytes, Baserequest запрос) Throws Selferror {try {mediaTypeenum mediaType = request.Mediatype (); Httpservletresponse servletresponse = (((ServletRequestattributes) requestOntextholder.getRequestattributes ()). GetResponse (); servletresponse.setContentType (mediaType.getMime ()); OutputStream OS = servletresponse.getOutputStream (); OS.Write (байты); os.flush (); os.close (); } catch (Exception e) {log.Error ("Общий return -stream error! req: {}, e: {}", request, e); if (stringutils.isnotblank (e.getMessage ())) {бросить новый InternalError (e.getMessage ()); } else {бросить новый InternalError (null); }}}иллюстрировать:
Пожалуйста, игнорируйте вышеупомянутые методы исключения. Когда вам нужно их использовать, вы можете полностью устранить эти пользовательские исключения; Здесь я кратко говорю о том, почему этот метод исключения используется в реальных проектах, в основном из -за следующих преимуществ
В сочетании с глобальным захватом исключений (ControllerAdvie) он очень удобен и прост в использовании
Все исключения обрабатываются в центре для облегчения статистики информации и тревоги.
Например, после выполнения количества исключений в унифицированном месте, а затем превышения определенного порога, назовите ответственного человека, поэтому нет необходимости активно похоронить место в каждом месте, где происходит случай исключения.
Избегайте слоя за слоем кодов состояния ошибки
- Это в основном для веб -сервисов. Как правило, он содержит соответствующий код состояния ошибки и сообщение об ошибке в возвращенной строке JSON.
- Дело исключения может появиться где угодно. Чтобы сохранить эту информацию об исключении, либо данные передаются на уровень контроллера по слою; или это найдено в Threadlocal; Очевидно, что ни один из этих методов не удобен для использования
Конечно, есть недостатки:
Метод исключений, дополнительные накладные расходы, поэтому в пользовательских исключениях я рассмотрел следующий метод, не имел полного стека
@OverridePublic Synchronized Throwable FilinStackTrace () {return this;}Некоторым людям может не понравиться этот метод кодирования
Кажется, не интересно просто сказать, что вы не практикуете. Вышеуказанный дизайн полностью отражен в проекте с открытым исходным кодом, который я поддерживал. Конечно, есть некоторые отличия от вышесказанного. В конце концов, это больше связано с бизнесом. Если вы заинтересованы, вы можете ссылаться на это.
QuickMedia: https://github.com/liuyueyii/quick-media:
Baseaction: com.hust.hui.quickmedia.web.wxapi.wxbaseAction#buildreturn
Выше всего содержание этой статьи. Я надеюсь, что это будет полезно для каждого обучения, и я надеюсь, что все будут поддерживать Wulin.com больше.