1. 서블릿 소개
Servlet은 Sun Company가 동적 웹 리소스를 개발하기 위해 제공하는 기술입니다.
Sun은 API에서 서블릿 인터페이스를 제공합니다. 사용자가 동적 웹 리소스를 보내려면 (즉, 브라우저에 데이터를 출력하기위한 Java 프로그램을 개발) 다음 두 단계를 완료해야합니다.
1. 서블릿 인터페이스를 구현하려면 Java 클래스를 작성하십시오.
2. 개발 된 Java 클래스를 웹 서버에 배포하십시오.
기존의 이름 습관에 따르면, 우리는 일반적으로 서블릿 인터페이스 서블릿을 구현하는 Java 프로그램을 호출합니다.
2. 서블릿의 작동 과정
서블릿 프로그램은 웹 서버에서 호출됩니다. 웹 서버가 클라이언트의 서블릿 액세스 요청을받은 후 :
web 웹 서버는 먼저로드되었는지 여부를 확인하고 서블릿의 인스턴스 개체를 생성합니다. 그렇다면 4 단계를 직접 실행하십시오. 그렇지 않으면 2 단계를 실행하십시오.
servlet 서틀의 인스턴스 개체를로드하고 만듭니다.
servlet 서틀 인스턴스 객체의 init () 메소드를 작성하십시오.
http httpergrequest 객체를 작성하여 http 요청 메시지와 httpergelrequest 객체를 만들고 http 응답 메시지를 나타내는 httpservletresponse 객체를 캡슐화 한 다음 servlet 's service () 메소드를 호출하고 요청 및 응답 객체를 매개 변수로 전달하십시오.
Web 웹 애플리케이션이 중지되거나 다시 시작되기 전에 서블릿 엔진은 서블릿을 제거하고 제거하기 전에 서블릿의 Destroy () 메소드를 호출합니다.
3. 서블릿 호출 다이어그램
4. 일식에서 서블릿을 개발하십시오
Eclipse에서 새로운 웹 프로젝트를 작성하면 Eclipse는 아래 그림에 표시된 디렉토리 구조를 자동으로 작성합니다.
4.1. 서블릿 인터페이스 구현 클래스
Servlet Interface Sun Company는 GenericServlet과 Httpservlet의 두 가지 기본 구현 클래스를 정의합니다.
httpservlet은 HTTP 요청을 처리 할 수있는 서블릿을 말합니다. 원래 서블릿 인터페이스에 일부 HTTP 프로토콜 처리 방법을 추가하는데, 이는 서블릿 인터페이스보다 강력합니다. 따라서 서블릿을 작성할 때 개발자는 일반적 으로이 클래스를 상속하고 서블릿 인터페이스를 직접 구현하지 않아야합니다.
httpservlet가 서블릿 인터페이스를 구현하면 서비스 메소드를 덮어 씁니다. 메소드 본문의 코드는 사용자의 요청 메소드를 자동으로 결정합니다. GET 요청 인 경우 httpservlet의 doget 메소드가 호출됩니다. 게시물 요청 인 경우 Dopost 메소드가 호출됩니다. 따라서 서블릿을 작성할 때 개발자는 일반적으로 서비스 메소드를 덮어 쓰는 대신 DOGET 또는 DOPOST 메소드를 덮어 쓸 필요가 있습니다.
4.2. 일식을 통해 서블릿을 만들고 쓰십시오
아래 그림과 같이 gacl.servlet.study 패키지, 마우스 오른쪽 버튼을 클릭하고 새 → 서블릿을 선택하십시오.
이런 식으로, 우리는 Eclipse를 사용하여 Servletdemo1이라는 이름의 서블릿을 만드는 데 도움이됩니다. 생성 된 servletdemo01에는 다음 코드가 있습니다.
패키지 gacl.servlet.study; import java.io.ioexception; import java.io.printwriter; import javax.servlet.servletexception; import javax.servlet.http.httpservlet; import javax.servlet.http.htttp.httervletrequest; 가져 오기; javax.servlet.http.httpservletresponse; public class servletdemo1은 httpservlet { /*** 서블릿의 doget 메소드를 확장합니다. <br> * *이 방법은 양식에 태그 값 메소드가있는 경우 호출됩니다. * * @param 요청 클라이언트가 서버로 보내는 요청을 요청합니다 * @Param 응답 서버가 클라이언트로 보내는 응답 * @Throws ServleTeXception * @throws ioException */ public void doget (httpservletRequest 요청, httpservletResponse 응답) servletexception, ioexception, ioexception em { Response.setContentType ( "Text/Html"); printwriter out = response.getwriter (); out.println ( "<! doctype html public/"-// w3c // dtd html 4.01 Transitional // en/">"); out.println ( "<head> <title> a servlet </title> </head>"); out.println ( "<body>"); out.print ( "이것은"IS "); out.print (this.getClass ()); out.println ( ", get 메소드 사용"); out.println ( "</body>"); out.println ( "</html>"); out.flush (); out.close (); } /*** 서블릿의 도스트 방법. <br> * *이 메소드는 양식에 태그 값 메소드가 게시되는 경우 호출됩니다. * * @param 요청 클라이언트가 서버로 보내는 요청을 요청합니다 * @param 응답 서버가 클라이언트로 보내는 응답 * @throws servleTexception * @throws ioexception */ public void dopost (httpservletRequest 요청, httpservletResponse 응답) servletexception, ioexception, ioexcemption ^ Response.setContentType ( "Text/Html"); printwriter out = response.getwriter (); out.println ( "<! doctype html public/"-// w3c // dtd html 4.01 Transitional // en/">"); out.println ( "<html>"); out.println ( "<head> <title> a servlet </title> </head>"); out.println ( "<body>"); out.println ( "<body>"); out.println ( "이것은"IS "); out.print (this.getClass ()); out.println ( "포스트 메소드 사용"); out.println ( "</body>"); out.println ( "</html>"); out.flush (); out.close (); }}이 코드는 Eclipse에 의해 자동으로 생성되며 Web.xml 파일에는 <Servlet> </servlet> 및 <servlet-mapping> </servlet-mapping>에 두 개의 태그가 있습니다. 이 두 쌍의 태그는 아래 그림과 같이 ServletDemo1로 구성됩니다.
그런 다음 아래 그림과 같이 브라우저를 통해 Servletdemo1 서블릿에 액세스 할 수 있습니다.
5. 서블릿 개발의 세부 사항에주의를 기울이십시오
5.1. 서블릿 액세스 URL 매핑 구성
클라이언트는 URL 주소를 통해 웹 서버의 리소스에 액세스하므로 서블릿 프로그램이 외부 세계에서 액세스하려는 경우 서블릿 프로그램을 URL 주소에 매핑해야합니다. 이 작업은 <Servlet> 요소 및 <Servlet-Mapping> 요소를 사용하여 web.xml 파일에서 수행됩니다.
<Servlet> 요소는 서블릿을 등록하는 데 사용됩니다. 여기에는 <servlet-name>과 <servlet-class>의 두 가지 주요 자식 요소가 포함되어 있으며, 여기에는 각각 서블릿의 등록 이름과 서블릿의 전체 클래스 이름을 설정하는 데 사용됩니다.
<서블릿 맵핑> 요소는 외부 액세스 경로를 등록 된 서블릿에 매핑하는 데 사용됩니다. 여기에는 <servlet-name>과 <url-pattern>의 두 가지 자식 요소가 포함되어 있으며, 여기에는 서블릿의 등록 이름과 서블릿의 외부 액세스 경로를 지정하는 데 사용됩니다. 예를 들어:
<Servlet> <Servlet-name> servletdemo1 </servlet-name> <servlet-class> gaCl.servlet.study.servletdemo1 </servlet-class> </servlet> <servlet-mapping> <servlet-name> servletdemo1 </servlet-name> <url-pattern/servletn> </urpattern> 동일한 서블릿은 여러 URL에 매핑 될 수 있습니다. 즉, 여러 <servlet-mapping> 요소의 <servlet-name> 하위 요소의 설정 값은 동일한 서블릿의 등록 이름 일 수 있습니다. 예 : <Servlet> <Servlet-name> servletdemo1 </servlet-name> <servlet-class> gacl.servlet.study.servletdemo1 </servlet-class> </servlet> <servlet-mapping> <servlet-name> servletdemo1 </servlet-name> <Url-pattern>/servlet/servletdemo1 </url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name> servletdemo1 </servlet-name> <url-pattern> /1.htm </url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name> servletmo1 <Url-pattern> /2.jsp </url-pattern> </servlet-mapping> <servlet-mapping> <servlet-mapping> <servlet-name> servletdemo1 </servlet-name> <url-pattern> /3.php </url-pattern> <servlet-mapping> <servlet-mapping> <servlet-name> servlet-name> <Url-pattern> /4.aspx </url-pattern> </servlet-mapping>
위의 구성을 통해 Servletdemo1이라는 이름의 서플릿에 액세스하려면 다음 주소를 사용하여 액세스 할 수 있습니다.
http : // localhost : 8080/javaweb_servlet_study_20140531/servlet/servletdemo1
http : // localhost : 8080/javaweb_servlet_study_20140531/1.htm
http : // localhost : 8080/javaweb_servlet_study_20140531/2.jsp
http : // localhost : 8080/javaweb_servlet_study_20140531/3.php
http : // localhost : 8080/javaweb_servlet_study_20140531/4.aspx
Servletdemo1은 여러 URL에 매핑됩니다.
5.2. 서블릿 액세스 URL에 * 와일드 카드 매핑을 사용하십시오
*와일드 카드 문자는 서블릿이 맵핑하는 URL에서도 사용할 수 있지만 두 가지 고정 형식 만있을 수 있습니다. 하나는 "*. 확장"이고 다른 하나는 앞쪽 슬래시 (/)로 시작하고 "/*"로 끝납니다. 예를 들어:
<Servlet> <servlet-name> servletdemo1 </servlet-name> <servlet-class> gacl.servlet.study.servletdemo1 </servlet-class> </servlet> <servlet-mapping> <servlet-name> servletdemo1 </servlet-name> <Url-pattern>/*</url-pattortn>
*모든 문자와 일치 할 수 있으므로 아래 그림과 같이 모든 URL을 사용하여 Servletdemo1 서블릿에 액세스 할 수 있습니다.
아래의 일부 매핑 관계의 경우 :
servlet1지도 /abc /*
servlet2지도 /*
Servlet3 맵 /ABC
servlet4는 *.do에 맵핑됩니다
질문:
요청 URL이 "/abc/a.html", "/abc/*"및 "/*"인 경우 서블릿 엔진에 응답하는 서블릿은 Servlet1을 호출합니다.
요청 URL이 "/abc"인 경우 "/abc/*"및 "/abc"일치는 서블릿 엔진에 응답하는 서블릿이 Servlet3을 호출합니다.
요청 URL이 "/abc/a.do"인 경우 "/abc/*"및 "*.do"일치 모두 서블릿 엔진에 응답하는 Servlet가 Servlet1을 호출합니다.
요청 URL이 "/a.do"인 경우 "/*"및 "*.do"일치는 서블릿 엔진에 응답하는 서블릿이 Servlet2를 호출합니다.
요청 URL이 "/xxx/yyy/a.do"인 경우, "/*"및 "*.do"일치는 서블릿 엔진에 응답하는 Servlet가 Servlet2를 호출합니다.
일치하는 원리는 "더 보이는 사람은 누구나 더 보이는 사람을 찾을 것"입니다.
5.3. 서블릿과 일반 Java 클래스의 차이점
Servlet은 다른 Java 프로그램 (Servlet Engines)의 호출을위한 Java 클래스입니다. 독립적으로 실행할 수 없으며 작업은 서블릿 엔진에 의해 완전히 제어되고 예약됩니다.
클라이언트의 여러 서플렛 요청의 경우 일반적으로 서버는 서블릿 인스턴스 개체 만 생성합니다. 즉, 일단 서블릿 인스턴스 객체가 생성되면 메모리에 상주하고 다른 후속 요청을 제공합니다. 서블릿 인스턴스 객체는 웹 컨테이너가 종료 될 때까지 파괴되지 않습니다.
서블릿의 전체 수명 동안 서블릿의 초기 방법은 한 번만 호출됩니다. 서블릿에 대한 각 액세스 요청은 서블릿 엔진이 서블릿 서비스 방법을 한 번 호출하게합니다. 각 액세스 요청에 대해 서블릿 엔진은 새로운 httpservletrequest 요청 객체와 새로운 httpservletreponse 응답 객체를 생성 한 다음이 두 객체를 호출하는 서플릿의 서비스 () 메소드로 전달합니다. 그런 다음 서비스 메소드는 요청 메소드에 따라 DOXXX 메소드를 호출합니다.
<broad-on-startup> 요소가 <servlet> 요소에 구성되면 웹 응용 프로그램이 시작되면 Servlet 인스턴스 개체를로드하여 생성하고 Servlet 인스턴스 개체의 init () 메소드를 호출합니다.
예를 들어:
<Servlet> <Servlet-name> invoker </servlet-name> <servlet-class> org.apache.catalina.servlets.invokerservlet </servlet-class> <load-on-startup> 1 </load-on-startup> </servlet>
목적 : 웹 애플리케이션에 대한 initservlet을 작성하십시오. 이 서블릿은 스타트 업에로드하여 전체 웹 응용 프로그램에 필요한 데이터베이스 테이블 및 데이터를 작성하도록 구성됩니다.
5.4. 기본 서블릿
서블릿의 매핑 경로가 전방 슬래시 (/) 만 있으면이 서블릿은 현재 웹 애플리케이션의 기본 서블릿이됩니다.
web.xml 파일에서 찾을 수없는 일치하는 <Servlet-Mapping> 요소의 모든 URL은 액세스 요청이 처리를 위해 기본 서블릿에 양도됩니다. 즉, 기본 서블릿은 다른 서블릿이 처리하지 않은 액세스 요청을 처리하는 데 사용됩니다. 예를 들어:
<Servlet> <Servlet-name> servletdemo2 </servlet-name> <servlet-class> gaCl.servlet.study.servletdemo2 </servlet-class> <load-on-startup> 1 <! <!-Servletdemo2를 부정형 서브로 구성합니다-> <servlet-mapping> <Servlet-name> servletdemo2 </servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
존재하지 않는 서블릿에 액세스 할 때 구성된 기본 서블릿은 아래 그림과 같이 처리에 사용됩니다.
<tomcat installation directory> /conf/web.xml 파일에서 org.apache.catalina.servlets.defaultservlet이라는 서플릿이 등록되어 있으며이 서블릿은 기본 서블릿으로 설정됩니다.
<Servlet> <servlet-name> 기본값 </servlet-name> <servlet-class> org.apache.catalina.servlets.defaultservlet </servlet-class> <init-param> <param-name> debug </param-name> <param- value> 0 </param-value> <init-param> <param-param> <param-param> <param-param> <Param-value> false </param-value> </init-param> </init-startup> 1 </load-on-startup> </servlet> <!-기본 서플렛의 매핑-> <servlet-mapping> <servlet-name> 기본값 </servlet-name> <url-pattern>/</url-fattern>
Tomcat 서버에서 정적 HTML 파일과 이미지에 액세스 할 때는 실제로이 기본 서블릿에 액세스 할 수 있습니다.
5.5. 서틀 스레드 안전 문제
여러 클라이언트가 동일한 서블릿에 동시에 액세스하면 웹 서버는 각 클라이언트의 액세스 요청에 대한 스레드를 생성 하고이 스레드에서 Servlet의 서비스 메소드를 호출합니다. 따라서 서비스 방법에서 동일한 리소스에 액세스하면 스레드 안전 문제가 발생할 수 있습니다. 예를 들어 다음 코드 :
스레드 안전 문제가없는 코드 :
패키지 gacl.servlet.study; import java.io.ioexception; import javax.servlet.servletxception; import javax.servlet.http.httpservlet; import javax.servlet.http.httpservletrequest; import javax.servlet.httpp.httpp.httpp.http.http.http.httppervletrequest.; javax.servlet.http.httpervletresponse; public class servletdemo3는 httpservlet {public void doget (httpservletrequest request, httpservletreponse 응답을 던지기)을 확장합니다. I 변수는 여러 스레드에 의해 동시에 액세스되지만 DOGET 메소드의 로컬 변수이기 때문에 스레드 안전 문제가 없습니다. * 다중 스레드가 동시에 DOGET 메소드에 액세스 할 때 각 스레드는 고유 한 I 변수를 갖습니다. * 각 스레드는 고유 한 I 변수를 작동 시키므로 스레드 안전 문제가 없으므로 멀티 스레드가 특정 메소드에 동시에 액세스 할 때 일부 리소스 (변수, 컬렉션 등)가있는 경우 모든 스레드가 이러한 것들이 있으므로 스레드 안전 문제가 없습니다 */ int i = 1이 없습니다. i ++; Response.getWriter (). 쓰기 (i); } public void dopost (httpservletRequest 요청, httpservletResponse 응답) servletexception, ioexception {doget (요청, 응답); }} 스레드 안전 문제가있는 코드 :
패키지 gacl.servlet.study; import java.io.ioexception; import javax.servlet.servletexception; import javax.servlet.http.httpservlet; import javax.servlet.http.httpservletrequest; import javax.servlet.httppepront.httppletrsponse; httpservlet을 확장 {int i = 1; public void doget (httpservletrequest request, httpservletresponse 응답)은 servletexception, ioexception {i ++; try {thread.sleep (1000*4); } catch (InterruptedException e) {e.printstacktrace (); } response.getWriter (). 쓰기 (i+""); } public void dopost (httpservletRequest 요청, httpservletResponse 응답) servletexception, ioexception {doget (요청, 응답); }}I를 글로벌 변수로 정의하십시오. 다중 스레드가 변수에 액세스하면 동시에 아래 그림과 같이 스레드 안전 문제가 발생합니다. 동시에 동일한 서블릿에 대한 동시 액세스를 시뮬레이션하기 위해 동시에 두 브라우저를 켜십시오. 일반적으로 첫 번째 브라우저에는 2가 보이고 두 번째 브라우저에는 3이 표시되지만 두 브라우저 모두 3을 보며 정상이 아닙니다.
스레드 안전 문제는 여러 스레드가 동시에 동시에 동시에 작동하는 경우에만 존재합니다. 따라서 서블릿을 작성할 때 특정 리소스 (변수, 수집 등)에 동시에 액세스 할 경우 스레드 안전 문제가 발생합니다. 그렇다면이 문제를 해결하는 방법은 무엇입니까?
다음 코드를 살펴 보겠습니다.
패키지 gacl.servlet.study; import java.io.ioexception; import javax.servlet.servletexception; import javax.servlet.http.httpservlet; import javax.servlet.http.httpservletrequest; import javax.servlet.httppepront.httppletrsponse; httpservlet을 확장 {int i = 1; 공개 void doget (httpservletrequest request, httpservletreponse response)은 servletexception, ioexception { /*** 동기화 된 후에 동시에 액세스 할 때 스레드 안전 문제가 없습니다. * 동기화 된 후 스레드 안전 문제가없는 이유는 무엇입니까? * 이제 서블릿 객체에 액세스하는 스레드가 있으면 먼저 서블릿 객체의 잠금을 가져옵니다. 먼저 서블릿 객체의 잠금을 가져 오기 때문에 * 다른 스레드가 서블릿 객체에 액세스 할 때, 이전 스레드에 의해 잠금이 제거 되었기 때문에 후속 스레드는 줄에서만 기다릴 수 있습니다 * */synchronized (this) {// Java에서는 각 객체가 잠금을 가지고 있으며, 여기서는 서틀 객체 i ++; try {thread.sleep (1000*4); } catch (InterruptedException e) {e.printstacktrace (); } response.getWriter (). 쓰기 (i+""); }} public void dopost (httpservletrequest 요청, httpservletreponse 응답) servletexception, ioexception {doget (요청, 응답); }}이제이 접근법은 서틀 객체에 잠금 장치를 추가하여 하나의 스레드만이 언제든지 서블릿 객체의 리소스에 액세스 할 수 있도록하는 것이므로 아래 그림과 같이 스레드 안전 문제가 없습니다.
이 접근법은 스레드 안전 문제를 해결하지만 서블릿을 작성하는 것은 이러한 방식으로 스레드 안전 문제를 처리해서는 안됩니다. 9999 명이 서블릿에 동시에 접근하면이 9999 명이 순서대로 액세스 할 수 있도록 대기해야합니다.
서블릿의 스레드 안전 문제에 대한 응답으로 Sun은 솔루션을 제공합니다. Servlet이 SinglethreadModel 인터페이스를 구현하도록합니다. 서블릿이 Singlethreadmodel 인터페이스를 구현하면 서블릿 엔진은 단일 스레드 모드에서 서비스 메소드를 호출합니다.
Sevlet API를 살펴보면 SingleThreadModel 인터페이스가 방법이나 상수를 정의하지 않음을 알 수 있습니다. Java에서는 방법이나 상수를 정의하지 않는 인터페이스를 태그 인터페이스라고합니다. 자주 보는 가장 일반적인 태그 인터페이스 중 하나는 "직렬화 가능"입니다. 이 인터페이스는 또한 방법이나 상수를 정의하지 않습니다. Java에서 태그 인터페이스를 사용하는 것은 무엇입니까? 주요 기능은 객체를 표시하고 JVM 에게이 객체에게 할 수있는 일을 알려주는 것입니다. 예를 들어, "직렬화 가능한"인터페이스를 구현하는 클래스의 객체는 직렬화 될 수 있으며 "클로닝 가능한"인터페이스도 있으며, 이는 또한 태그 인터페이스입니다. 기본적으로 Java의 물체는 실제 생활의 사람들과 마찬가지로 복제 할 수 없지만 복제는 허용되지 않지만 "클로닝 가능한"인터페이스가 구현되는 한 객체를 복제 할 수 있습니다.
서블릿이 SinglethreadModel 인터페이스를 구현하도록하고, 선언을 추가하여 SingleThreadModel 인터페이스를 서블릿 클래스의 정의에 구현하기 만하면됩니다.
Singlethreadmodel 인터페이스를 구현하는 서블릿의 경우 서블릿 엔진은 여전히 서블릿에 대한 멀티 스레드 동시 액세스를 지원합니다. 이 방법은 여러 servlet 인스턴스 개체를 생성하는 것이며 각 동시 스레드는 독립적 인 서블릿 인스턴스 객체를 별도로 호출합니다.
Sorglethreadmodel 인터페이스 구현은 서블릿의 스레드 안전 문제를 실제로 해결할 수 없습니다. 서블릿 엔진은 여러 서블릿 인스턴스 개체를 생성하고 멀티 스레드 안전 문제를 실제로 해결하면 여러 스레드에 의해 서블릿 인스턴스 개체가 호출되는 문제를 참조합니다. 실제로 Servlet API 2.4에서 SinglethreadModel은 더 이상 사용되지 않은 것으로 표시되었습니다 (구식).
위의 내용은이 기사에 관한 모든 것입니다. 모든 사람의 학습에 도움이되기를 바랍니다.