본문 바로가기

Server/Servlet & JSP

Servlet 기본 개념

  • Servlet이란?
    - 웹 서비스를 위한 자바 클래스
      (자바를 이용하여 웹을 만들기 위해 필요한 기술)

    - 웹 프로그래밍에서 클라이언트의 요청(Request)을 처리하고,
      그 결과를 다시 클라이언트에게 응답(Response)하는
      Servlet 클래스의 구현 규칙을 지킨 자바 프로그래밍 기술

    - Servlet은 자바로 구현된 CGI(Common Gateway Interface)라고 함

    - Servlet은 자바 애플리케이션 코딩을 하듯 웹 브라우저용 출력화면(HTML)을 만드는 방법

  • Servlet의 특징
    - 클라이언트의 요청에 대해 동적으로 작동하는 웹 애플리케이션 컴포넌트
       → 클라이언트 요청에 대한 서버 응답 시 미리 만들어준 화면(정적)이 아닌
            요청 받을 때마다 알맞은 화면을 만들어(동적) 응답함

    - http프로토콜 서비스를 지원하는 javax.servlet.http.HttpServlet 클래스를 상속 받음

  • Servlet의 단점
    - Servlet에 작성한 html 코드 변경 시 다시 컴파일 해야 함

  • Servlet의 상속 관계
    - Servlet 코드를 작성할 클래스는 반드시
       javax.servlet.http.HttpServlet 클래스를 상속 받아 메소드를 구현해야 함

  • Servlet의 동작 방식
    - index.html [메인 페이지 역할] → Servlet 프로젝트에 요청 전달
      → web.xml 파일에서 연결 작업 수행 → doGet / doPost 방식을 통해 전달 받은 Parameter값 처리

    - index.html : 메인 페이지 역할
[index.html]
<!DOCTYPE html>
<head>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <title>Servlet 테스트 프로젝트</title>
</head>
<body>
   <h1>index라는 이름이 붙은 파일은 메인 페이지 역할을 합니다.</h1>
   
   <hr>
   
   <pre>
      form 태그 : 내부에 작성된 input 태그의 값을 지정된 서버 또는 페이지로 제출(전달)하는 역할
      
      ★ 이때, 어떤 input 태그에 작성된 값이 제출된건지 알 수 있도록
         input 태그에 name 속성을 반드시 작성해야 함!
      ★ form 태그 속성
         - action : input 태그의 값을 전달할 서버 또는 페이지 주소를 작성하는 속성
         - method : 데이터 전달 방식을 지정하는 속성(get / post)
   </pre>
   
   <!-- http://localhost:포트번호/ServletProject/
        - http://아이피:포트번호 : 통신 규약, 서버 컴퓨터의 위치를 지정(고정)
        - /ServletProject/ : 요청하고자 하는 내용을 나타내는 주소
   -->
   
   <form action="/ServletProject/example.do">
      <!-- ServletProject 프로젝트에 example.do 라는 요청을 전달함 -->
      
      이름 : <input type="text" name="inputName"> <br>
      나이 : <input type="text" name="inputAge"> <br>
      
      <button type="submit">서버로 제출하기</button>
   </form>

   - Servlet 프로젝트 클래스

package edu.kh.servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

// Servlet 클래스를 만들기 위해서는
// javax.servlet.http.HttpServlet 추상 클래스를 반드시 상속받아야 함!
// -> doGet() / doPost()를 필요한 형태로 오버라이딩 진행

public class ServletEx1 extends HttpServlet{
    // /ServletProject/example.do 주소로 요청이 왔을 때
    // 해당 클래스가 응답할 수 있도록 연결하는 작업이 필요
    
    // -> web.xml 파일에서 연결작업 수행
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{
       // HttpServletRequest : 클라이언트 + 요청 정보가 담긴 객체
       // HttpServletResponse : 서버가 클라이언트한테 응답하는 방법을 제공하는 객체
       
       // 요청 시 전달된 input 태그의 값(== Parameter)을 얻어오는 방법
       // req.getParameter("input 태그의 name 속성");
       
       String inputName = req.getParametr("inputName");
       String inputAge = req.getParameter("inputAge");
       
       System.out.println(inputName);
       System.out.println(inputAge);
   }

   - 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>ServletProject</display-name>
  
  <!-- 메인 페이지 목록 -->
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.jsp</welcome-file>
    <welcome-file>default.htm</welcome-file>
  </welcome-file-list>
  
  <!-- ServletEx1 클래스를 Servlet으로 등록(자격 부여) -->
  <servlet>
    <servlet-name>example1</servlet-name>
    <!-- Servlet으로 등록하고자 하는 클래스 파일의 패키지명 + 클래스명 -->
    <servlet-class>edu.kh.servlet.ServletEx1</servlet-class>
  </servlet>
  
