Struts2 和 Hibernate - 在 Servlet 外部访问 ActionContext.getContext().getSession()
Struts2 and Hibernate - Access ActionContext.getContext().getSession() outside a Servlet
我尝试在 2 种不同的情况下在 Struts (Struts2) 操作之外访问 ActionContext.getContext() 并且我得到了不同的结果,关于我尝试的地方:
- 从 CurrentTenantIdentifierResolverImpl 一个(我的)CurrentTenantIdentifierResolver 实现,它是一个 Hibernate 接口 --> KO(结果为空)
- 来自 AbstractRoutingDataSource 的(我的)AbstractDataSource 实现,它是一个 Spring 接口 --> OK
我找到了另一种使用 ThreadLocal 使我的 CurrentTenantIdentifierResolverImpl 工作的解决方案,但是:
- 为什么它适用于 Spring 而不适用于 Hibernate?
- 为什么我不能访问 ActionContext(也包括 ThreadLocal),而我可以访问 MY ThreadLocal(我设置的与 ActionContext 完全一样,相同的位置,相同的数据)?
CurrentTenantIdentifierResolverImpl : 应该给使用的租户,这样 hibernate 就可以连接到良好的数据库。
import java.util.Map;
import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
import com.opensymphony.xwork2.ActionContext;
public class CurrentTenantIdentifierResolverImpl implements CurrentTenantIdentifierResolver {
@Override
public String resolveCurrentTenantIdentifier() {
if (ActionContext.getContext() != null) {
AbstractRoutingDataSource :相同但由 Spring
处理
import java.util.Map;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import com.opensymphony.xwork2.ActionContext;
public class RoutingDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
if (ActionContext.getContext() != null) {
当我查看两种情况下的堆栈时,我可以看到:
- AbstractRoutingDataSource 在堆栈中获取了我的 Servlet (HomeAction)
- CurrentTenantIdentifierResolver 在堆栈中没有我的 Servlet (HomeAction)
这是堆栈跟踪。
休眠:
Daemon Thread [http-bio-8081-exec-4] (Suspended (breakpoint at line 24 in CurrentTenantIdentifierResolverImpl))
owns: SocketWrapper<E> (id=184)
CurrentTenantIdentifierResolverImpl.resolveCurrentTenantIdentifier() line: 24
SessionFactoryImpl$SessionBuilderImpl.<init>(SessionFactoryImpl) line: 1572
SessionFactoryImpl.withOptions() line: 1019
SessionFactoryImpl.openSession() line: 999
OpenSessionInViewFilter.openSession(SessionFactory) line: 203
OpenSessionInViewFilter.doFilterInternal(HttpServletRequest, HttpServletResponse, FilterChain) line: 139
OpenSessionInViewFilter(OncePerRequestFilter).doFilter(ServletRequest, ServletResponse, FilterChain) line: 107
ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 243
ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 210
CharacterEncodingFilter.doFilterInternal(HttpServletRequest, HttpServletResponse, FilterChain) line: 88
CharacterEncodingFilter(OncePerRequestFilter).doFilter(ServletRequest, ServletResponse, FilterChain) line: 107
ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 243
ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 210
StandardWrapperValve.invoke(Request, Response) line: 222
StandardContextValve.invoke(Request, Response) line: 123
NonLoginAuthenticator(AuthenticatorBase).invoke(Request, Response) line: 502
StandardHostValve.invoke(Request, Response) line: 171
ErrorReportValve.invoke(Request, Response) line: 100
AccessLogValve.invoke(Request, Response) line: 953
StandardEngineValve.invoke(Request, Response) line: 118
CoyoteAdapter.service(Request, Response) line: 408
Http11Processor(AbstractHttp11Processor<S>).process(SocketWrapper<S>) line: 1041
Http11Protocol$Http11ConnectionHandler(AbstractProtocol$AbstractConnectionHandler<S,P>).process(SocketWrapper<S>, SocketStatus) line: 603
JIoEndpoint$SocketProcessor.run() line: 312
ThreadPoolExecutor(ThreadPoolExecutor).runWorker(ThreadPoolExecutor$Worker) line: 1145
ThreadPoolExecutor$Worker.run() line: 615
TaskThread(Thread).run() line: 722
Spring:
Daemon Thread [http-bio-8081-exec-2] (Suspended (breakpoint at line 20 in RoutingDataSource))
owns: SocketWrapper<E> (id=562)
RoutingDataSource.determineCurrentLookupKey() line: 20
RoutingDataSource(AbstractRoutingDataSource).determineTargetDataSource() line: 196
RoutingDataSource(AbstractRoutingDataSource).getConnection() line: 164
DatasourceConnectionProviderImpl.getConnection() line: 139
AbstractSessionImpl$NonContextualJdbcConnectionAccess.obtainConnection() line: 380
LogicalConnectionImpl.obtainConnection() line: 228
LogicalConnectionImpl.getConnection() line: 171
StatementPreparerImpl.connection() line: 63
StatementPreparerImpl.doPrepare() line: 162
StatementPreparerImpl(StatementPreparerImpl$StatementPreparationTemplate).prepareStatement() line: 186
StatementPreparerImpl.prepareQueryStatement(String, boolean, ScrollMode) line: 160
QueryLoader(Loader).prepareQueryStatement(String, QueryParameters, LimitHandler, boolean, SessionImplementor) line: 1885
QueryLoader(Loader).executeQueryStatement(String, QueryParameters, boolean, List<AfterLoadAction>, SessionImplementor) line: 1862
QueryLoader(Loader).executeQueryStatement(QueryParameters, boolean, List<AfterLoadAction>, SessionImplementor) line: 1839
QueryLoader(Loader).doQuery(SessionImplementor, QueryParameters, boolean, ResultTransformer) line: 910
QueryLoader(Loader).doQueryAndInitializeNonLazyCollections(SessionImplementor, QueryParameters, boolean, ResultTransformer) line: 355
QueryLoader(Loader).doList(SessionImplementor, QueryParameters, ResultTransformer) line: 2554
QueryLoader(Loader).listUsingQueryCache(SessionImplementor, QueryParameters, Set<Serializable>, Type[]) line: 2399
QueryLoader(Loader).list(SessionImplementor, QueryParameters, Set<Serializable>, Type[]) line: 2362
QueryLoader.list(SessionImplementor, QueryParameters) line: 497
QueryTranslatorImpl.list(SessionImplementor, QueryParameters) line: 387
HQLQueryPlan.performList(QueryParameters, SessionImplementor) line: 236
SessionImpl.list(String, QueryParameters) line: 1264
QueryImpl.list() line: 103
HibernateTemplate.doInHibernate(Session) line: 875
HibernateTemplate.doInHibernate(Session) line: 864
HibernateTemplate.doExecute(HibernateCallback<T>, boolean) line: 340
HibernateTemplate.executeWithNativeSession(HibernateCallback<T>) line: 308
HibernateTemplate.find(String, Object...) line: 864
AideGestionDaoImpl(GenericHibernateDAO<T,ID>).find(String, Object...) line: 92
AideGestionDaoImpl.findByGerantAndDate(Long, Date) line: 54
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]
NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25
Method.invoke(Object, Object...) line: 597
AopUtils.invokeJoinpointUsingReflection(Object, Method, Object[]) line: 317
ReflectiveMethodInvocation.invokeJoinpoint() line: 190
ReflectiveMethodInvocation.proceed() line: 157
MethodInvocationProceedingJoinPoint.proceed() line: 85
DAOAudit.daoProfiling(ProceedingJoinPoint) line: 30
GeneratedMethodAccessor101.invoke(Object, Object[]) line: not available
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25
Method.invoke(Object, Object...) line: 597
AspectJAroundAdvice(AbstractAspectJAdvice).invokeAdviceMethodWithGivenArgs(Object[]) line: 621
AspectJAroundAdvice(AbstractAspectJAdvice).invokeAdviceMethod(JoinPoint, JoinPointMatch, Object, Throwable) line: 610
AspectJAroundAdvice.invoke(MethodInvocation) line: 68
ReflectiveMethodInvocation.proceed() line: 168
ExposeInvocationInterceptor.invoke(MethodInvocation) line: 92
ReflectiveMethodInvocation.proceed() line: 179
JdkDynamicAopProxy.invoke(Object, Method, Object[]) line: 207
$Proxy108.findByGerantAndDate(Long, Date) line: not available
HomeAction.buildTabSyn() line: 241
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]
NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25
Method.invoke(Object, Object...) line: 597
DefaultActionInvocation.invokeAction(Object, ActionConfig) line: 450
DefaultActionInvocation.invokeActionOnly() line: 289
DefaultActionInvocation.invoke() line: 252
ParametersInterceptor.doIntercept(ActionInvocation) line: 239
ParametersInterceptor(MethodFilterInterceptor).intercept(ActionInvocation) line: 98
DefaultActionInvocation.invoke() line: 246
ActionMappingParametersInteceptor(ParametersInterceptor).doIntercept(ActionInvocation) line: 239
ActionMappingParametersInteceptor(MethodFilterInterceptor).intercept(ActionInvocation) line: 98
DefaultActionInvocation.invoke() line: 246
MultiselectInterceptor.intercept(ActionInvocation) line: 73
DefaultActionInvocation.invoke() line: 246
CheckboxInterceptor.intercept(ActionInvocation) line: 91
DefaultActionInvocation.invoke() line: 246
PrepareInterceptor.doIntercept(ActionInvocation) line: 171
PrepareInterceptor(MethodFilterInterceptor).intercept(ActionInvocation) line: 98
DefaultActionInvocation.invoke() line: 246
ServletConfigInterceptor.intercept(ActionInvocation) line: 164
DefaultActionInvocation.invoke() line: 246
ExceptionLoggingInterceptor(ExceptionMappingInterceptor).intercept(ActionInvocation) line: 189
DefaultActionInvocation.invoke() line: 246
StrutsActionProxy.execute() line: 54
Dispatcher.serviceAction(HttpServletRequest, HttpServletResponse, ServletContext, ActionMapping) line: 563
ExecuteOperations.executeAction(HttpServletRequest, HttpServletResponse, ActionMapping) line: 77
StrutsPrepareAndExecuteFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 99
ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 243
ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 210
ResponseOverrideFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 125
ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 243
ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 210
SessionFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 52
ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 243
ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 210
UserLogFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 43
ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 243
ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 210
FilterChainProxy$VirtualFilterChain.doFilter(ServletRequest, ServletResponse) line: 330
FilterSecurityInterceptor.invoke(FilterInvocation) line: 118
FilterSecurityInterceptor.doFilter(ServletRequest, ServletResponse, FilterChain) line: 84
FilterChainProxy$VirtualFilterChain.doFilter(ServletRequest, ServletResponse) line: 342
ExceptionTranslationFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 113
FilterChainProxy$VirtualFilterChain.doFilter(ServletRequest, ServletResponse) line: 342
SessionManagementFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 103
FilterChainProxy$VirtualFilterChain.doFilter(ServletRequest, ServletResponse) line: 342
AnonymousAuthenticationFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 113
FilterChainProxy$VirtualFilterChain.doFilter(ServletRequest, ServletResponse) line: 342
SecurityContextHolderAwareRequestFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 150
FilterChainProxy$VirtualFilterChain.doFilter(ServletRequest, ServletResponse) line: 342
RequestCacheAwareFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 45
FilterChainProxy$VirtualFilterChain.doFilter(ServletRequest, ServletResponse) line: 342
UsernamePasswordAuthenticationFilter(AbstractAuthenticationProcessingFilter).doFilter(ServletRequest, ServletResponse, FilterChain) line: 199
FilterChainProxy$VirtualFilterChain.doFilter(ServletRequest, ServletResponse) line: 342
LogoutFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 110
FilterChainProxy$VirtualFilterChain.doFilter(ServletRequest, ServletResponse) line: 342
WebAsyncManagerIntegrationFilter.doFilterInternal(HttpServletRequest, HttpServletResponse, FilterChain) line: 50
WebAsyncManagerIntegrationFilter(OncePerRequestFilter).doFilter(ServletRequest, ServletResponse, FilterChain) line: 107
FilterChainProxy$VirtualFilterChain.doFilter(ServletRequest, ServletResponse) line: 342
ConcurrentSessionFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 125
FilterChainProxy$VirtualFilterChain.doFilter(ServletRequest, ServletResponse) line: 342
SecurityContextPersistenceFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 87
FilterChainProxy$VirtualFilterChain.doFilter(ServletRequest, ServletResponse) line: 342
FilterChainProxy.doFilterInternal(ServletRequest, ServletResponse, FilterChain) line: 192
FilterChainProxy.doFilter(ServletRequest, ServletResponse, FilterChain) line: 160
DelegatingFilterProxy.invokeDelegate(Filter, ServletRequest, ServletResponse, FilterChain) line: 344
DelegatingFilterProxy.doFilter(ServletRequest, ServletResponse, FilterChain) line: 261
ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 243
ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 210
OpenSessionInViewFilter.doFilterInternal(HttpServletRequest, HttpServletResponse, FilterChain) line: 150
OpenSessionInViewFilter(OncePerRequestFilter).doFilter(ServletRequest, ServletResponse, FilterChain) line: 107
ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 243
ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 210
OpenSessionInViewFilter.doFilterInternal(HttpServletRequest, HttpServletResponse, FilterChain) line: 150
OpenSessionInViewFilter(OncePerRequestFilter).doFilter(ServletRequest, ServletResponse, FilterChain) line: 107
ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 243
ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 210
CharacterEncodingFilter.doFilterInternal(HttpServletRequest, HttpServletResponse, FilterChain) line: 88
CharacterEncodingFilter(OncePerRequestFilter).doFilter(ServletRequest, ServletResponse, FilterChain) line: 107
ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 243
ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 210
StandardWrapperValve.invoke(Request, Response) line: 222
StandardContextValve.invoke(Request, Response) line: 123
NonLoginAuthenticator(AuthenticatorBase).invoke(Request, Response) line: 502
StandardHostValve.invoke(Request, Response) line: 171
ErrorReportValve.invoke(Request, Response) line: 100
AccessLogValve.invoke(Request, Response) line: 953
StandardEngineValve.invoke(Request, Response) line: 118
CoyoteAdapter.service(Request, Response) line: 408
Http11Processor(AbstractHttp11Processor<S>).process(SocketWrapper<S>) line: 1041
Http11Protocol$Http11ConnectionHandler(AbstractProtocol$AbstractConnectionHandler<S,P>).process(SocketWrapper<S>, SocketStatus) line: 603
JIoEndpoint$SocketProcessor.run() line: 312
ThreadPoolExecutor$Worker.runTask(Runnable) line: 895
ThreadPoolExecutor$Worker.run() line: 918
TaskThread(Thread).run() line: 662
ActionContext 似乎是由 Filter 初始化的 "StrutsPrepareAndExecuteFilter":
doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
try {
prepare.setEncodingAndLocale(request, response);
prepare.createActionContext(request, response);
在我的 "hibernate" 案例中,此过滤器未执行(参见我问题中的堆栈跟踪)==> ActionContext 未初始化。
所以结论是: 是的,您可以在 Servlet 外部访问 ActionContext,但如果您的堆栈是 "classic"。如果您尝试从框架或横向代码访问它,请小心。
这是我对 Hibernate 问题的解决方案:
我创建了自己的过滤器来访问 HttpSession(我们可以从这里访问)并将我需要的信息放在 ThreadLocal 中。
我的过滤器:
public class TenantIdentifierFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(
HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
HttpSession session = request.getSession();
String tenantCode = (String) session.getAttribute(WorkSession.CONNECTED_ENTITY);
UserTenantContext.set(tenantCode);
logger.debug("VPD-MultiTenancy - tenantCode : " + tenantCode);
filterChain.doFilter(request, response);
}
}
我的本地线程:
public class UserTenantContext {
public static final ThreadLocal<String> userTenantCode = new ThreadLocal<String>();
/**
* Set user in the context of the ThreadLocal
* @param user
*/
public static void set(String tenantCode) {
userTenantCode.set(tenantCode);
}
public static void unset() {
userTenantCode.remove();
}
/**
* @return get user in the context of the ThreadLocal
*/
public static String get() {
return userTenantCode.get();
}
}
我的web.xml(一定要把你的过滤器放在休眠过滤器之前,这样你的ThreadLocal就会被初始化):
...
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- VPD-MultiTenancy-ADD-->
<filter>
<filter-name>tenantFilter</filter-name>
<filter-class>
amundi.sits.mgs.web.services.user.TenantIdentifierFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>tenantFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- VPD-MultiTenancy-ADD/ -->
<filter>
<filter-name>hibernateFilter</filter-name>
<filter-class>
org.springframework.orm.hibernate4.support.OpenSessionInViewFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>hibernateFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
...
我尝试在 2 种不同的情况下在 Struts (Struts2) 操作之外访问 ActionContext.getContext() 并且我得到了不同的结果,关于我尝试的地方:
- 从 CurrentTenantIdentifierResolverImpl 一个(我的)CurrentTenantIdentifierResolver 实现,它是一个 Hibernate 接口 --> KO(结果为空)
- 来自 AbstractRoutingDataSource 的(我的)AbstractDataSource 实现,它是一个 Spring 接口 --> OK
我找到了另一种使用 ThreadLocal 使我的 CurrentTenantIdentifierResolverImpl 工作的解决方案,但是:
- 为什么它适用于 Spring 而不适用于 Hibernate?
- 为什么我不能访问 ActionContext(也包括 ThreadLocal),而我可以访问 MY ThreadLocal(我设置的与 ActionContext 完全一样,相同的位置,相同的数据)?
CurrentTenantIdentifierResolverImpl : 应该给使用的租户,这样 hibernate 就可以连接到良好的数据库。
import java.util.Map;
import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
import com.opensymphony.xwork2.ActionContext;
public class CurrentTenantIdentifierResolverImpl implements CurrentTenantIdentifierResolver {
@Override
public String resolveCurrentTenantIdentifier() {
if (ActionContext.getContext() != null) {
AbstractRoutingDataSource :相同但由 Spring
处理import java.util.Map;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import com.opensymphony.xwork2.ActionContext;
public class RoutingDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
if (ActionContext.getContext() != null) {
当我查看两种情况下的堆栈时,我可以看到:
- AbstractRoutingDataSource 在堆栈中获取了我的 Servlet (HomeAction)
- CurrentTenantIdentifierResolver 在堆栈中没有我的 Servlet (HomeAction)
这是堆栈跟踪。
休眠:
Daemon Thread [http-bio-8081-exec-4] (Suspended (breakpoint at line 24 in CurrentTenantIdentifierResolverImpl))
owns: SocketWrapper<E> (id=184)
CurrentTenantIdentifierResolverImpl.resolveCurrentTenantIdentifier() line: 24
SessionFactoryImpl$SessionBuilderImpl.<init>(SessionFactoryImpl) line: 1572
SessionFactoryImpl.withOptions() line: 1019
SessionFactoryImpl.openSession() line: 999
OpenSessionInViewFilter.openSession(SessionFactory) line: 203
OpenSessionInViewFilter.doFilterInternal(HttpServletRequest, HttpServletResponse, FilterChain) line: 139
OpenSessionInViewFilter(OncePerRequestFilter).doFilter(ServletRequest, ServletResponse, FilterChain) line: 107
ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 243
ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 210
CharacterEncodingFilter.doFilterInternal(HttpServletRequest, HttpServletResponse, FilterChain) line: 88
CharacterEncodingFilter(OncePerRequestFilter).doFilter(ServletRequest, ServletResponse, FilterChain) line: 107
ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 243
ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 210
StandardWrapperValve.invoke(Request, Response) line: 222
StandardContextValve.invoke(Request, Response) line: 123
NonLoginAuthenticator(AuthenticatorBase).invoke(Request, Response) line: 502
StandardHostValve.invoke(Request, Response) line: 171
ErrorReportValve.invoke(Request, Response) line: 100
AccessLogValve.invoke(Request, Response) line: 953
StandardEngineValve.invoke(Request, Response) line: 118
CoyoteAdapter.service(Request, Response) line: 408
Http11Processor(AbstractHttp11Processor<S>).process(SocketWrapper<S>) line: 1041
Http11Protocol$Http11ConnectionHandler(AbstractProtocol$AbstractConnectionHandler<S,P>).process(SocketWrapper<S>, SocketStatus) line: 603
JIoEndpoint$SocketProcessor.run() line: 312
ThreadPoolExecutor(ThreadPoolExecutor).runWorker(ThreadPoolExecutor$Worker) line: 1145
ThreadPoolExecutor$Worker.run() line: 615
TaskThread(Thread).run() line: 722
Spring:
Daemon Thread [http-bio-8081-exec-2] (Suspended (breakpoint at line 20 in RoutingDataSource))
owns: SocketWrapper<E> (id=562)
RoutingDataSource.determineCurrentLookupKey() line: 20
RoutingDataSource(AbstractRoutingDataSource).determineTargetDataSource() line: 196
RoutingDataSource(AbstractRoutingDataSource).getConnection() line: 164
DatasourceConnectionProviderImpl.getConnection() line: 139
AbstractSessionImpl$NonContextualJdbcConnectionAccess.obtainConnection() line: 380
LogicalConnectionImpl.obtainConnection() line: 228
LogicalConnectionImpl.getConnection() line: 171
StatementPreparerImpl.connection() line: 63
StatementPreparerImpl.doPrepare() line: 162
StatementPreparerImpl(StatementPreparerImpl$StatementPreparationTemplate).prepareStatement() line: 186
StatementPreparerImpl.prepareQueryStatement(String, boolean, ScrollMode) line: 160
QueryLoader(Loader).prepareQueryStatement(String, QueryParameters, LimitHandler, boolean, SessionImplementor) line: 1885
QueryLoader(Loader).executeQueryStatement(String, QueryParameters, boolean, List<AfterLoadAction>, SessionImplementor) line: 1862
QueryLoader(Loader).executeQueryStatement(QueryParameters, boolean, List<AfterLoadAction>, SessionImplementor) line: 1839
QueryLoader(Loader).doQuery(SessionImplementor, QueryParameters, boolean, ResultTransformer) line: 910
QueryLoader(Loader).doQueryAndInitializeNonLazyCollections(SessionImplementor, QueryParameters, boolean, ResultTransformer) line: 355
QueryLoader(Loader).doList(SessionImplementor, QueryParameters, ResultTransformer) line: 2554
QueryLoader(Loader).listUsingQueryCache(SessionImplementor, QueryParameters, Set<Serializable>, Type[]) line: 2399
QueryLoader(Loader).list(SessionImplementor, QueryParameters, Set<Serializable>, Type[]) line: 2362
QueryLoader.list(SessionImplementor, QueryParameters) line: 497
QueryTranslatorImpl.list(SessionImplementor, QueryParameters) line: 387
HQLQueryPlan.performList(QueryParameters, SessionImplementor) line: 236
SessionImpl.list(String, QueryParameters) line: 1264
QueryImpl.list() line: 103
HibernateTemplate.doInHibernate(Session) line: 875
HibernateTemplate.doInHibernate(Session) line: 864
HibernateTemplate.doExecute(HibernateCallback<T>, boolean) line: 340
HibernateTemplate.executeWithNativeSession(HibernateCallback<T>) line: 308
HibernateTemplate.find(String, Object...) line: 864
AideGestionDaoImpl(GenericHibernateDAO<T,ID>).find(String, Object...) line: 92
AideGestionDaoImpl.findByGerantAndDate(Long, Date) line: 54
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]
NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25
Method.invoke(Object, Object...) line: 597
AopUtils.invokeJoinpointUsingReflection(Object, Method, Object[]) line: 317
ReflectiveMethodInvocation.invokeJoinpoint() line: 190
ReflectiveMethodInvocation.proceed() line: 157
MethodInvocationProceedingJoinPoint.proceed() line: 85
DAOAudit.daoProfiling(ProceedingJoinPoint) line: 30
GeneratedMethodAccessor101.invoke(Object, Object[]) line: not available
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25
Method.invoke(Object, Object...) line: 597
AspectJAroundAdvice(AbstractAspectJAdvice).invokeAdviceMethodWithGivenArgs(Object[]) line: 621
AspectJAroundAdvice(AbstractAspectJAdvice).invokeAdviceMethod(JoinPoint, JoinPointMatch, Object, Throwable) line: 610
AspectJAroundAdvice.invoke(MethodInvocation) line: 68
ReflectiveMethodInvocation.proceed() line: 168
ExposeInvocationInterceptor.invoke(MethodInvocation) line: 92
ReflectiveMethodInvocation.proceed() line: 179
JdkDynamicAopProxy.invoke(Object, Method, Object[]) line: 207
$Proxy108.findByGerantAndDate(Long, Date) line: not available
HomeAction.buildTabSyn() line: 241
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]
NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25
Method.invoke(Object, Object...) line: 597
DefaultActionInvocation.invokeAction(Object, ActionConfig) line: 450
DefaultActionInvocation.invokeActionOnly() line: 289
DefaultActionInvocation.invoke() line: 252
ParametersInterceptor.doIntercept(ActionInvocation) line: 239
ParametersInterceptor(MethodFilterInterceptor).intercept(ActionInvocation) line: 98
DefaultActionInvocation.invoke() line: 246
ActionMappingParametersInteceptor(ParametersInterceptor).doIntercept(ActionInvocation) line: 239
ActionMappingParametersInteceptor(MethodFilterInterceptor).intercept(ActionInvocation) line: 98
DefaultActionInvocation.invoke() line: 246
MultiselectInterceptor.intercept(ActionInvocation) line: 73
DefaultActionInvocation.invoke() line: 246
CheckboxInterceptor.intercept(ActionInvocation) line: 91
DefaultActionInvocation.invoke() line: 246
PrepareInterceptor.doIntercept(ActionInvocation) line: 171
PrepareInterceptor(MethodFilterInterceptor).intercept(ActionInvocation) line: 98
DefaultActionInvocation.invoke() line: 246
ServletConfigInterceptor.intercept(ActionInvocation) line: 164
DefaultActionInvocation.invoke() line: 246
ExceptionLoggingInterceptor(ExceptionMappingInterceptor).intercept(ActionInvocation) line: 189
DefaultActionInvocation.invoke() line: 246
StrutsActionProxy.execute() line: 54
Dispatcher.serviceAction(HttpServletRequest, HttpServletResponse, ServletContext, ActionMapping) line: 563
ExecuteOperations.executeAction(HttpServletRequest, HttpServletResponse, ActionMapping) line: 77
StrutsPrepareAndExecuteFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 99
ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 243
ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 210
ResponseOverrideFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 125
ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 243
ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 210
SessionFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 52
ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 243
ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 210
UserLogFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 43
ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 243
ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 210
FilterChainProxy$VirtualFilterChain.doFilter(ServletRequest, ServletResponse) line: 330
FilterSecurityInterceptor.invoke(FilterInvocation) line: 118
FilterSecurityInterceptor.doFilter(ServletRequest, ServletResponse, FilterChain) line: 84
FilterChainProxy$VirtualFilterChain.doFilter(ServletRequest, ServletResponse) line: 342
ExceptionTranslationFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 113
FilterChainProxy$VirtualFilterChain.doFilter(ServletRequest, ServletResponse) line: 342
SessionManagementFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 103
FilterChainProxy$VirtualFilterChain.doFilter(ServletRequest, ServletResponse) line: 342
AnonymousAuthenticationFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 113
FilterChainProxy$VirtualFilterChain.doFilter(ServletRequest, ServletResponse) line: 342
SecurityContextHolderAwareRequestFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 150
FilterChainProxy$VirtualFilterChain.doFilter(ServletRequest, ServletResponse) line: 342
RequestCacheAwareFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 45
FilterChainProxy$VirtualFilterChain.doFilter(ServletRequest, ServletResponse) line: 342
UsernamePasswordAuthenticationFilter(AbstractAuthenticationProcessingFilter).doFilter(ServletRequest, ServletResponse, FilterChain) line: 199
FilterChainProxy$VirtualFilterChain.doFilter(ServletRequest, ServletResponse) line: 342
LogoutFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 110
FilterChainProxy$VirtualFilterChain.doFilter(ServletRequest, ServletResponse) line: 342
WebAsyncManagerIntegrationFilter.doFilterInternal(HttpServletRequest, HttpServletResponse, FilterChain) line: 50
WebAsyncManagerIntegrationFilter(OncePerRequestFilter).doFilter(ServletRequest, ServletResponse, FilterChain) line: 107
FilterChainProxy$VirtualFilterChain.doFilter(ServletRequest, ServletResponse) line: 342
ConcurrentSessionFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 125
FilterChainProxy$VirtualFilterChain.doFilter(ServletRequest, ServletResponse) line: 342
SecurityContextPersistenceFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 87
FilterChainProxy$VirtualFilterChain.doFilter(ServletRequest, ServletResponse) line: 342
FilterChainProxy.doFilterInternal(ServletRequest, ServletResponse, FilterChain) line: 192
FilterChainProxy.doFilter(ServletRequest, ServletResponse, FilterChain) line: 160
DelegatingFilterProxy.invokeDelegate(Filter, ServletRequest, ServletResponse, FilterChain) line: 344
DelegatingFilterProxy.doFilter(ServletRequest, ServletResponse, FilterChain) line: 261
ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 243
ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 210
OpenSessionInViewFilter.doFilterInternal(HttpServletRequest, HttpServletResponse, FilterChain) line: 150
OpenSessionInViewFilter(OncePerRequestFilter).doFilter(ServletRequest, ServletResponse, FilterChain) line: 107
ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 243
ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 210
OpenSessionInViewFilter.doFilterInternal(HttpServletRequest, HttpServletResponse, FilterChain) line: 150
OpenSessionInViewFilter(OncePerRequestFilter).doFilter(ServletRequest, ServletResponse, FilterChain) line: 107
ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 243
ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 210
CharacterEncodingFilter.doFilterInternal(HttpServletRequest, HttpServletResponse, FilterChain) line: 88
CharacterEncodingFilter(OncePerRequestFilter).doFilter(ServletRequest, ServletResponse, FilterChain) line: 107
ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 243
ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 210
StandardWrapperValve.invoke(Request, Response) line: 222
StandardContextValve.invoke(Request, Response) line: 123
NonLoginAuthenticator(AuthenticatorBase).invoke(Request, Response) line: 502
StandardHostValve.invoke(Request, Response) line: 171
ErrorReportValve.invoke(Request, Response) line: 100
AccessLogValve.invoke(Request, Response) line: 953
StandardEngineValve.invoke(Request, Response) line: 118
CoyoteAdapter.service(Request, Response) line: 408
Http11Processor(AbstractHttp11Processor<S>).process(SocketWrapper<S>) line: 1041
Http11Protocol$Http11ConnectionHandler(AbstractProtocol$AbstractConnectionHandler<S,P>).process(SocketWrapper<S>, SocketStatus) line: 603
JIoEndpoint$SocketProcessor.run() line: 312
ThreadPoolExecutor$Worker.runTask(Runnable) line: 895
ThreadPoolExecutor$Worker.run() line: 918
TaskThread(Thread).run() line: 662
ActionContext 似乎是由 Filter 初始化的 "StrutsPrepareAndExecuteFilter":
doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
try {
prepare.setEncodingAndLocale(request, response);
prepare.createActionContext(request, response);
在我的 "hibernate" 案例中,此过滤器未执行(参见我问题中的堆栈跟踪)==> ActionContext 未初始化。
所以结论是: 是的,您可以在 Servlet 外部访问 ActionContext,但如果您的堆栈是 "classic"。如果您尝试从框架或横向代码访问它,请小心。
这是我对 Hibernate 问题的解决方案: 我创建了自己的过滤器来访问 HttpSession(我们可以从这里访问)并将我需要的信息放在 ThreadLocal 中。
我的过滤器:
public class TenantIdentifierFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(
HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
HttpSession session = request.getSession();
String tenantCode = (String) session.getAttribute(WorkSession.CONNECTED_ENTITY);
UserTenantContext.set(tenantCode);
logger.debug("VPD-MultiTenancy - tenantCode : " + tenantCode);
filterChain.doFilter(request, response);
}
}
我的本地线程:
public class UserTenantContext {
public static final ThreadLocal<String> userTenantCode = new ThreadLocal<String>();
/**
* Set user in the context of the ThreadLocal
* @param user
*/
public static void set(String tenantCode) {
userTenantCode.set(tenantCode);
}
public static void unset() {
userTenantCode.remove();
}
/**
* @return get user in the context of the ThreadLocal
*/
public static String get() {
return userTenantCode.get();
}
}
我的web.xml(一定要把你的过滤器放在休眠过滤器之前,这样你的ThreadLocal就会被初始化):
...
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- VPD-MultiTenancy-ADD-->
<filter>
<filter-name>tenantFilter</filter-name>
<filter-class>
amundi.sits.mgs.web.services.user.TenantIdentifierFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>tenantFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- VPD-MultiTenancy-ADD/ -->
<filter>
<filter-name>hibernateFilter</filter-name>
<filter-class>
org.springframework.orm.hibernate4.support.OpenSessionInViewFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>hibernateFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
...