在Tomcat中获取和保存应用程序范围变量



这是一个基于Java 1.8和Tomcat 9的应用程序,没有Spring。

我希望能够在应用程序范围中保存一个对象,并使其可由任何其他会话获取。只有一个Tomcat服务器,它无论如何都不是联邦服务器。在这种情况下,我们有基于已验证的AUTH_USER和ROLE_ID标头的应用程序授权。代码会运行,但每次将对象保存到应用程序范围时,它都会被遗忘,或者以某种方式无法访问任何未来的请求。因此,不会发生缓存。

我的问题是如何保存在一个请求中创建的对象,并通过应用程序范围为下一个请求提供它。请查看代码中的注释,看看我认为它应该在哪里工作。

请求是通过web 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;
}

我的server.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>

Carlos,您是否意识到,在方法getAuthorizedHubRequest中,您实际上正在缓存变量结果,代码后面的变量结果必须为null,而不是新变量authorizedHubRequest?我认为这就是问题所在。

这是一个基于Java 1.8和Tomcat 9的应用程序,没有Spring。

Java Servlet属性可用于在请求之间传递数据。有三个不同的作用域:请求作用域、会话作用域和应用程序作用域。

我的问题是如何保存在一个请求中创建的对象,并通过应用程序范围为下一个请求提供它。请查看代码中的注释,看看我认为它应该在哪里工作。

应用程序范围与您的web应用程序相关联。只要部署了web应用程序,此作用域就会一直存在。您可以在servlet上下文属性中设置应用程序范围的值属性。例如

@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");
// ...
}

也许您需要会话,而不是应用程序范围。会话将属性存储在HttpSession中,所以保存的信息将仅可用于来自同一用户的请求。

最新更新