  <!-- 요청주소를 처리할 Servlet과 연결을 지정 -->
  <servlet-mapping>
    <servlet-name>example1</servlet-name>
    <url-pattern>/example1.do</url-pattern>
  </servlet-mapping>
  
  </web-app>

   - 결과 출력


  • GET 방식 요청 및 응답
    - 요청하려는 주소 뒤에 전달하려는 값(input 태그에 작성된 값)을
       문자열 형태로 붙여서 서버로 전달하는 방식
    - 장점 : 단순함, 캐싱 가능(요청 저장 가능 == 북마크, 즐겨찾기)
    - 단점 : 보안에 취약함
    - form 태그_method 속성의 기본값

    - index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Servlet 테스트 프로젝트</title>
</head>
<body>
<form action="/ServletProject/example2.do" method="get">
   주문자 : <input type="text" name="orderer"><br>

   <label>
      <input type="checkbox" name="coffee" value="아이스 아메리카노">
      아이스 아메리카노
   </label>
   <br>
   <label>
      <input type="checkbox" name="coffee" value="카라멜 마끼야또">
      카라멜 마끼야또
   </label>
   <br>
   <label>
      <input type="checkbox" name="coffee" value="녹차 라떼">
      녹차 라떼
   </label>
   <br>
   <label>
      <input type="checkbox" name="coffee" value="초코칩 프라페">
      초코칩 프라페
   </label>
   <br>
   <label>
      <input type="checkbox" name="coffee" value="밀크쉐이크">
      밀크쉐이크
   </label>
   <br>
       
   <button>주문서 제출하기</button>
</form>
</body>
</html>

   - Servlet 프로젝트 클래스

package edu.kh.servlet;

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;

public class ServletEx2 extends HttpServlet {

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		
		// getParameter()는 전달된 input 태그의 name이 하나일 때만 가능
		
		// -> 같은 name 이 여러 개면 String[]로 반환하는
		//    getParameterValues()를 사용
		String[] coffee = req.getParameterValues("coffee");
		
		// 체크된 메뉴가 있는 경우
		String orderer = "";
		
		if(coffee != null) {
			orderer = req.getParameter("orderer");
			System.out.println("주문자 : " + orderer);
			
			for(String cof : coffee) {
				System.out.println(cof);
			}
		}
		
		// HttpServletRequest : 클라이언트 정보 + 전달된 값
		// HttpServletResponse : 서버가 클라이언트에게 응답할 방법을 제공
		
		// Write : 서버가 클라이언트에게 쓰다 == 출력
		// resp.getWriter() : 서버가 클라이언트에게 응답할 수 있는
		//                    출력 전용 스트림을 HttpServletResponse에서 얻어옴
		
		resp.setContentType("text/html; charset=UTF-8");
		PrintWriter out = resp.getWriter();
		
		// ★★ 스트림을 통해서 그냥 문자열을 내보내면 정상 출력되지 않는 문제 발생 ★★
		// 왜? 전달되는 응답 데이터가 어떤 형식인지,
		//     문자 인코딩은 어떤 건지 지정해주지 않았기 때문에
		
		// ****************************************************************
		/* Dynamic Web Project(동적 웹 프로젝트)
		 * 
		 * - 요청에 따라서 응답되는 화면(HTML)을 실시간으로 만들어내서(동적)
		 *   클라이언트에게 응답하는 프로젝트
		 * */
		// ****************************************************************
		
		// HTML 코드를 자바(Servlet)에서 작성하여
		// 클라이언트와 연결된 응답 출력용 스트림(out)을 이용해서 출력
		out.println("<!DOCTYPE html>");
		out.println("<html>");
		
		out.println("<head>");
		out.println("<title>" + orderer + "님의 주문 내역</title>");
		out.println("</head>");
		
		out.println("<body>");
		
		out.println("<ul>");
		if(coffee != null) {
			for(String c : coffee) {
				out.println("<li>" + c + "</li>");
			}
		}
		out.println("</ul>");
		
		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_4_0.xsd" id="WebApp_ID" version="4.0">
  <display-name>ServletProject</display-name>
  
  <!-- 메인 페이지 목록 -->
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.jsp</welcome-file>
    <welcome-file>default.htm</welcome-file>
  </welcome-file-list>
  
    <!-- ServletEx2 클래스를 Servlet으로 등록(자격 부여) -->
  <servlet>
  	<servlet-name>example2</servlet-name>
  	<servlet-class>edu.kh.servlet.ServletEx2</servlet-class>
  </servlet>
  
