[필기정리] Day84-1 - EL(Expression Language), ContextParam 등

Web/JSP

2020. 10. 26. 11:00

# EL(Expression Language)

콤마(,)와 대괄호([])를 사용하여

자바 빈의 프로퍼티나 맵, 리스트, 배열의 값을 보다 쉽게 꺼내게 해주는 기술

 

# JSP에서 표현 언어 사용 설정

JSP 페이지에서 표현 언어(EL)를 사용하기 위해서는 page 디렉티브의 isELIgnored 속성을 false로 설정해야 한다.

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isELIgnored="false" %>

그러나 이 속성은 명시하지 않는 경우 기본값이 false이므로 true로만 설정하지 않으면 된다.

 

- EL 표기법

멤버 값 출력
${member.no}
또는
객체이름 프로퍼티

${member["no"]} // 상단배열
객체이름 프로퍼티

 

- 자바 코드 표현 시

Member obj = (Member)pageContext.findAttribute("member");
int value = obj.getNo();

// view에서 자바 소스 코드를 사용하는 것은 분업화를 위해 권장하지 않는다.

 

PageContextfindAttribute()는 다음 순서에 따라 보관소(Scope Objects)를 뒤져서 객체를 찾는다.

마지막까지 뒤졌는데 없다면 null을 반환한다. // null 반환 시 아무 것도 출력하지 않는다.

JspContext - ServletRequest - HttpSession - ServletContext - null (찾는 순서)

 

# EL에서 검색 범위 지정

EL<jsp:useBean>처럼 네 군데 보관소에서 값을 꺼낼 수 있다.

다만 <jsp:useBean>과 다른 점은 EL로는 객체를 생성할 수 없다는 것이다.

 

EL에서 보관소를 참조할 때 사용하는 이름

pageScope -> JspContext
requestScope -> ServletRequest
sessionScope -> HttpSession
applicationScope -> ServletContext

- ServletRequest 보관소에서 값을 꺼내는 EL 코드이다.

${requestScope.member.no}

- 자바 코드 표현 시

Member obj = (Member)request.getAttribute("member");
int value = obj.getNo();

 

객체를 찾는 범위를 지정하지 않으면 JspContext부터 ServletContext까지 순차적으로 찾지만,

앞의 코드와 같이 범위를 지정하게 되면 해당 보관소에서만 객체를 찾는다.

못 찾으면 null을 반환한다.

// 저장영역 미설정 시 낮은 - 높은 순으로 영역에서 값을 찾아 가져온다.

 

# JSP에서 제공하는 EL 기본 객체

객체 설명 코드
pageContext JSP PageContext 객체  
servletContext ServletContext 객체 ${pageContext.servletContext.객체명}
session HttpSession 객체 ${pageContext.session.객체명}
request ServletRequest 객체 ${pageContext.request.객체명}
response ServletResponse 객체  
param 요청 매개변수의 값 조회 ${param.매개변수명}
paramValues 요청 매개변수의 값 배열 조회 ${paramValues.매개변수명}
header Http 헤더의 값 조회 ${header.헤더명}
headerValues Http 헤더의 값 배열 조회 ${headerValues.헤더명}
cookie 쿠키 값 조회 ${cookie.쿠키명}
initParam 컨텍스트 초기화 매개변수의 값 조회 ${initParam.매개변수명}
pageScope page 보관소의 값 조회 ${pageScope.객체명}
requestScope request 보관소의 값 조회 ${requestScope.객체명}
sessionScope session 보관소의 값 조회 ${sessionScope.객체명}
applicationScope application 보관소의 값 조회 ${applicationScope.객체명}

 

# EL 기본 문법

- 리터럴 표현식

EL 블록("${})에서 사용할 수 있는 값은 문자열, 정수, 부동소수점, 참거짓(Boolean), (Null)이 가능하다.

// EL 표현식 + 실행결과

블록 값 내용 블록 값 실행결과
문자열 ${"test"} 문자열 test
문자열 ${'test'} 문자열 test
정수 ${20} 정수 20
부동소수점  ${3.14} 부동소수점 3.14
참거짓 ${true} 참거짓 true
null ${null} null 빈 문자열

 

- 값 표현식

자바 객체, 배열, List, Map으로 부터 값을 꺼낼 때 사용하는 EL 표현식을 알아보면

① 배열에서 값 꺼내기

ex) EL 표현식

