-
[Servlet] 001. Servlet 개념SsY/Class 2023. 6. 2. 18:00728x90
Servlet (서블릿) 의 개념
■■■ Servlet(서블릿) ■■■ // 정적인 웹 페이지(html) -> 동적인 페이지(Servlet) 등장 // 단, Servlet 을 작성하기가 굉장히 복잡했음 -> 클라이언트와 서버 사이에서 사전처리를 할 JSP 등장 // 다만, 클라이언트를 만날 필요가 없는 페이지는 JSP 로 구성하면 다시 한 번 Servlet 으로 변환과정이 필요 // -> 이러한 부분은 Servlet 으로 작성하자 // ※ 클라이언트의 진입지점을 확인 ※ // 클라이언트가 뷰 페이지를 직접 요청하는 상황 - Model 1 방식 // 클라이언트가 서블릿(컨트롤러)에게 요청하는 상황 - Model 2 방식 // MVC 방식 -> controller 역할 수행 : Servlet(Java) 0. 웹 어플리케이션을 구축하기 위한 웹 프로그램을 구성하는 언어의 한 종류 (JAVA 기반) 1. JSP 에서 정적인 부분을 담당하고, Servlet 에서는 동적인 처리를 위한 부분으로 사용되어 보다 효율적인 웹 어플리케이션을 구축할 수 있다. - JSP → 단점, MVC 패턴을 적용하기 힘들다. - Servlet → 단점, 웹 페이지(view) 작성이 번거롭고 복잡하다. - Servlet + JSP → MVC 패턴 적용 및 웹 페이지(view)를 보다 편리하게 작성. 단점, 구조가 복잡해지게 된다. 2. JSP 는 내부적으로 Web Container 가 Servlet 으로 변경시켜준다. 3. WEB-INF 는 환경 설정 파일이 저장되는 곳 (→ 외부에서는 접근 불가/금지) check!!! - lib : 라이브러리 파일을 저장(ojdbc.jar, jstl.jar 등) - J2SE - J2EE - clasess : class 파일이 저장(servlet) 『classess > com > Util > MyUtil.css』 원래는 이렇게 만들어야 하지만 이클립스가 자동으로 연결 실제 위치는 『C:\WebStudy\.metadata\.plugins\org.eclipse.wst.server.core \tmp0\work\Catalina\localhost\WebApp20\org\apache\jsp』 *.jar : java *.war : web(프로젝트 아래 모든 것을 압축할 때) *.ear : jar + war web.xml : context path 의 환경 설정 //-- 이곳에 파일을 생성해서 - 클라이언트가 접근을 하지 못하도록 의도적으로 만들것 //-- 요청은 Java Resources 에 구성해둔 서블릿에 요청하게 됨 //-- 서블릿은 Web-INF 에 접근이 가능(약간 같은 클래스의 메소드 같은 느낌으로 불러온다)! // 서블릿이 클라이언트의 요청을 허용할 수도, 거절할 수도 있음 // 또한 클라이언트가 페이지를 직접요청하지 않기 때문에 서블릿이 요청을 보고 알맞은 객체(?) 를 가져다 주게 됨 4. 『init()』 과 『destroy()』는 단 한 번 호출되며 『service()』는 클라이언트의 요청이 있을 때 마다 호출된다. 이제는 JSP 를 『service()』 메소드 내부에 코딩하는 것과 같다. 5. 일반적으로 『GenericServlet』 이나 『HttpServlet』을 활용한다. //-- 웹 기반일 경우 HttpServlet 으로 구성하는 것이 일반적 6. URL 패턴을 지정하는 방법은 크게 3 가지 이다. - 『/a』 - 『/*』 - 『.do』 7. web.xml 을 수정하면 서버를 꼭 재구동한 이후에 실행해야 한다. //-- 배치 기술서? //-- 클라이언트 요청 전에 일을 할 수 잇는 준비가 되었는지 확인이 필요하기 때문에 서버 작동 확인 필요 8. JSP 를 공부한 지금까지는 JSP(입력) → JSP(처리, 결과)의 구조였으나 Servlet 을 다루게 된 이후에는 JSP(입력) → Servlet(결과를 위한 처리) → JSP(결과) 방식으로 구성된다.
WebApp21
- 번호별 비교하여 확인하기!- Test1.java (Servlet)
/* ======================= Test1.java ======================== */ package com.svt; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class Test1 extends HttpServlet { private static final long serialVersionUID = 1L; @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGetPost(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGetPost(request, response); } protected void doGetPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // main() 이 없지만 HttpServlet 상속받음 -> 즉 HttpServlet 이 된 것 // 클라이언트 서비스 요청에 대해 응답할 준비를 함 // 클라이언트가 구체적인 서비스를 요청할 때 -> 구동 할 수 있도록 지정해야 함. // 그러한 상태를 지정해 주는 것이 Web.xml (배치 기술서) // ① /* response.setContentType("text/html;charset=UTF-8"); PrintWriter pw = response.getWriter(); pw.println("<html>"); pw.println("<head>"); pw.println("<title>" + "Test.java" + "</title>"); pw.println("</head>"); pw.println("<body>"); pw.println("<h1>name : 깡벼리</h1>"); pw.println("<h1>age : 19</h1>"); pw.println("</body>"); pw.println("</html>"); */ // ② /* String name = "깡벼리"; String age = "19"; response.setContentType("text/html;charset=UTF-8"); PrintWriter pw = response.getWriter(); pw.println("<html>"); pw.println("<head>"); pw.println("<title>" + "Test.java" + "</title>"); pw.println("</head>"); pw.println("<body>"); pw.println("<h1>name : " + name + "</h1>"); pw.println("<h1>age : " + age + "</h1>"); pw.println("</body>"); pw.println("</html>"); */ // ③ /* // 『ServletConfig』 //-- 컨테이너가 서블릿을 초기화 할 때 // 서블릿 당 하나씩 ServletConfig 을 생성하게 된다. ServletConfig config = getServletConfig(); // 『web.xml』에 『<init-param>』 사용 String name = config.getInitParameter("name"); String age = config.getInitParameter("age"); response.setContentType("text/html;charset=UTF-8"); PrintWriter pw = response.getWriter(); pw.println("<html>"); pw.println("<head>"); pw.println("<title>" + "Test.java" + "</title>"); pw.println("</head>"); pw.println("<body>"); pw.println("<h1>name : " + name + "</h1>"); pw.println("<h1>age : " + age + "</h1>"); pw.println("</body>"); pw.println("</html>"); */ // ④ ServletConfig config = getServletConfig(); // 『web.xml』에 『<init-param>』 사용 String name = config.getInitParameter("name"); String age = config.getInitParameter("age"); // 『ServletContext』 //-- ServletConfig는 서블릿에 대한 환경을 설정하는 과정에서 // 필요한 값들을 전달하는 형태로 주로 사용된다면... // ServletContext 는 서블릿에서 사용되는 컨텍스트를 구성하는 형태로 활용된다. ServletContext context = getServletContext(); // 『web.xml』에 『<context-param>』 사용 String type = context.getInitParameter("type"); response.setContentType("text/html;charset=UTF-8"); PrintWriter pw = response.getWriter(); pw.println("<html>"); pw.println("<head>"); pw.println("<title>" + "Test.java" + "</title>"); pw.println("</head>"); pw.println("<body>"); pw.println("<h1>name : " + name + "</h1>"); pw.println("<h1>age : " + age + "</h1>"); pw.println("<h1>type : " + type + "</h1>"); pw.println("</body>"); pw.println("</html>"); } }
- Web.xml
<?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" id="WebApp_ID" version="3.1"> <display-name>WebApp00</display-name> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> <!-- Test1 클래스 → Servlet 구성 ① --> <!-- <servlet> <servlet-name>planet</servlet-name> 3.찾은 이름의~ <servlet-class>com.svt.Test1</servlet-class> 4.클래스를 실행하거라~ </servlet> <servlet-mapping> <servlet-name>planet</servlet-name> 2. 이런 이름을 찾아라~ <url-pattern>/test1</url-pattern> 1.이런 요청이 오면 </servlet-mapping> --> <!-- Test1 클래스 → Servlet 구성 ② --> <!-- <servlet> <servlet-name>planet</servlet-name> <servlet-class>com.svt.Test1</servlet-class> </servlet> <servlet-mapping> <servlet-name>planet</servlet-name> <url-pattern>/test1</url-pattern> </servlet-mapping> --> <!-- Test1 클래스 → Servlet 구성 ③ --> <!-- <servlet> <servlet-name>planet</servlet-name> <servlet-class>com.svt.Test1</servlet-class> ┌> 구조화하는 과정에서 - init 과정에서 parameter를 초기화 하겠다 라는 의미 <init-param> <param-name>name</param-name> <param-value>담곰이</param-value> </init-param> <init-param> <param-name>age</param-name> <param-value>13</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>planet</servlet-name> <url-pattern>/test1</url-pattern> </servlet-mapping> --> <!-- Test1 클래스 → Servlet 구성 ④ --> <servlet> <servlet-name>planet</servlet-name> <servlet-class>com.svt.Test1</servlet-class> <init-param> <param-name>name</param-name> <param-value>담곰이</param-value> </init-param> <init-param> <param-name>age</param-name> <param-value>13</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>planet</servlet-name> <url-pattern>/test1</url-pattern> </servlet-mapping> <context-param> <param-name>type</param-name> <param-value>유머러스</param-value> </context-param> </web-app>
doGetPost 1번 방식 -> 정적으로 구성
더보기doGetPost 1번 방식
- 정적인 구성
doGetPost 2번 방식
- (정적인)변수지정하여 구성
※ 3, 4 번 방식 중요! - 추가 클래스 구성 없이 xml 만으로 변수 받기 ※
doGetPost 3번 방식 : ServletConfig
- 배포는 class 파일 (즉, 변수를 받아올 수 없음) -> xml 은 컴파일 과정이 없음 (있는 그대로 보관,유지,처리)
doGetPost 4번 방식 : ServletContext
※ 서블릿 구동시
-> web.xml 을 찾아서 확인 : 어떤 것을 운용하기로 했는지 확인
-> 서블릿이 해당 사항을 운용할 수 있는지 점검
-> 이 때 서블릿 하나 당 ServletConfig 를 생성하게 된다.
-> 하나의 서블릿에서 멀티스레드로 돌아가는데 - 이 때 서블릿컨피그로 운용하게 된다.
순서 : Test2.jsp 작성 -> Web.xml 에 test2ok 등록 -> servlet (Test2Ok.java) 작성 -> Test2_ok.jsp 작성
- Test2.jsp
<%@ page contentType="text/html; charset=UTF-8"%> <% request.setCharacterEncoding("UTF-8"); String cp = request.getContextPath(); %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Test2.jsp</title> <link rel="stylesheet" type="text/css" href="css/main.css"> </head> <body> <div> <h1>서블릿에서 데이터 흐름</h1> <hr /> </div> <div> <!-- 서블릿을 요청하는 주소로 만드는 것 --> <form action="<%=cp %>/test2ok" method="post"> 이름 <input type="text" name="name" class="txt"/><br> 나이 <input type="text" name="age" class="txt"/><br /> <button type="submit" class="btn">확인</button> </form> </div> </body> </html>
- web.xml
<?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" id="WebApp_ID" version="3.1"> <display-name>WebApp00</display-name> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> <!-- Test2ok 클래스 → Servlet 구성 --> <servlet> <servlet-name>test2okservlet</servlet-name> <servlet-class>com.svt.Test2Ok</servlet-class> </servlet> <servlet-mapping> <servlet-name>test2okservlet</servlet-name> <url-pattern>/test2ok</url-pattern> </servlet-mapping> </web-app>
- Test2Ok.java
/* ======================= Test2Ok.java ======================== */ package com.svt; import java.io.IOException; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class Test2Ok extends HttpServlet { private static final long serialVersionUID = 1L; @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGetPost(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGetPost(request, response); } protected void doGetPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 서블릿 관련 코딩 // 이전 페이지(Test2.jsp)로부터 데이터 수신 // (스크립릿 영역에서만 구성했던 클라이언트와 만나지 않는 페이지) // → name, age // 한글 깨짐 방지 인코딩 철리 request.setCharacterEncoding("UTF-8"); // 데이터 수신 String strName = request.getParameter("name"); String strAge = request.getParameter("age"); // 업무 처리 String str = "이름은 " + strName + "이며, 나이는 " + strAge + "세 입니다."; // 처리한 업무 넘기기 request.setAttribute("result", str); //-- 포워딩하는 페이지에 처리한 값을 넘기기 위한 준비(설정) // 즉, str 값을 result 라는 이름으로 Test2_ok.jsp 페이지로 넘길 준비 // 포워딩 -- 클라이언트는 업무처리가 다른 페이지(문번호 38 ~ 49)에서 된 것을 확인 할 수 없다 RequestDispatcher rd = request.getRequestDispatcher("/Test2_ok.jsp"); rd.forward(request, response); } }
- Test2_ok.jsp
<%@ page contentType="text/html; charset=UTF-8"%> <% request.setCharacterEncoding("UTF-8"); String cp = request.getContextPath(); %> <% // 이전 페이지(Test2Ok.java)로부터 데이터 수신 // →result String result = (String)request.getAttribute("result"); %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Test2_ok.jsp</title> <link rel="stylesheet" type="text/css" href="css/main.css"> </head> <body> <div> <h1>최종 결과값 수신</h1> <hr /> </div> <div> <h2><%=result %></h2> </div> </body> </html>
하지만 아직까지 첫 페이지는 클라이언트가 직접 가져가게 되므로
+ 추가로 xml 파일에 Test2클래스 servlet 구성- web.xml
<?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" id="WebApp_ID" version="3.1"> <display-name>WebApp00</display-name> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> <!-- ▼▼▼ 추가 구성된 부분 ▼▼▼ --> <!-- Test2 클래스 → Servlet 구성 --> <servlet> <servlet-name>test2servlet</servlet-name> <servlet-class>com.svt.Test2k</servlet-class> </servlet> <servlet-mapping> <servlet-name>test2servlet</servlet-name> <url-pattern>/test2</url-pattern> </servlet-mapping> <!-- ▲▲▲ 추가 구성된 부분 ▲▲▲ --> <!-- Test2ok 클래스 → Servlet 구성 --> <servlet> <servlet-name>test2okservlet</servlet-name> <servlet-class>com.svt.Test2Ok</servlet-class> </servlet> <servlet-mapping> <servlet-name>test2okservlet</servlet-name> <url-pattern>/test2ok</url-pattern> </servlet-mapping> </web-app>
- Test2.java
/* ================= Test2.java ==================== */ package com.svt; import java.io.IOException; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class Test2 extends HttpServlet { private static final long serialVersionUID = 1L; @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGetPost(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGetPost(request, response); } protected void doGetPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 포워딩 RequestDispatcher rd = request.getRequestDispatcher("/Test2.jsp"); rd.forward(request, response); } }
다만 지금까지의 흐름으로는 클라이언트가 뷰페이지를 jsp 페이지를 요청하면
접속이 가능하기 때문에 해당 흐름을 제어할 필요가 있다.
좌) 개발자가 의도하지 않은 흐름
우) 개발자가 의도한 흐름
-> 즉, 개발자가 의도하지 않은 흐름을 제어해야한다는 의미
Test2.jsp 와 Test2_ok.jsp 의 경로를 WebContent 에서 WEB-INF 안으로 옮긴다
- Test2.java
- 에 포워딩 주소 변경
즉, servlet 에 요청해서 접근하게 된다는 것!
/* ================= Test2.java ==================== */ package com.svt; import java.io.IOException; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class Test2 extends HttpServlet { private static final long serialVersionUID = 1L; @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGetPost(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGetPost(request, response); } protected void doGetPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 포워딩 RequestDispatcher rd = request.getRequestDispatcher("/WEB-INF/Test2.jsp"); rd.forward(request, response); } }
- Test2Ok.java
- 위와 동일하게 주소 수정
/* ================= Test2Ok.java ==================== */ package com.svt; import java.io.IOException; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class Test2Ok extends HttpServlet { private static final long serialVersionUID = 1L; @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGetPost(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGetPost(request, response); } protected void doGetPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 서블릿 관련 코딩 // 이전 페이지(Test2.jsp)로부터 데이터 수신 // (스크립릿 영역에서만 구성했던 클라이언트와 만나지 않는 페이지) // → name, age // 한글 깨짐 방지 인코딩 철리 request.setCharacterEncoding("UTF-8"); // 데이터 수신 String strName = request.getParameter("name"); String strAge = request.getParameter("age"); // 업무 처리 String str = "이름은 " + strName + "이며, 나이는 " + strAge + "세 입니다."; // 처리한 업무 넘기기 request.setAttribute("result", str); //-- 포워딩하는 페이지에 처리한 값을 넘기기 위한 준비(설정) // 즉, str 값을 result 라는 이름으로 Test2_ok.jsp 페이지로 넘길 준비 // 포워딩 -- 클라이언트는 업무처리가 다른 페이지(문번호 38 ~ 49)에서 된 것을 확인 할 수 없다 RequestDispatcher rd = request.getRequestDispatcher("/WEB-INF/Test2_ok.jsp"); rd.forward(request, response); } }
※ 실습상 편의를 위해 WebContent 폴더에 test2 (서블릿에 구성한 최초주소의 url-pattern) 로 일반 빈 파일을 만들면
이클립스에서 Ctrl + F11 를 통해서 페이지를 바로 띄울 수 있다.728x90'SsY > Class' 카테고리의 다른 글
[Servlet] 003. DBCP(DataBase Connection Pool) 개념 및 관찰 (0) 2023.06.07 [Servlet] 002. EL과 JSTL 개념 & JSTL Core 구문 관찰 (1) 2023.06.07 [JSP] 010. JDBC 연동 게시판 작성 실습 (0) 2023.06.02 [JSP] 009. JSP 액션 태그(Action Tag) (2) (0) 2023.05.30 [JSP] 008. JSP 액션 태그(Action Tag) (1) 2023.05.26