본문 바로가기

수업 정리

49일차 수업정리(Request, Response 객체, web.xml)

**request 객체

    => 클라이언트의 요청정보가 저장된 객체

    => 자료형 : HttpServletRequest

    => jsp 페이지 : 이미 만들어져 있어 바로 사용가능

         Servlet : 요청처리 메소드의 매개변수로 만들어져 있음

 

1. 클라이언트 관련 메소드

  1) getRemoteAddr() : 접속한 클라이언트의 IP주소를 문자열로 리턴해주는 메소드

    => 자기 컴퓨터로 접속시 127.0.0.1이나 0:0:0:0:0:0:0:1 로 리턴

        - Windows7이하에서는 127.0.0.1, 그 외 운영체제에서는 0:0:0:0:0:0:0:1

  2) getContextPath() : 서버 도메인이 문자열로 리턴

  3) getRequestURI() : 클라이언트의 전체 요청 경로가 문자열로 리턴

  4) getQueryString() : 파라미터를 가져오는 부분

ex) https://ggangpae1.tistory.com/275?category=840478

    => ContextPath : https://ggangpae1.tistory.com

    => RequestURI : https://ggangpae1.tistory.com/275

    => 서버에서 클라이언트 요청 처리를 위해서는 RequestURI를 알아야 함

        - RequestURI로 직접 작업은 주소가 길어 실제 구현시 RequestURI에서 ContextPath를 제외한 부분만 가지고 처리

        - 프레임워크에서는 이 부분이 이미 구현되어 있음

    => Parameter : category=840478

  5) getMethod() : 전송방식을 문자열로 리턴

  6) getContentLength() : 클라이언트가 전송한 데이터의 크기를 long으로 리턴

    - 클라이언트의 업로드 제한을 가함

 

2. Parameter 처리

  1) parameter : Web Client에서 서버에게 넘겨주는 데이터

  2) 전송방식

    => GET : url의 맨 마지막에 ?를 추가하고 이름=값의 형태로 붙여서 전송하는 방식

        - 2개 이상일 때는 &로 구분

        - QueryString이라고도 함

        - POST로 별도 지정이 없으면 GET방식으로 전송

        - 장점 : 바로 해석할 수 있어 속도는 POST보다 빠르고 자동 재전송 기능이 있음

        - 단점 : URL뒤에 파라미터를 붙여서 전송하므로 파라미터의 보안이 안되고 길이에 제한이 있음

    => POST : header에 파라미터를 숨겨서 전송하는 방식

        - 장점 : 파라미터 길이에 제한이 없고 URL에 붙이지 않으므로 파라미터 보안이 가능

        - 단점 : 자동 재전송기능이 없음

        - form에서 method를 post로 지정하거나 ajax로 요청을 할 때, method를 post로 지정해야 사용가능

    => 조회시는 GET방식을 이용하지만 그 이외의 경우는 POST방식

        - 삽입, 삭제, 갱신은 POST방식으로 하는 것을 권장

        - form에 password, textarea, file이 있을 때는 POST방식으로 처리

        - 최근에는 Create - POST, Read - GET, Update - PUT, Delete - DELETE 방식으로 처리 권장

          (PUT과 DELETE 방식이 적용되지 않는 브라우저가 있음)

  3) request에서 파라미터 읽기

    - String getParameter(String name) : name에 해당하는 파라미터값을 문장열로 리턴(name X = null리턴)

    - String[] getParameterValues(String name): name에 해당하는 파라미터값을 문자열배열로 리턴(name X = null리턴)

    - Enumeration getParameterNames() : 파라미터 이름 전체를 Enumeration(Iterator 이전버전)으로 리턴

    - Map getParameterMap() : 파라미터 이름과 값 전체를 Map으로 묶어서 리턴

    => 대다수 파라미터는 getParameter로, checknox, select처럼 다중선택가능 항목은 getParameterValues로 읽어야 함

    => 파라미터는 입력 형식에 상관없이 항상 문자열

  4) 파라미터 만들기

    => form 안의 요소는 name속성을 설정

    => ajax에서는 별도의 객체로 생성 - FormData나 {이름:값, 이름:값...}

    => 링크를 이용할 때는 URL뒤에 ?를 추가하고 이름=값의 형태로 추가

    => 파라미터를 만들 때는 반드시 인코딩을 해야 함

  5) 파라미터 처리하기 실습

    => inputparameter

