Struts2和Hibernate - 在Servlet外部访问ActionContext.getContext()。getSession()

时间:2015-04-01 16:17:45

标签: spring hibernate struts2 thread-local actioncontext

我尝试在两种不同的情况下访问Struts(Struts2)操作之外的ActionContext.getContext(),并得到一个不同的结果,关于我在哪里尝试:

  1. 来自CurrentTenantIdentifierResolverImpl(我的)CurrentTenantIdentifierResolver的实现,它是一个Hibernate接口 - > KO(结果为空)
  2. 来自AbstractRoutingDataSource的一个(我的)AbstractDataSource实现,它是一个Spring接口 - >行
  3. 我找到了另一种解决办法,让我的CurrentTenantIdentifierResolverImpl使用ThreadLocal,但是:

    1. 为什么它适用于Spring而不适用于Hibernate?
    2. 为什么我无法访问ActionContext(ThreadLocal),我可以访问我的ThreadLocal(我设置的方式与ActionContext完全相同,位置相同,数据相同)?
    3. 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
      

      弹簧:

      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$5.doPrepare() line: 162   
          StatementPreparerImpl$5(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$29.doInHibernate(Session) line: 875   
          HibernateTemplate$29.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  
      

1 个答案:

答案 0 :(得分:2)

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);

在我的“休眠”情况下,此过滤器未执行(参见我的问题中的堆栈跟踪)==&gt; ActionContext未初始化。

所以作为结论:是的,您可以访问Servlet外部的ActionContext,但是如果您的堆栈是“经典”。如果您尝试从框架或横向代码访问它,请小心。

这是我的Hibernate问题的解决方案: 我创建了自己的Filter来访问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);
    }

}

My ThreadLocal:

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 (请确保在hibernate过滤器之前放置过滤器,以便初始化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>
  ...