본문 바로가기

JAVA SPRING

서블릿 확장 API, 쿠키와 세션, 필터와 리스너

 

1. 포워드 

 

포워드 : 하나의 서블릿에서 다른 서블릿이너 JSP와 연동하는 방법. 

- 요청에 대한 추가 작업을 다른 서블릿에게 수행하게 한다.

- 요청에 포함된 정보를 다른 서블릿이나 JSP와 공유한다.

- 요청에 정보를 포함시켜 다른 서블릿에 전달한다.

- 모델2 개발 시 서블릿에서 JSP로 데이터를 전달하는 데 사용된다.

 

- redirect 방법 : HttpServletResponse 객체의 sendRedirect()메서드를 사용한다. 웹브라우저에 재요청 하는 방식이며, sendRedirect("포워드할 서블릿 또는 JSP") 로 사용한다.

- Refresh 방법 : HttpServletResponse 객체의 addHeader() 메서드를 사용한다. response.addHeader("Refresh", 경과시간(초); url=요청할 서블릿 또는 JSP) 로 사용한다.

- location 방법 : 자바스크립트 location 객체의 href 속성을 이용한다. location.href='요청할 서블릿 또는 JSP'

- dispatch 방법 : 일반적인 포워드 기능을 지칭하며, 서블릿이 직접 요청하는 방법이다. RequestDispatcher클래스의 forward()메서드를 이용한다. 

 

 

■ redirect 실습

 

- 클라이언트의 웹브라우저에서 첫 번째 서블릿에 요청한다.

- 첫 번째 서블릿은 sendRedirect()메서드를 이용해 두 번째 서블릿을 웹브라우저를 통해 요청한다.

- 웹 브라우저는 sendRedirect()메서드가 지정한 두 번쨰 서블릿을 다시 요청한다.

 

1. response.sendRedirectt("second"); 를 통해 두 번째 서블릿을 웹브라우저를 통해 요청한다. 

 

2. SecondServlet 에서 out.println을 통해 두 번째 서블릿이 호출되었음을 알리는 웹페이지를 작성한다. 

3. /first로 웹브라우저에서 요청하면, 바로 /second 서블릿으로 연결되며 페이지가 나타난다. 즉, /first로 요청하면 sendRedirect()를 호출해 웹 브라우저에게 다시 /second를 요청하는 것이다.

 

■ refresh 실습

 

- 클라이언트의 웹 브라우저에서 첫 번째 서블릿에 요청한다.

- 첫 번째 서블릿은 addHeader() 메서드를 이용해 두 번째 서블릿을 웹브라우저를 통해 요청한다.

