Эффективный доступ к HttpServletRequest для отладочной печати.
-
14-09-2020 - |
Вопрос
Чтобы отладить неудачные запросы, я хотел бы распечатать всю информацию, поступающую из HttpServletRequest.
Теперь возможно, что запрос частично завершится неудачей (например.Несколько совпадений успешны, но одно не удалось), и в этом случае я хотел бы перехватить исключение во внутреннем методе, который не удался, напечатать ошибку + ServletUtil.toStringHttpServletRequest() и продолжить предоставление услуги (ухудшенной, но все еще полезной по сравнению сполный провал запроса).
Наша текущая реализация либо перехватывает исключение и печатает глупую информацию («getRules не удалось»), либо выдает исключение до doGet() (фактически отменяя обслуживание для пользователя), где, как и в doGet(), у меня есть доступ к HttpServletRequest, где я могу напечатайте соответствующую информацию об отладке (заголовки, параметры...).
Передача HttpServletRequest каждой функции, вызываемой во время запроса, который может потерпеть неудачу, кажется немного некрасивым, я сделаю это, если не появится другое элегантное решение.
Создание предшествующего заголовка ServletUtil.toStringHttpServletRequest() и сохранение его на карте ThreadLocal было бы расточительным как по памяти, так и по процессорному времени.По какой-то причине кажется неправильным хранить объект HttpServletRequest в ThreadLocal (пожалуйста, поправьте, если я ошибаюсь).
Информация об отладке записывается как в журнал локального компьютера, так и отправляется по электронной почте непосредственно разработчикам (отличная работа, log4j). TLSSMTPAppender), так что заходить в несколько мест будет непрактично (нужно будет собрать несколько писем, чтобы понять, что происходит), а заходить на сервер по ssh - это старость :) (у нас тут все пасмурно...сервер может не существовать к тому времени, когда я увижу ошибку)
Итак, мое решение получает доступ к PrintErrorUtility (TODO:лучше назови).Он получит (String errorMsg, Throwable t, HttpServletRequest), который напечатает ошибку вместе со всей соответствующей информацией...Это будет вызываться из внутренних блоков try {} catch, которые уведомят об ошибке, но не отменят запрос из-за нее.
Очевидно, я говорю о серверах, работающих в производстве.
Комментарии?Пожалуйста, порекомендуйте.
Спасибо, Максим.
Решение
Выполните это задание в Filter
после тот FilterChain#doFilter()
вызов.А ServletRequest
объект уже есть.В бизнес-коде, где это исключение должно корректно подавляться, сохраните исключение как атрибут запроса и просто позвольте Filter
проверьте/возьмите его из запроса.
Обновлять:согласно комментариям, вот пример:
public class Context {
private static ThreadLocal<Context> instance = new ThreadLocal<Context>();
private HttpServletRequest request;
private List<Exception> exceptions = new ArrayList<Exception>();
private Context(HttpServletRequest request) {
this.request = request;
this.request.setAttribute("exceptions", exceptions);
}
public static Context getCurrentInstance() {
return instance.get();
}
public static Context newInstance(HttpServletRequest request) {
Context context = new Context(request);
instance.set(context);
return context;
}
public void release() {
instance.remove();
}
public void addException(Exception exception) {
exceptions.add(exception);
}
}
И вот как использовать его в сервлете контроллера:
Context context = Context.newInstance(request);
try {
executeBusinessCode();
} finally {
context.release();
}
И вот как вы можете использовать его в исполняемом бизнес-коде:
} catch (Exception e) {
Context.getCurrentInstance().addException(e);
}