<!-- inputparameter.html -->

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>파라미터 입력</title>
</head>
<body>
	<a href="process1.jsp?boardnum=120&nickname=SGSG">파라미터 직접 작성</a>
	<br/>
	<!-- action이 처리할 서버의 URL Method가 전송방식을 생략하면 GET 
	file이 있는 경우 enctype을 multipart/form-data로 설정
	클라이언트에서 유효성검사를 하고자하는 경우 id를 부여-->
	<form action="process2.jsp">
		이름<input type="text" name="name"/><br/>
		
		성별<input type="radio" name="gender" value="man" checked="checked"/>남자
		<input type="radio" name="gender" value="woman"/>여자<br/>
		
		취미<input type="checkbox" name="hobby" value="reading"/>독서
		<input type="checkbox" name="hobby" value="computer"/>컴퓨터
		<input type="checkbox" name="hobby" value="game"/>게임<br/>
		
		<input type="submit" value="전송"/>
	</form>
</body>
</html>
<!-- process1.jsp -->

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>파라미터 읽기</title>
</head>
<body>
<%
	//boardnum 파라미터 읽기
	String boardnum = request.getParameter("boardnum");
	//nickname 파라미터 읽기
	String nickname = request.getParameter("nickname");
	//없는 파라미터 읽기
	String readcnt = request.getParameter("readcnt");
%>
<p>boardnum : <%=boardnum %></p>
<p>nickname : <%=nickname %></p>
<p>readcnt : <%=readcnt %></p>
</body>
</html>
<!-- process2.jsp -->

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>폼의 파라미터 읽기</title>
</head>
<body>
<%
	//name, gender, hobby의 값 읽어보기
	String name = request.getParameter("name");
	String gender = request.getParameter("gender");
	//hobby는 여러개를 선택할 수 있으므로 배열로 읽어야 함
	String[] hobby = request.getParameterValues("hobby");
	
	String resultHobby = "";
	if(hobby == null)
		resultHobby = "선택하지 않음";
	else{
		for(int i=0; i<hobby.length; i+=1)
			resultHobby += hobby[i] + " ";
	}
	
%>

<p>name : <%=name %></p>
<p>gender : <%=gender %></p>
<p>hobby : <%=resultHobby %></p>
</body>
</html>

    => 404에러가 나면 링크나 action에 설정된 파일이 존재하는 지 확인

    => 값이 안보이는 경우는 입력은 안한 것

    => null이 나오면 getParameter에 삽입한 name이 잘못된 경우이거나 체크박스, 라디오버튼에서 선택하지 않은 것

 

6) inputparameter.html 파일의 form에 method="POST"를 추가한 후 다시 전송하고 URL확인

 

7) parameter 한글 처리

    => inputparameter.html 파일의 form의 method를 get과 post로 변경하고, 이름 입력란에 한글 입력후 전송

    => get인 경우는 한글이 제대로 출력, post인 경우 한글이 깨짐(인코딩문제)

    => get방식은 WAS가 인코딩을 처리, post방식은 코드가 인코딩을 처리

        - get방식 : server.xml 파일에 인코딩 처리하는 설정을 추가(tomcat8.0부터는 기본인코딩이 utf-8)

        - post방식 : 파라미터를 읽기전에 request 객체를 가지고 setCharacterEncodeing("인코딩방식")을 호출하여 처리

    => process2.jsp 파일의 자바코드 상단에 아래코드 추가

//파라미터 인코딩 설정
request.setCharacterEncoding("utf-8");

 

3. Header 처리

    => header는 파라미터와 함께 전송되는 클라이언트의 데이터의 일종인데, URL 창에 보이지 않고 전송

    => 헤더에 데이터를 저장해서 전송하는 이유는 URL에 보일 필요가 없는 데이터를 전송, 데이터 크기 문제 때문

    => 헤더를 읽는 메소드는 문자열 뿐 아니라 숫자로 읽어주는 메소드도 존재

    => 헤더를 이용하여 날짜를 저장하는 일이 많기 때문에 날짜 연산을 편하게 하기 위해서

    => 메소드 : getHeader(String name), getHeaders(String name), getHeaderNames(), getIntHeader(String name),

                    getDataHeader(String name)등

    => Enumeration, Iterator, Cursor 등은 여러 데이터를 순차적으로 접근하게 해주는 포인터의 개념, 모든 언어에 존재

        - for(int i=0; i<ar.length; i+=1){ ar[i]; }  // 아래에 비해 속도가 느림, 데이터 위치기억 X

        - for(int temp : ar){  temp;  }  //속도 빠름, 데이터의 위치를 기억하고 전진만 가능

 