- 웹 브라우저는 addHeader(0 메서드가 지정한 두 번째 서블릿을 다시 요청한다.

 

 

1. addHeader("Refresh", "1(경과시간(초));url=second(url=서블릿 이름)"); 으로 1초 후 second 서블릿에 브라우저에서 재요청하게 한다.

 

2. 메시지를 출력하는 두 번째 서블릿을 작성한다. 

 

3. /first로 요청하면 동일한 결과가 나타난다.

 

 

■ location 실습

 

 

1. 서블릿에서 PrintWriter로 자바스크립트 코드를 출력해 서블릿 second로 재요청한다. location.href="서블릿이름" 을 사용하였다. 

 

2. 결과를 출력하는 두 번째 서블릿을 작성한다. 

 

3. 결과 

 

 

 

■ redirect 방식으로 다른 서블릿에 데이터 전달하기

 

 

1. respons.sendRedirect() 으로 데이터를 다른 서블릿에 전달한다. 이름/값 쌍으로 작성한다.

 

2. getParameter("name") 으로 전달된 name의 lee라는 값을 받아와 저장해 출력한다.

3. /first로 웹브라우저에서 요청해본다.

 

 

 

■ dispatch를 이용한 포워드

 

- 서버에서 포워딩이 진행되므로 웹 브라우저 주소창의 url이 변경되지 않는다. 즉, 클라이언트 측에서는 포워드의 진행을 알 수 없다.

- 클라이언트의 웹브라우저에서 첫 번째 서블릿에 요청한다.

- 첫 번째 서블릿은 RequestDispatcher을 이용해 두 번째 서블릿으로 포워드한다.

 

1. RequestDispatcher 클래스를 이용해 두 번째 서블릿인 second를 지정한 후,

RequestDispatcher 객체.forward(request, response) 메서드를 이용하여 포워드한다. 이때, ("포워드서블릿?name=값") 을 통해 데이터도 함께 전송해본다. getRequestDispatcher 이므로 get방식의 전송이 적용되었다. 

 

2. 결과를 도출할 두 번째 서블릿을 작성한다. 이때, getParameter를 통해 name에 전달된 값을 출력한다. 

 

3. 결과. get 방식으로 데이터를 전달하였으나 url이 변경되지 않았다. 

 

 

 

2. 바인딩

 

바인딩 : 웹 프로그램 실행 시 자원을 서블릿 관련 객체에 저장하는 방법. 저장된 자원은 프로글매 실행 시 서블릿이나 JSP에서 공유하여 사용한다. 실제 모델2, 스트럿츠, 스프링 프레임워크로 구현하는 웹 프로그램은 이 바인딩 기능을 이용해 서블릿이나 JSP간 데이터를 전달하고 공유한다. 

 

 

■ HttpServletRequest를 이용한 redirect 포워딩 시 바인딩 실습

- 브라우저에서 전달받은 request를 서블릿에서 redirect 방식으로 다른 서블릿에 전달한다. 

 

1. setArrtibut("키", "값") 쌍으로 데이터를 바인딩하고, sendRedirect("서블릿명") 으로 두 번째 서블릿을 호출한다.

2. getAttribute를 통해 값을 가져와본다. 

3. null이 출력된다.

 

redirect 방식으로는 서블릿에서 바인딩한 데이터를 다른 서블릿으로 전송할 수 없다는 것을 알 수 있다.

 

 

 

■ dispatch를 이용한 포워딩 시 바인딩

 

1. address에 서울시 성북구를 setAttribute 하고, RequestDispatcher 객체 dispatch를 생성해, second 서블릿을 호출한다. 

 

2. request.getAttribute를 통해 address에 바인딩된 값을 가져온다. 

 

3. dispatch 방식은 성공적으로 데이터를 바인딩 할 수 있다. 첫 번째 서블릿에서 두 번째 서블릿으로 전달되는 request가 redirect 방식과는 다르게 브라우저를 거치치 않고 바로 전달되었기 때문에, 첫 번째 서블릿의 request에 바인딩된 데이터가 그대로 전달된 것이다. 

 

 

■ dispatch를 이용한 포워딩, 바인딩, 조회 실습

 

 

1. memberservlet을 작성한다. DAO 객체를 생성하여 list에 조회된 회원 정보를 저장하고, 바인딩한 request를 viewMembers 서블릿으로 포워딩한다. 

2. 바인딩해서 넘어온 request에서 회원 정보를 가져온다.

 

3. 얼라리

 

- 왜이렇게 된걸까..? 했더니 SQL을 꺼놔서 그런거였다. 재실행시킨다. 그리고 저번에 했던대로 Context.xml 에 DataSource 기능도 설정한다. 

 

아주 자연스럽게 sql developer 오류를 또 만난다. 업체 코드 17002. 

 

당연히 이녀석들 문제다. 서비스에서 아래 세 항목을 실행시켜주면 된다.

 

접속 성공! 

 

4. /member로 요청하니 무사히 조회된다. 

 

 

 

■ ServletContext와 ServletConfig 사용법

 

- ServletContext 클래스는 톰캣 실행 시 컨텍스트마다 한 개의 servletContext객체를 생성한다. 그리고 톰캣이 종료하면 객체 역시 소멸된다. 이 객체는 웹이 실행되면서 애플리케이션 전체의 공통 자원이나 정보를 미리 바인딩하여 서블릿들이 공유해서 사용한다. 서블릿 파일 접근 기능, 자원 바인딩 기능, 로그 파일 기능, 컨텍스트에서 제공하는 설정 정보 제공 기능 등을 제공한다. 

 

1. getServletContext()를 이용해 ServletContext 객체를 가져오고, setAttribute로 데이터를 바인딩한다. 

 

2. getAttrubute를 이용해 바인딩된 회원 정보를 가져온다. 

 

3. 결과

 

 

ServletContext에 바인딩된 데이터는 모든 서블릿들이 접근할 수 있으므로, 공통으로 사용하는 데이터를 바인딩해 놓고 사용하면 편리하다. 

 

 

■ ServletContext의 매개변수 설정 기능

 

1. web.xml에 메뉴 항목을 작성한다. 

2. ContextParamServlet를 작성한다. 출력 스트림을 받아서, SevletContext 객체를 가져온 뒤 web.xml의 <param-name>태그의 이름으로 value 태그의 값인 메뉴 이름들을 받아온다. 

3. 출력

 

4. ServletContext의 파일 입출력 기능을 실습해본다. bin 폴더를 만들어 init.txt를 만든 뒤 메뉴 항목을 입력한 후 저장한다.

 

5. getServletContext()메서드로 ServletContext에 접근하여 getResourceAsStream()메서드에서 읽어 들일 파일 위치를 지정한 후, 파일에서 데이터를 입력받는다. 이때 콤마(,) 를 구분자로 메뉴 항목을 분리한다. 

 

 

6. init.text에 있는 내용들이 무사히 읽혀 출력되었다. 

 

 

■ ServletConfig 실습

 

- 이는 각 Servlet 객체에 대해 생성된다. 이 인터페이스는 GenericServlet 클래스가 실제로 수현하고 있다. 객체를 얻는 기능과 서블릿에 대한 초기화 작업 기능을 제공하고, 각 서블릿에서만 접근할 수 있으며 공유는 불가능하다. 

- 서블릿에서 초기화하는 방법으로는 @WebServlet 애너테이션을 이용하는 방법과 web.xml 에 설정하는 방법이 있다.

 

 

@WebServlet의 구성 요소

- urlPatterns : 서블릿 요청 시 사용하는 매핑 이름

- name : 서블릿 이름

- loadOnStartUp : 컨테이너 실행 시 서블릿이 로드되는 순서 지정

- initParams : @WebInitParam애너테이션을 이용해 매개변수를 추가하는 기능

- description : 서블릿에 대해 설명

 

 

아래와 같이 서블릿을 작성해서 매개변수를 설정하고, 이 매개변수를 출력하도록 한다. 

 urlPatterns에 작성한 두 가지의 매핑 이름으로 요청해본다.

 

 

■ load-on-startup 기능 

 

- 톰캣이 실행되면서 미리 서블릿을 실행한다.

- 지정 숫자가 0보다 크면 톰캣이 실행되며 서블릿이 초기화된다.

- 지정 숫자는 우선순위를 의미하며 작은 숫자부터 먼저 초기화된다. 

 

 

1. @WebServlet(name = "서블릿 이름", urlPatterns = { "/웹에서 요청 시 사용하는 서블릿 매핑 이름" }, loadOnStartup = 우선순위) 를 사용해 클래스를 작성한다. 

 

2. init 메서드를 호출하면 getInitParameter()메서드를 이용해 web.xml의 메뉴 정보를 읽어들이 후, 다시 ServletContext 객체에 setAttribute() 메서드로 바인딩한다. 브라우저에서 요청하면 SerlvetContext 객체에서 메뉴 항목을 가져온 후 출력하므로 파일에서 읽어와 출력하는 것보다 빨리 출력할 수 있다. 


 

3. 쿠키와 세션 

 

HTTP 프로토콜은 서버-클라이언트 통신 시 STATELESS 방식으로 통신을 한다. 따라서 웹 페이지나 서블릿끼리 상태나 정보를 공유하려면 웹페이지 연결 기능, 세션 트래킹을 이용해야 한다.

웹페이지 연동법 : <hidden> 태그, URL Rewriting, 쿠키, 세션

 

 

■ 쿠키(Cookie) : 웹 페이지 사이의 공유 정보를 클라이언트 PC 에 저장해 놓는 방법. 

- 정보가 클라이언트 PC에 저장된다.

- 저장 정보 용량에 제한이 있다.

- 보안이 취약하다. 클라이언트 브라우저에서 사용 유무를 설정할 수 있다.

- 도메인 당 쿠키가 만들어진다.

 

- javax.servlet.http.Cookie를 이용한다. HttpServletResponse의 addCookit()메서드를 이용해 브라우저에 쿠키를 전송한 후 저장하고, Request의 getCookie()메서드를 이용해 쿠키를 서버로 가져온다.

 

- Persistence 쿠키 : 파일로 생성, 쿠키를 삭제하거나 쿠키 설정 값이 종료된 경우 종료되며 로그인 유무 또는 팝업창 제한 시 사용. setMaxAge() 인자 값으로 양수 지정. 

- Session 쿠키 : 브라우저 메모리에 생성. 브라우저 종료 시 종료되며, 사이트 접속 시 Session 인증 정보를 유지할 때. setMaxAge() 인자 값으로 음수를 지정하거나 메서드 사용하지 않고 쿠키 만들 시 적용.

 

 

1. Cookie c= new Cookie("쿠키이름",  URLEncoder.encode("쿠키 내용", "인코딩 언어") 를 통해 쿠키를 생성하고, setMaxAge 메서드에 유효 기간을 설정한다. response.addCookie(c) 를 통해 생성된 쿠키를 브라우저로 전송한다.

2. request.getCookies()를 통해 쿠키 정보를 배열로 가져와 출력한다. 

 

3. 결과

 

 

 

■ 세션(Session) : 서버의 메모리에 생성되어 정보를 저장하는 방법. 사용자당 한 개가 생성된다. 서버에 부하를 줄 수 있고, 유효시간을 가진다. 

 

- 브라우저로 사이트에 접속한다.

- 서버는 접속한 브라우저에 대한 세션 객체를 생성한다.

- 서버는 생성된 세션 id를 클라이언트 브라우저에 응답한다.

- 브라우저는 서버로부터 받은 세션 id를 브러우저가 사용하는 메모리의 세션 쿠키에 저장한다(jsessionId)

- 브라우저가 재접속하면 브라우저는 Session 쿠키에 저장된 세션 id를 서버에 전달한다.

- 서버는 전송된 세션 id를 이용해 해당 세션에 접근해 작업을 수행한다. 

 

 

1. getSession으로 최초 요청 시 세션 객체를 새로 생성하거나, 기존 세션을 반환한다.

 

2. 최초 요청 시 '새 세션이 만들어졌습니다.' 를 적고, 다시 요청하면 이미 존재하는 세션을 불러오므로 새 세션이 만들어졌습니다 라는 문장이 출력되지 않는다. 

 

session.setMaxInactiveInterval()를 통해 세션의 유효시간을 설정할 수 있다. 유효시간이 지난 뒤 다시 세션을 요청하면 기존 세션은 삭제되고 새 세션이 생성된다. 

 

■ 세션을 이용한 로그인 정보 바인딩 실습 

 

 

1. 톰캣이 종료된 후에도 세션이 메모리에서 삭제되지 않는 경우가 있으므로 context.xml을 확인한다.

 

2. login2.html을 작성해 서블릿으로 id와 pw를 전송한다.

 

3. session을 생성하여 새로 생성된 세션일 경우 id를 바인딩하고, 세션이 이미 존재할 경우 get으로 바인딩된 id를 불러와 환영인사를 띄운다. 

4. 결과

 

■ encodeURL() : 브라우저에서 쿠키 기능을 사용할 수 없게 설정했을 경우, 직접 서버에서 브라우저로 응답을 먼저 보내어 URL Rewriting 방법을 이용해 jsessionId를 서버로 전송하여 세션 기능을 사용하는 방법.

 

 

 

결과는 상위와 동일하다. 

 

 

세션 로그인 예제

 

 

1. 로그인 창 작성 

 

2. 서블릿 작성. user_id와 user_pwd를 받아와서 저장한 다음, VO 객체에 set 한 뒤, 다시 이 vo객체를 DAO 객체를 생성해 전달한다. DAO 클래스에서는 오라클의 decode() 함수를 이용해서 아이디와 비밀번호를 존재한다. 테이블에 존재한다면 true를, 존재하지 않으면 false를 조회한다. 

 

3. 로그인 상태를 확인하기 위해 getSession 메소드를 호출하여 세션을 얻은 다음, isLogOn을 인자로 전달해 로그인 상태를 가져온다. 만약 true라면 회원 정보를, 존재하지 않거나 false라면 다시 로그인창으로 이동한다. 

 

4. 결과. 테이블에 존재하지 않는 아이디와 패스워드인 test를 입력하면 다시 로그인하기가 뜨고, 테이블에 존재하는 아이디와 pwd를 입력하면 정상적인 결과가 출력된다. 


 

서블릿 스코프 : 서블릿 API에 바인딩된 속성에 대한 접근 범위.

스코프의 기능 : 로그인 상태 유지 기능, 장바구니 기능 ,MVC Model과 View의 데이터 전달 기능.

 

-ServletContext : 애플리케이션 스코프

-HttpSession : 세션 스코프

-HttpServletRequest : 리퀘스트 스코프

 

- 서블릿의 url 패턴 : 서블릿의 매핑 이름. 

ㄴ 정확히 이름까지 일치하는 URL 패턴

ㄴ 디렉터리 이름까지 일치하는 패턴

ㄴ 확장자만 일치하는 패턴

ㄴ /* : 모든 요청 URL 패턴

 

 

필터 : 브라우저에서 서블릿에 요청하거나 응답할 때 미리 요청이나 응답과 관련해 여러가지 작업을 처리하는 기능.

ㄴ 서블릿의 공통 작업을 미리 필터에서 처리한다. 

ㄴ요청 필터 : 사용자 인증, 권한 검사 / 요청 시 요청 관련 로그 작업 / 인코딩 기능

ㄴ응답 필터 : 응답 결과에 대한 암호화 작업 / 서비스 시간 측정

 

1. login.html 작성 

 

 

 

2. 한글 인코딩 부분을 주석처리하여 깨지게 한다.  

 

3. 이름에 한글을 입력하면, 인코딩이 되지 않아 깨진 결과가 출력된다. 

 

4. 필터를 만든다. 

패턴을 /*로 설정하면, 모든 요청이 필터를 거치게 할 수 있다. 

 

doFilter 안에서 실제 필터 기능을 구현한다.  한글 인코딩 설정 작업을 하고, 콘솔 로그에서 확인해보기 위해 요청한 url과 실제 경로, 컨텍스트 이름을 가져와 출력해본다. long begin = System.currentTimeMillis(); 아래부터는 응답 필터 기능으로, 작업 시간을 구하는 코드이다. 

 

 

4. 결과 

 

 

■ Listener API

 

 

HttpSessionBindingListener - 접속자 수 표시

 

 

1. LoginImpl 작성. 리스너 인터페이스를 사용해 구현하고, 사용자 접속이 확인되면 접속자 수를 증가시킨다.

 

2. Impl클래스 객체를 생성하여 id와 pw값을 넘겨준다. 그리고 세션이 새로 생성되면 loginUser를 보내 접속자 수가 증가되도록 한다. 

 

3. 결과. 이클립스 내에서 chali로 접속하면 접속자 수가 1이 되고, 

 

그상태에서 크롬을 켜 새로운 접속을 늘리면 접속자 수가 2가 된다. 

 

 

 

'JAVA SPRING' 카테고리의 다른 글

JSTL  (0) 2021.07.27
JSP 스크립트, 액션 태그  (0) 2021.07.27
서블릿 - get, post, @WebServlet, 비즈니스 로직 처리(DAO, VO, 커넥션풀)  (0) 2021.07.23
HTTP method, MY Batis 실습  (0) 2021.07.19
웹 프로그래밍 - 2일차  (0) 2021.07.09