<% // 값 준비
pageContext.setAttribute("scores", new int[] {90, 80, 70, 100}); // 배열 생성 하면서 초기화 한 것
%>
<%-- 배열에서 인덱스 2의 값 꺼내기 --%>
${scores[2]} // 실행결과 : 70

List 객체에서 값 꺼내기

ex) EL 표현식

<% // 값 준비
List<String> nameList = new LinkedList<String>();
nameList.add("홍길동");
nameList.add("임꺽정");
nameList.add("일지매");
pageContext.setAttribute("nameList", nameList);
%>
<%-- 리스트 객체에서 인덱스 1의 값 꺼내기 --%>
${nameList[1]} // 실행결과 : 임꺽정

③ Map 객체에서 값 꺼내기

ex) EL 표현식

<% // 값 준비
Map<String, String> map = new HashMap<String, String>();
map.put("s01", "홍길동"); // key, value
map.put("s02", "임꺽정");
map.put("s03", "일지매");
pageContext.setAttribute("map", map);
%>
<%-- 맵 객체에서 키 s02로 저장된 값 꺼내기 --%>
${map.s02} // 실행결과 : 임꺽정

 

# 연산자

연산부호 연산자 기능
+ + 숫자 덧셈
- - 숫자 뺄셈
* * 숫자 곱셈
/ / 숫자 나눗셈
&& and 논리연산자 AND
|| or 논리연산자 OR
== eq 동일
!= ne 다름
< gt(Greater than)
> lt(Less than) 작음
<= ge(Greater or equal) 이상
>= le(Less or equal) 이하
  empty 객체가 값이 없는지 구분
  func(파라미터) 함수 호출 
! not 값을 반대로 만듬
ture → false
false → true
% mod 나머지 값을 구함
.(온점)   bin의 property나
Map의 entry 접근
[ ]   배열이나 리스트 엘리먼트 접근
( )   괄호, 표현식의 연산순서를 바꿔서 연산하게 할 때

EL 블록에서도 간단한 연산을 수행할 수 있다

EL에서 제공하는 연산자 중 몇몇은 기호뿐만 아니라 동일한 기능의 영문으로 된 연산자도 있다.

다음은 EL에서 지원하는 주요 연산자에 대한 설명이다.

 

① 산술 연산자 : 더하기(+), 빼기(-), 곱하기(*), 나누기(/, div), 나머지(%, mod)

                      // div, mod는 소스 가독성을 위해 있는 것

ex) EL 표현식

// Tip : ${' 앞에 '\'가 붙으면 '${'EL 문법이 아닌 일반 텍스트로 취급한다.

\${10 + 20} = ${10 + 20} <br/>
\${10 - 20} = ${10 - 20} <br/>
\${10 * 20} = ${10 * 20} <br/>
\${10 / 20} = ${10 / 20} <br/>
\${10 div 20} = ${10 div 20} <br/>
\${10 % 20} = ${10 % 20} <br/>
\${10 mod 20} = ${10 mod 20} <br/>

 

실행결과

${10 + 20} = 30
${10 - 20} = -10
${10 * 20} = 200
${10 / 20} = 0.5
${10 div 20} = 0.5
${10 % 20} = 10
${10 mod 20} = 10

 

② 논리 연산자 : AND(&&, and), OR(||, or) NOT(!, not)

ex) EL 표현식

\${true && false} = ${true && false}<br/>
\${true and false} = ${true and false}<br/>
\${true || false} = ${true || false}<br/>
\${true or false} = ${true or false}<br/>
\${not true} = ${not true}<br/>
\${!true} = ${!true}<br/>

실행결과

${true && false} = false
${true and false} = false
${true || false} = true
${true or false} = true
${not true} = false
${!true} = false

 

③ 관계 연산자 : 같다(==, eq), 같지 않다(!=, ne), 크다(>, gt), 작다(<, lt), 크거나 같다(>=, ge), 작거나 같다(<=, le)

ex) EL 표현식

\${10 == 11} = ${10 == 11} <br/>
\${10 eq 11} = ${10 eq 11} <br/>
\${10 != 11} = ${10 != 11} <br/>
\${10 ne 11} = ${10 ne 11} <br/>
\${10 < 11} = ${10 < 11} <br/>
\${10 lt 11} = ${10 lt 11} <br/>
\${10 > 11} = ${10 > 11} <br/>
\${10 gt 11} = ${10 gt 11} <br/>
\${10 <= 11} = ${10 <= 11} <br/>
\${10 le 11} = ${10 le 11} <br/>
\${10 >= 11} = ${10 >= 11} <br/>
\${10 ge 11} = ${10 ge 11} <br/>

