Статическая локальная переменная потока в веб-приложении — Есть ли какие-либо проблемы с безопасностью / производительностью?

#java #session #servlet-filters #thread-local

#java #сессия #servlet-фильтры #поток-локальный

Вопрос:

Я исследую и экспериментирую с потоковой локальной переменной в моем веб-приложении Java. Я использую переменную ThreadLocal для сохранения имени пользователя (собранного из сеанса) перед запросом, а затем удаляю его после запроса. Я сделал это, вызвав статический служебный метод в ServletFilter. Причина, по которой я просто не извлекаю имя пользователя из сеанса, заключается в том, что я унаследовал систему с длительно выполняющимися процессами, выполнение которых иногда занимает больше времени, чем позволяет время ожидания сеанса. Моя идея состоит в том, чтобы захватить имя пользователя до обработки запроса и сохранить его в переменной ThreadLocal, таким образом предоставляя мне доступ к имени пользователя на протяжении всего времени выполнения запроса, даже если это занимает больше 15 минут.

Мой вопрос:

Есть ли какие-либо проблемы с безопасностью / производительностью при таком дизайне, и если да, то какое решение было бы лучшим? Даже если нет никаких проблем с безопасностью и / или производительностью, приветствуются идеи получше. Фрагменты из моего решения показаны ниже:

Вот мой служебный класс, который будет вызываться в моем фильтре и везде, где мне понадобится имя пользователя.

 public abstract class UserUtil {
private static final ThreadLocal<String> threadUser = new ThreadLocal<String>();

public static String getUserId(){
    return threadUser.get();
}

public static void setUserId(String userId){
    threadUser.set(userId);
}

public static void removeUserId(){
    threadUser.remove();
}
}
  

Вот мой фильтр сервлета, используемый для установки имени пользователя перед запросом (и очистки его через блок finally после запроса).

 public class UserFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}

public void destroy() {
}

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    try {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        UserBean userBean = (UserBean) ((HttpServletRequest) servletRequest).getSession().getAttribute("userBean");
        UserUtil.setUserId(userBean.getUserId());

        filterChain.doFilter(servletRequest, servletResponse);
    } finally{
        UserUtil.removeUserId();
    }
}

}
  

Вот мой web.xml конфигурация:

 <!--web.xml-->
<web-app>

...
...
...

<filter>
    <filter-name>UserFilter</filter-name>
    <filter-class>filter.UserFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>UserFilter</filter-name>
    <url-pattern>*.jsf</url-pattern>
</filter-mapping>
  

Любые идеи высоко ценятся 🙂

Комментарии:

1. Я бы рекомендовал запустить асинхронный поток для выполнения длительной работы и взаимодействия с пользователем в потоке сервлета.

Ответ №1:

На самом деле это довольно распространенный подход для прикрепления информации о безопасности к потоку выполнения (или любой другой информации, связанной с выполнением).

Он используется на серверах Java EE внутри, а также сторонним кодом / утилитами, такими как Spring.

Это будет работать просто отлично.