**response 객체

    => 자료형은 HttpServletResponse

    => 응답객체

    => 서버에서 클라이언트에게 응답하기 위한 정보를 저장하는데 이용

 

1. Header에 값을 저장하기 위한 메소드

    - addDateHeader(String name, long value)

    - setDateHeader(String name, long value)

 

    - addIntHeader(String name, long value)

    - setIntHeader(String name, long value)

 

    - addHeader(String name, long value)

    - setHeader(String name, long value)

 

2. Data Caching

    => 출력 데이터를 브라우저에 저장. 다음 요청시, 서버에 요청하지 않고 브라우저에 저장된 데이터를 출력하는 기능

    => 자주 변경되는 데이터가 브라우저에 캐싱되어 있으면 매번 새로운 데이터로 변경하기 위해서 새로고침을 해야 함

    => 이러한 문제를 해결하기 위해서 브라우저에 캐싱 기능을 중지 시키는 방법

    

    - response.setHeader("Pragma", "no-cache");

    - response.setHeader("Cache-Control", "no-cache");

    - response.addHeader("Cache-Control", "no-store");

    - response.setDateHeader("Expires", 1L);

 

3. Redirect

    => 서버가 특정 요청으로 이동하고자 할 때 사용하는 방식

    => URL이 변경되고 request객체와 response 객체로 새로 만들어 짐

    => 기존 요청을 종료하고 새로운 요청이 만들어지는 것

    => 조회를 제외한 모든 작업의 마지막은 redirect

    => 방법 : response.sendRedirect(String url);

 

**out 객체

    => 웹 브라우저에 데이터를 전송하는 역할을 수행하는 출력 스트림

    => 서블릿에서는 response 객체의 getWriter()라는 메소드를 호출하여 생성

    => 자료형은 JspWriter

    => write나 print 메소드를 이용하여 html을 출력 가능

    => jsp 학습을 할 때는 출력을 편하게 하기 위해서 사용하지만 이후에는 자주 사용하지 않음

 

**pageContext 객체

    => jsp 페이지 1개와 매핑되는 객체

    => 다른 객체들을 가져오는 메소드가 존재

    => forwarding : 서버에서 다른 페이지의 결과를 가져오기 위한 방법

    => URL이 변경되지 않고, request와 response 객체를 이전 URL로부터 가져오기 때문에 공유가 됨

    => pageContext.forward(String url)

    => 도메인 내의 곳으로 만 가능

 

**web.xml

    => 자바 웹 프로젝트의 환경설정 파일

    => 프로젝트의 WebContext/WEB-INF 디렉토리에 존재해야 함

    => 프로젝트 안에 이 파일이 없으면 구동이 될 때 서버로부터 이 파일을 복사하여 사용

    => 이 파일을 수정하면 서버는 다시 시작되어야 변경 내용이 적용

    => 이 파일은 서버가 애플리케이션 실행시 1회만 읽기 때문

 

1. 설정

    => 필터 설정

    => 서블릿 설정

    => 세션 설정

    => 리스너 설정

    => welcome file 설정

    => error page 설정

    => 초기화 파라미터 설정

 

2. welcome file

    => 프로젝트를 실행했을 때 처음 보여지는 요청을 설정

    => 프로젝트가 실행되면 WAS는 web.xml 파일을 읽어서 welcome-file-list 설정이 있는 지 확인

        - 설정이 있으면 위에서 순서대로 요청을 처리하려고 하고, 처리시 처리 페이지를 화면에 출력

 

3. 초기화 파라미터 설정

    - <context-param>

            < description>설명문</description>

            < param-name>파라미터 명</param-name>

            < param-value>파라미터 값/param-value>>

    </context-para>

    => 여러개 생성 가능

 

4. 변경 가능성이 있는 고정 문자열 사용

    => 소스코드를 수정하면 컴파일을 다시하여 클래스를 만드록 빌드를 다시 해야함

    => 테스트 수행시 사용하는 데이터 중에서 배포하면 변경될 가능성이 있는 데이터를 소스코드에 직접 입력(비권장)

    => 대표적인 데이터는 데이터베이스 경로와 같은 데이터

    => 데이터 베이스 연동기능을 테스트할때 실제 데이터베이스에 전속하지 않고 대부분 로컬이나 더미 데이터 베이스

        를 가지고 하다가 배포를 할때면 실제 데이터베이스 경로로 변경

        - 소스코드에 데이터베이스 경로를 직접 입력하게 되면 테스트 수행 후 배포시 데이터베이스 경로를 변경해야 하

         는데 소스코드를 수정했기 때문에 컴파일을 다시하고 빌드를 다시하게 되어 예기치 않은 오류를 발생 시킬수 있

         고 오래 걸리게 됨

        - 이런 데이터들은 외부 파일에 작성하여, 코드를 수정하더라도 서버만 재구동하거나, 다시 구동하지 않더라도 변

         경된 내용이 적용되도록 해야 함

 

