백엔드/JSP

웹 프로그래밍의 시작 (3)

두개의 문 2023. 6. 18. 11:50
HTTPServlet

- HttpServlet을 상속하는 별도의 서블릿을 정의하고 이를 이용

- HttpServlet의 특징

 ① HttpServlet은 doGet( ), doPost( ) 메서드 등을 제공

     → 필요한 메서드를 오버라디드하여 처리 가능 

 ② HttpServlet을 상속받은 클래스 객체는 톰캣과 같은 WAS의 내부에서 자동으로 객체 생성 및 관리됨

 ③ HttpServlet은 멀티 스레드에 의해서 동시에 실행될 수록 처리됨 

 

 


서블릿 lifecycle

- 서블릿 ( Servlet ) : 웹 서버가 동적인 웹 페이지를 제공할 수 있도록 도와주는 애플리케이션

[출처] 성낙현의 JSP_Chapter01

 

 

· 서블릿 : 서버 측에서 실행 ( 클라이언트의 요청을 받으면 서버에서 처리한 후, 응답으로는 결과값만 보내주는 구조 )

             자바 파일(.java)을 컴파일한 클래스 파일(.class) 형태

· 서블릿 컨테이너 : 서블릿을 실행하고 관리해주는 런타임 서버로, Apache Tomcat이 대표적인 서블릿 컨테이너

 

 

  ▷ 서블릿의 특징

  ❶ 클라이언트의 요청에 대해 동적으로 작동하는 웹 애플리케이션 컴포넌트

  ❷ HTML을 사용하여 요청에 응답함

  ❸ Java Thread를 이용하여 동작함

  ❹ MVC 패턴에서 Controller로 이용됨

  ❺ HTTP 프로토콜 서비스를 지원하는 javax.servlet.http.HttpServlet 클래스를 상속 받음

  ❻ HTML 변경 시 Servlet을 재컴파일해야 하는 단점

 

 

 ▷ 서블릿 동작 방식 

서블릿은 HTTP 프로토콜을 사용하는 웹 환경이나 서버환경에서 쓰이는 기술이므로, HTTP에 대한 이해가 필요함( 참고자료 )

전체적인 흐름은 쓰레드를 배운 후, 공부하기로 하고 우선 대략적인 흐름만 공부하자 

 

① 브라우저가 톰캣에 서블릿이 처리햐야 하는 특정한 경로 호출

② 톰캣은 해당 경로에 맞는 서블릿 클래스를 로딩하고 객체 생성 ( HttpServletRequest, HttpServletResponse 객체 )

     서블릿의 init( ) 메서드를 이용해 서블릿 객체가 동작하기 전에 수행해야 하는 일들을 처리 

③ 생성된 서블릿 객체는 브라우저의 요청에 대한 정보를 분석해 GET / POST 등의 정보와 함께 같이 전달되는 파라미터들을 HttpServletRequest 객체의 파라미터로 전달 받음, 이 과정에서 응답을 처리하는 데 필요한 기능들은 HttpServletResponse 객체로 전달 받음 

④ 서블릿 내부에서는 GET / POST에 맞게 doGet( ) / doPost( ) 등의 메서드 실행 

    ※ 이 후 동일한 주소의 호출이 있을 때 서블릿은 동일한 객체 하나만을 이용해서 처리함 

⑤ 톰캣이 종료될 때는 서블릿의 destroy( ) 메서드 실행시켜 HttpServletRequest, HttpServletResponse 객체는 소멸됨

 

 

 

( 요약 )

❶ 서블릿의 객체는 경로에 맞게 하나만 생성

❷ 매번 호출 시에는 자동으로 doGet( ) / doPost( ) 메서드를 이용해 처리

 

 

 

SampleServlet을 생성 후, 실행해보자. 

 

처음 실행 시, init( ) 메서드와 doGet( ) 메서드 실행되는 것을 확인 할 수 있음

 

 

이 상태에서 여러번 호출할 경우,

더 이상 init( ) 메서드는 호출되지 않고, doGet( ) 메서드만 호출됨 

또한, this의 결과로 출력되는 @ 이하의 값이 동일한 것을 확인 할 수 있음 

→ 서블릿의 객체는 경로에 맞게 하나만 생성된 후, 매번 호출 시 자동으로 doGet( ) 또는 doPost( ) 메서드를 이용해 처리됨을 확인할 수 있음 

 

