티스토리 뷰

1.    요청 포워딩 ( request forwarding )

-      사용자의 요청을 받은 서블릿 또는 JSP에서 또 다른 컴포넌트( 서블릿, JSP, html )로 요청을 위임할 수 있는 방법이다.

-      포워드( forward )하는 이유는 직접 요청받은 서블릿 또는 JSP에서 모든 작업을 처리하지 않고, 모듈화시킨 다른 컴포넌트로 요청을 위임하여 재사용성도 높이고 유지보수를 쉽게 해주기 위해서다.

-      보통 요청을 처리하는 웹 컴포넌트는 FrontController 패턴을 적용한 서블릿으로,

-      응답을 처리하기 위한 웹 컴포넌트 JSP로 구현한다.

-      이런 구조를 MVC( Model, View, Controller ) 패턴이라고 한다.

-      + MVC 패턴 ( == 모델2 아키텍쳐 ) : 웹개발에서 백엔드의 최상의 구현방식

-      + M == Model ( 비즈니스 수행결과 데이터 ) : 공유데이터 영역

-      + V == View ( 비즈니스 데이터가 반영된 응답화면 ) : 웹 컴포넌트 - JSP

-      + C == Controller ( 요청처리 흐름을 제어하는 자 ) : 웹 컴포넌트 – FrontController

-      + 하나의 요청이 처리되어 응답이 웹 브라우저로 나가기까지 여러 개의 웹 컴포넌트( Servlet, JSP )를 거쳐서 처리될 수 있다.


[ 1 -1. MVC 패턴 - 요청 포워딩 ] (*****)

 

package org.zerock.myapp;

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;

import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;


@Log4j2
@NoArgsConstructor

// MVC 패턴의 Controller의 역할을 한다.
@WebServlet("/Request")
public class RequestServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
    
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
		
		log.trace("service(req, res) invoked.");
		
		// 비지니스 로직 수행
		
		// 비지니스 데이터 ( == Model ) : request Scope에 공유 데이터 올리기
		req.setAttribute("name", "홍길동");
		req.setAttribute("address", "서울");
		
		// === 응답을 만들어낼 웹 컴포넌트( Servlet / JSP )에 요청을 위임 ( View ) ===
		
		// forward : 요청을 위임
		RequestDispatcher dis = req.getRequestDispatcher("/Response");
		dis.forward(req, res);
		
		log.info("Forward request to the /Response");
		
	} // service

} // end class

 

[ 1 - 2. MVC 패턴 - 응답하는 웹 컴포넌트 생성 ] (*****)

 

package org.zerock.myapp;

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;

import lombok.Cleanup;
import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;


@Log4j2
@NoArgsConstructor

@WebServlet("/Response")
public class ResponseServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	@Override
	protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
		
		log.trace("service(req, res) invoked.");
		
		// 1. 공유데이터 영역( Request Scope )에서 Model 데이터 얻어내기
		String name = (String) req.getAttribute("name");
		String address = (String) req.getAttribute("address");
		
		log.info("Model - name : {}, address : {}", name, address);
		
		// ======================================================
		
		// 응답문서 준비
		
		// 2. Model을 이용한 응답문서의 생성 및 전송
		res.setContentType("text/html; charset=utf8");
		
		@Cleanup
		PrintWriter out = res.getWriter();
		
		out.println("<html><head></head><body>");
		out.println("<h1> /Response </h1>");
		out.println("<hr>");
		
		out.println("<h2> 1. name 값 : " + name + "</h2>");
		out.println("<h2> 2. address 값 : " + address + "</h2>");
		
		out.println("</body></html>");
		out.flush();
		
	} // service

} // end class

[ 2 - 1. Redirect - 자신이 처리할 것이 아닐때 재요청하기 + 쿼리 스트링 이용하기 ] (***)

 

package org.zerock.myapp;

import java.io.IOException;
import java.net.URLEncoder;

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 javax.servlet.http.HttpSession;