5. 로컬에 저장할지 서버에 저장할지의 여부를 결정

    => 해당 데이터의 변경 여부나 간격

        - 절대로 변경되지 않고, 용량이 크지 않은 경우 -> 로컬

        - 변경이 자주 일어나고, 용량이 큰 경우 -> 서버

 

6. Application 객체

    => 웹 애플리케이션 전체에 매핑되는 객체

    => 1개만 생성됨

    => request 객체의 getServletContext() 메소드를 이용하여 생성이 가능

  1) 초기화 파라미터 관련 메소드

    => String getInitParameter(String name) : name에 해당하는 파라미터 값을 리턴

    => Enumeration getParameterNames() : 파라미터 이름 전체를 접근할 수 있는 Enumeration을 리턴

  2) web.xml 파일에 초기화 파라미터를 설정

  <!-- 초기화 파라미터 설정 예시
  <context-param>
  	<description>설명문</description>
  	<param-name>파라미터 이름</param-name>
  	<param-value>파라미터 값</param-value>
  </context-param>-->
  
  <context-param>
  	<description>MySQL의 URL</description>
  	<param-name>url</param-name>
  	<param-value>http://localhost:8080/WebProject0616/process2.jsp</param-value>
  </context-param>

 

7. 절대 경로와 상대경로

  1) 절대경로 : 루트부터 작성하는 경로로 불변의 경로

    => 웹 주소의 경우 절대경로 작성이 어렵지 않지만 운영체제의 절대경로는 운영체제 마다 다르므로 작성에 유의

        - Windows는 디렉토리 기호가 \이고, 나머지 운영체제는 /가 디렉토리 기호

  2) 상대경로 : 현재 위치를 기준으로 하는 경로로 현재 위치가 어디냐에 따라 변경되는 경로

    - ../ : 상위 디렉토리

    - ./ : 현재 디렉토리

    - / : 도메인의 경로

        - http://localhost:8080/WebProject0616/application.jsp라면 /는 http://localhost:8080/WebProject0616 인데 html

          이나 jsp 파일에 /라고 적으면 http://localhost:8080이 됨

    => jsp나 서블릿에서 프로젝트 경로를 적을 때 request.getContextPath()를 사용

  3) 현재 프로젝트 내의 경로의 절대경로 찾기

    => 현재 프로젝트의 root 디렉토리는 WebContent

    => WebContent 안에 존재하는 디렉토리의 절대경로

        - application.getRealPath("/디렉토리 명");  //HttpServlet 3.0 부터 사용 가능

        - request.getRealPath("/디렉토리 명"); //HttpServlet 버전에 상관없이 사용 가능

 

8. 서버에서의 데이터 저장

    => 서버에서는 4개의 객체를 이용해서 데이터를 저장

    => page, request, session, application

  1) 영역의 개념

    - page는 현재 페이지 내에서만 유효, 다른 페이지로 가면 page는 새로 생성됨

    - request는 하나의 요청에 대해서만 유효, forwarding으로 이동한 경우 request가 공유되지만 그 외 방법으로 페이지

     이동시 request는 다시 생성되므로 공유 되지 않음

    - session은 하나의 윈도우에 대해서만 유효, 어떤 방식으로 페이지를 이동해도 데이터를 공유

      (사용자가 웹브라우저를 실행하고 계속 사용해야 하는 데이터가 있으면 session에 저장 - 로그인)

    - application은 웹 애플리케이션 전체에 1개만 생성되고 모든 사용자가 공유

  2) 데이터 관련 메소드

    - void setAttribute(String name, object data) : 데이터 저장

    - Object getAttribute(String name) : 데이터를 가져오는 메소드. 리턴 타입 Object라서 사용시 원자료형으로 형변환

                                                   없는 이름 사용시 null 리턴

    - void removeAttribute(String name) : name에 해당하는 데이터를 삭제

 

