서블릿 컨테이너= WAS
。서블릿 객체를 생성 및생명주기를 관리하는컨테이너
▶HTTP 요청을 수신 시컨테이너내부의어플리케이션에 구현된 알맞은서블릿에게 전달 및응답을클라이언트로 반환
。WAS내부에 디스패처 서블릿을 포함한 다수의서블릿 객체를 구현한Java 어플리케이션을 포함하여 구동
▶JAVA / Spring이Tomcat상에서 구동되는 이유
。TCP/IP 5계층상전송계층으로부터 전달된Message를HttpServletRequest/HttpServletResponse의자바 객체로 변환하여 내부어플리케이션의 각Servlet으로 전달
▶ 이후어플리케이션으로부터HttpServletResponse를 반환받아서 다시전송계층으로 전달
。Apache Tomcat은WAS이자서블릿 컨테이너역할을 수행
▶요청당스레드를 하나씩 할당 후 처리하는 특징으로Thread Safe한 특징이 존재
서블릿 컨테이너요청/응답처리 과정
1.클라이언트가Web Server의URL로HTTP 요청전송
2.Web Server에서 수신 및WAS의URL로요청전송
3.WAS에서 수신 및 해당URL의서블릿으로요청을 전달
。요청을HttpServletRequest 객체로변환후 비어있는HttpServletResponse 객체와 함께서블릿에게 전달
4.WAS에서서블릿으로부터HttpServletReponse 객체수신 및Web Server -> 클라이언트에게 응답
서블릿( Servlet )
。JAVA에서네트워크 통신을 위한명세역할의표준 인터페이스
▶Server-Side에서Client의Request와Response를 처리
。MVC 디자인패턴의Controller역할을 수행
。현재는Spring MVC의Dispatcher Sevlet을 통해 받은 모든요청을@Controller Class의@GetMapping 어노테이션으로라우팅하여 손쉽게Http Request와Http Response를 수행하므로HttpServlet를 사용하지 않는다.
▶Spring이요청과응답을 수행하는HttpServlet의 기능을추상화한계층을 제공
Spring MVC
Servlet특징
Client에게요청을 받는 즉시HTML을 동적으로 생성하여 반환 가능
。초기Servlet등장 이전에는정적으로문서를 작성.
▶Servlet을 통해클라이언트에게 받은 값을 기준으로 동적으로문자열을 다룰 수 있으므로,WAS는 이를 통해동적 컨텐츠를 제공 가능
서블릿은저수준 모듈이므로,URL 패턴당 하나의Servlet을 구축해야하는 단점이 존재
。API가 많아질수록,Boiler-plate code가 많아지는 단점이 존재하므로 현재는고수준의Spring MVC를 활용
HttpServlet를 상속하고,@WebServlet 어노테이션을 선언하여서블릿 클래스정의
。정의된서블릿 클래스를 포함한어플리케이션은WAS(tomcat등 ) 내에서 관리되며,WAS로부터 전달된HttpServletRequest와HttpServletResponse를 처리@WebServlet( name = "서블릿명칭", urlPatterns = {"/호출될엔드포인트"} ) public class HtmlStringServlet extends HttpServlet { // 코드 }▶ 해당
서블릿 클래스이 정의된 경우Tomcat내부에서 어플리케이션 배포 시서블릿으로서 작동
@WebServlet
name = "서블릿명" 속성:서블릿 명칭을 지정
▶ 지정하지 않는 경우클래스명으로 설정됨
urlPatterns = { "/호출될엔드포인트" }: 외부에서서블릿으로 접근할엔드포인트명을 지정
▶ 여러개의url pattern을 정의가능하지만,서블릿당url을 하나 지정하는 것이 원칙
HttpServlet:javax.servlet.http.HttpServlet
。서블릿에서HTTP 요청을 처리하기 위한기본 클래스
。서블릿 클래스에서상속및GET, POST,..등의요청 처리에 필요한메서드 오버라이딩하여요청 처리를 수행
▶Servlet내doGet(),doPost() , ...등의메서드를오버라이딩후Servlet의URL에Http Method에 해당하는요청을 수신 시 처리
HttpServletRequest/HttpServletRequest
。클라이언트와서블릿을 통해데이터 통신시WAS(=Tomcat)를 통해데이터를 전달받고 반환하는자바객체
▶웹 통신을자바 객체를 통해규격화하는 용도로 활용
。MVC 패턴의Dispatcher Sevlet의 경우도 해당객체를 활용하여통신을 수행
HttpServletRequest:
。클라이언트로 부터전송계층을 통해 전달된HTTP 요청을WAS에 의해캡슐화된자바객체
。HTTP 요청 구조 그대로Request Line,Headers,Query Parameter,Request Body,Cookie,Session를 포함한다.
request객체.getMethod():
。해당HTTP 요청에서Http Method를 추출
request객체.getRequestURI():
。HTTP 요청의대상 URI를 추출
request객체.getHeader("헤더명")
。해당헤더명에 해당하는헤더값을 반환
request객체.getHeaderNames():
。HTTP 요청에서 포함된 모든헤더명를 추출하여Enumeration 객체로 반환
▶request객체.getHeader("헤더명")과 함께 사용Enumeration<String> headers = req.getHeaderNames(); Collections.list(headers).forEach(headerName -> { System.out.println("header : " + req.getHeader(headerName)); });
request객체.getParameterMap()
。HTTP 요청의Query String을Map<String,String[]> 객체로서 반환
HttpServletResponse:
。클라이언트에게반환할HTTP 응답을 정의하는자바객체
▶ 처음에는비어있는 객체로 전달되며,헤더및데이터를 포함 후 반환하도록 설정 시WAS에 의해전송 계층을 통해클라이언트에게 전송
。HTTP 응답 구조그대로Http Status Code,Response Header,Response Body를 포함
。Response Body작성 즉시클라이언트로응답
▶Http Status Code/Response Header는Response Body작성 전에 우선 설정해야한다.
。템플릿 엔진에서VIEW생성 시HttpServletResponse에 포함 후Dispatcher Servlet -> 브라우저로 전달
response객체.setStatus(응답코드)
。HTTP응답에Http Status Code를 설정
▶ 보통Enum을 통해HttpServletResponse.SC_상태명을 설정
response객체.setContentType("타입")
。HTTP응답의ContentType설정
▶text/html,application/json등
。text/html설정 시브라우저는렌더링을 우선적으로 시도
response객체.setCharacterEncoding("인코딩")
。HTTP응답의인코딩설정
▶UTF-8등
response객체.setHeader("헤더명", "헤더값")
。HTTP응답에헤더를 설정
。헤더이름 규칙:헤더이름은대문자로 작성 및kebab-case로 작성
ex )X-CUSTOM-HEADER
。헤더 길이를 매우 크게하면 안된다.
▶헤더를 매우 크게 하는 공격법들이 존재하므로.
response객체.addCookie(쿠키객체)
。HTTP응답에쿠키를 추가
▶쿠키:new Cookie();
response객체.getWriter()
。Http Response Body를 작성 시 활용하는Writer 객체를 생성
▶Buffer로 작성되며, 작성이 끝난 즉시Buffer는HTTP Response Body로삽입되어 전송됨
writer객체.write(문자열)
。문자열그대로버퍼에 작성 및null입력 시NPE발생
writer객체.print(문자열)
。문자열그대로버퍼에 작성하지만,write()와 달리null을 넣으면문자열 null로 작성됨
writer객체.println(문자열)
。print()에 줄바꿈까지 지원
writer객체.flush()
。Buffer에 축적된데이터를Http Request Body로 보냄.
▶ 이후HTTP 응답을클라이언트에게 전송
톰캣을 활용하여서블릿을 포함하는WAR 파일배포하기
- 톰캣 설치 및 압축해제
Jakarta EE Project생성
。Application Server에 해당Apache Tomcat의디렉토리 경로를 설정
Edit Configuration - Deployment를 통해 각각의WAR파일에 대해URL Prefix정의
。Tomcat 서버는 여러WAR파일을배포할 수 있으므로,URL Prefix를 통해Artifact명을 할당하여WAR파일들을 구분
▶ 해당WAR 파일에 대해url prefix : /로 설정
서블릿 클래스정의
。@WebServlet 어노테이션선언 및HttpServlet상속
。해당urlPattern으로GET 요청전송 시HttpServlet으로부터메서드 오버라이딩한doGet()을 통해요청 처리
▶POST 요청등에 대한요청처리가 추가적으로 필요 시doPost() , ...를오버라이딩
▶톰캣에서HttpServletRequest / HttpServletResponse를매개변수로서 전달
。HttpServletResponse은비어있는 객체로 전달되며,헤더와데이터를 정의하여톰캣에게 반환하여클라이언트에게응답
。resp객체.setContentType("text/html;charset=utf-8");을 설정하여브라우저에텍스트전달 시브라우저는텍스트를HTML문으로 인식하도록 설정@WebServlet( name = "HtmlServlet", urlPatterns = {"/c01/01"} ) public class HtmlStringServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 톰캣(WAS)에서 HttpServletRequest / HttpServletResponse 를 전달 // HttpServletResponse은 비어있는 객체로 전달되며, 헤더와 데이터를 정의하여 톰캣에게 반환 resp.setContentType("text/html;charset=utf-8"); PrintWriter writer = resp.getWriter(); writer.println("<!DOCTYPE html>"); writer.println("<html>"); writer.println("<head>"); writer.println("<title>Servlet::title</title>"); writer.println("</head>"); writer.println("<body>"); writer.println("<div>"); // 동적 출력 IntStream.rangeClosed(1, 3) .forEach(i -> writer.println("동적 출력" + (i) + "</p>")); writer.println("</div>"); writer.println("</body>"); writer.println("</html>"); } }
서버 구동및 실행
。localhost:8080/c01/01접속 시for문을 통한동적 콘텐츠가응답
▶톰캣의 기본포트번호 : 8080이므로.