Servlet & JSP (2)

HoJeong Im·2022년 8월 17일
0
post-thumbnail

개요

  • HTML 복습
<h1>회원 가입</h1>
아이디 : <input type="text" size="12" />
비밀번호 : <input type="text" size="12" />
이름 : <input type="text" size="30" />
권한 : <input type="text" size="12" disabled/>
  • checked : Default로 radio 버튼을 선택되게 합니다.

  • tr : table에서의 가로줄을 의미, 하나의 tr 안쪽에는 td를 사용할 수 있음

<table border="1" cellpadding="0" cellspacing="0">
  <tr>
    <td>1</td><td>2</td>    
  </tr>
  <tr>
    <td colspan="2" align="center">aaaa</td>
  </tr>
</table>
  • colspan : 비어있는 공간을 없앨 수 있음

  • cellpadding, cellspacing은 HTML 5에서부터 사용되지 않습니다.

https://developer.mozilla.org/en-US/docs/Web/API/HTMLTableElement/cellPadding

  • input type="hidden" : 브라우저에 보이지 않지만, 값을 직접 보내줄 수 있음 ==> 대신에 눈에 보이지 않을 뿐입니다.

  • 중요 정보를 전달해주어야 하기 때문 ==> 그래서 seq 정보를 hidden을 통해 구현

  • seq를 URL에 데이터로 태워보내는 게 맞는가? ==> 아니라고 생각하지만 ㅠㅠ

Container?

  • 어떠한 자료를 관리하려면, 명세(설명서)가 필요합니다.

  • Tomcat 서버 구동 => Servlet Container가 자동으로 생성

    • Container가 Servlet을 관리 및 생성합니다.

    • web.xml이라는 명세를 읽어, 여러 종류의 제품들을 관리합니다.

Java

  • request.getParameterValues : 파라미터에서 여러 값을 가져온다.

  • Servlet은 Servlet Container가 담당합니다.

    • 상식적으로, service 메소드를 호출하려면 HttpServletRequest, HttpServletResponse 타입의 변수를 매개변수로 넘겨주어야 합니다.

      • 기본형도 아니고, 참조형!

      • 이 메소드를 호출하기 전에, 각각 생성해서, service 메소드가 호출될 때 주소를 넘겨주어야지

  • HttpServletRequest, HttpServletResponse 객체도 Servlet Container가 생성해줍니다.

  • Container는 service 메소드를 호출하기 바로 직전에 request, response 객체를 생성해, 요청 프로토콜에 있는 모든 값들을 채워넣는다.

    • Http 요청 데이터 객체 = request 객체
  • Start line 정보

request.getMethod()
request.getRequestURI()
request.getProtocol()
  • Message Header 정보
request.getHeader("User-Agent");
  • Message Body 정보
request.getParameter('id');

개발자는 동작원리를 이해해야 한다. - 엔지니어로 커리어를 쌓는 것은

  • 문제가 발생했을 때, 문제를 진단하고 적절하게 판단해야 합니다.
  • 동작 원리, 내부 흐름을 알려고 노력해야 한다.

Request, Response 객체 중요 메서드!

  • Request

  • Response

web.xml

  • Tomcat 서버에 프로젝트가 여러 개 등록되어 있으면 안 됩니다.

  • 또한, 서버의 프로젝트 경로를 바꾸기 위해서는 server.xml => Context 객체의 path 경로를 /로 바꾸어줍니다!

  • 그런데, path가 자동으로 바뀌는 경우가 있음

    • Tomcat 내부에 프로젝트를 변경하는 순간!
  • Tomcat 서버를 사용할 때, Servers 폴더의 server.xml을 반드시 체크하라

서블릿은 언제 생성되는가

  • 직접 요청이 들어오거나,

lazy loading

  • 클라이언트가 요청을 하기 전까지 해당 객체의 생성을 미루는(늦추는) 것

<-> Pre-loading : 컨테이너가 생성되는 순간 동시에 객체를 생성하는 것

Servlet

load-on-startup 태그

  • 기본적으로 lazy loading이지만, load-on-startup을 통해 preloading 방식으로 바꿀 수 있다.

  • 브라우저의 요청이 없는 상태에서 바로 pre-loading이 되는 것을 알 수 있다.

