Servlet / Param, 스코프(Scope), Filter, 요청 위임

Cheol·2023년 7월 10일
1

edu day 39, 40

Update

2023/07/10 : Param, 스코프
2023/07/11 : Filter API, 요청 위임

😁ContextParam의 사용

: 모든 servlet에서 사용할 수 있는 파라미터 값이다.
Web.xml에서 사용할 값을 아래 형식과 같이 작성하면 servlet에서 사용할 수 있다.

  • web.xml
	<context-param>
		<param-name>userid</param-name>
		<param-value>aaa</param-value>
	</context-param>
	<context-param>
		<param-name>email</param-name>
		<param-value>aaa@naver.com</param-value>
	</context-param>
  • Servlet.java
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    	System.out.println("ContextParamServlet.doget");
    	
    	//web.xml에 ContextParam 설정
    	//context 파라미터 얻기
    	ServletContext ctx = getServletContext();
    	String userid = ctx.getInitParameter("userid");
    	String email = ctx.getInitParameter("email");
    	System.out.println(userid+"\t"+email);
        //aaa	aaa@naver.com 출력
    }

--> Servlet2.java 파일에서도 Contextparam useridemail을 똑같이 사용할 수 있다.



🤔InitParam의 사용

: ContextParam과 달리 지정된 서블릿 내에서만 쓸 수 있는 값이다. 형식은 다음과 같다.

  • web.xml
  <servlet>
  	<servlet-name>InitParamServlet</servlet-name>
  	<servlet-class>com.controller.InitParamServlet</servlet-class>
  	<init-param>
  		<param-name>userid</param-name>
  		<param-value>aaa</param-value>
  	</init-param>
  	<init-param>
  		<param-name>email</param-name>
  		<param-value>aaa@naver.com</param-value>
  	</init-param>
  </servlet>	
  
  <servlet-mapping>
  	<servlet-name>InitParamServlet</servlet-name>
  	<url-pattern>/xxx</url-pattern>
  </servlet-mapping>

-- 서블릿파일명, 경로 설정 -> 사용할 파라미터값 지정 -> 매핑

  • Servlet.java
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//web.xml에서 context주소 설정함 - InitParam설정됨
		System.out.println("InitParamServlet.doGet");
		//초기 파라미터 얻기
		String userid = getInitParameter("userid");
		String email = getInitParameter("email");
		System.out.println(userid+"\t"+email);
		//초기 파라미터 얻기2
		Enumeration<String> enu = getInitParameterNames();
		while(enu.hasMoreElements()) {
			String key = enu.nextElement();
			String value = getInitParameter(key);
			System.out.println(">>>"+userid+"\t"+email);
		}
	}

--> 같은 내용의 servlet2.java 파일은 userid와 email의 파라미터값을 쓸 수 없으므로 null, null값이 된다.


❗❗스코프(scope)❗❗

서블릿에서는 필요시 임의의 데이터를 저장하고 나중에 저장된 데이터를 사용할 수 있는 3가지 특별한 저장소를 제공한다.

  • request 스코프
    • HttpServletRequest API
    • 요청 ~ 응답까지의 Life Cycle을 가짐
    • setAttrivute(key, value)와 getAttribute(key) 메서드 이용

  • session 스코프
    • HttpSession API
    • 브라우저의 Life Cycle을 가짐
    • setAttribute(key, value) 와 getAttribute(key) 메서드 이용

  • application 스코프
    • ServletContext API
    • 웹 어플리케이션에서의 context의 Life Cycle을 가진다.
    • setAttrivute(key, value)와 getAttribute(key) 메서드 이용

스코프 종류별 동작 비교

  • SetScopeServlet.java
package com.controller;

import java.io.IOException;

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

@WebServlet("/SetScopeServlet")
public class SetScopeServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//1. request객체에 데이터 저장
		request.setAttribute("request", "홍길동");
		String name = (String)request.getAttribute("request");
		System.out.println(name);
		
		//2.Session Scope에 저장
		HttpSession session = request.getSession();//세션 생성
		session.setAttribute("session", "이순신");
		System.out.println("setservlet session=="+ session.getAttribute("session"));
		
		//3.application scope에 저장
		ServletContext ctx = getServletContext();
		ctx.setAttribute("application", "유관순");
		System.out.println("setServlet application=="+ctx.getAttribute("application"));
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}

}
  • GetScopeServlet.java
package com.controller;

import java.io.IOException;

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

@WebServlet("/GetScopeServlet")
public class GetScopeServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//		1. requset
		String x = (String)request.getAttribute("request");
		System.out.println(x);
		
		//2. Session Scope에 저장
		HttpSession session = request.getSession();//세션 생성
		System.out.println("getservlet session=="+ session.getAttribute("session"));

		//3.application scope에 저장
		ServletContext ctx = getServletContext();//세션 생성
		System.out.println("GetScopeservlet application=="+ ctx.getAttribute("application"));
		
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}

}

--> SetScopeServlet.java 코드에서 스코프별로 값을 setAttribute를 이용해 저장시킨다. 그 후 GetScopeServlet.java 코드에서 getAttribute를 이용해 저장된 데이터를 사용할 수 있는지 확인한다.

  • 결과 : request는 값을 사용할 수 없고, session과 application만 값을 사용할 수 있었다.