실행결과

${10 == 11} = false
${10 eq 11} = false
${10 != 11} = true
${10 ne 11} = true
${10 < 11} = true
${10 lt 11} = true
${10 > 11} = false
${10 gt 11} = false
${10 <= 11} = true
${10 le 11} = true
${10 >= 11} = false
${10 ge 11} = false

 

④ empty : 값이 비어 있거나 null인지를 조사할 때 사용하는 연산자

              값이 null이면 true를 반환한다.

              또한, 문자열과 배열, Map, Collection 객체의 크기가 0인 경우에도 true를 반환한다.

               그 밖에는 false를 반환한다.

 

ex) EL 표현식

<% // 값 준비
pageContext.setAttribute("title" "EL 연산자!");
%>
<%-- 자바빈에서 프로퍼티 email의 값 꺼내기 --%>
\${empty title} = ${empty title}<br/>
\${empty title2} = ${empty title2}<br/>

실행결과

${empty title} = false
${empty title2} = true

 

⑤ 조건 : 자바의 조건 연산자(삼항연산자)와 쓰임이 같다.

    'A ? B : C'에서 A 조건이 참이면 B를 실행하고, A 조건이 거짓이면 C 조건을 실행합니다.

 

ex) EL 표현식

\${10 > 20 ? "크다" : "작다"} = ${10 > 20 ? "크다" : "작다"}

실행결과

${10 > 20 ? "크다" : "작다"} = 작다

 

# 예약 키워드

다음은 EL에서 사용하거나 사용하기로 예약한 키워드이다.

and, or, not, eq, ne, lt, ge, true, false, null, instanceof, empty, div, mod

 

JspContextSevletRequest, HttpSession, ServletContext 보관소에 객체를 저장할 때,

그 식별자()EL의 예약 키워드 이름과 같아서는 안 된다.

EL을 사용하지 않는다면 문제가 되지 않겠지만, EL을 사용한다면 오류가 발생할 것이다.

다음 예제는 객체 식별자의 이름이 예약 키워드의 이름과 같을 때, 오류가 발생하는 것을 보여준다.

 

ex) EL 표현식

<% // 값 준비
pageContext.setAttributte("ne", "오호라!");
%>
<%-- pageContext에서 값 꺼내기 --%>
${ne}
<%-- 예약어를 써서 오류남 --%>

 

# 서블릿 초기값 : 특정 서블릿에 초기값을 주는 것

- web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>InitTest</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
  <servlet>
  	<servlet-name>InitTest</servlet-name>
  	<servlet-class>com.superman.ex.InitTest</servlet-class>
  	<init-param>
  		<param-name>startNum</param-name>
  		<param-value>1</param-value>
  	</init-param>
  	<init-param>
  		<param-name>endNum</param-name>
  		<param-value>100</param-value>
  	</init-param>
  </servlet>
 
  <servlet-mapping>
  	<servlet-name>InitTest</servlet-name>
  	<url-pattern>/InitTest</url-pattern>
  </servlet-mapping>

</web-app>

ex) 1부터 100까지의 합 구하기

package com.superman.ex;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

//@WebServlet("/InitTest")
public class InitTest extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    public InitTest() {
        super();
    }

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String startNumStr = getInitParameter("startNum"); // 1
		String endNumStr = getInitParameter("endNum"); // 100
		int startNum = Integer.parseInt(startNumStr); // 문자열을 숫자로 형변환하는 것
		int endNum = Integer.parseInt(endNumStr);
		int sum = 0;
		
		for(int i=startNum;i<=endNum;i++){
			sum += i;
		}
		response.setContentType("text/html;charset=UTF-8");
		PrintWriter out = response.getWriter();
		out.println("<!DOCTYPE html>");
		out.println("<html>");
		out.println("<body>");
		out.println("합은 : " + sum);		
		out.println("</body>");
		out.println("</html>");
	}
}

- web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>InitTest2</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
  <servlet>
    <servlet-name>Test3Servlet</servlet-name>
    <servlet-class>com.superman.ex.Test3Servlet</servlet-class>
    <init-param>
      <param-name>start</param-name>
      <param-value>1</param-value>
    </init-param>
    <init-param>
      <param-name>end</param-name>
      <param-value>10</param-value>
    </init-param>
  </servlet>
  <servlet-mapping>
    <servlet-name>Test3Servlet</servlet-name>
    <url-pattern>/Test3Servlet</url-pattern>
  </servlet-mapping>
</web-app>