import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;


@Log4j2
@NoArgsConstructor
@WebServlet("/RequestRedirect")
public class RequestRedirectServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	@Override
	protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
		
		log.trace("service(req, res) invoked.");
		
		// 비지니스 로직 수행
		
		// 1. 비지니스 데이터 ( == Model ) : request Scope에 속성 바인딩
		// req.setAttribute("name", "홍만만");
		// req.setAttribute("address", "주소");
		
		// 1 - 2. 섹션 영역으로 공유 데이터 올려 놓기
		// HttpSession sess = req.getSession();
		// sess.setAttribute("name", "난섹션이다.");
		// sess.setAttribute("address", "주소");
		
		// 2. Redirect 응답 전송
		String queryStr = "?name="+URLEncoder.encode("홍길동","utf8")+"&address="+URLEncoder.encode("서울","utf8");
		// URLEncoder.encode("문자열","utf8"); ( 값부분만 바꿔주면 된다. )
		// 이 방법을 사용할 경우 URL에 name과 address가 보여진다.
		// 왜 URL 전체를 한번에 인코딩하지 않은 이유는, 그렇게 되면 특수문자까지도 인코딩으로 바뀌기때문이다.
		// 그렇기 때문에 값부분만 인코딩해줘야 한다.(***)
		
		res.sendRedirect("/ResponseRedirect" + queryStr); // (***)
		
		// + 이때 queryStr는 한글을 허용하지 않는 언어이기에, utf8로 URLEncoding을 해야 한다.
		
		log.info("Succeed to send a Redirection to the web browser");
		// Redirect의 경우 URL이 위임한 곳으로 변경된다.
		
	} // service

} // end class

 

[ 2 - 1. Redirect - 응답하기 ]

 

package org.zerock.myapp;

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;
import javax.servlet.http.HttpSession;

import lombok.Cleanup;
import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;


@Log4j2
@NoArgsConstructor
@WebServlet("/ResponseRedirect")
public class ResponseRedirectServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
		
		log.trace("service(req, res) invoked.");
		
		// 1. 공유데이터 영역( Request Scope )에서 Model 데이터 얻어내기
		// String name = (String) req.getAttribute("name");
		// String address = (String) req.getAttribute("address");
		
		// 1 - 2. 공유데이터 영역( Session Scope )에서 Model 데이터 얻어내기
		// HttpSession sess = req.getSession();
		// String name = (String) sess.getAttribute("name");
		// String address = (String) sess.getAttribute("address");
		
		// 1 - 3. 전송파라미터로 얻기
		req.setCharacterEncoding("UTF-8");
		String name = req.getParameter("name");
		String address = req.getParameter("address");
		log.info("Model - name : {}, address : {}", name, address);
		
		// ======================================================
		
		// 2. Model을 이용한 응답문서의 생성 및 전송
		res.setContentType("text/html; charset=utf8");
		
		@Cleanup
		PrintWriter out = res.getWriter();
		
		out.println("<html><head></head><body>");
		out.println("<h1> /ResponseRedirect </h1>");
		out.println("<hr>");
		
		out.println("<h2> 1. name 값 : " + name + "</h2>");
		out.println("<h2> 2. address 값 : " + address + "</h2>");
		
		out.println("</body></html>");
		out.flush();
		
		// ======================================================
		
		// Redirect는 name과 address가 모두 null로 나오는데,
		// 그 이유는 redirect는 재요청을 응답으로 보내버리기 때문에
		// Request Scope에 올려 놓았던 name과 address가 없어져 버린다.
		// 그렇기에 출력하기 위해서는 다른 방법을 사용해야 한다.
		
		// ======================================================
				
	} // service

} // end class

[ 3. 인코딩과 디코딩 ]

 

package org.zerock.myapp;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.DisplayNameGenerator.Standard;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.TestInstance.Lifecycle;
import org.junit.jupiter.api.TestMethodOrder;
import org.junit.jupiter.api.Timeout;

