edu day 39, 40
Update
2023/07/10 : Param, 스코프
2023/07/11 : Filter API, 요청 위임
: 모든 servlet에서 사용할 수 있는 파라미터 값이다.
Web.xml에서 사용할 값을 아래 형식과 같이 작성하면 servlet에서 사용할 수 있다.
<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>
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 userid
와 email
을 똑같이 사용할 수 있다.
: ContextParam
과 달리 지정된 서블릿 내에서만 쓸 수 있는 값이다. 형식은 다음과 같다.
<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>
-- 서블릿파일명, 경로 설정 -> 사용할 파라미터값 지정 -> 매핑
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
값이 된다.
서블릿에서는 필요시 임의의 데이터를 저장하고 나중에 저장된 데이터를 사용할 수 있는 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) 메서드 이용
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);
}
}
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
를 이용해 저장된 데이터를 사용할 수 있는지 확인한다.
앞으로 주로 session 위주로 사용할 것이다.
메서드명 | 설명 |
---|---|
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>
<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>
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로부터 받는 것이다.
위의 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의 전달은 이루어지지 않는다.
같은 코드에서 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의 값까지 사용할 수 있다는 것을 확인할 수 있다.