ex)

package com.superman.ex;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

//@WebServlet("/Test3Servlet")
public class Test3Servlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    public Test3Servlet() {
        super();
    }

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		ServletConfig config = this.getServletConfig();
		//ServletConfig 객체를 획득한다.
		//실제로는 HttpServlet이 ServletConfig를 구현했기 때문에
		//이렇게 객체를 획득할 필요 없이 this를 사용해도 무방하다.
		String start = config.getInitParameter("start");
		String end = this.getInitParameter("end");
		//config 객체를 통해서도 this를 통해서도 초기화 매개변수를 획득할 수 있다.
		
		int startNumber = Integer.parseInt(start);
		int endNumber = Integer.parseInt(end);
		//초기화 매개변수로 전달된 값은 문자열이므로 숫자로 변환한다.
		
		int sum = 0;
		for(int i = startNumber; i <= endNumber; ++i) 
			sum += i;
		//시작 수에서 끝 수까지의 총합을 구한다.
		
		response.setContentType("text/html;charset=UTF-8");
		//응답에 대한 MIME과 Encode를 설정한다.
		PrintWriter out = response.getWriter();
		//출력 객체를 생성한다.
		out.println("<html><body><center>");
		out.println(startNumber + " ~ " + endNumber + "사이의 합은 ");
		out.println(sum + "입니다.");
		out.println("</center></body></html>"); // HTML5는 <center> 태그 사라짐
		//결과를 출력한다.
		out.close();
		//출력 객체를 종료한다.
	}
}

- web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">
  <display-name>InitTest3</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
</web-app>

ex)

package com.superman.www;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(
		urlPatterns = { "/InitTest3" }, 
		initParams = { 
				@WebInitParam(name = "start", value = "1"), // 초기값 설정
				@WebInitParam(name = "end", value = "10")
		})
public class InitTest3 extends HttpServlet {
	private static final long serialVersionUID = 1L;
       

    public InitTest3() {
        super();
    }

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		ServletConfig config = this.getServletConfig();
		//ServletConfig 객체를 획득한다.
		//실제로는 HttpServlet이 ServletConfig를 구현했기 때문에
		//이렇게 객체를 획득할 필요 없이 this를 사용해도 무방하다.
		String start = config.getInitParameter("start");
		String end = this.getInitParameter("end");
		//config 객체를 통해서도 this를 통해서도 초기화 매개변수를 획득할 수 있다.
		
		int startNumber = Integer.parseInt(start);
		int endNumber = Integer.parseInt(end);
		//초기화 매개변수로 전달된 값은 문자열이므로 숫자로 변환한다.
		
		int sum = 0;
		for(int i = startNumber; i <= endNumber; ++i) 
			sum += i;
		//시작 수에서 끝 수까지의 총합을 구한다.
		
		response.setContentType("text/html;charset=UTF-8");
		//응답에 대한 MIME과 Encode를 설정한다.
		PrintWriter out = response.getWriter();
		//출력 객체를 생성한다.
		out.println("<html><body><center>");
		out.println(startNumber + " ~ " + endNumber + "사이의 합은 ");
		out.println(sum + "입니다.");
		out.println("</center></body></html>");
		//결과를 출력한다.
		out.close();
		//출력 객체를 종료한다.
	}
}

// Tip : eclipse에서 servlet 생성 시 Initialization parameters 추가하는 법

 

# ContextParam : 모든 서블릿이 공유하는 초기값을 주는 것

Q.

① ErrorTest.htm 파일을 만든다.

② 그 안에 input text를 두 개를 만들고 각각 숫자 두 개를 입력 받도록 하자.

③ 그리고 나누기라는 버튼을 누르면 ErrorServlet 으로 이동을 해서 결과 값을 출력하도록 하자.

④ 숫자 대신 글자가 입력이 되었을 때 에러코드를 510, “정수를 입력하지 않은 오류!”라고 출력하도록 하고,

    제수가 0일때 에러코드 511, “부적합 연산 관련 오류!”라고 출력하도록 하자.

 

A. 

- web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>ContextParamTest</display-name>
  <context-param> // context 내 요소 
    <param-name>companyName</param-name>
    <param-value>좋은회사</param-value>
  </context-param>
  <context-param>
    <param-name>companyTel</param-name>
    <param-value>012-3456-7890</param-value>
  </context-param>
  <context-param>
    <param-name>companyEmail</param-name>
    <param-value>goodCompany@good.com</param-value>
  </context-param>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
</web-app>

