2013-02-19 2 views
7

저는 GlassFish에서 RESTful Java 백엔드를 실행하고 있습니다. 그것에 첨부 된 HTML5/JS 프론트 엔드는 webapp 프로젝트에 넣을 수 있고 (종속성으로 백엔드를 포함 할 수 있음) 다른 위치에서 IIS 웹 서버에서 실행할 수 있습니다. CORS는 문제가되지 않습니다. 이 다음과 같은 문제를 해결한다 무엇 이건 :ThreadLocal Singleton

상황 :

  1. 사용자 1가 로그온 및 데이터베이스 경로가 데이터베이스에 'DB/사용자 1 /'
  2. 사용자 1 삽입 '값 1'로 설정되어
  3. 사용자 2 로그 에 데이터베이스 경로로 설정 'dB/사용자 2 /'
  4. 사용자 1이

사용자 1이되지 않을 것 데이터베이스에서 '값 1'을 삭제하려고

  • db/user1에서 값 1을 삭제할 수 있습니다. 데이터베이스 경로가 db/user2로 변경되고 해당 데이터베이스에 값 1이 없기 때문입니다.

    public class DataAccess{ 
        private static DataAccess dataaccess; 
        private String databasepath; 
    
        public static DataAccess getInstance() { 
         if (dataaccess == null) { 
          dataaccess = new DataAccess(); 
         } 
        } 
    } 
    

    어떻게 getInstance() 메서드를 수정하여 싱글 톤으로 작동하지만 해당 사용자의 스레드 내부에서만 작동합니까? threadlocal이라는 것을 보았지만 완전히 이해하지 못했습니다. 아마 해결책일까요?

    모든 도움을 받으실 수 있습니다.

  • +0

    9 개의 질문을하고 0을 수락했습니다. 개선해주십시오. – gaborsch

    +0

    어떻게 대답을 받아 들일 수 있습니까? –

    +0

    FAQ에서이 장을 읽으십시오. 심지어 스크린 샷이 있습니다 : http://stackoverflow.com/faq#howtoask – gaborsch

    답변

    9

    당신 공장 패턴으로 ThreadLocal 클래스를 사용할 수 있습니다

    public class DataAccess{ 
        private static ThreadLocal<DataAccess> THREAD_LOCAL = new ThreadLocal() { 
        @Override 
        protected DataAccess initialValue() { 
          return new DataAccess(); 
        } 
        }; 
        private String databasepath; 
    
        public static DataAccess getInstance() { 
         return THREAD_LOCAL.get(); 
        } 
    } 
    

    이 의지하지만, 메모리 누수가 발생할. 그래서 당신은 요청의 시작 값을 설정하는 Servlet Filter를 사용하고 마지막에 삭제해야, 몇 가지 같은 :

    public void doFilter(ServletRequest request, 
         ServletResponse response, FilterChain chain) 
         throws IOException, ServletException { 
         DataAccess.set(new DataAccess("SomeValue")); 
         try { 
         chain.doFilter(request, wrapper); 
         } finally { 
         DataAcess.remove(); 
         } 
        } 
    

    당신은 따라서 귀하의 web.xml에 추가 Filter 구현하는 class이 있으면 :

    <!--Filter for adding in dataccess objects--> 
    <filter> 
        <filter-name>DataccessFilter</filter-name> 
        <filter-class>my.package.DataccessFilter</filter-class> 
    </filter> 
    <filter-mapping> 
        <filter-name>DataccessFilter</filter-name> 
        <url-pattern>/*</url-pattern> 
    </filter-mapping> 
    

    This 페이지 필터 및 매핑의 일례를 제공한다. 아마 자바에서 메모리 누수의 원인 중 하나이기 때문에

    public class DataAccess{ 
        private static ThreadLocal<DataAccess> THREAD_LOCAL = new ThreadLocal(); 
        private String databasepath; 
    
        public DataAcess(final String databasepath) { 
         this.databasepath = databasepath; 
        } 
    
        public static DataAccess getInstance() { 
         return THREAD_LOCAL.get(); 
        } 
        public static void set(final DataAccess dataAccess) { 
         THREAD_LOCAL.set(dataAccess); 
        } 
        public static void remove() { 
         THREAD_LOCAL.remove(); 
        } 
    } 
    

    ThreadLocal매우주의 : 같은
    그리고 당신의 DataAccess가 보일 것이다. 스레드 풀이있는 웹 서버를 사용하면 올바르게 정리하지 않으면 더 심각한 버그가 발생할 수 있습니다.

    +0

    +1, 나는 똑같이 쓰고 싶었지만 더 빨랐습니다. :) – gaborsch

    +1

    대답의 속도는 항상 나를 깜짝 놀라게했다. –

    +2

    특별한 것을 사용하면'ThreadLocal's가 작동하지 않는다는 것에 주목하자. 비동기식 EJB, Comets/Continuations 등이있다. 실행중인 Thread를 다른 Thread로 대체하기 때문이다. – gaborsch

    0

    는 ThreadLocal를 귀하의 사용 사례와 함께 당신을 도울 것을 보이는 :

    http://docs.oracle.com/javase/6/docs/api/java/lang/ThreadLocal.html

    이 클래스는 thread 로컬 변수를 제공합니다. 이 변수들은 과 정상적인 대응점이 다르므로 에 액세스하는 각 스레드 (get 또는 set 메소드를 통해)는 독립적으로 초기화 된 변수 사본을 가지고 있습니다.