Помимо регистрации ByteArrayHttpMessageConverter
, вы можете использовать ResponseEntity
вместо @ResponseBody
. Для меня работает следующий код:
@RequestMapping("/photo2")
public ResponseEntity<byte[]> testphoto() throws IOException {
InputStream in = servletContext.getResourceAsStream("/images/no_image.jpg");
final HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.IMAGE_PNG);
return new ResponseEntity<byte[]>(IOUtils.toByteArray(in), headers, HttpStatus.CREATED);
}
Решение основано на этом коммите Криса в библиотеке Синдре 'on-change' ]. [1 123]
Объяснение решения Крисом:
В ловушке
blockquote>set
моя цель - определить, является ли предоставленное значениеProxy
, созданным предыдущий вызов в ловушкуget
. Если это такойProxy
, любой доступ к свойству будет перехвачен нашей собственнойget
ловушкой. Поэтому, когда я получу доступ кvalue[proxyTarget]
, будет вызвана нашаget
ловушка, которая закодирована так, чтобы возвращатьtarget
приproperty === proxyTarget
(строка 46). Если значение, переданное вset
, не является прокси-сервером, созданным при изменении, тогдаvalue[proxyTarget]
будетundefined
.Полный код решения:
(object, onChange) => { let inApply = false; let changed = false; function handleChange() { if (!inApply) { onChange(); } else if (!changed) { changed = true; } } const handler = { get(target, property, receiver) { const descriptor = Reflect.getOwnPropertyDescriptor(target, property); const value = Reflect.get(target, property, receiver); // Preserve invariants if (descriptor && !descriptor.configurable) { if (descriptor.set && !descriptor.get) { return undefined; } if (descriptor.writable === false) { return value; } } try { return new Proxy(value, handler); } catch (_) { return value; } }, set(target, property, value) { const result = Reflect.set(target, property, value); handleChange(); return result; }, defineProperty(target, property, descriptor) { const result = Reflect.defineProperty(target, property, descriptor); handleChange(); return result; }, deleteProperty(target, property) { const result = Reflect.deleteProperty(target, property); handleChange(); return result; }, apply(target, thisArg, argumentsList) { if (!inApply) { inApply = true; const result = Reflect.apply(target, thisArg, argumentsList); if (changed) { onChange(); } inApply = false; changed = false; return result; } return Reflect.apply(target, thisArg, argumentsList); } }; return new Proxy(object, handler); };
Это решило мою проблему, не прибегая к взлому проверки методов модификации массива.
Исходное решение:
Пока что я отсортировал это с помощью сообщения Дэвида Уолша здесь . Это все еще уродливо, но пока работает.
Обновлен создатель прокси
onChanged
с ловушкой рекурсивного выходаget
.get: function (target, property, receiver) { let retval; try { retval = new Proxy(target[property], handler); } catch (err) { retval = Reflect.get(target, property, receiver); } if (mutators.includes(property)) onChange(target, property, receiver); return retval; },
Также добавлен список функций для проверки ловушки get (некрасивый, хакерский бит):
const mutators = [ "push", "pop", "shift", "unshift", "splice", "reverse", "fill", "sort" ]
Это, кажется, работает в моем тестировании до сих пор.
Спасибо, что указали в правильном направлении.