- ContextParamTest.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="description" content="HTML Study">
<meta name="keywords" content="HTML,CSS,XML,JavaScript">
<meta name="author" content="Bruce">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Insert title here</title>
</head>
<body>
<%
	String companyName = application.getInitParameter("companyName"); // getInitParameter는 application 클래스 내 존재하기 때문
%>
<%= companyName %>
</body>
</html>

- ContextParamTest2.java

package com.superman.ex;

import java.io.IOException;
import java.io.PrintWriter;

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;

@WebServlet("/ContextParamTest2")
public class ContextParamTest2 extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    public ContextParamTest2() {
    }

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html;charset=UTF-8");
		response.setCharacterEncoding("UTF-8");
		ServletContext context = getServletContext(); // 해당 메소드 내 context-param 존재함
		String companyName = context.getInitParameter("companyName");
		String companyTel = context.getInitParameter("companyTel");
		String companyEmail = context.getInitParameter("companyEmail");
		
		PrintWriter out = response.getWriter();
		out.println("<!DOCTYPE html>");
		out.println("<html>");
		out.println("<head>");
		out.println("<meta charset='UTF-8'>");
		out.println("</head>");
		out.println("<body>");
		out.println("<h2>" + companyName + "</h2>");
		out.println("<h2>" + companyTel + "</h2>");
		out.println("<h2>" + companyEmail + "</h2>");
		out.println("</body>");
		out.println("</html>");
	}
}

 

# 테이블 정보 보기 //  데이터베이스 정보 - 보안성을 위함

- web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://xmlns.jcp.org/xml/ns/javaee"
	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
	id="WebApp_ID" version="3.1">
	<display-name>TableInfo</display-name>
	<servlet>
		<servlet-name>TableInfoForm</servlet-name>
		<jsp-file>/TableInfoForm.jsp</jsp-file>
		<init-param>
			<param-name>driver</param-name>
			<param-value>com.mysql.cj.jdbc.Driver</param-value>
		</init-param>
		<init-param>
			<param-name>url</param-name>
			<param-value>jdbc:mysql://localhost:3306/testdb?serverTimezone=UTC</param-value>
		</init-param>
		<init-param>
			<param-name>user_id</param-name>
			<param-value>root</param-value>
		</init-param>
		<init-param>
			<param-name>user_pw</param-name>
			<param-value>1234</param-value>
		</init-param>
	</servlet>
	<servlet-mapping>
		<servlet-name>TableInfoForm</servlet-name>
		<url-pattern>/TableInfoForm</url-pattern>
	</servlet-mapping>
	<welcome-file-list>
		<welcome-file>index.html</welcome-file>
		<welcome-file>index.htm</welcome-file>
		<welcome-file>index.jsp</welcome-file>
		<welcome-file>default.html</welcome-file>
		<welcome-file>default.htm</welcome-file>
		<welcome-file>default.jsp</welcome-file>
	</welcome-file-list>

</web-app>

- TableInfoForm.jsp

<%@page import="java.sql.*"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<!DOCTYPE html>
<html>
<head>
	<script>
		//테이블 명은 반드시 입력해야 하기 때문에 공백 체크를 한다.
		function check_form() { // 에러 체크 함수
			var table_name = myform.table_name.value;
			if(table_name == '') {
				alert('테이블 명은 반드시 입력해야 합니다.');
				myform.table_name.focus();
				return false;
			}
		}
	</script>
