서블릿의 구조인스턴스화, 세션, 공유 변수 및 멀티스레딩
다수의 서블릿을 저장하는 웹 서버가 있다고 가정해 보겠습니다.이러한 서블릿 간에 전달되는 정보에 대해서는 세션 및 인스턴스 변수를 설정합니다.
여기서 2명 이상의 사용자가 이 서버에 요구를 송신하면 세션 변수는 어떻게 됩니까?
모든 사용자에게 공통입니까, 아니면 사용자마다 다른 것입니까?
서로 다른 경우 서버는 어떻게 다른 사용자를 구별할 수 있었습니까?
질문이 .「 「 」가 있는 경우」n
사용자가 특정 서블릿에 액세스하면 이 서블릿은 첫 번째 사용자가 서블릿에 액세스할 때만 인스턴스화됩니까?아니면 모든 사용자에 대해 개별적으로 인스턴스화됩니까?
아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아!
ServletContext
Apache Tomcat과 같은 서블릿 컨테이너가 시작되면 모든 웹 응용 프로그램을 배포하고 로드합니다.웹 응용 프로그램이 로드되면 서블릿 컨테이너는 한 번을 작성하여 서버의 메모리에 보관합니다.웹 앱의web.xml
된 ★★★★★★web-fragment.xml
되어 각 파일이 해석됩니다.<servlet>
,<filter>
★★★★★★★★★★★★★★★★★」<listener>
각 에는 「」(「」)로 이 붙어 있습니다)@WebServlet
,@WebFilter
★★★★★★★★★★★★★★★★★」@WebListener
1회 되며, 됩니다.ServletContext
각 필터에 그 필터는init()
메서드는 새로운 인수와 함께 호출되며, 이 인수에는 관련 인수가 포함됩니다.ServletContext
.
의 경우Servlet
가지고 있다<servlet><load-on-startup>
★★★★★★★★★★★★★★★★★」@WebServlet(loadOnStartup)
큰 0
그 후, 「」, 「」init()
method는 시작 시 새로운 인수와 함께 호출됩니다.이 인수에는 관련 인수가 포함됩니다.ServletContext
은, 그1
1등입니다.2
') 여러 각 은 에 기재되어 과 같은 됩니다.web.xml
,web-fragment.xml
, 「」@WebServlet
시 하지 않는 , " " " " 는 " " 입니다.init()
메서드는 HTTP 요구가 그 서블릿에 처음 히트할 때마다 호출됩니다.
서블릿 컨테이너가 위에서 설명한 모든 초기화 단계를 완료하면는 다음 명령어를 사용하여 호출됩니다.ServletContextEvent
된 ""가 됩니다"가 포함됩니다.ServletContext
는 또 다른 할 수 Servlet
,Filter
★★★★★★★★★★★★★★★★★」Listener
.
프로그램이 되고 "서블릿 컨테이너"가 됩니다.destroy()
모든 초기화된 서블릿 및 필터의 메서드와Servlet
,Filter
그리고.Listener
를 통해 등록된 인스턴스ServletContext
엉망진창이 되어 있어요마지막으로 가 호출되고ServletContext
그 자체가 파괴될 것이다.
HttpServletRequest
그리고.HttpServletResponse
서블릿 컨테이너는 특정 포트 번호로 HTTP 요구를 리슨하는 웹 서버에 접속됩니다(포트 8080은 보통 개발 중에 사용되며 포트 80은 실제 가동 중에 사용됩니다).클라이언트(예를 들어 웹 브라우저를 사용하는 사용자 또는 프로그래밍 방식으로 를 사용하는 사용자)가 HTTP 요청을 전송하면 서블릿 컨테이너는 새로운 개체와 개체를 생성하여 정의된 개체를 통과시킵니다.Filter
체인으로 묶고, 결국엔Servlet
사례.
필터의 경우,doFilter()
메서드가 호출됩니다.서블릿 컨테이너의 코드가 호출될 때chain.doFilter(request, response)
요구와 응답은 다음 필터로 계속 진행됩니다.나머지 필터가 없는 경우는 서블릿을 누릅니다.
서블릿의 경우service()
메서드가 호출됩니다.디폴트로는 이 메서드에 의해 다음 중 어느 것이doXxx()
기반으로 호출하는 메서드request.getMethod()
결정된 메서드가 서블릿에 없는 경우 HTTP 405 오류가 응답으로 반환됩니다.
요청 개체는 URL, 헤더, 쿼리 문자열 및 본문 등의 HTTP 요청에 대한 모든 정보에 액세스할 수 있습니다.응답 오브젝트를 사용하면 헤더와 본문(통상은 JSP 파일에서 생성된HTML 콘텐츠를 사용하여)을 설정하는 등 HTTP 응답을 원하는 방식으로 제어 및 전송할 수 있습니다.HTTP 응답이 커밋되고 완료되면 요청 개체와 응답 개체가 모두 재활용되어 재사용할 수 있게 됩니다.
HttpSession
클라이언트가 웹 앱을 처음 방문하는 경우 및/또는 를 통해 처음 얻는 경우request.getSession()
, servlet 컨테이너는 새로운 것을 만듭니다.HttpSession
오브젝트: 길고 고유한 ID를 생성합니다(이 ID를 통해 얻을 수 있습니다).session.getId()
서버 메모리에 저장합니다.서블릿 컨테이너는 또한 에 를 설정합니다.Set-Cookie
HTTP 응답 헤더JSESSIONID
이름으로, 하나의 세션 ID를 값으로 지정합니다.
HTTP cookie 사양(적절한 웹 브라우저 및 웹 서버가 준수해야 하는 계약)에 따라 클라이언트(웹 브라우저)는 다음 요구에서 이 쿠키를 반환해야 합니다.Cookie
(즉, 고유 ID는 만료되지 않은 세션을 참조해야 하며 도메인과 경로가 올바릅니다.)브라우저의 기본 제공 HTTP 트래픽 모니터를 사용하여 쿠키가 유효한지 확인할 수 있습니다(Chrome / Firefox 23+ / IE9+에서 F12를 누르고 Net/Network 탭을 확인하십시오).servlet 컨테이너는 다음 항목을 확인합니다.Cookie
cookie의 존재에 대한 모든 착신 HTTP 요청의 헤더JSESSIONID
그 값(세션 ID)을 사용하여 관련지어져 있는HttpSession
서버 메모리에서 가져옵니다.
그HttpSession
는 아이돌 상태가 될 때까지(즉, 요구에 사용되지 않을 때까지) 에 지정된 타임아웃 값을 초과하여 존속합니다.<session-timeout>
, 의 설정web.xml
. 타임아웃 값은 디폴트로 30분으로 설정되어 있습니다.따라서 클라이언트가 지정된 시간 이상 웹 앱을 방문하지 않으면 서블릿 컨테이너가 세션을 폐기합니다.cookie를 지정한 경우에도 이후의 모든 요청은 동일한 세션에 더 이상 액세스할 수 없습니다.서블릿 컨테이너는 새 세션을 만듭니다.
클라이언트 측에서는 브라우저 인스턴스가 실행되고 있는 한 세션쿠키는 활성 상태로 유지됩니다.따라서 클라이언트가 브라우저 인스턴스(모든 탭/윈도우)를 닫으면 세션은 클라이언트 측에서 폐기됩니다.새 브라우저 인스턴스에서는 세션과 관련된 쿠키가 존재하지 않으므로 더 이상 전송되지 않습니다.이것은 완전히 새로운 것을 야기한다.HttpSession
완전히 새로운 세션쿠키를 사용하여 작성됩니다.
한마디로 말하면
- 그
ServletContext
웹 앱이 살아있는 한 오래 살 수 있습니다.모든 세션의 모든 요구 간에 공유됩니다. - 그
HttpSession
는 클라이언트가 동일한 브라우저 인스턴스로 웹 앱과 상호 작용하고 세션이 서버 측에서 타임아웃되지 않는 한 지속됩니다.같은 세션의 모든 요구 간에 공유됩니다. - 그
HttpServletRequest
그리고.HttpServletResponse
라이브는 서블릿이 클라이언트로부터HTTP 요구를 수신한 시점부터 완전한 응답(Web 페이지)이 도착할 때까지 실행됩니다.다른 곳에서는 공유되지 않습니다. - 모든.
Servlet
,Filter
그리고.Listener
인스턴스는 웹 앱이 살아있는 동안 계속됩니다.모든 세션의 모든 요구 간에 공유됩니다. - 조금도
attribute
에 정의되어 있다.ServletContext
,HttpServletRequest
그리고.HttpSession
문제의 물체가 살아있는 한 살 수 있습니다.개체 자체는 JSF, CDI, 스프링 등의 콩 관리 프레임워크에서 "범위"를 나타냅니다.이러한 프레임워크는 스코프된 콩을 저장하여attribute
가장 가까운 범위입니다.
스레드 안전성
단, 가장 큰 관심사는 스레드 안전성일 수 있습니다.이제 서블릿과 필터가 모든 요청 간에 공유된다는 것을 알아야 합니다.Java의 장점은 멀티스레드와 다른 스레드(읽기: HTTP 요청)가 동일한 인스턴스를 사용할 수 있다는 것입니다.그렇지 않으면 재작성하는 데 비용이 너무 많이 들 것입니다.init()
그리고.destroy()
모든 요구에 대응합니다.
또한 요청 또는 세션 범위 데이터를 서블릿 또는 필터의 인스턴스 변수로 할당해서는 안 됩니다.다른 세션의 다른 모든 요구 간에 공유됩니다.그건 안전하지 않아!다음 예시는 이를 나타내고 있습니다.
public class ExampleServlet extends HttpServlet {
private Object thisIsNOTThreadSafe;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Object thisIsThreadSafe;
thisIsNOTThreadSafe = request.getParameter("foo"); // BAD!! Shared among all requests!
thisIsThreadSafe = request.getParameter("foo"); // OK, this is thread safe.
}
}
다음 항목도 참조하십시오.
- JSF, Servlet 및 JSP의 차이점은 무엇입니까?
- Java에서의 세션 관리를 위한 최적의 옵션
- 서블릿 매핑 URL 패턴의 /와 /*의 차이
- Servlet에서의 doGet 및 doPost
- Servlet은 여러 개의 동시 브라우저 요청을 동시에 처리하는 것 같습니다.
- 서블릿이 스레드 세이프가 아닌 이유
세션
한마디로 웹 서버는 방문자마다 첫 방문 시 고유 식별자를 발급합니다.방문객이 다음에 알아볼 수 있도록 그 신분증을 다시 가져와야 합니다.또한 이 식별자에 의해 서버는 세션이 소유한 객체를 다른 세션과 적절히 분리할 수 있습니다.
서블릿 인스턴스화
기동시의 로드가 false인 경우:
기동시의 부하가 참인 경우:
일단 그가 서비스 모드로 전환되면, 같은 서블릿이 다른 모든 클라이언트의 요구에 대해 작동하게 됩니다.
클라이언트당 1개의 인스턴스를 갖는 것이 좋지 않은 이유는 무엇입니까?생각해 보세요.오더할 때마다 피자 사원을 한 명 고용할 건가요?그렇게 하면 금방 폐업할 거예요.
그래도 약간의 위험이 수반됩니다.이 한 사람이 주문 정보를 모두 주머니에 넣고 있기 때문에 서블릿의 스레드 안전에 주의를 기울이지 않으면 특정 고객에게 잘못된 주문을 할 수 있습니다.
Java 서블릿의 세션은 PHP와 같은 다른 언어의 세션과 동일합니다.이는 사용자에게 고유합니다.서버는 쿠키, URL 개서 등 다양한 방법으로 이를 추적할 수 있습니다.이 Java 문서 문서에서는 Java 서블릿의 컨텍스트에서 설명하고 세션의 정확한 유지 방법은 서버 설계자에게 남겨진 구현 세부 사항임을 나타냅니다.사양에서는, 서버에의 복수의 접속에 걸쳐, 유저에 대해서 일의로서 유지할 필요가 있는 것만을 규정하고 있습니다.두 가지 질문에 대한 자세한 내용은 Oracle에서 제공하는 이 문서를 참조하십시오.
편집 서블릿 내에서 세션을 사용하는 방법에 대한 훌륭한 튜토리얼이 있습니다.다음은 Java Servlet에 대한 Sun의 장, Java Servlet의 개요 및 사용 방법에 대한 설명입니다.이 두 기사 중에서 당신은 당신의 모든 질문에 대답할 수 있을 것입니다.
servlet 컨테이너(Apache Tomcat 등)가 기동하면 web.xml 파일(어플리케이션당1개만)에서 오류가 발생하거나 컨테이너측 콘솔에 오류가 표시될 경우 servlet 컨테이너는 web.xml을 사용하여 모든 웹 응용 프로그램을 배포하고 로드합니다(즉, 배포 디스크립터라고 합니다.
서블릿 인스턴스화 단계에서는 서블릿인스턴스가 준비되지만 다음 두 가지 정보가 없기 때문에 클라이언트 요구에 대응할 수 없습니다.
1: 컨텍스트 정보
2: 초기 설정 정보
Servlet 엔진은 인수로서 servletConfig 오브젝트 참조를 제공하여 위의 누락된 정보를 servlet 엔진에서 servlet의 init()를 호출하는 servletConfig 인터페이스 개체를 만듭니다.init()가 완전히 실행되면 서블릿은 클라이언트 요구에 대응할 수 있습니다.
Q) 서블릿의 라이프 타임 동안 인스턴스화와 초기화가 몇 번 발생합니까?
A) 클라이언트 요구는 1회(새로운 스레드가 작성될 때마다) 1개의 서블릿 인스턴스만이 임의의 수의 클라이언트 요구를 처리합니다.즉, 1개의 클라이언트 요구 서버를 서비스한 후에는 정지하지 않습니다.다른 클라이언트 요구를 기다립니다.즉, 서블릿(내부 서블릿엔진이 스레드를 작성한다)에 의해 어떤 CGI(새로운 프로세스가 작성될 때마다) 제한이 극복되는지를 나타냅니다.
Q) 세션 개념은 어떻게 작동합니까?
A) httpServletRequest 개체에서 getSession()이 호출될 때마다
스텝 1: 착신 세션 ID에 대해 요청 개체가 평가됩니다.
스텝 2: ID를 사용할 수 없는 경우 완전히 새로운 HttpSession 객체가 생성되어 대응하는 세션 ID가 httpservlet 응답 객체에 저장되고 HttpSession 객체의 참조가 서블릿(DoGet/doPost)으로 반환됩니다.
스텝 3: ID 사용 가능한 새 세션 개체가 생성되지 않은 경우 세션 ID를 키로 세션 ID를 세션 컬렉션에서 검색합니다.
검색이 성공하면 세션 ID가 HttpServletResponse에 저장되고 기존 세션오브젝트 참조가 UserDefineservlet의 doGet() 또는 doPost()로 반환됩니다.
주의:
1) 제어가 서블릿코드에서 클라이언트로 넘어갈 때 session 객체가 서블릿컨테이너, 즉 서블릿엔진에 의해 유지되고 있음을 잊지 마세요.
2) 멀티스레드는 서블릿 개발자에게 맡겨져 있습니다.즉, 멀티스레드 코드에 대해 신경 쓸 필요 없이 클라이언트의 여러 요구를 처리할 수 있습니다.
인사트 형식:
서블릿은 응용 프로그램이 시작될 때(서블릿 컨테이너에 배치됨) 또는 서블릿이 처음 액세스될 때(로드 온 스타트 설정에 따라 다름) 서블릿의 init() 메서드가 호출된 후 서블릿(하나의 유일한 인스턴스)이 모든 요구(its service() 메서드가 다중에 의해 호출됨)를 처리합니다.스레드).따라서 동기화가 권장되지 않습니다.또한 어플리케이션이 전개되지 않은 경우(서블릿컨테이너가 정지된 경우), destroy() 메서드가 호출됩니다.
세션 - Chris Thompson이 말한 것.
인스턴스화 - 컨테이너가 서블릿에 매핑된 첫 번째 요청을 수신하면 서블릿이 인스턴스화됩니다(서블릿이 시작 시 로딩되도록 설정되어 있지 않은 경우).<load-on-startup>
에 요소를 넣다.web.xml
). 같은 인스턴스가 후속 요청을 처리하는 데 사용됩니다.
Servlet 사양 JSR-315에서는 서비스(및 doGet, doPost, doPut 등) 메서드(2.3.3.1 멀티스레딩 문제, 페이지9)에서 웹 컨테이너 동작을 명확하게 정의하고 있습니다.
서블릿 컨테이너는 서블릿의 서비스 메서드를 통해 동시 요청을 전송할 수 있습니다.요청을 처리하기 위해 Servlet Developer는 서비스 메서드에서 여러 스레드를 동시에 처리할 수 있는 적절한 준비를 해야 합니다.
권장되지 않지만, 개발자를 위한 다른 방법은 컨테이너가 서비스 메서드에 한 번에 요청 스레드가 하나만 있음을 보증하는 SingleThreadModel 인터페이스를 구현하는 것입니다.서블릿 컨테이너는 서블릿에서 요청을 직렬화하거나 서블릿 인스턴스 풀을 유지함으로써 이 요건을 충족할 수 있습니다.서블릿이 배포 가능으로 표시된 웹 응용 프로그램의 일부인 경우 컨테이너는 응용 프로그램이 배포되는 각 JVM의 서블릿 인스턴스 풀을 유지할 수 있습니다.
SingleThreadModel 인터페이스를 구현하지 않은 서블릿의 경우 synchronized 키워드로 서비스 메서드(또는 Http Servlet 추상 클래스의 서비스 메서드에 디스패치되는 doGet 또는 doPost 등)가 정의되어 있는 경우 서블릿컨테이너는 인스턴스 풀접근법을 사용할 수 없지만 이를 통해 요구를 시리얼화해야 합니다.퍼포먼스에 악영향을 미치기 때문에, 이러한 상황에서는, 개발자는 서비스 방법(또는 그 방법에 파견되는 방법)을 동기화하지 않는 것을 강하게 추천합니다.
아니요. 서블릿은 스레드 세이프가 아닙니다.
이를 통해 한 번에 여러 스레드에 액세스할 수 있습니다.
스레드로서 서블릿을 안전하게 하고 싶은 경우는, 다음의 순서를 실행할 수 있습니다.
Implement SingleThreadInterface(i)
이 인터페이스는 공백 인터페이스입니다.
방법들
또는 동기 방식을 사용할 수 있습니다.
synchronized를 사용하여 전체 서비스 방법을 동기화할 수 있습니다.
메서드 앞에 있는 키워드
예:
public Synchronized class service(ServletRequest request,ServletResponse response)throws ServletException,IOException
또는 동기화된 블록에 코드 블록을 넣을 수 있습니다.
예:
Synchronized(Object)
{
----Instructions-----
}
Synchronized Block이 전체 방법을 만드는 것보다 낫다고 생각합니다.
동기화됨
위의 설명에서 알 수 있듯이 SingleThreadModel을 구현함으로써 서블릿 컨테이너에 의해 스레드 안전성을 확보할 수 있습니다.컨테이너 실장에서는, 다음의 2개의 방법으로 이것을 실행할 수 있습니다.
1) 단일 인스턴스에 대한 요구 시리얼화(큐잉) - 이는 SingleThreadModel을 구현하지 않고 서비스/doXX 메서드를 동기화하는 서블릿과 유사합니다.
2) 인스턴스 풀 작성 - 서블릿을 호스트하는 환경의 제한적인 파라미터(메모리/CPU 시간)와 비교하여 서블릿의 부트업/초기화 작업/시간 간에 균형을 유지하는 것이 좋습니다.
언급URL : https://stackoverflow.com/questions/3106452/how-do-servlets-work-instantiation-sessions-shared-variables-and-multithreadi
'programing' 카테고리의 다른 글
"이진수 비트 연산자와 함께 부호 있는 정수 피연산자 사용" - 부호 없는 쇼트 사용 시 (0) | 2022.07.12 |
---|---|
C에서 동적으로 할당된 메모리의 크기를 확인합니다. (0) | 2022.07.12 |
v-show에 표시된 후 입력에 초점을 맞춥니다. (0) | 2022.07.12 |
ES6 구문을 사용하여 vue에서 여러 구성 요소를 가져올 수 없음 (0) | 2022.07.11 |
Vue 3 스토어를 Vuex 없이 유지하는 방법 (0) | 2022.07.11 |