import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;

@NoArgsConstructor
@Log4j2

@TestInstance(Lifecycle.PER_CLASS)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class URLEncodingDecodingTests {
	
	@Test
	@Order(1)
	@DisplayName("testURLEncoder")
	@Timeout(value = 1000, unit = TimeUnit.MILLISECONDS)
	void testURLEncoder() throws UnsupportedEncodingException {
		
		log.trace("testURLEncoder() invoked.");
		
		String str1 = "한글"; // 한글은 utf8로 인코딩된다.
		String str2 = "ABCDEFG1234567"; // 영어와 숫자는 인코딩해도 변함이 없다.
		String str3 = "ABCDEFG 1234567"; // 공백은 +로 바뀐다.
		
		// 인코딩하기
		String urlencodedStr = URLEncoder.encode(str1, "utf8");
		log.info("\t + urlencodedStr : {}", urlencodedStr);
		
		// 디코딩하기
		// String urldecoedeStr = URLDecoder.decode(urlencodedStr, StandardCharsets.UTF_8);
		String urldecoedeStr = URLDecoder.decode(urlencodedStr, "utf8");
		log.info("\t + urldecoedeStr : {}", urldecoedeStr);
		
	}// testURLEncoder

} // end class

[ 4. MVC 패턴으로 FrontController 바꾸기 ] (*****)

 

package org.zerock.myapp;

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;

import org.zerock.myapp.domain.EmpDTO;
import org.zerock.myapp.exception.BizProcessException;
import org.zerock.myapp.service.DeleteService;
import org.zerock.myapp.service.InsertService;
import org.zerock.myapp.service.SelectService;
import org.zerock.myapp.service.Service;
import org.zerock.myapp.service.UnknownReqService;
import org.zerock.myapp.service.UpdateService;

import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;


@Log4j2
@NoArgsConstructor