<meta charset="UTF-8">
<meta name="description" content="HTML Study">
<meta name="keywords" content="HTML,CSS,XML,JavaScript">
<meta name="author" content="Bruce">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Insert title here</title>
</head>
<body>
		<h2>테이블 정보 출력!</h2>
	<%
	//GET 방식으로 호출 될 때에는 테이블을 검색할 수 있는 화면만 표시한다.
	if(request.getMethod().equalsIgnoreCase("GET")) { // 대소문자를 무시하고 같은지 같지 않은지 판단하는 것
	%>
	<form name='myform' method='post' onSubmit='return check_form()'>
		<table>
			<tr>
			<th width='100' align='right'>테이블명</th>
			<td><input type='text' name='table_name' size='30'/></td>
			</tr>
			<tr>
			<th width='100' align='right'>조건절</th>
			<td><input type='text' name='table_where' size='30'/></td>
			</tr>
			<tr>
			<td colspan='2' align='right'>
				<input type='submit' value='테이블 정보 획득'/>&nbsp;
			</td>
			</tr>
		</table>
	</form>
	<%
	//POST 방식으로 호출이 되면
	} else if(request.getMethod().equalsIgnoreCase("POST")) {
		//요청한 테이블 이름과 조건절의 값을 가져온다.
		String table_name = request.getParameter("table_name");
		String table_where = request.getParameter("table_where");
		if(table_where == null) table_where = "";
	%>
	<form name='myform' method='post' onSubmit='return check_form()'>
		<table>
			<tr>
			<th width='100' align='right'>테이블명</th>
			<td><input type='text' name='table_name' size='30' value='<%= table_name %>'/></td>
			</tr>
			<tr>
			<th width='100' align='right'>조건절</th>
			<td><input type='text' name='table_where' size='30' value='<%= table_where %>'/></td>
			</tr>
			<tr>
			<td colspan='2' align='right'>
				<input type='submit' value='테이블 정보 획득'/>&nbsp;
			</td>
			</tr>
		</table>
	</form>
	<%
		//config 디폴트 객체를 통해 web.xml에 지정된 초기화 매개변수의 
		//값들을 읽어온다.
		String driver = config.getInitParameter("driver");
		String url = config.getInitParameter("url");
		String user_id = config.getInitParameter("user_id");
		String user_pw = config.getInitParameter("user_pw");
		Connection conn = null;
		try {
			//DB를 연동할 때 해당 변수의 값들로 설정한다.
			Class.forName(driver);
			conn = DriverManager.getConnection(url, user_id, user_pw);
			String query = "SELECT * FROM " + table_name;
			//조건절이 있다면 query에 추가한다.
			if(table_where != null && table_where.trim().length() != 0)
				query += " " + table_where;
			Statement stmt = conn.createStatement();
			
			//쿼리 수행 결과 셋을 가져온다.
			ResultSet rs = stmt.executeQuery(query);
			
			//결과 셋으로 가져온 내용의 Header를 획득한다.
			//헤더의 메타 정보는 Column_Name, Column_Type 등이 있다.
			ResultSetMetaData rsmd = rs.getMetaData();
	%> 	
	<table border='1'>
		<tr>
		<%
			//메타 정보를 통해 Column_Name을 먼저 출력한다.
			for(int i = 1; i <= rsmd.getColumnCount(); ++i) {
				out.println("<td>" + rsmd.getColumnName(i) + "</td>");
			}
		%>
		</tr>
		<%
			//결과 셋을 통해 각 Column별 데이터들을 추출한다.
			//여기서 나머지 자료형들은 전부 getString() 으로 추출할 수 있지만
			//Date 관련 값은 반드시 getDate() 라고 추출해야 오류가 없다.
			while(rs.next()) {
				out.println("<tr>");
				for(int i = 1; i <= rsmd.getColumnCount(); ++i) {
					//해당 Column의 Type이 Date Type 인지의 여부를 확인한다.
					if(rsmd.getColumnTypeName(i).equalsIgnoreCase("Date"))
						out.println("<td>" + rs.getDate(i) + "</td>");
					else
						out.println("<td>" + rs.getString(i) + "</td>");
				}
				out.println("</tr>");
			}
		%>
	</table>
	<%
		}catch(Exception ex) {			
			out.println("ERROR : " + ex.getMessage() + "<br/><br/>");
		}finally{
			if(conn != null) conn.close();
			conn = null;
		}		
	}
	%>
</body>
</html>

 

# Header

- HeaderForm.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<form method="POST" action="HeaderForm">
		★ 이름 : <input type="text" name="name"/><br/>
		★ 보유 SKIL을 모두 선택하세요!<br/>
		<input type="checkbox" name="skil" value="c"/>C<br/>
		<input type="checkbox" name="skil" value="c++"/>C++<br/>
		<input type="checkbox" name="skil" value="java"/>JAVA<br/>
		<input type="checkbox" name="skil" value="jsp"/>JSP<br/>
		<input type="submit" value="전송"/>
	</form>
</body>
</html>

- HeaderForm.java