init-param 태그

  • local-parameter 개념과 비슷

  • 같은 레벨에 선언된 서블릿에서만 사용할 수 있다.

  • init 메소드 : 콜백 메소드(특정 시점에 컨테이너가 자동으로 실행해주는 메소드)

  • 최초의 요청에 대해서 init 메소드가 오버라이드 되어있다면,

    • 딱 한 번 실행됨
    • 서블릿 객체가 실행된 직후
@Override
	public void init(ServletConfig config) throws ServletException {
		// TODO Auto-generated method stub
		super.init(config);
		
	}
  • config 객체 안에 init-param 정보들도 채워줌
@Override
	public void init(ServletConfig config) throws ServletException {
		// TODO Auto-generated method stub
		// <init-param>으로 설정한 초기화 파라미터(로컬 파라미터) 정보를 추출한다. 
		encoding = config.getInitParameter("encoding");
		nickname = config.getInitParameter("nickname");
		
		System.out.println(nickname+"의 인코딩 : " + encoding);
	}
  • 서버 실행 중, java 소스를 건드리지 않는다 => 컴파일을 다시 하지 않는다.

  • 만약 init을 주석처리하면 어떻게 해야하는가?

  • 정보 추출에는 2가지 방법 존재

    • 1) init 메소드를 사용하는 방법
    	public void init(ServletConfig config) throws ServletException {
    			// TODO Auto-generated method stub
    			// <init-param>으로 설정한 초기화 파라미터(로컬 파라미터) 정보를 추출한다. 
    			encoding = config.getInitParameter("encoding");
    			nickname = config.getInitParameter("nickname");
    		
    			System.out.println(nickname+"의 인코딩 : " + encoding);
    		}
    • 2) getServletConfig를 사용하는 방법
    ServletConfig config = getServletConfig(); // 부모한테 상속받음 
    			encoding = config.getInitParameter("encoding");
    			nickname = config.getInitParameter("nickname");
    			System.out.println(nickname+"의 인코딩 : " + encoding);
    		
    • ServletConfig는 하나의 서블릿과 관련된 객체 => 로컬 파라미터와 관련된 부분

서블릿 컨텍스트

  • ServletConfig : 로컬 파라미터 정보 추출(하나의 서블릿을 위한 객체)

  • ServletContext : 글로벌 파라미터 정보 추출(모든 서블릿을 위한 객체)

  • 만약에 내가 서블릿을 하나 더 등록했다면?

    • 여기도 인코딩 설정이 필요해!
// web.xml
 <context-param>
  		<param-name>encoding</param-name>
  		<param-value>UTF-8</param-value>
  </context-param>
  • 서버 하나에 웹 어플리케이션을 여러 개 등록할 수 있습니다!

  • 서버에 등록된 프로젝트 하나당 웹 어플리케이션 하나가 등록되는 것

    • 하나 당 Servlet Container가 만들어짐

    • 서버 하나 당 만들어지는 것으로 알고 있음

  • getInitParameter 함수 사용

private String encoding;

ServletContext context = getServletContext();
encoding = context.getInitParameter("encoding");
System.out.println("인코딩 : " + encoding);

상태정보 유지 기술 ****

  • Request, session, Servlet-context 3가지를 같이 알아두자

  • 상태정보 : 브라우저가 서버 쪽에 전달하는 DATA

Session?

  • 로그인을 안 했는데도 글 목록을 볼 수 있다?

  • 서블릿이 로그인이 되었는지, 안 되었는지 판단할 수 있어야 해

  • 데이터가 필요함

  • 그 데이터를 기준으로 해서 로그인 된 상태인지, 안 된 상태인지 파악할 수 있어야 해

HttpSession session = request.getSession();
  • 세션 객체는 브라우저 하나 당 하나만 생성된다.

    • request 객체는 요청 정보가 세팅되어 있는 거

    • 그 때마다, 요청 request가 계속 새롭게 만들어진다.

  • 브라우저와 매핑된 세션 객체가 메모리에 있다면?

    • 메모리의 주소만 리턴해 재사용하도록

    • 메모리에 없다면? 새롭게 생성된 객체의 주소를 리턴

  • request.getSession()이 실행될 때마다, 매번 새로운 객체가 만들어지는 게 아님

  • 첫 세션

  • 재사용 세션

  • 브라우저를 전부 종료하고 나서, 다시 실행하면?