@WebServlet("*.do") // 다른 서블릿이 *.do로 매핑하고 있으면 오류발생할 수 있다.
public class FrontControllerServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
		
		log.trace("service(req, res) invoked.");
		
		// =======================================
			// 1. ContextPath와 URL/URI(요청)확인
		// =======================================
		
		String contextPath = req.getContextPath();
		String requestURI = req.getRequestURI();
		String requestURL = req.getRequestURL().toString();
		
		// =======================================
		
		log.info("\t + 0. contextPath : {}", contextPath); // /maven01 or /myapp
		
		// + contextPath가 그냥 /(루트)일 경우 빈문자열이기에, 출력되지 않는다.
		// + 즉 그냥 루트일 경우에는 substring할 필요 없이 URI를 사용하면 된다.
		
		// =======================================
		
		log.info("\t + 1. requestURI : {}", requestURI); // /*.do
		log.info("\t + 2. requestURL : {}", requestURL); // http://localhost:8080/*.do
		
		// 현재 모든 URL 중 .do로 끝나는 모든 요청을 여기에 집중시키고 있다.
		
		// =======================================
		
		// substring으로 URI에서 컨텍스트 페스를 제외한 문자열을 돌려준다.
		// String command = requestURI.substring(contextPath.length());
		
		String command = requestURI;
		log.info("\t + 3. command : {}", command); // /*.do
		
		// + command는 contextPath가 그냥 루트일 경우 URI와 동일하게 나온다.
		
		// =======================================
			// 2. 전송파라미터를 DTO객체로 수집 (*****) <----- 여기서부터 시작해도 된다.
		// =======================================
		
		// req.setCharacterEncoding("UTF-8"); 은 이미 필터에서 수행되었다.
		
		String empno = req.getParameter("empno");
		String ename = req.getParameter("ename");
		String sal = req.getParameter("sal");
		String deptno = req.getParameter("deptno");
		
		// 전송파라미터를 하나씩 계속 전달하면, 너무 비효율적이기에 DTO 객체에 저장해서 사용한다.
		// 수집된 각 전송 파라미터를 DTO 객체에 저장 ( 이제, 이 객체를 전달하면 된다. )
		// DTO 객체는 웹3계층(표현/비지니스/영속 계층)의 뒤로 전달되면서 사용된다.
		EmpDTO dto = new EmpDTO();
		
		// null이 아니고 빈문자열도 아니어야 한다.
		if( empno != null && !"".equals(empno) ) { dto.setEmpno(Integer.parseInt(empno)); } // if - empno
		
		if( ename != null && !"".equals(ename) ) { dto.setEname(ename); } // if - ename
		
		if( sal != null && !"".equals(sal) ) { dto.setSal(Double.parseDouble(sal)); } // if - sal
		
		if( deptno != null && !"".equals(deptno) ) { dto.setDeptno(Integer.parseInt(deptno)); } // if - deptno
		
		// + 전송파라미터는 String으로 들어오기에, 필요시 형변환을 해줘야 한다.
		
		// =======================================
			// 3. 요청 URI에 따라, command(요청유형) 결정
		// =======================================
		
		// Request Scope 공유 데이터 영역에 DTO 객체를 속성으로 바인딩
		// * 주의 * : 모든 Service 객체의 비지니스 로직 수행에 필요한 전송파라미터를
	    // 전달해주는 DTO 객체를, 또 다른 공유데이터 영역인 "Request Scope"을 통해 전달
	    // ( accessed by HttpServletRequest )

		// -> 비지니스 로직 수행에 필요한 데이터를 가지고 있는 것이 DTO 객체이기 때문에 이를 넘겨줘야 한다.
		
		req.setAttribute(Service.DTO, dto);
		
		// req.getAttributeNames();
		// 이를 통해서 공유된 데이터의 이름을 파악할 수 있다.
		
		// =======================================
		// 4. command 에 따라, 적합한 비지니스 서비스 객체 선택 및 비지니스 로직 수행
		// =======================================
		
		try {
			
			//  command(요청유형)에 따라, 각 요청을 처리하는 서비스 객체의 생성 및 비지니스 로직 수행(execute 메소드)
	        // * 주의 * : 비지니스 로직 수행 결과 데이터는, 공유데이터 영역인 "Application Scope"(accessed by ServletContext)에 바인딩
			
			switch( command ) {
			
			// 아래의 모든 service 객체에 필요한 전송파라미터를 전달해주는
			// DTO 객체는 3번째 공유데이터 영역인 Request Scope을 통해 전달된다.
			
				case "/insert.do":
					log.info("\t + 4. insert request.");
					new InsertService().execute(req, res); // 객체 생성 후 메소드 실행
					break;
					
				case "/update.do":
					log.info("\t + 4. update request.");
					new UpdateService().execute(req, res); // 객체 생성 후 메소드 실행
					break;
					
				case "/delete.do":
					log.info("\t + 4. delete request.");
					new DeleteService().execute(req, res); // 객체 생성 후 메소드 실행
					break;
					
				case "/select.do":
					log.info("\t + 4. select request.");
					new SelectService().execute(req, res); // 객체 생성 후 메소드 실행
					break;
					
				default : // == if-else
					log.info("\t + 4. unknown request.");
					new UnknownReqService().execute(req, res); // 객체 생성 후 메소드 실행
					break;
		
			} // switch
			
		} catch(BizProcessException e) {
			;;
		} // try - catch
		
		// =======================================
			// 응답 문서 준비 --> /View로 이동
		// =======================================
		
		// =======================================
			// MVC 패턴 적용
		// =======================================
		
		RequestDispatcher dis = req.getRequestDispatcher("/View");
		dis.forward(req, res);
		
		log.info("Forwarded request into /View");
		
	} // service

} // end class

 

[ 4 - 2. Service 변경 -> Application Scope에서 Request 공유영역으로 바꾸기 ] 

 

package org.zerock.myapp.service;