package com.superman.ex;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
import java.util.Vector;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/HeaderForm")
public class HeaderForm extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    public HeaderForm() {
        super();
    }

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8");
		//한글 인코드 설정
		String name = request.getParameter("name");
		//name 이라는 객체명으로 전송된 데이터를 획득
		String[] skils = request.getParameterValues("skil");
		//skil 이라는 객체명으로 전송된 데이터를 획득
		//단, 여러 개의 데이터가 같은 이름으로 전송될 수 있기 때문에
		//getParameterValues()를 이용해 배열로 획득
		
		Enumeration enu = request.getHeaderNames();
		//헤더 정보의 이름 값들을 모두 획득
		Vector names = new Vector();
		//헤더 정보의 이름을 모두 담기 위한 객체 선언
		Vector values = new Vector();
		//헤더 정보의 이름에 대한 값들을 모두 담기 위한 객체 선언
		while(enu.hasMoreElements()) { // hasNext()와 동일한 의미  
			String header_name = (String)enu.nextElement();
			//헤더 이름들 중 하나를 추출해서
			String header_value = request.getHeader(header_name);
			//헤더 이름에 담겨있는 값을 추출.			
			
			names.add(header_name);
			values.add(header_value);
			//헤더의 이름과 값을 각각의 Vector 영역에 보관
		}
		
		response.setContentType("text/html;charset=euc-kr");
		//응답에 대한 MIME과 Encode를 설정
		PrintWriter out = response.getWriter();
		out.println("<html><body>");
		
		out.println("★ 전달받은 데이터들 ★<br/>");
		out.println("name : " + name + "<br/>");
		out.println("skil : ");
		for(int i = 0; i < skils.length; ++i) {
			out.println(skils[i] + "&nbsp;"); 
		}
		out.println("<br/><br/><br/><br/>");
		
		out.println("★ 전달받은 헤더 정보들 ★<br/>");
		for(int i = 0; i < names.size(); ++i) { // 전체 헤더 네임 갯수만큼 반복
			String header_name = (String)(names.elementAt(i));			
			String header_value = (String)(values.elementAt(i));
			out.println(header_name + " : ");
			out.println(header_value + "<br/>");			
			
		}
		//헤더의 정보를 출력하는 코드
		
		out.println("</body></html>");
		out.close();
	}
}

- HeaderRe.java

package com.superman.ex;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/HeaderRe")
public class HeaderRe extends HttpServlet {
	private static final long serialVersionUID = 1L;
	private int cnt = 0;
       
    public HeaderRe() {
    }


	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html;charset=euc-kr");
		response.setHeader("refresh", "3");
		//헤더 속성 중 페이지를 갱신하는 refresh라는 속성을
		//3초 라는 시간값을 주어 설정해 두면
		//3초에 한번씩 페이지를 갱신한다.
		
		PrintWriter out = response.getWriter();
		out.println("<html><body>");
		out.println("cnt = " + cnt++);
		//cnt의 값 변화를 통해 페이지가 reload되는 것을 확인한다.
		out.println("</body></html>");
		out.close();
	}

}

 

// HTTP 헤더

① 일반 헤더(서버 ↔ 클라이언트) : 클라이언트, 서버 양쪽 모두 사용

헤더 설명
Connection 클라이언트와 서버가 요청/ 응답 연결에 대한 옵션을 정할 수 있게 해줌
Date 메시지가 언제 만들어졌는지 날짜와 시간 제공
MIME-Version 발송자가 사용한 MIME 버전 알려줌
Trailer chunked transfer 인코딩된 메시지 끝부분에 위한 헤더 목록 나열해줌
Transfer-Encoding 수신자에게 메시지에 어떤 인코딩이 적용되었는지 말해줌
Upgrade 발송자가 업그레이드 하길 원해는 새 버전이나 프로토콜 알려줌
Via 이 메시지가 어떤 중개자(프락시, 게이트웨이)를 거쳐 왔는지 보여줌
Cache-Control 메시지와 함께 캐시 지시자를 전달하기 위해 사용

② 요청 헤더(클라이언트 → 서버) : 요청 메시지를 위한 헤더로 서버에게 클라이언트가 부가정보 제공

