JSP피피티 05강 WebHelper, 페이지 강제이동
WebHelper
-공통 기능들을 구현해 놓은 모듈
- 모듈이란 본디 프로그램 구현에 사용되는 부품들을 이르는 용어.(레고블럭같은)
- 프로그래밍을 하는 과정에서 빈번하게 자주 등장하는 구현 코드를 간단하게 호출할 수 있도록 클래스로 구현해 놓은 형태.
- 모든 개발자들이 자신만의 모듈을 갖고 있다.
- 이점
-코드가 축약된다.
-개발자는 페이지를 구현하는데 필요한 데이터 처리 로직에만 집중하고 그 밖의 부가적인 처리들은 모듈이 맡아서 수행한다. - 웹에서 사용될 공통 기능들을 모듈화 해 놓은 싱글톤 클래스(ex> 페이지 강제이동, JSON데이터 처리등)
/src/study.jsp.model1.helper/WebHelper.java
package study.jsp.model1.helper;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class WebHelper {
/* 기본 인코딩 타입 설정 */
private String encType="UTF-8";
/* JSP의 request 내장 객체 */
//-> import javax.servlet.http.HttpServletRequest;
private HttpServletRequest request;
/* JSP의 reponse 내장 객체 */
//-> import javax.servlet.http.HttpServletResponse;
private HttpServletResponse response;
//--------------싱글톤 객체 생성 시작----------
private static WebHelper current;
//JSP의 내장 객체는 일반 JAVA클래스가 생성할 수 없기 때문에
//JSP 페이지로부터 request와 response 객체를 전달받아야 한다.
//--> import javax.servlet.httpServletRequest;
//--> import javax.servlet.httpServletResponse;
//getInstance() : 싱글턴패턴, 하나의 인스턴스만 가지고 공유해서 쓴다.
public static WebHelper getInstance(HttpServletRequest request, HttpServletResponse response) {
if(current == null) {
current = new WebHelper();
}
//JSP 내장객체를 연결하기 위한 메서드를 호출
current.init(request, response);
return current;
}
public static void freeInstance() {
current = null;
}
private WebHelper() {
super();
}
/**
* 싱글톤 객체가 생성될 때 호출되는 메서드로 JSP의 주요 내장객체를 멤버변수에 연결한다.
* @param request
* @param response
*/
public void init(HttpServletRequest request, HttpServletResponse response) {
this.request = request; //JSP내장 객체 참조하기
this.response = response; // JSP내장객체 참조하기
String methodName = request.getMethod(); //Get방식인지, Post방식인지 조회한다.
String url = request.getRequestURL().toString(); //현재 URL을 획득한다.
String queryString = request.getQueryString(); //URL에서 "?" 이후의 Get파라미터 문자열을 모두 가져온다.
if (queryString != null) {
url = url +"?" +queryString;
}
log.debug(String.format("[%s] %s",methodName, url)); //획득한 정보를 로그로 표시한다.
/* 내장객체 초기화 -> utf-8설정 */
//--> import java.io.UnsupportedEncodingException;
try {
this.request.setCharacterEncoding(this.encType);
this.response.setCharacterEncoding(this.encType);
}catch(UnsupportedEncodingException e) {
e.printStackTrace();
}
}
public void redirect(String url, String msg) {
//획득한 정보를 로그로 표시한다.
log.debug(String.format("-->[redirect] %s >> %s",url, msg));
//가상의 view로 만들기 위한 HTML 태그 구성
String html ="<!doctype html>";
html +="<html>";
html +="<head>";
html +="<meta charset='" + this.encType + "'>";
//메시지 표시
if(msg != null) {
html += "<script type='text/javascript'>alert('" +msg+"');</script>";
}
//페이지 이동
if(url != null) {
html +="<meta http-equiv='refresh' content='0; url=" +url+"'>";
}else {
html +="<script type='text/javascript'>history.back();</script>";
}
html +="</head>";
html +="<body></body>";
html +="</html>";
//구성된 HTML을 출력하낟.
try {
//브라우저에 결과값을 출력하기 위한 out객체를 생성한다. (예외처리 필요)
PrintWriter out = this.response.getWriter();
//준비된 html태그를 출력한다.
out.print(html);
}catch(IOException e) {
e.printStackTrace();
}
}
public String getencType() {
return encType;
}
public void setencType(String encType) {
this.encType = encType;
}
public HttpServletRequest getRequest() {
return request;
}
public void setRequest(HttpServletRequest request) {
this.request = request;
}
public HttpServletResponse getResponse() {
return response;
}
public void setResponse(HttpServletResponse response) {
this.response = response;
}
}
- 클래스를 추가하고 필요한 멤버변수를 정의 (WebHelper클래스)
-기본 인코딩 타입 설정
-JSP의 request 내장 객체
-JSP의 response 내장 객체 - 싱글톤 객체 구성
-대부분의 모듈들은 프로그램 전역에서 공통으로 사용되는 기능들의 모음이므로 매번 객체를 생성하기 보다는 하나의 객체를 재사용하는 것이 효율적 - JSP 내장객체를 주입받기 위한 메서드 추가 (init())
-자바 클래스에서는 JSP내장 객체를 생성할 수 없기 때문에 JSP 페이지로부터 내장 객체를 주입받기 위한 메서드를 준비해야 한다. - 현재 페이지의 실행 위치를 로그로 기록하기 위한 기능 추가 (init()메서드 안에)
-로그에 쌓이는 정보는 매우 방대하기 때문에 어떤 페이지에 사용자들이 접속했는지 쉽게 파악하기 어려움
-실행되는 페이지의 URL을 로그로 기록해 놓으면 향후 이 값을 분석하여 사용자들이 가장 많이 열람한 컨텐츠에 대한 데이터 분석이 가능하다.
*JSP 페이지의 내장 객체(더보기)
내장 객체 |
리턴 타입(Return Type) |
설명 |
request |
javax.servlet.http.HttpServletRequest |
웹 브라우저의 요청 정보를 저장하고 있는 객체 |
response |
javax.servlet.http.HttpServletResponse |
웹 브라우저의 요청에 대한 응답 정보를 저장하고 있는 객체 |
out |
javax.servlet.jsp.jsp.jspWriter |
JSP 페이지에 출력할 내용을 가지고 있는 출력 스트림 객체이다. |
session |
javax.servlet.http.HttpSession |
하나의 웹 브라우저의 정보를 유지하기 위한 세션 정보를 저장하고 있는 객체 |
application |
javax.servlet.ServletContext |
웹 어플리케이션 Context의 정보를 저장하고 있는 객체 |
pageContext |
javax.servlet.jsp.PageContext |
JSP 페이지에 대한 정보를 저장하고 있는 객체 |
page |
java.lang.Object |
JSP 페이지를 구현한 자바 클래스 객체 |
config |
javax.servlet.ServletConfig |
JSP 페이지에 대한 설정 정보를 저장하고 있는 객체 |
exception |
java.lang.Throwable |
JSP 페이지서 예외가 발생한 경우에 사용되는 객체 |
출처: https://hyeonstorage.tistory.com/78 [개발이 하고 싶어요]JSP 페이지의 내장 객체
webhelper.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page trimDirectiveWhitespaces="true" %>
<%@ page import="study.jsp.model1.helper.WebHelper" %>
<%
WebHelper webHelper = WebHelper.getInstance(request, response);
//위의 코드가 있으면 웹페이지 주소칸에 어떤 주소를 입력했고, 어떤 방식으로 접근했는지 알려준다.
//주소끝에 변수까지도.
%>
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello JSP</title>
</head>
<body>
<h1>webhelper.jsp</h1>
</body>
</html>
위와 같이 주소가 'webhelper.jsp'인 (WebHelper가 참조 되어있는)HTML 코드가 있을때 사용자(클라이언트)가 도메인에 webhelper.jsp라고 주소를 입력하면 바로 WebHelper.java가 실행된다.
WebHelper.java
package study.jsp.model1.helper;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class WebHelper {
/* 기본 인코딩 타입 설정 */
private String encType="UTF-8";
/* JSP의 request 내장 객체 */
//-> import javax.servlet.http.HttpServletRequest;
private HttpServletRequest request;
/* JSP의 reponse 내장 객체 */
//-> import javax.servlet.http.HttpServletResponse;
private HttpServletResponse response;
//--------------싱글톤 객체 생성 시작----------
private static WebHelper current;
//JSP의 내장 객체는 일반 JAVA클래스가 생성할 수 없기 때문에
//JSP 페이지로부터 request와 response 객체를 전달받아야 한다.
//--> import javax.servlet.httpServletRequest;
//--> import javax.servlet.httpServletResponse;
//getInstance() : 싱글턴패턴, 하나의 인스턴스만 가지고 공유해서 쓴다.
public static WebHelper getInstance(HttpServletRequest request, HttpServletResponse response) {
if(current == null) {
current = new WebHelper();
}
//JSP 내장객체를 연결하기 위한 메서드를 호출
//필요한 값들의 초기화 함수에 자주 사용
current.init(request, response);
return current;
}
public static void freeInstance() {
current = null;
}
private WebHelper() {
super();
}
//--------------싱글톤 객체 생성 끝----------
/**
* 싱글톤 객체가 생성될 때 호출되는 메서드로 JSP의 주요 내장객체를 멤버변수에 연결한다.
* @param request
* @param response
*/
public void init(HttpServletRequest request, HttpServletResponse response) {
this.request = request; //JSP내장 객체 참조하기
this.response = response; // JSP내장객체 참조하기
String methodName = request.getMethod(); //Get방식인지, Post방식인지 조회한다.
String url = request.getRequestURL().toString(); //현재 URL을 획득한다.
String queryString = request.getQueryString(); //URL에서 "?" 이후의 Get파라미터 문자열을 모두 가져온다.
if (queryString != null) {
url = url +"?" +queryString;
}
log.debug(String.format("[%s] %s",methodName, url)); //획득한 정보를 로그로 표시한다.
/* 내장객체 초기화 -> utf-8설정 */
//--> import java.io.UnsupportedEncodingException;
try {
this.request.setCharacterEncoding(this.encType);
this.response.setCharacterEncoding(this.encType);
}catch(UnsupportedEncodingException e) {
e.printStackTrace();
}
}
싱글톤 객체가 생성될때 init()함수가 실행되어 이클립스 콘솔에 아래와같이 로그가 남고 webhelper.jsp가 로드된다.
[2020-08-20 09:37:44.328][DEBUG] WebHelper.init(WebHelper.java:68) [GET] http://localhost:8080/Model1/01_strart/webhelper.jsp
-기본인코딩 타입 설정하고
-JSP의 내장객체 request와 response를 가지고 싱글톤객체 생성
-request(요청)객체로 사용자가 도메인에 입력한 주소와, 접속방식(Get or Post), URL에서 ?이후의 파라미터 문자열 까지 로그로 출력(확인)할 수 있다.
싱글톤패턴??(더보기클릭)
Single Ton 디자인 패턴
- 프로그램 내의 여러 곳에서 반복적으로 사용되어야 하는 객체에 대해 전역적인 범위를 갖도록 객체를 생성하고, 이 객체를 여러곳에서 공유하기 위한 클래스 작성 패턴.
- 이러한 패턴을 통해 생성된 객체를 싱글톤 객체라고 한다.
Single Ton 객체의 이점
- 프로그램의 전역에서 활용할 재료로 사용되는 공유 기능을 하나만 생성하여 여러곳에서 재사용함으로 해서 메모리를 효율적으로 사용할 수 있다.
- 단 한번만 객체를 생성하면 다시 객체를 생성할 필요가 없기 때문에 해당 기능을 사용할 때마다 객체를 일일이 생성해야 하는 번거로움을 피할수 있다.
[선생님 자바 ppt07 35p 참조]
여기서 싱글톤 부분은 WebHelper클래스 안에 있지만 독립된 객체이다.
getInstance()
new()와 getInstance()의 차이
new() : 객체를 계속계속 만들 수 있다.
getInstance() : 싱글턴패턴, 하나의 인스턴스만 가지고 공유해서 쓴다.
싱글턴패턴
: 생성자를 private로 선언하여 다른클래스에서 해당 클래스의 인스턴스를
new로 생성하지 못하게 하고, getInstance()함수를 통해서 인스턴스를 갖도록 한다.
싱글턴패턴쓴다고 하면 getInstace() 하는것 같다.
아 선생님꺼 싱글톤 예제를 보니 싱글톤객세를 사용하는 방법으로 getInstance()하네
ex) Clac loader1 = Calc.getInstance();
loader1.plus(100, 50);
Calc.getInstance().minus(100,50);
init()
필요한 값들을 초기화에 init()를 많이 사용합니다.
출처: https://selectwiggle.tistory.com/24 [위글위글]
페이지 강제이동
before.jsp ↓↓
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page trimDirectiveWhitespaces="true" %>
<%@ page import="study.jsp.model1.helper.WebHelper" %>
<%
WebHelper webHelper = WebHelper.getInstance(request, response);
%>
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello JSP</title>
</head>
<body>
<a href="after.jsp">after.jsp로 이동</a>
</body>
</html>
after.jsp↓↓
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page trimDirectiveWhitespaces="true" %>
<%@ page import="study.jsp.model1.helper.WebHelper" %>
<%
WebHelper webHelper = WebHelper.getInstance(request, response);
//메시지 없이 이전 페이지로 이동
//webHelper.redirect(null, null);
//메시지 표시이후 이전 페이지로 이동
webHelper.redirect(null, "이전 페이지로 돌아갑니다.");
//메시지 없이 webhelper.jsp 페이지로 이동
//webHelper.redirect("webhelper.jsp", null);
//메시지 표시 후 webhelper.jsp 페이지로 이동
//webHelper.redirect("webhelper.jsp", "Hello World");
%>
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello JSP</title>
</head>
<body>
</body>
</html>
- 정상적인 데이터 전송의 경우
-<meta>태그를 확용하여 페이지 이동을 구현해야 한다. - 파라미터가 정상적이지 않거나 유효성 검사를 통과하지 못한 경우 Javsscript를 활용하여 이전 페이지로 돌려보내야 한다. 이 경우 대부분 메시지 박스를 표시해야만 한다.
입력폼 (after.jsp) |
submit -----------------------> |
Action (WebHelper.java에서 redirect()) |
<meta> -----------------------> 페이지 강제 이동시 JSP의"response.sendRedirect()" 를 사용하면 JS와의 병행 사용이 불가능하므로 <meta>태그를 사용하는것이 좋다. |
결과확인 |
[js]history.back() 문제가 생겼을 경우 <---------------------- |
사용자가 before.jsp 페이지에서 'after.jsp로 이동'을 눌렀을때 webHelper 객체가 생성되고 redirect()함수가 실행된다.
전달되는 파라미터의 값에 따라 결과가 바뀐다.
(아래의 코드는 위의 WebHelper클래스와 이어지는 코드이다.)
public void redirect(String url, String msg) {
//획득한 정보를 로그로 표시한다.
log.debug(String.format("-->[redirect] %s >> %s",url, msg));
//가상의 view로 만들기 위한 HTML 태그 구성
String html ="<!doctype html>";
html +="<html>";
html +="<head>";
html +="<meta charset='" + this.encType + "'>";
//메시지 표시
if(msg != null) {
html += "<script type='text/javascript'>alert('" +msg+"');</script>";
}
//페이지 이동
if(url != null) {
html +="<meta http-equiv='refresh' content='0; url=" +url+"'>";
//↗대기시간 0초 후에 url로 이동하라
}else {
html +="<script type='text/javascript'>history.back();</script>";
}
html +="</head>";
html +="<body></body>";
html +="</html>";
//구성된 HTML을 출력하낟.
try {
//브라우저에 결과값을 출력하기 위한 out객체를 생성한다. (예외처리 필요)
PrintWriter out = this.response.getWriter();
//준비된 html태그를 출력한다.
out.print(html);
}catch(IOException e) {
e.printStackTrace();
}
}
public String getencType() {
return encType;
}
public void setencType(String encType) {
this.encType = encType;
}
public HttpServletRequest getRequest() {
return request;
}
public void setRequest(HttpServletRequest request) {
this.request = request;
}
public HttpServletResponse getResponse() {
return response;
}
public void setResponse(HttpServletResponse response) {
this.response = response;
}
}
redirect 함수는 이동할 페이지의 url과 화면에 표시할(alert로) 메세지를 파라미터로 가져간다.
redirect함수가 호출되어 실행되면
- 모든 메서드가 어떻게 동작하는지 확인할 로그를 남기기 위해 이클립스 콘솔에 log를 쓰고
- 가상의 view(html페이지)가 만들어지기 시작한다.
- 만약 redirect에 파라미터로 받은 url과 msg의 값에 따라 if문이 실행되고
-여기 'url' if문에서 meta 태그로 페이지가 이동되는데 meta 태그로 이동시키는 이유는
예를들어
*회원가입 하고 action에서 결과페이지로 이동할때 자바스크립트로 '완료되었습니다.' 메세지를 보낼수도 있지만 response.sendRedirect()를 써서 페이지를 이동하면 모든 알럿창이 죽는다 그래서 안씀
*결제페이지에서 window.location()을 쓰면 결제가 완료되었습니다. 알럿창 띄우고 결과 화면으로 가는데 window.location()은 페이지 이동내역이 history에 남는다 그래서 뒤로가기를 누를 경우 또 결제가 될 수도 있다.그래서 meta태그로 화면 이동 구현(자바스크립트와 병행 가능)
- ↑이런 이유에서 meta 태그로 페이지 이동해야 한다고 하셨는데 막 받아 적느라 정확한지 모르겠다. - response.getWriter() 해가지고 결과출력
(response[응답].[을]getWriter()[출력할겁니다] 라고 이해하기로 했다.)