import java.sql.SQLException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.zerock.myapp.domain.EmpDTO;
import org.zerock.myapp.exception.BizProcessException;
import org.zerock.myapp.persistence.EmpDAO;

import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;


@Log4j2
@NoArgsConstructor
public class DeleteService implements Service {

	@Override
	public void execute(HttpServletRequest req, HttpServletResponse res) throws BizProcessException {
		
		log.trace("execute(req, res) invoked.");
		
		try {
			
			EmpDTO dto = (EmpDTO) req.getAttribute(Service.DTO);
			
			EmpDAO dao = new EmpDAO();
			
			int deleteRows = dao.delete(dto);
			
			// req.getServletContext().setAttribute(Service.BIZ_RESULT, deleteRows);
			// 위는 Application Scope에 올려 놓은 것이다.
			
			req.setAttribute(Service.BIZ_RESULT, deleteRows); // Request Scope에 올려 놓았다.
			
			log.info("\t + insertRows : {}", deleteRows);
			
		} catch(SQLException e) {
			throw new BizProcessException(e);
		} // try - catch 

	} // execute

} // end class
package org.zerock.myapp.service;

import java.sql.SQLException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.zerock.myapp.domain.EmpDTO;
import org.zerock.myapp.exception.BizProcessException;
import org.zerock.myapp.persistence.EmpDAO;

import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;


@Log4j2
@NoArgsConstructor
public class InsertService implements Service {

	@Override
	public void execute(HttpServletRequest req, HttpServletResponse res) throws BizProcessException {
		
		log.trace("execute(req, res) invoked.");
		
		try {
			
			EmpDTO dto = (EmpDTO) req.getAttribute(Service.DTO);
			
			EmpDAO dao = new EmpDAO();
			
			int insertRows = dao.insert(dto);
			
			// req.getServletContext().setAttribute(Service.BIZ_RESULT, insertRows);
			// 위는 Application Scope에 올려 놓은 것이다.
			
			req.setAttribute(Service.BIZ_RESULT, insertRows); // Request Scope에 올려 놓았다.
			
			log.info("\t + insertRows : {}", insertRows);
			
		} catch(SQLException e) {
			throw new BizProcessException(e);
		} // try - catch 

	} // execute

} // end class
package org.zerock.myapp.service;

import java.sql.SQLException;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.zerock.myapp.domain.EmpVO;
import org.zerock.myapp.exception.BizProcessException;
import org.zerock.myapp.persistence.EmpDAO;

import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;


@Log4j2
@NoArgsConstructor
// select.do 요청을 실제 처리할 비지니스 로직
public class SelectService implements Service {

	@Override
	public void execute(HttpServletRequest req, HttpServletResponse res) throws BizProcessException {
		
		log.trace("execute(req, res) invoked.");
		
		// =======================================
		// 실제 로직
		// =======================================
		
		try {
			
			// 영속계층에서 데이터를 가지고 오는 DAO객체 생성
			EmpDAO dao = new EmpDAO();
			
			// + dao의 selectAll메소드를 한 결과를 반환한다.
			// + 즉, sql문대로 실행한 결과를 List<EmpVO>타입으로 반환한다.
			
			// 비지니스 수행결과 데이터 발생
			List<EmpVO> list = dao.selectAll();
			
			// 공유데이터 영역에 비지니스 제이터를 속성 바인딩시킨다.
			// ServletContext sc = req.getServletContext();	// Application scope 객체
			// sc.setAttribute(Service.BIZ_RESULT, list); // 인터페이스에서 정적객체 가지고 오기
			// 위는 Application Scope에 올려 놓은 것이다.
			
			req.setAttribute(Service.BIZ_RESULT, list); // Request Scope에 올려 놓았다.
			
		} catch(SQLException e) {
			throw new BizProcessException(e);
		} // try - catch 
		
	} // execute

} // end class
package org.zerock.myapp.service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.zerock.myapp.exception.BizProcessException;

import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;