HttpSession session = request.getSession();
		if(session.isNew()) {
			System.out.println("===> 처음 생성된 세션이다.");
		}
		else {
			System.out.println("===> 재사용 세션이다.");
		}
  • session.getAttribute() : 문자열로 name을 넘겨주면 value가 튀어나옴
HttpSession session = request.getSession();
		if(session.getAttribute("userId") == null) {
			response.sendRedirect("login.html"); // 로그인부터 해!
		}
  • 지금은 session의 id를 저장하고 이동합니다.
if(user != null) {
	// 로그인 성공한 경우, 사용자가 입력한(상태정보) 아이디를 세션에 등록한다. 
	HttpSession session = request.getSession();
	session.setAttribute("userId", user.getId());

	// 글 목록 화면으로 이동한다. 
	response.sendRedirect("getBoardList.kt");
}

  • getAttribute로 꺼내고, setAttribute로 집어넣음

  • 브라우저를 종료하기 전까지 모든 서블릿에서 setAttribute로 설정한 부분을 가져다 쓸 수 있습니다.

session.setAttribute("userId", user.getId());
session.setAttribute("userName", user.getName());
  • getAttribute로 하면 Object 타입이라, 명시적 형변환을 해야 합니다!
//			session.setAttribute("userId", user.getId());
//			session.setAttribute("userName", user.getName());
//			session.setAttribute("userRole", user.getRole());
			
			session.setAttribute("user", user);
  • 세션에 여러 정보를 등록할 바에야, VO 객체 자체를 등록해서 관리하자
HttpSession session = request.getSession();
UserVO user = (UserVO) session.getAttribute("user");
if(user == null) {
response.sendRedirect("login.html"); // 로그인부터 해!
}
  • Key가 중복되면 덮어씀!

			session.setAttribute("user", user);
//			session.setAttribute("user", "몰라"); // 덮어씀
  • removeAttribute() : 등록된 키에 해당하는 value를 삭제

  • 만약, 30분 동안 세션을 메모리에 유지하다가, 아무런 변경이 없다면

    • 30분씩 갱신됨

    • 상세화면 볼라고 하면, 세션이 날아감

    • 이 시간을 정할 수 있음

session.setMaxInactiveInterval(10); 
// 60 * 60 * 3 ==> 3시간 연장 
// 10 => 10초 

로그아웃은?

  • 만약 로그인을 성공했어 => 이 브라우저와 매핑된 세션이 사라지게 하려면?

    • 30분 동안, 멍 때리거나 브라우저 꺼야하는건가???

      • 멍청한 방법입니다.
  • 로그아웃 버튼 눌러서, 이 브라우저와 매핑된 세션을 메모리에서 제거하라고 요청하면 됨

HttpSession session = request.getSession();
session.invalidate();

response.sendRedirect("/");

요청 재지정

  • sendRedirect
response.sendRedirect("second.kt");
  • requestDispatcher
RequestDispatcher dispatcher = request.getRequestDispatcher("second.kt");
dispatcher.forward(request, response);
  • redirect vs forward

정보 공유

  • session, servlet에 setAttribute, getAttribute가 모두 있습니다.

  • forward에서, 전송된 request에서 속한 attribute를 쓸 수 있음

  • redirect와 forward의 관련되는 객체의 차이!

  • sendRedirect는 공유할 데이터를 request에 저장하면 안 됨

  • request에 데이터를 담아서 공유하는 경우는! forward일 때

  • ServletContext > session > request 순으로 관리가 됨

    • 서버만 살아있어도 공유 데이터 > 브라우저 단위 공유 데이터 > 요청 별 공유 데이터

추가!

  • request는 수명이 제일 짧음

    • 요청이 유지되는 범위 : forward 관계에서만 request.setAttribute에 등록된 정보를 getAttribute로 꺼내쓸 수 있는 것

    • redirect의 경우, 새로운 request가 만들어지는 것

  • Session : redirect했다면, 공유할 데이터를 session에 저장해야 함

    • session은 브라우저가 살아만 있으면, redirect를 해도 session은 유지가 됩니다.

    • 하지만, 브라우저를 종료해버리면 session도 사라져버림

  • ServletContext : 브라우저가 종료되어도, 서버만 살아있으면 사용가능하고 싶어!

    • ServletContext는 서버만 살아있어도 계속 유효합니다.
profile
꾸준함이 제일 빠른 길이었다

0개의 댓글