톰캣 종료시, destroy( ) 메서드가 호출됨 

 

∴ init( )와 destroy( ) 메서드는 한 번씩만 호출, doGet( ), doPost( )는 동일한 객체를 이용해서 여러 번 호출됨 

 

 

 


HttpServletRequest의 주요 기능

- HttpServletRequest는 HTTP 메시지 형태로 들어오는 요청에 대한 정보를 파악하는 주요 메서드

메서드 설명
String getParameter(name) 파라미터 변수 name에 저장된 변수를 얻어내는 메서드로, 이때 변수의 값은 String으로 리턴됨
즉, key을 이용해서 value을 얻는 역할 
만일, 해당 파라미터가 존재하지 않은 경우, null을 반환함 ( 항상 null 체크 주의하기 )
String[] getParameterValues(name) 파라미터 변수 name에 저장된 모든 변수값을 얻어내는 메서드로, 이때 변수의 값은 String 배열로 리턴됨 → 주로 checkbox에서 사용됨
Enumeration getParameterNames() 요청에 의해 넘어오는 모든 파라미터 변수를 java.util.Enumeration 타입으로 리턴함
void setAttribute( String name, Object obj ) JSP로 전달할 데이터를 추가할 때 사용하는 메서드로, "key 이름", "value"의 형태로 데이터를 저장 
key는 문자열로 지정, value는 모든 객체 타입 이용 가능 

 

 

- RequestDispatcher 객체의 메서드 

  → RequestDispatcher 객체 : 현재의 요청을 다른 서버의 자원에게 전달하는 용도로 사용 

메서드 설명 
RequestDispatcher getRequestDispatcher( String path ) HttpServletRequest의 getRequestDispatcher( ) 메서드를 이용해 RequestDispatcher 타입의 객체를 구할 수 있음 
void javax.servlet.RequestDispatcher.forward( ServletRequest request, ServletResponse response ) 현재까지의 모든 응답(response) 내용은 무시하고, JSP가 작성하는 내용만을 브라우저로 전달 
void javax.servlet.RequestDispatcher.include( ServletRequest request, ServletResponse response ) 지금까지의 만들어진 응답(response) 내용 + JSP가 만든 내용을 브라우저로 전달 

 

 


HttpServletResponse의 주요 기능

 

- HttpServletResponse는 쓰는 기능을 담당

메서드 설명
void setHeader(name, value) 헤더 정보의 값을 수정하는 메서드로, name에 해당하는 헤더 정보를 value 값으로 설정함
void setContentType(type) 웹 브라우저의 요청의 결과로 보일 페이지의 contentType을 설정함
void sendRedirect(url) 페이지를 이동시키는 메서드로, url로 주어진 페이지로 제어가 이동함 


- sendRedirect( ) 메서드로 경로를 지정하면, HTTP에서 'Location' 이름의 HTTP 헤더로 전달됨

  → 브라우저는 'Location'이 있는 응답을 받으면, 화면을 처리하는 대신에 주소창에 지정된 주소로 이동 후, 다시 호출

 

 

▷ TodoListController 구현 

 - 목록을 보여주는 기능 / GET방식 

package org.zerock.w1.todo;

import java.io.IOException;
import java.util.List;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.zerock.w1.todo.dto.TodoDTO;
import org.zerock.w1.todo.service.TodoService;

@WebServlet(name="todoListController", urlPatterns="/todo/list")
public class TodoListController extends HttpServlet{
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
		// 콘솔 창에 로그 출력 
       		System.out.println("/todo/list");

		RequestDispatcher rd = req.getRequestDispatcher("/WEB-INF/todo/list.jsp");
		rd.forward(req, res);	
	}
}

 

 

* list.jsp 파일 생성 ( /WEB-INF/todo/list )

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
  
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>List Page</h1>
</body>
</html>

 

 

▷ TodoRegisterController 구현 

 - 등록(입력) / GET 방식 

package org.zerock.w1.todo;

import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class TodoRegisterController
 */
@WebServlet(name="todoRegister", urlPatterns="/todo/register")
// 접근해야 할 웹 서비스의 위치를 알려주는 역할
public class TodoRegisterController extends HttpServlet {
    
