Получение и сохранение переменной области приложения в Tomcat - PullRequest
2 голосов
/ 14 июля 2020

Это приложение на основе Java 1.8 и Tomcat 9, с без Spring .

Я хочу сохранить объект в области приложения и получить его с помощью любой другой сеанс. Есть только один сервер Tomcat, он все равно не интегрирован. В этом случае у нас есть авторизация приложения, которая происходит на основе проверенных заголовков AUTH_USER и ROLE_ID. Код выполняется, но каждый раз, когда он сохраняет объект в области приложения, он забывается или каким-то образом становится недоступным для любого будущего запроса. В результате кэширования не происходит.

Мой вопрос в том, как сохранить объект, созданный в одном запросе, и сделать его доступным через область приложения для следующего запроса. Пожалуйста, просмотрите комментарии в коде, чтобы увидеть, где, по моему мнению, это должно работать.

Запросы поступают через веб-функцию типа JAX-RS. То, что у меня ниже, не совсем то, как это закодировано, но упрощено, чтобы избежать ненужных деталей. Пример одного из них:

    @POST
    @Path("getDashboardTotalHubs")
    @Produces({ MediaType.APPLICATION_JSON + AppConstants.COMMA + MediaType.CHARSET_PARAMETER + AppConstants.UTF_8 })
    @Consumes(MediaType.APPLICATION_JSON)
    public Response getDashboardTotalHubs(@Context HttpServletRequest httpServletRequest,
            HubRequestFilter hubRequestFilter) {
        // I want to get check authorization based on the value of the HTTP request headers here.  
        this.httpServletRequest = httpServletRequest;
        AuthorizedHubRequest = getCachedAuthorizedHubRequestMap();
        
    }


    private Map<String,AuthorizedHubRequest> getCachedAuthorizedHubRequestMap() {
        // I thought getSevletContext gave me the global application scope, but I'm somehow
        // wrong.  
        ServletContext context = this.getHttpServletRequest().getServletContext();
        Map<String,AuthorizedHubRequest> result = (Map<String, AuthorizedHubRequest>) context.getAttribute(AuthorizedHubRequest.class.getName());
        if(result == null) {
            result = new HashMap<String,AuthorizedHubRequest>();
            context.setAttribute(AuthorizedHubRequest.class.getName(),result);
        }
        return result;
    }

    private String getAuthorizedHubRequestCacheKey() {
        return this.authUser + "-"+ this.httpServletRequest.getHeader("Authorization") + "-"+ this.roleId;
    }
        
    private AuthorizedHubRequest getAuthorizedHubRequestFromCache() {
        String key = getAuthorizedHubRequestCacheKey();
        return getCachedAuthorizedHubRequestMap().get(key);  // This always returns null
    }

    private void saveAuthorizedHubRequestToCache(AuthorizedHubRequest authorizedHubRequest) {
        String key = getAuthorizedHubRequestCacheKey();
        getCachedAuthorizedHubRequestMap().put(key,authorizedHubRequest);
    }

    public AuthorizedHubRequest getAuthorizedHubRequest() throws SCExceptions {
        AuthorizedHubRequest result = getAuthorizedHubRequestFromCache();
        if(result != null) {
            logger.info("SC_TRACE_ID: "+this.traceId+" Retrieved authorization from cache");
        } else {
            logger.info("SC_TRACE_ID: "+this.traceId+" Authorization not in cache.  Creating.");
            authorizedHubRequest = new AuthorizedHubRequest().withHubRequestFilter(hubRequestFilter).withTraceId(traceId);
            if (this.pageNumber != null && this.pageSize != null) {
                authorizedHubRequest.setPageNumberRequested(pageNumber);
                authorizedHubRequest.setPageSize(pageSize);
            }

            if(this.maximumCacheDuration!=null) {
                authorizedHubRequest.setMaximumCacheDuration(maximumCacheDuration);
            }

            SCHubAuthorizationServiceHandler authHandler = new SCHubAuthorizationServiceHandler();
            authorizedHubRequest.setHubAuthorizations(authHandler.getHubAuthorization(traceId, authUser, roleId));
            saveAuthorizedHubRequestToCache(result);
        }

        return this.authorizedHubRequest;
    }

Мой сервер. xml это

<Server port="8015" shutdown="SHUTDOWN">
  <Listener className="org.apache.catalina.startup.VersionLoggerListener"/>
  <Listener SSLEngine="on" className="org.apache.catalina.core.AprLifecycleListener"/>
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener"/>
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener"/>
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener"/>
  <GlobalNamingResources>
    <Resource auth="Container" description="User database that can be updated and saved" factory="org.apache.catalina.users.MemoryUserDatabaseFactory" name="UserDatabase" pathname="conf/tomcat-users.xml" type="org.apache.catalina.UserDatabase"/>
  </GlobalNamingResources>
  <Service name="Catalina">
    <Connector connectionTimeout="20000" port="8090" protocol="HTTP/1.1" redirectPort="8443"/>
    <Engine defaultHost="localhost" name="Catalina">
      <Realm className="org.apache.catalina.realm.LockOutRealm">
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/>
      </Realm>
      <Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true">
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" pattern="%h %l %u %t &quot;%r&quot; %s %b" prefix="localhost_access_log" suffix=".txt"/>
      </Host>
    </Engine>
  </Service>
</Server>

Ответы [ 3 ]

2 голосов
/ 18 июля 2020

Карлос, вы осознали, что в методе getAuthorizedHubRequest вы фактически кэшируете результат переменной, который после вашего кода должен иметь значение null, а не новую переменную authorizedHubRequest? Думаю, в этом проблема.

1 голос
/ 18 июля 2020

Возможно, вам нужен сеанс, а не область применения. Атрибуты хранилища сеансов в HttpSession, поэтому сохраненная информация будет доступна только для запросов от одного и того же пользователя.

1 голос
/ 18 июля 2020

Это приложение на основе Java 1.8 и Tomcat 9, без Spring.

Атрибуты сервлета Java могут использоваться для передачи данных между запросами. Существует три различных области действия: область запроса, область сеанса и область приложения.

Мой вопрос заключается в том, как сохранить объект, созданный в одном запросе, и сделать его доступным через область приложения для следующего запроса. Пожалуйста, просмотрите комментарии в коде, чтобы узнать, где, по моему мнению, это должно работать.

Область применения связана с вашим веб-приложением. Эта область существует, пока развернуто веб-приложение. Вы можете установить атрибуты значений в области приложения в атрибуте контекста сервлета. Например,

@WebServlet("/set-application-scope-attributes")
public class SetAttributesServlet extends HttpServlet{

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        // set application scoped attribute
        req.getServletContext().setAttribute("name", "application scoped attribute");
// ...

}

Сохраненный атрибут на уровне приложения может быть получен путем вызова другого конкретного типа запроса. Например:

@WebServlet("/get-application-scoped-attribute")
public class GetAttributesServlet extends HttpServlet{

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        // get application scoped attribute
        String applicationScope = (String)req.getServletContext().getAttribute("name");

// ...

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...