9. 서버에서 결과 페이지로 이동

  1) forwarding

    => 결과 페이지의 실행결과를 출력하는 것

    => 실제 결과 페이지로 이동하지 않고 겨로가 페이지의 실행결과를 가져와서 출력

    => 브라우저의 url이 변경되지 않음

    => 새로고침을 하게되면 URL이 다시 호출되어 이전에 수행했던 작업을 다시 수행

    => 삽입, 삭제, 갱신작업시 forwarding을 이용하여 결과페이지로 이동하면 안됨

        (새로고침시 이전 작업 다시 수행)

    - RequestDispatcher 변수명 = request.getRequestDispatcher(String 포워딩할 페이지);

    - 변수명.forward(request객체, response 객체);

  2) redirect

    => 현재 요청의 흐름을 종료하고 새로운 흐름을 만들어서 결과 페이지로 이동

    => 새로고침을 해도 결과 페이지만 새로고침

    => 삽입, 삭제, 갱신 작업 후에는 redirect로 이동해야 새로고침 문제가 발생하지 않음

 

10. 웹 서버에서 요청 처리하는 방식(요청페이지 -> 처리 페이지 및 처리 코드-> 결과 페이지)

    => parameter : 요청페이지에서 처리페이지에게 넘겨주는 데이터

    => attribute : 처리 페이지에서 처리후 결과 페이지에 넘겨주는 데이터

    => 요청 페이지에서 처리페이지로 요청하는 방법 : a, form 태그, javascript 사용

    => 처리페이지에서 결과 페이지로 이동하는 방법 : forwarding, redirect

 

    => 처리페이지 부분이 jsp가 아닌 servlet, java class로 변경되면 Model2라고 함

 

11. 데이터 조회 작업

    => 요청 페이지에서 필요한 파라미터를 가지고 처리 페이지에 요청

    => 처리 페이지에서 파라미터를 읽고, 데이터베이스에서 조회한 후 결과를 생성하여 request에 저장

    => 결과 페이지로 포워딩

    => 결과 페이지에서는 request에 저장된 데이터를 읽어서 출력

 

  1) 요청 페이지

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>요청페이지</title>
</head>
<body>
	<a href="process.jsp?name=oop">요청</a>
</body>
</html>

 

  2) 처리 페이지 - process.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.util.*" %>
<%
	//파라미터 읽기
	String name = request.getParameter("name");
	//콘솔에 출력
	System.out.println("name : " + name);
	
	//Business Logic 처리
	
	//결과를 생성
	Map<String, Object> oop1 = new HashMap<>();
	oop1.put("name", "encapsulation");
	oop1.put("description", "불필요한 부분은 숨기고 필요한 부분만 외부로 노출하여 클래스를 만드는 것");
	
	Map<String, Object> oop2 = new HashMap<>();
	oop2.put("name", "inheritance");
	oop2.put("description", "하위 클래스가 상위클래스의 모든 것을 물려받는 것 - 재사용성 증가");
	
	Map<String, Object> oop3 = new HashMap<>();
	oop3.put("name", "polymorphism");
	oop3.put("description", "동일한 메시지에 대하여 다르게 방응하는 성질- 동일코드가 다른 메소드 호출");
	
	List<Map> list = new ArrayList<>();
	list.add(oop1);
	list.add(oop2);
	list.add(oop3);
	
	//이동 방법에 따라 데이터를 저장
	//포워딩 할 것이라서 request에 저장
	request.setAttribute("list", list);
	
	//결과 페이지로 이동 -포워딩
		//결과 페이지로 이동 - 포워딩
	RequestDispatcher requestDispatcher = 
		request.getRequestDispatcher("output.jsp");
	requestDispatcher.forward(request, response);
	
	
%>

 

  3) 결과 페이지 - output.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>OOP</title>
</head>
<body>
<%@ page import="java.util.*" %>
	<%
	//저장된 데이터 읽어오기
	//데이터를 사용하기 위해서는 원래의 자료형으로 형변환 하여 가져와야 함
		List<Map<String, Object>> list = 
		(List<Map<String, Object>>)request.getAttribute("list");

	//데이터를 출력
	for(Map<String, Object> map : list){
		out.print("<div>" + map.get("name") + 
				" : " + map.get("description")+ "</div>");
	}
	%>
</body>
</html>

  4) 포워딩

    => 포워딩은 결과페이지의 URL로 변경되지 않음(결과페이지에 출력하여 내용을 가져옴)

    => 새로고침시 처리를 다시하여 결과를 재출력