	// forwardJSP() 메서드 : 서블릿이 요청한 View(JSP Page)를 대신 실행하는 역할 
	// 파라미터 : 
	// 		jspFilePath ; 실행할 jsp 파일의 위치 -> WEB-INF 폴더 내 위치 
	//		req - HttpServletRequest ; 요청 객체 
	//		res - HttpServletResponse ; 응답 객체 
	// 		* JSP는 서블릿의 요청객체를 받아 데이터를 처리한 후 응답객체로 바로 웹 브라우저로 보냄 
	
	private void forwardJSP(
			String jspFilePath, 
			HttpServletRequest req, 
			HttpServletResponse res ) throws ServletException, IOException {	
            		// 예외 처리는 forwardJSP의 상위인 Servlet으로 보냄 
		
            	// 메서드 구현부 
		RequestDispatcher rd = req.getRequestDispatcher(jspFilePath);	// * 디버그 중단점 
		rd.forward(req, res);
	}
	
	
	protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
		// 콘솔창에 로그 출력 
        	System.out.println("TodoRegisterController1//doGet()");
		System.out.println("Method " + req.getMethod() + " 입력화면을 볼 수 있도록 조정");	// * 디버그 중단점 
		// String javax.servlet.http.HttpServletRequest.getMethod() 
		// -> register.jsp의 지정된 method 방식을 문자열로 출력하는 메서드 
		
		String jspPath = "/WEB-INF/todo/register.jsp";
		
		// 실제 jsp 실행 결과를 마지막으로 처리하는 것이 서블릿임을 확인해보자. 
		// 확인용 tempReq와 tempRes객체 변수를 선언 
		HttpServletRequest tmpReq = req;
		HttpServletResponse tmpRes = res;
		
		forwardJSP(jspPath, tmpReq, tmpRes);
		//forwardJSP(jspPath, req, res);
	}
}

 

 

* register.jsp 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Todo 등록</title>
</head>
<body>
	<form action="/todo/register2" method="post" >
		<input type="text" name="num1" value="1000" />
		<input type="text" name="num2" value="2000" />
		<button type="submit">등록처리</button>
	</form>
</body>
</html>

 

 

▷ TodoRegisterController2 구현

 - 등록(처리) / POST 방식 

package org.zerock.w1.todo;

import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class TodoRegisterController2
 */
@WebServlet(name="todoRegisterController2", urlPatterns="/todo/register2")
public class TodoRegisterController2 extends HttpServlet {
	private static final long serialVersionUID = 1L;
	// 서블릿으로 들어온 요청을 대신 처리(위임)하는 View 기능 호출 
	// req : 요청 변수 / res : 응답 변수  
	private void forwardJSP(
			String jspFilePath,
			HttpServletRequest req,
			HttpServletResponse res) throws ServletException, IOException {
		
		RequestDispatcher rd = req.getRequestDispatcher(jspFilePath);
		rd.forward(req, res);
		
	}
	
	@Override
	// 상속받은 메서드이므로 접근제어자를 'protected'로 설정 
	protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
		// 로그 출력 
		System.out.println("TodoRegisterController2//doGet()");
		System.out.println("Method " + req.getMethod() + " 입력화면을 볼 수 있도록 조정");
		
		// View역할 jsp 파일의 위치 
		String jspPath = "/WEB-INF/todo/result.jsp";
		forwardJSP(jspPath, req, res);
		
		// String redirectUrl = "/todo/list";
		// res.sendRedirect(redirectUrl);
		
	}
	
	@Override 
	protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
		// 로그 출력 
		System.out.println("TodoRegisterController2//doPost()");
		System.out.println("Method " + req.getMethod() + " 입력화면을 볼 수 있도록 조정");		
		
		// View역할 jsp 파일의 위치 
		String jspPath = "/WEB-INF/todo/result.jsp"; 
		forwardJSP(jspPath, req, res);
		
	}
}

 

 

* result.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h1>NUM1 ${param.num1}</h1>
	<h1>NUM2 ${param.num2}</h1>
	<h1>SUM ${
		Integer.parseInt(param.num1) + 
		Integer.parseInt(param.num2)
	 }</h1>
</body>
</html>

 

'백엔드 > JSP' 카테고리의 다른 글

JSP : EL  (0) 2023.06.20
JSP : JSTL  (0) 2023.06.19
웹 프로그래밍의 시작 (2)  (0) 2023.06.16
웹 프로그래밍의 시작 (1)  (0) 2023.06.14
JSP Servlet 기초 (8) : Session  (0) 2023.06.13