@Log4j2
@NoArgsConstructor

// 잘못된 요청(command)에 대한 처리를 수행하는 서비스 객체
public class UnknownReqService implements Service {

	@Override
	public void execute(HttpServletRequest req, HttpServletResponse res) throws BizProcessException {

		log.trace("execute(req, res) invoked.");
		
		// ServletContext sc = req.getServletContext();	// Application scoe 객체
		// sc.setAttribute(Service.BIZ_RESULT, "Bad Request"); // 인터페이스에서 정적객체 가지고 오기
		// 위는 Application Scope에 올려 놓은 것이다.
		
		req.setAttribute(Service.BIZ_RESULT, "Bad Request"); // Request Scope에 올려 놓았다.
		
	} // execute

} // UnknownReqService
package org.zerock.myapp.service;

import java.sql.SQLException;
import java.util.List;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.zerock.myapp.domain.EmpDTO;
import org.zerock.myapp.domain.EmpVO;
import org.zerock.myapp.exception.BizProcessException;
import org.zerock.myapp.persistence.EmpDAO;

import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;


@Log4j2
@NoArgsConstructor
public class UpdateService implements Service {

	@Override
	public void execute(HttpServletRequest req, HttpServletResponse res) throws BizProcessException {
		
		log.trace("execute(req, res) invoked.");
		
		try {
			
			EmpDTO dto = (EmpDTO) req.getAttribute(Service.DTO);
			
			EmpDAO dao = new EmpDAO();
			
			int updateRows = dao.update(dto);
			// req.getServletContext().setAttribute(Service.BIZ_RESULT, updateRows);
			// 위는 Application Scope에 올려 놓은 것이다.
			
			req.setAttribute(Service.BIZ_RESULT, updateRows); // Request Scope에 올려 놓았다.
			
			log.info("\t + insertRows : {}", updateRows);
			
		} catch(SQLException e) {
			throw new BizProcessException(e);
		} // try - catch 

	} // execute

} // end class

 

[ 4 - 3. 위임할 /View Servlet 생성 ] 

 

package org.zerock.myapp;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletContext;
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.myapp.service.Service;

import lombok.Cleanup;
import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;


@NoArgsConstructor
@Log4j2

@WebServlet("/View")
public class ViewServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	@Override
	protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
		
		log.trace("service(req,res) invoked.");
		
		log.info(">>>> /View <<<<");
		
		res.setContentType("text/html; charset=utf8");
		
		@Cleanup
		PrintWriter out = res.getWriter();
		out.println("<html><head></head><body>");
		
		// 위의 각 command 별로 수행되는 Service 개체의 execute 메소드의 수행결과를 Request Scope에서
		// 얻어서, 응답문서를 만들어 준다!
		Object bizResult = req.getAttribute(Service.BIZ_RESULT);
		
		out.println("<p>" + bizResult + "</p>");
		
		out.println("</body></html>");
		out.flush();
		
	} // service

} // end class

[ 5. 세션 아이디 확인하는 방법 ]

 

package org.zerock.myapp;

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;
import javax.servlet.http.HttpSession;

import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;


@NoArgsConstructor
@Log4j2
@WebServlet(name = "Hello2", urlPatterns = { "/hello2" })
public class Hello2Servlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
	protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
		
		log.trace("service(req, res) invoked.");
		
		HttpSession sess = req.getSession();
		log.info("JSE Session ID : {}",sess.getId());
		// 세션 아이디 확인하는 방법
		
		PrintWriter out =  res.getWriter();
		out.println("<h1>World!!!</h1>");
		// WAS는 이처럼 동적으로 태그를 넣어서 문서를 만들 수 있다.
		
		out.flush();
		out.close();
		
	} // service
	
	// + service는 GET과 POST방식 모두 요청을 받을 수 있다.(***)

} // end class
728x90
댓글
«   2025/06   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
최근에 올라온 글
Total
Today
Yesterday
공지사항