앞으로 주로 session 위주로 사용할 것이다.


🔎HttpSession API에서 제공하는 메서드

메서드명설명
request.getSession()session 영역을 얻을 때 사용하며 session 영역이 없으면 새로 생성하고, 있으면 생성된 영역을 참조한다.
request.getSession(true) 메서드와 동일한 기능이다.
일반적으로 세션을 처음 생성하는 서블릿에서 지정한다.
session.getid()생성된 세션 ID값을 반환한다.
session.setAttribute(key,value)session 영역에 속성(Attribute)값을 설정한다.
session scope를 따르기 때문에 브라우저를 종료하기 전에 사용 가능하다. 단, 기본으로 30분 이상 요청이 없을 시 제거된다.
session.getAttribute(key)session 영역에 저장된 속성 값을 반환한다.
session.removeAttribute(key)session 영역에 저장된 속성을 제거한다.
setMaxInactiveinterval(sec)지정된 시간만큼 세션을 유지시킨다. 단위는 초(sec).
session.invalidate()즉시 session 영역을 제거한다. 로그아웃 기능 시 사용된다.


Filter API

클라이언트에서 서블릿으로 요청하고 응답을 처리할 때, 서블릿이 요청받기 전과 응답처리 전에 임의의 특정 작업을 수행할 수 있도록 Filter API를 사용할 수 있다.
즉, 서블릿이 실행되기 전의 선처리작업과 응답 전의 후처리 작업이 가능하다.

간단하게 다음 그림과 같다.

예제

  • web.xml
	<filter>
        <filter-name>MyEncodingFilter</filter-name>
        <filter-class>com.filter.MyEncodingFiter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>MyEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern><!--  모든 주소에 대해 처리함 -->
    </filter-mapping>
  • MyEncodingFilter.java
    javax.sevlet.Filter를 implements해주고 오버라이딩한다.
package com.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class MyEncodingFilter implements Filter{

	@Override
	public void destroy() {
		System.out.println("MyEncodinFilter.destory");
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		System.out.println("MyEncodingFilter.doFilter요청");
		//request 인코딩설정
		request.setCharacterEncoding("utf-8");
		chain.doFilter(request, response);
		
		System.out.println("MyEncodingFilter.doFilter응답");
	}

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {

		System.out.println("MyEncodingFilter.doFilter init");
	}
	
}

--> 이제 Servlet 파일에서 request.setCharacterEncoding("utf-8") << 한글처리 안해도 필터링을 거쳐 한글이 깨지지 않고 정상적으로 출력되는 것을 확인할 수 있다.



요청 위임

사용자의 요청을 받은 서블릿 또는 JSP에서 다른 컴포넌트(서블릿/JSP)로 요청을 위임할 수 있는 방법이다.
종류는 2가지이다.

리다이렉트 ( redirect )
response.sendRedirect(target);

리다이렉트는 클라이언트의 요청에 대해 응답 헤더 Location값에 특정 URL을 할당하여 HTTP상태코드 302로 응답한다.
이때 클라이언트(Web browser)는 서버의 리다이렉션 응답을 받게되면 응답 메시지 헤더 내 Location에 포함된 해당 URL로 재요청을 보내게 된다.

즉, 위의 그림과 같이 서버에 두 번의 요청을 보내는 것이며, 처음 요청을 보낸 URL이 아닌 새로운 URL로 바뀌게 된다.

❗다만 새로운 URL로 재요청하기 때문에 request의 전달은 이루어지지 않는다.

포워드 ( forward )

포워드는 서버가 클라이언트의 요청을 받으면 이를 다른 서버에게 전달하는 것이다.
위의 그림처럼 클라이언트가 서블릿에 요청을 보냈지만 응답은 JSP로부터 받는 것이다.


🤔redirect 실습

위의 3가지 스코프와 같은 코드에서 response.sendRedirect("TestController2")를 추가하였다.

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("TestController.doGet");
		request.setAttribute("request", "홍길동");
		HttpSession session = request.getSession();
		session.setAttribute("session", "이순신");
		ServletContext ctx = getServletContext();
		ctx.setAttribute("application", "유관순");
		
		//1. redirect방법
		//response.sendRedirect("hello.jsp");	//request의 전달은 이루어 지지 않음
		response.sendRedirect("TestController2");	//request의 전달은 이루어 지지 않음
	}

바로 TestController2 서블릿으로 요청을 위임하여 실행한다.
request의 전달은 이루어지지 않는다.


😁forward 실습

같은 코드에서 request방식을 forward로 바꿔주었다.
코드는 아래와 같다.

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("TestController.doGet");
		request.setAttribute("request", "홍길동");
		HttpSession session = request.getSession();
		session.setAttribute("session", "이순신");
		ServletContext ctx = getServletContext();
		ctx.setAttribute("application", "유관순");
		
		//2. forward 방법
		RequestDispatcher dis = request.getRequestDispatcher("TestController2");
		dis.forward(request, response);
	}

아래 결과를 보면 testcontroller 2 에 요청을 위임함과 동시에 request의 값까지 사용할 수 있다는 것을 확인할 수 있다.

0개의 댓글