#spring-boot
Вопрос:
Когда в моем бэкэнде возникают ошибки, SpringBoot возвращает результат json с ошибками.
Я хотел изменить метку времени в json, чтобы она была читаемой, поэтому я настроил атрибуты:
@Component
public class CustomErrorAttributes extends DefaultErrorAttributes {
private static final DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
private static final String TIMESTAMP = "timestamp";
@Override
public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {
//Let Spring handle the error first
Map<String, Object> errorAttributes = super.getErrorAttributes(webRequest, includeStackTrace);
//Format amp; update timestamp
Object timestamp = errorAttributes.get(TIMESTAMP);
if(timestamp == null) {
errorAttributes.put(TIMESTAMP, dateFormat.format(new Date()));
} else {
errorAttributes.put(TIMESTAMP, dateFormat.format((Date)timestamp));
}
return errorAttributes;
}
}
Однако теперь, когда есть 404, из-за этой настройки возникает исключение:
E 23:21:36 88 [DispatcherServlet].log — Servlet.service() для сервлета [DispatcherServlet] выдал исключение
java.lang.Исключение ClassCastException: java.lang.Строка не может быть приведена к java.util.Date
в org.springframework.boot.autoconfigure.web.servlet.ошибка.Ошибка автоконфигурации$StaticView.render(ошибка автоконфигурации.java:224) ~[весенняя загрузка-автоконфигурация-2.1.4.РЕЛИЗ.jar:2.1.4.РЕЛИЗ]
Конфигурация ErrorMvcAutoConfiguration пытается проанализировать атрибут метки времени:
@Override
public void render(Map<String, ?> model, HttpServletRequest request,
HttpServletResponse response) throws Exception {
if (response.isCommitted()) {
String message = getMessage(model);
logger.error(message);
return;
}
StringBuilder builder = new StringBuilder();
Date timestamp = (Date) model.get("timestamp");
Как я могу настроить метку времени в ответе на ошибку, не влияя на другую стандартную обработку ошибок?
Ответ №1:
Похоже, вы работаете с устаревшей версией spring mvc.
И мы говорим о ErrorMvcAutoConfiguration.java
Там была ошибка: Смотрите здесь
Он был исправлен в фиксации d1d953819ac9f0c0ece5160b96899030cabda46c
12 сентября 2020 года в репозитории spring boot Филом Уэббом в версии 2.2.x, а также был объединен в версии 2.3.x и 2.4.x.
Так что теперь это выглядит так:
private static class StaticView implements View {
private static final MediaType TEXT_HTML_UTF8 = new MediaType("text", "html", StandardCharsets.UTF_8);
private static final Log logger = LogFactory.getLog(StaticView.class);
@Override
public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response)
throws Exception {
if (response.isCommitted()) {
String message = getMessage(model);
logger.error(message);
return;
}
response.setContentType(TEXT_HTML_UTF8.toString());
StringBuilder builder = new StringBuilder();
// !!!note this line!!!!
Object timestamp = model.get("timestamp");
Object message = model.get("message");
Object trace = model.get("trace");
if (response.getContentType() == null) {
response.setContentType(getContentType());
}
builder.append("<html><body><h1>Whitelabel Error Page</h1>").append(
"<p>This application has no explicit mapping for /error, so you are seeing this as a fallback.</p>")
// !!! and this line !!!
.append("<div id='created'>").append(timestamp).append("</div>")
.append("<div>There was an unexpected error (type=").append(htmlEscape(model.get("error")))
.append(", status=").append(htmlEscape(model.get("status"))).append(").</div>");
if (message != null) {
builder.append("<div>").append(htmlEscape(message)).append("</div>");
}
if (trace != null) {
builder.append("<div style='white-space:pre-wrap;'>").append(htmlEscape(trace)).append("</div>");
}
builder.append("</body></html>");
response.getWriter().append(builder.toString());
Сказав это, обычно люди настраивают страницу ошибок (по крайней мере, по моему опыту) и даже не используют это представление по умолчанию.
Об этом есть множество учебных пособий, вот одно из них