  <!-- 요청 주소를 처리할 Servlet과 연결을 지정 -->
  <servlet-mapping>
  	<servlet-name>example2</servlet-name>
  	<url-pattern>/example2.do</url-pattern>
  </servlet-mapping>
  
  </web-app>

   - 결과 출력

주문서 제출하기 클릭 시
GET 방식 - URL을 통해 입력 받은 값을 서버로 전달


  • Servlet 예제
    - 요청 주소(action) : /ServletProject/example3.do
    - 데이터 전달 방식(method) : GET
    - 비밀번호가 일치하지 않으면
      응답화면에 h1태그로 "비밀번호가 일치하지 않습니다"
    - 일치하면 가입된 회원 정보 출력
    - 좋아하는 색을 체크하지 않으면 "없습니다" 출력
    - (참고) 
      서버로 제출된 input 태그 값은 모두 [String] 입니다.
       input type="password" 는 화면에서만 안 보이고, 서버로 제출된 경우 입력된 값이 그대로 보입니다.

    - index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Servlet 테스트 프로젝트</title>
</head>
<body>    
    <form action="/ServletProject/example3.do" method="GET">

        아이디 : <input type="text" name="inputId"> <br>
        비밀번호 : <input type="password" name="inputPw1"> <br>
        비밀번호 확인 : <input type="password" name="inputPw2"> <br>
        
        이름 : <input type="text" name="inputName"> <br>
        이메일 : <input type="email" name="inputEmail"> <br>

        좋아하는 색<br>
        <label><input type="checkbox" name="color" value="빨강">빨강</label>
        <label><input type="checkbox" name="color" value="노랑">노랑</label>
        <label><input type="checkbox" name="color" value="초록">초록</label>
        <br>
        <label><input type="checkbox" name="color" value="파랑">파랑</label>
        <label><input type="checkbox" name="color" value="분홍">분홍</label>
        <label><input type="checkbox" name="color" value="검정">검정</label>

        <br>

        <button>회원 정보 제출하기</button>
	</form>
</body>
</html>

   - Servlet 프로젝트 클래스

package edu.kh.servlet;

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;

public class ServletEx3 extends HttpServlet{
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		
		// HttpServletRequest : 클라이언트 정보 + 전달된 값
		// HttpServletResponse : 서버가 클라이언트에게 응답할 방법을 제공
		
		String inputId = req.getParameter("inputId");
		String inputName = req.getParameter("inputName");
		String inputEmail = req.getParameter("inputEmail");
		String[] color = req.getParameterValues("color");
		
		// Dynamic Web Project (동적 웹 프로젝트)
		// ★요청★에 따라서 ★응답★ 화면(HTML)을 실시간으로 만드는 것(동적)
		
		String inputPw1 = req.getParameter("inputPw1");
		String inputPw2 = req.getParameter("inputPw2");
		
		resp.setContentType("text/html; charset=UTF-8");
		PrintWriter out = resp.getWriter();
		
		out.println("<!DOCPTYPE>");
		out.println("<html>");
		out.println("<head>");
		out.println("<title>회원정보</title>");
		out.println("</head>");
		out.println("<body>");
		if(!inputPw1.equals(inputPw2)) {
			out.print("<h1>비밀번호가 일치하지 않습니다.</h1>");
		} else {
			out.println("<ul>");
			out.println("<li>아이디 : " + inputId + "</li>");
			out.println("<li>이름 : " + inputName + "</li>");
			out.println("<li>이메일 : " + inputEmail + "</li>");
			out.println("<li>좋아하는 색 : ");
			if(color != null) {
				for(String col : color) {
					out.println(col + " ");
				}
			} else {
				out.println("없습니다.");
			}
			out.println("</li>");
			out.println("</ul>");
		}
		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_4_0.xsd" id="WebApp_ID" version="4.0">
  <display-name>ServletProject</display-name>
  
  <!-- 메인 페이지 목록 -->
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.jsp</welcome-file>
    <welcome-file>default.htm</welcome-file>
  </welcome-file-list>
  
      <!-- ServletEx3 클래스를 Servlet으로 등록(자격 부여) -->
  <servlet>
  	<servlet-name>example3</servlet-name>
  	<servlet-class>edu.kh.servlet.ServletEx3</servlet-class>
  </servlet>
  
  <!-- 요청 주소를 처리할 Servlet과 연결을 지정 -->
  <servlet-mapping>
  	<servlet-name>example3</servlet-name>
  	<url-pattern>/example3.do</url-pattern>
  </servlet-mapping>
  
</web-app>

   - 결과 화면

비밀번호가 일치하지 않는 경우
좋아하는 색이 없는 경우
정상 입력한 경우
정상 입력 시 결과 화면