-
서블릿 설정과 변수카테고리 없음 2019. 2. 21. 21:52
서블릿을 요청할때 서블릿클래스이름을 그대로 사용하지 않고 재정의 해서 해당 이름으로 처리 할수 있다.
또한 서블릿이 실행될때 필요한 초기환경설정값을 서버에 전달할 수도 있다.
서블릿에서 사용하는 변수는 일반 다른 환경에서 실행되는 변수와 다르게 주의 해서 사용해야한다.
서블릿 환경설정
서블릿은 웹에서 클라이언트로 부터 요청을 받아 실행되는 자바프로그램, 주로 서비스 처리를 위한 준비작업과메소드 호출역할을 한다.이러한 작업은 서블릿 페이지가 아닌 서버에서 설정해야하는 부분이다.서블릿에서 설정한 내용을 추출하여 사용하는 방법에 대해 알아본다.web.xml
서버에서 서블릿 실행에 관한 정보를 설정할때느 web.xml에 <servlet> 태그로 설정한다.web.xml 파일은 서버가 시작하때 웹서버가 사용하는 파일인데.웹 애플리케이션 서비스 실행에 관한 전반적인 내용을 정의하는 환경설정 파일이다.서블릿 또한 웹 애플리케이션 실행을 위해 존재하는 파일이므로 web.xml에 정의한다.web.xml 파일에 서블릿을 정의 하려면 다음과 같이 <servlet>태그를 추가한다.web.xml123456789101112131415161718192021222324252627282930313233<?xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"><display-name>edu</display-name><servlet><servlet-name>addInfo</servlet-name><servlet-class>com.edu.test.AdditionalInfoServlet</servlet-class></servlet><servlet-mapping><servlet-name>addInfo</servlet-name><url-pattern>/addInfo/*</url-pattern></servlet-mapping><servlet><servlet-name>initParam</servlet-name><servlet-class>com.edu.test.InitParamServlet</servlet-class><init-param><param-name>id</param-name><param-value>guest</param-value></init-param><init-param><param-name>password</param-name><param-value>1004</param-value></init-param><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>initParam</servlet-name><url-pattern>/initParam</url-pattern></servlet-mapping></web-app>cs 1)servlet태그
설정하려는 서블릿을 등록한다.
하위에 namer과 클래스가 나와야됨
2)init-Param 태그
서블릿을 실행하면서 필요한 값을 외부에서 전달받아 실행할수 있다.
서블릿 소스에서 직접값을 지정해서 사용해도 되지만 실행환경에 맞게 동적으로 값을 할당하고자
할때 외부에서 값을 전달할 수있다.
이렇게하면 동적으로 값을 할당할수있는 장점도있지만
객체 지향적인 측면에서 유지 보수성이 높다는 장점이 있다.
즉 서블릿 소스에 직접 값을 지정하면 수정작업때 직접 소스를 수정하고 컴파일후 다시 서버에 올려야하는 번거로운이 있다.
initParam 태그는 xml 을 수정하면 된다.
3)load-on-startup 태그
웹서비스가 시작될 때 서블릿 객체를 생성할 수 있다.
서블릿 객체가 메모리에 생성되는 시점은 클라이언트로부터 최초의 요청이 있을때
서버에 서블릿 클래스 파일이 존재하더라도 클라이언트로부터 실행 요청이 없으면 객체가 메모리에 생성되지 않는다.
준비 되어 있다가 서비스처리에 관여하는 서블릿은 클라이언트의 요청과 상관없이 웹 서비스가 시작될 때 객체를 생성하여 대기하고 있
어야한다.
이럴때 사용한다.
태그의 값으로 우선 순위를 지정한다. 숫자값이 낮을 수록 우선순위가 높다.
ServletConfig
web.xml파일의 서블릿 태그로 환경설정을 함,
서블릿태그의 이름, 초기 파라미터, 객체 생성여부
등의 서블릿에 관한 속성들을 설정할 수 있다.
설정했다면
web.xml 에서 서블릿으로 파라미터를 전달해야한다.
<init-param>의 변수를 추출해서 사용해야한다.
추출해낼때는 ServletConfig객체에서 제공하는 메소드를 사용한다.
서블릿 실행 시 객체 생성 순서
예제로 실험
123456789101112131415161718192021222324252627282930313233343536373839404142package com.edu.test;import java.io.IOException;import java.io.PrintWriter;import javax.servlet.ServletConfig;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class InitParamServlet extends HttpServlet {private static final long serialVersionUID = 1L;String id,password;@Overridepublic void init(ServletConfig config) throws ServletException {id = config.getInitParameter("id");password= config.getInitParameter("password");}public InitParamServlet() {super();}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {response.setContentType("text/html;charset=UTF-8");PrintWriter out = response.getWriter();out.print("<h2>서블릿 초기 추출 변수</h2>");out.print("<h3>ID : "+id+"</h3>");out.println("<h3>PASSWORD : "+password+"</h3>");}protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}}cs GenericServlet에서 상속받은init() 메소드를 재정의
최초로 실행할 때 한번만 호출되는 메소드로서 인자값으로 ServletConfig 객체가 전달됨
1)ServletConfig 또 다른 사용법
HttpServlet 객체를 이용하는것HttpServlet 객체는 웹상에서 자바프로그램이 요청되어 실행 될 수 있는 조건을 가지고 있는 자바 객체이기 때문이다.GenericServlet 객체가 상속하고 있는 인터페이스를 보면 앞서 봤던 ServletConfig가 있는것을 확인 가능하다.
GenericServlet 객체는 ServletConfig 객체가 가지고 있는 메소드들을 모두 재정의 하고 있다.
따라서 init ( ) 메소드 재정의 없이 ServletConfig 객체의 메소드를 바로 사용할 수 있다.
1234567891011121314151617181920212223242526package com.edu.test;import java.io.IOException;import java.io.PrintWriter;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class ServletConfigTestServlet extends HttpServlet {private static final long serialVersionUID = 1L;protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {response.setContentType("text/html;charset=UTF-8");PrintWriter out = response.getWriter();String env = this.getInitParameter("charset");System.out.println(env);request.setCharacterEncoding(env);out.print("<h3> 이름 : "+request.getParameter("name"));out.close();}}cs web.xml 파일에서 <init-param>으로 지정한 변수중에 "charset"이란 이름으로 설정된 <pram-name>을 찾는다.
그리고 charset과 매핑된 <param-value>의 값을 추출하여 변수 env에 저장한다.
setCharacterEncoding()에 initParam의 값을 넣어주니 인코딩값을 변경할때
소스를 수정하지 않고 XML을 수정하기만 하면 된다.
12345678910111213<!DOCTYPE html><html><head><meta charset="UTF-8"><title>Insert title here</title></head><body><form action="servletConfigTest" method="post">이름 : <input type="text" name ="name"><input type="submit" value="전송"></form></body></html>cs 12345678910111213141516171819202122232425262728293031323334353637383940414243<?xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"><display-name>edu</display-name><servlet><servlet-name>addInfo</servlet-name><servlet-class>com.edu.test.AdditionalInfoServlet</servlet-class></servlet><servlet-mapping><servlet-name>addInfo</servlet-name><url-pattern>/addInfo/*</url-pattern></servlet-mapping><servlet><servlet-name>initParam</servlet-name><servlet-class>com.edu.test.InitParamServlet</servlet-class><init-param><param-name>id</param-name><param-value>guest</param-value></init-param><init-param><param-name>password</param-name><param-value>1004</param-value></init-param><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>initParam</servlet-name><url-pattern>/initParamTest</url-pattern></servlet-mapping><servlet><servlet-name>servletConfigTest</servlet-name><servlet-class>com.edu.test.ServletConfigTestServlet</servlet-class><init-param><param-name>charset</param-name><param-value>UTF-8</param-value></init-param></servlet><servlet-mapping><servlet-name>servletConfigTest</servlet-name><url-pattern>/servletConfigTest</url-pattern></servlet-mapping></web-app>cs 서블릿 변수
서블릿 동시 요청
웹개발방식은 2가지 방식이있다,
1. 웹서버의 직접적이 호출로 실행하는 CGI 방시과
2. 애플리케이션 서버가 실행하는 방식
서블릿은 서블릿 컨테이너라고 하는 웹 애플리케이션 서버가 실행하는 방식이다.
CGI와 서블릿 실행 방식은 다르다.
CGI는 실행방식은 여러 사용자 요청이 빈번한 성격의 웹서비스로 적합하지 않다.
서버에 부하가 큼
서블릿은 최초요청시 하나의 프로세스를 생성하고
이후 부터는 프로세스 안에 스레드만 새로 생성하여 실행한다.
그래서 CGI프로그래밍 실행 방식 보다 서블릿 실행방식이 서버 부하나 메모리 사용면에서 효율적
서블릿 변수 특징
서블릿을 사용하면서 멤버변수인지 지역변수인지 구분하여 사용할 수 있어야한다.하나의 서블릿에서 여러 클라이언트가 공유하는 데이터는 멤버변수로 선언하며, 각각의 클라이언트가독립적으로 사용해야하는 데이터는 지역변수로 선언해야한다.서블릿은 하나의 프로세스를 생성한다음 ,동일한 서블릿을 요청하는 클라이언트에 대하여 공통적인 프로세스를 사용하며service( ) 메소드를 실행하기 위한 스레드만 클라이언트 별로 독립적으로 생성하여 실행한다.
멤버변수는 객체 생성시 힘 메모리에 생성되며 서블릿을 실행하는 클라이언트들이 공통으로 사용한다.service( ) 메소드가 사용하는 지역변수는 스택 메모리에 생성되며, 클라이언트마다 독립적으로 사용한다.이는 서블릿의 service() 메소드를 실행하는 스레드마다 스택 메모리가 독립적이기 때문이다.따라서 지역변수는 클라이언트마다 별개로 사용된다.서블릿에서 사용하는 변수에 대해 요약하자면 다음과 같이 정리가능하다."서블릿의 지역변수는 각요청마다 스레드별로 스택영역에 할당되지만 , 멤버변수는 힙영역에 할당되어 서블릿을 실행하는 여러스레드가 공유한다."자바의 변수
구분
멤버변수
지역변수
class 변수
instance변수
선언 위치
클래스의 멤버로 선언
메소드 안에서 선언
선언 방법
static 선언
-
-
사용 메모리
메소드(클래스,static)에어리어
heap영역
stack
생성 시점
프로그램 시작 시
객체 생성 시
메소드 실행시
제거 시점
프로그램 종료 시
가비지 컬렉터에 의해
메소드 종료시
서블릿의 지역변수
서블릿의 지역변수는 여러 클라이언트가 동시에 요청했을때 개별적으로 할당된다.
LocalTestServlet
1234567891011121314151617181920212223242526272829303132333435363738394041package com.edu.test;import java.io.IOException;import java.io.PrintWriter;import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;@WebServlet("/local")public class LocalTestServlet extends HttpServlet {private static final long serialVersionUID = 1L;protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {int num =0;String str = request.getParameter("msg");response.setContentType("text/html;charset=UTF-8");PrintWriter out = response.getWriter();out.println("<html><head><title>MultiThread Test</title></head>");out.println("<body><h2>처리 결과 (지역변수)</h2>");while(num++ <10) {out.print(str+":"+num+"<br>");out.flush();System.out.println(str+":"+num);try {Thread.sleep(1000);} catch (InterruptedException e) {System.out.println(e);}}out.println("<h2>Done "+str + "!!</h2>");out.println("</body></html>");out.close();}}cs http://localhost:8081/edu/local?msg=one
http://localhost:8081/edu/local?msg=two
두 개 브라우저를 띄운뒤 동시에 요청
예제의 처리 결과를 보면 두개의 클라이언트로 부터 동일한 서블릿 요청이 들어옴 service() 메소드를 실행하는
두개의 스레드가 동시에 실행중
클라이언트가 보낸 질의 문자열 msg의 값을 추출하여 저장하는 변수 str을 지역변수로 선언했다.
각 스레드의 스택영역에 별도의 str 변수가 클라이언트 별로 만들어져서
한 클라이언트 값을 변경해도 다른 클라이언트에 영향이 미치지 않는다.
자신의 스택영역에서 변수를 찾아 사용했기 때문에
서블릿 멤버변수
동일한 서블릿을 여러 클라이언트가 동시에 요청 했을때 서블릿 객체는 하나만 생성되어 멀리스레드로 동작하므로
서블릿 멤버변수는 여러 클라이언트가 공유하게 돈다.
클라이언트의 수의 상관없이 하나의 메모리 공간을 할당하여 전역적으로 처리할때 만 멤버 변수를 선언하여 활용한다.
123456789101112131415161718192021222324252627282930313233343536373839404142package com.edu.test;import java.io.IOException;import java.io.PrintWriter;import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;@WebServlet("/member")public class MemberTestServlet extends HttpServlet {private static final long serialVersionUID = 1L;String str;protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {int num =0;str = request.getParameter("msg");response.setContentType("text/html;charset=UTF-8");PrintWriter out = response.getWriter();out.println("<html><head><title>MultiThread Test</title></head>");out.println("<body><h2>처리 결과 (멤버변수)</h2>");while(num++ <10) {out.print(str+":"+num+"<br>");out.flush();System.out.println(str+":"+num);try {Thread.sleep(1000);} catch (InterruptedException e) {System.out.println(e);}}out.println("<h2>Done "+str + "!!</h2>");out.println("</body></html>");out.close();}}cs http://localhost:8081/edu/member?msg=one
http://localhost:8081/edu/member?msg=two
str 변수 멤버 변수이기때문에
뒤에접근한 클라이언트가 변수이름을 바꿔놓는다.
즉 힙역영의 변수를 클라이언트가 공유한다.