헤더 설명
GET 지정된 리소스(URI) 요청
POST 서버 : 클라이언트의 폼 입력 필드 데이터의 수락 요청함
클라이언트 : 서버로 HTTP body에 Data 전송
HEAD 문서의 헤더 정보만 요청
body 응답 데이터를 받지 않음
PUT 서버 : 클라이언트가 전송한 데이터를 지정한 URI로 대체
클라이언트 : 서버로 HTTP body에 Data 전송 
DELETE 클라이언트가 지정한 URI를 서버에서 삭제
TRACE 클라이언트가 요청한 자원에 도달하기까지의 경로 기록하는 루프백의 검사용
클라이언트가 요청 자원에 도달하기까지 거쳐가는 프록시나 게이트웨이의 중간 경로부터
최종 수진 서버까지의 경로를 알아낼 때 사용
Accept 클라이언트가 허용할 수 있는 파일 형식
*/* : 모든 파일 형식 지원 의미
User-Agent 요청을 보낸 어플리케이션의 이름을 서버에 알려줌
Host 요청의 대상이 되는 서버의 호스트명과 포트 줌
If-Modified-Since 주어진 날짜 이후에 리소스가 변경되지 않은 경우 요청 제한
Refer 현재의 요청 URI가 들어있던 문서의 URL 제공
Cookie 클라이언트가 서버에게 토큰을 전달할 때 사용
(쿠키 헤더는 RFC 2616에 정의되어 있지 않음)
Accept-Language 클라이언트가 인식할 수 있는 언어
우선 순위 지정 가능
Accept-Encoding 클라이언트가 인식할 수 있는 인코딩 방법
서버에서 gzip, deflate로 압축한 리소스를 클라이언트가 해석할 수 있다는 뜻
서버에서 압축한 경우 응답헤더에 Content-Encoding 헤더에 해당 압축 방법 명시됨

③ 응답 헤더 (서버 → 클라이언트) : 클라이언트에 부가 정보 보내줌

헤더 설명
GET 지정된 리소스(URI) 요청
Server 서버 어플리케이션의 이름, 버전 나타냄
Date 메시지가 언제 만들어졌는지 날짜, 시간 제공
Content-Type 이 본문이 어떤 종류의 객체인지 정보 제공
Last-Modified 요청한 파일의 최종 수정일 나타냄
Content-Length 헤더 이후 이어지는 데이터 길이 (바이트 단위)
ETag 캐시 업데이트 정보를 위한 임의의 식별 숫자

④ 엔터티 헤더 : 엔터티 본문에 대한 헤더

                      요청과 응답 양쪽 모두 엔터티를 포함할 수 있기 때문에 양 타입의 메시지에 모두 나타날 수 있음

헤더 설명
Allow 이 엔터티에 대해 수행될 수 있는 요청 메소드 나열
Location 클라이언트에게 엔터티가 실제로 어디에 위치하고 있는 말해줌
수신자에게 리소스에 대한 위치(URL) 알려줄 때 사용
Content-Length 헤더 이후 이어지는 데이터 길이 (바이트 단위)
ETag 캐시 업데이트 정보를 위한 임의의 식별 숫자

⑤ 확장 헤더 : 어플리케이션 개발자들이 만들었지만 승인된 HTTP 명세에 추가되지 않은 비표준 헤더

 

+ URL의 RFC 명세

www.w3.org/Protocols/rfc2616/rfc2616-sec14.html

 

HTTP/1.1: Header Field Definitions

part of Hypertext Transfer Protocol -- HTTP/1.1 RFC 2616 Fielding, et al. 14 Header Field Definitions This section defines the syntax and semantics of all standard HTTP/1.1 header fields. For entity-header fields, both sender and recipient refer to either

www.w3.org

// MIME

 

MIME - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. MIME(영어: Multipurpose Internet Mail Extensions)는 전자 우편을 위한 인터넷 표준 포맷이다. 전자우편은 7비트 ASCII 문자를 사용하여 전송되기 때문에, 8비트 이상의 코드

ko.wikipedia.org

// MediaType

 

미디어 타입 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 미디어 타입(media type), MIME 타입(MIME type), 콘텐츠 타입(content type)[1]은 인터넷에 전달되는 파일 포맷과 포맷 콘텐츠를 위한 2 부분의 식별자이다. IANA는 이러한 분

ko.wikipedia.org

// 엔터티의 미디어타입

 

[HTTP] 엔터티의 미디어 타입(Content-Type)

'HTTP 완벽 가이드, 15장'을 인용하였다 Content-Type 헤더 필드는 엔터티 본문의 MIME 타입을 ...

blog.naver.com

// content-type, pageEncoding을 사용한 인코딩

 

content-Type , pageEncoding 을 사용한 인코딩

질문 1 : Web 브라우저가 문자 코드를 판정하는 기준은 무엇입니까? 답 : HTTP의 Content-Type 헤더...

blog.naver.com

// https://stickyny.tistory.com/90

 

POST, MIME-Type, Content-Type, multipart, x-www-urlencoded

안드로이드 앱에서 유저의 프로필 이미지를 서버에 업로드하는 API를 구현중이다. 이 API는 POST 방식이고 Content-Type은 x-www-urlencoded 이다. API를 구현하기에 앞서 꼭 알고 있어야하는 지식들에 대해

stickyny.tistory.com

 

728x90