본문 바로가기

Sever

1. Sevlet?

Servlet

- 웹 서비스를 위한 자바 클래스(HTTP 요청을 처리하고 응답을 생성하는 Java 클래스 ) 

- 웹 프로그래밍에서 클라이언트의 요청(Request)를 처리하고, 그 결과를 다시 클라이언트에게 응답(Response)하는 프로그래밍 기술 

ex) 사용자가 로그인 시, 아이디와 비밀번호를 입력하고 로그인 버튼을 누르면 서버는 아이디와 비밀번호를 확인하여 다음 페이지를 띄움

 

 

특징

클라이언트 요청에 대해 동적으로 작동하는 웹 애플리케이션 컴포넌트 

 →클라이언트의 요청에 대한 서버 응답 시, 미리 만들어둔 정적인 화면이 아닌, 요청을 받을 때마다 알맞게 동적인 화면을 만들어 응답.

 

 

상속관계

1. 인터페이스: javax.servlet.Sevelt 

  ㄴ 2. 추상클래스: javax.servlet.GenericServlet 

        ㄴ 3. 클래스: javax.servlet.http.HttpServlet  → 서블릿 코드를 작성할 클래스는 반드시 이 클래스를 상속받아 메소드 구현

 

 

Servlet 동작 방식

1. 클라이언트(사용자)가 URL을 클릭하면 Http Request를 Servlet Container로 보냄

2. Http Request로 전송 받은 Servlet Container는 두 개의 객체 생성 

    - HttpServletRequest: 요청 관련 내용 저장 

    - HttpServletResponse: 응답 관련 내용 저장 

3. web.xml은 사용자가 요청한 URL을 분석하여 어떤 서블릿 클래스에 요청 내용을 전달할지 찾음 

4. 해당 서블릿에서 클라이언트로부터 전송 받은 방식인 GET, POST 여부에 따라 해당 메소드 호출(doGet/doPost) 

5. doGet/doPost 메소드는 동적인 페이지를 생성 후 HttpServletResponse 객체에 응답 

6. 응답 종료 시, HttpServletRequest, HttpServletResponse 객체 소멸 

 

 

메소드별 오버라이딩

웹 클라이언트 요청 방식이

1. GET → doGet() 메소드로 응답 

2. POST → doPost() 메소드로 응답 

    그러므로, 반드시 doGet(), doPost()는 오버라이딩을 해주어야 함. 

    첫 번째 파라미터: HttpServletRequest / 두 번째 파라미터: HttpServletResponse

 

 

* Get과 Post? 

Get

 - 데이터를 가져(얻어)오는 것으로  URL에 변수(데이터)를 포함시켜 요청한다. 보안에 취약하여 로그인 시 부적합하다. 

 - 데이터를 HTTP header 에 포함하여 전송하고 body는 빈 상태로 전송된다. 

 - 캐싱(즐겨찾기, 북마크) 이 가능하다. 

 

Post

 - 데이터를 서버로 제출하여 추가, 수정하기 위해 데이터를 전송 

 - URL을 변수(데이터)를 노출하지 않고, 요청 데이터를 HTTP body에 포함시켜 전송 

 - 캐싱 불가능  

  


Servlet 예제 

1. 이름과 나이를 입력받아 서버(Java)로 전달 

   - form 태그: 내부에 작성된 input 태그의 값을 저장된 경로(주소)의 서버 or 페이지로 제출(클라이언트 요청)

   - Input태그: 값을 입력하기 위한 입력 양식을 제공하는 태그로, 제출 시 input 태그의 name 속성값이 Key, 입력값이 value(Map형식) 

 

  1)  HTML

 <h3>이름과 나이를 입력 받아 서버(Java) 쪽으로 전달(제출)</h3>
    <form action="/ServletProject1/example1.do">
         이름: <input type="text" name="inputName"><br>
         나이: <input type="number" name="inputAge">
         <button type="submit">서버로 제출하기</button>
    </form>

→ 제출 시 ServletProject1 프로젝트(다이나믹 웹 프로젝트)에 있는 example1.do라는 서비스 요청 

     (요청 시 내부에 작성된 input 태그의 값도 같이 전달)

 

* Web Dynamic Project 

더보기

Java 기반의 웹 애플리케이션을 개발하기 위한 프로젝트 구조로, Java EE(Enterprise Edition) 기술을 사용하여 다양한 서버 사이드 기증을 개발하고 수행하는 동적 웹 프로젝트(애플리케이션)

 

[구성요소]

1. Servlet : HTTP  요청을 처리하고 응답을 생성하는 Java 클래스 

2. JSP : HTML 코드와 Java 코드를 혼합하여 동적인 웹 페이지 생성하는 기술 

3. JavaBeans : 데이터를 저장하고 처리하는 Java 클래스 

4. JDBC : Java에서 데이터베이스를 연결하고 데이터를 검색, 추가, 수정 및 삭제하는 데 사용되는 API 

 

Web Dynamic Project 는 일반적으로 웹 애플리케이션 서버에 배포되며, 대표적인 서버로 Tomcat, JBoss 등이 있음

 

즉, 요청에 따라 응답되는 화면(HTML)을 실시간으로 만들어(동적) 클라이언트에게 응답하는 프로젝트 

 

  2) web.xml

 <!-- 특정 클래스를 Servlet으로 등록하고 이름을 지정하는 태그 -->
  <servlet>
  
  	<!-- 해당 Servlet을 부르기 위한 이름 지정 -->
  	<servlet-name>ex1</servlet-name>
  	
  	<!-- Servlet으로 등록하고자하는 클래스의 패키지명+클래스명 -->
  	<servlet-class>edu.kh.servlet.controller.ServletEx1</servlet-class>
  </servlet>
  
  
  <!-- 요청 주소를 처리할 Servlet 지정 -->
  <servlet-mapping>
  
  	<!-- 요청을 처리할 Servlet의 이름 -->
  	<servlet-name>ex1</servlet-name>
  	
  	<!-- 요청 주소 작성(앞에 프로젝트명까지는 제외 [/ServeltProject1]/example.do) -->
  	<url-pattern>/example1.do</url-pattern>
  
  </servlet-mapping>

* XML파일

더보기

XML(Extensible Markup Language) 

데이터를 저장하고 전송하기 위한 마크업 언어로, HTML과 유사하나 HTML은 문서의 구조와 표시를 목적으로 하고 XML은 데이터의 구조와 표시를 목적으로 함. 

* 마크업 언어: 일반 텍스트에 태그를 추가하여 문서나 데이터의 구조와 의미를 정의(ex: HTML)

 

[구성요소]

1. 태그: 데이터의 구조 

2. 속성: 태그에 대한 추가 정보 

3. 값: 태그가 나타내는 데이터 자체 

 

XML 파일은 다양한 프로그래밍 언어 및 플랫폼 간 데이터를 교환하는 데 사용(ex: Java에서 XML파일을 파싱하여 데이터를 처리)

 

Java 웹 애플리케이션에서 XML파일은 구성 파일이나 데이터 파일로 사용된다. 예를 들어, web.xml파일은 Java 웹 애플리케이션의 구성파일로 사용된다. 이 파일은 서블릿 및 필터의 Mapping, 보안설정, 오류페이지 및 세션 관리와 같은 애플리케이션 설정을 정의한다.

 

  3) java

package edu.kh.servlet.controller;

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;


// Servlet 코드를 작성하기 위해서는 HttpServlet을 상속받아야 한다. 
public class ServletEx1 extends HttpServlet{
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// HttpServletRequest : 클라이언트의 정보 + 요청 관련 정보가 담긴 객체 
		// HttpServeltResponse : 서버가 클라이언트에게 응답하는 방법을 제공하는 객체
		
		// 요청 시 함께 전달된 input 태그 값(=parameter)을 얻어오는 방법
		// req.getParameter("input 태그의 name 속성값")
		// ** 얻어온 파라미터는 무조건 String ** 
		
		String inputName = req.getParameter("inputName");
		String inputAge = req.getParameter("inputAge");
		
		System.out.println(inputName + "/" + inputAge);
		
		// 문서 형식 + 문자 인코딩 지정 
		// : html문서이고 문자는 UTF-8 형식으로 인코딩 되어있음
		resp.setContentType("text/html; charset=UTF-8");
		
		// 서버가 클라이언트에게 응답할 수 있는 스트림 얻어오기 
		PrintWriter out = resp.getWriter();
		
		out.print(inputName + "님의 나이는 " + inputAge + "세 입니다.");
		// html 코드도 작성 가능.. 
	}

}

 

 

 

 

2) GET 방식으로 요청 및 응답 

 - 요청하는 주소 뒤에 전달하려는 값을 key = value 형태로 붙여서 전달하는 방식

   ex) /프로젝트이름/서비스 요청 주소?key=value?key=value?... (QueryString) 

 - 장점: 단순함, 캐싱 가능(요청 주소 저장=북마크, 즐겨찾기, 링크 공유 등)

 - 단점: 캐싱으로 인한 보안 취약, 글자 수 제한 

 → 검색, 게시글, 뉴스 공유 등 이용할 때 좋음 

 

 1) HTML

 <form action="/ServletProject1/example2.do" method="get">
        주문자 : <input type="text" name="orderer"><br>
        hot <input type="radio" name="type" value="hot">
        ice <input type="radio" name="type" value="ice">

        <br><br>

        커피 : 
        <select name="coffee">
            <option>Espresso</option>
            <option>Americano</option>
            <option>Capucino</option>
            <option>Cafelatte</option>
            <option>Mochalatte</option>
        </select>

        <br><br>

        옵션 : <br>
        add 1 shot <input type="checkbox" name="opt" value="shot1"><br>
        add 2 shot <input type="checkbox" name="opt" value="shot2"><br>
        change soymilk <input type="checkbox" name="opt" value="soymilk">
        <br><br>

        <button>주문하기</button>
    </form>

 

 2) XML

  <!-- example2.do 요청에 대한 Servlet 연결 -->
  <servlet>
	  <servlet-name>ex2</servlet-name>
	  <servlet-class>edu.kh.servlet.controller.ServletEx2</servlet-class>
  </servlet>
  
  <servlet-mapping> 
 	<servlet-name>ex2</servlet-name>
  	<url-pattern>/example2.do</url-pattern> 
  </servlet-mapping>

 

3) Java

package edu.kh.servlet.controller;

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 {
	
	
	// Get 방식 요청을 처리하는 메서드 
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
	
		// 전달된 input 태그의 값을 얻어와 변수에 저장 
		String orderer = req.getParameter("orderer");
		
		// radio 버튼 1개만 선택 가능 = 값 한 개만 서버로 제출됨 
		String type = req.getParameter("type");
		
		// selectbox 1개의 옵션 값만 선택 가능 = 값 한 개만 서버로 제출됨 
		String coffee = req.getParameter("coffee");
		
		// checkbox와 같이 하나의 name 속성으로 여러 값이 전달될 경우 사용하는 메소드
		// 1. req.getParameter() 
  		//   => 여러 값 중 첫 번째 값만 얻어옴(String)
		// 2. req.getParameterValues() 
		//   => 여러 값을 모두 얻어옴(String[] or 값이 하나도 없으면 null) 
		String[] opt = req.getParameterValues("opt");
		
		System.out.println("주문 내용을 정상적으로 전달 받음");
		
		// 응답 위해 준비 
		// 1. 문서 형식 + 문자 인코딩 지정
		resp.setContentType("text/html; charset=UTF-8");
		
		// 2. 응답을 서버->클라이언트 스트림 얻어오기 
		PrintWriter out = resp.getWriter();
		
		//------------------------------------------------- 
		// HTML 코드를 응답용 스트림을 이용해서 출력 
 		// -> HTML 코드로 해석되서 보여짐(jsp 통해 간단히 표현 가능)
		//(HTML, CSS, JS 등 브라우저가 해석할 수 있는 코드는 모두 해석돼 보여짐)
				
				out.println("<!DOCTYPE html>");
				out.println("<html>");
				
				out.println("<head>");
				out.println("<title>"+ orderer +"님의 주문 내역</title>");
				out.println("</head>");
				
				out.println("<body>");
				
				out.printf("<h3>주문자명 : %s</h3>\n", orderer);
				
				out.println("<h3>");
				out.println("주문한 메뉴 : ");
				
				if(type.equals("hot")) {
					out.println("따뜻한 ");
				}else {
					out.println("아이스 ");
				}
				
				out.println(coffee);
				
				out.println("</h3>");
				
				
				// 옵션이 있을 경우에만 출력
				if(opt != null) {
					out.println("<ul>");
					
					// 향상된 for문
					for(String o : opt) {
						String temp = "";
						
						switch(o){
						case "shot1" : temp = "1샷 추가"; break;
						case "shot2" : temp = "2샷 추가"; break;
						case "soymilk" : temp = "두유변경"; break;
						}
						
						out.printf("<li>%s</li>\n", temp);
					}
					
					out.println("</ul>");
				}
				
				out.println("</body>");
				out.println("</html>");
					
	}

}

 

 

 

3. POST 방식 요청 및 응답 

 - GET 방식과 다르게 주소 뒤에 전달하는 값이 붙는 것이 아닌, HTTP Protocol의 Body 부분에 숨겨져 전달되는 방식 

 - 장점: 길이 제한X, 보안성 향상(데이터가 직접적으로 보이지 않음) 

 - 단점: 캐싱 불가, 추가적인 문자 인코딩 처리 필요 

 

 1) HTML

    <form action="/ServletProject1/signUp.do" method="post">
        아이디: <input type="text" name="inputId"><br>
        비밀번호: <input type="password" name="inputPw"><br>
        비밀번호 확인: <input type="password" name="inputPw"><br>
        이메일: <input type="email" name="inputEmail"><br>
        이메일 수신동의(선택): <input type="checkbox" name="agree"><br>

        <button>가입하기</button>
    </form>

 

 2) Java

package edu.kh.servlet.controller;

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("요청주소")
 *  - 해당 클래스를 Servlet으로 등록하고(<servlet>) 
 *    어떤 요청 주소를 처리할지 지정(<servlet-mapping>) == web.xml의 맵핑과 같음
 *    -> 이 모든 내용을 한번에 작성할 수 있는 어노테이션, 해당 클래스 바로 위에 작성
 * */


@WebServlet("/signUp.do")
public class ServletEx3 extends HttpServlet {
	
	// doPost() : Post 방식 요청을 처리하는 메서드 
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		
		// POST 방식은 문자 데이터가 깨질 수 있음 
		//-> 브라우저, 서버 간 문자 인코딩의 차이 때문에..  
		//-> 해결: 요청 정보에 담긴 데이터의 문자 인코딩을 UTF-8로 변경 
		req.setCharacterEncoding("UTF-8");
		
		// 파라미터를 얻어와 변수에 저장
		String inputId = req.getParameter("inputId");
		String[] inputPw = req.getParameterValues("inputPw");
		String inputEmail = req.getParameter("inputEmail");
		String agree = req.getParameter("agree");
		
		System.out.println(inputId);
		System.out.println(inputPw[0]);
		System.out.println(inputPw[1]);
		System.out.println(inputEmail);
		System.out.println(agree);
		
		
		// 응답 위해 준비 
		// 1. 문서 형식 + 문자 인코딩 지정
		resp.setContentType("text/html; charset=UTF-8");
			
		// 2. 응답을 서버->클라이언트 스트림 얻어오기 
		PrintWriter out = resp.getWriter();
		
		
		// -------------------------------
		
		out.println("<!DOCTYPE html>");
		out.println("<html>");
		out.println("<head> <title> 회원 가입 결과 </title> </head>");
		
		out.println("<body>");
		
		if(inputPw[0].equals(inputPw[1])) { // 비밀번호가 같을 경우
			// 정상 가입한 경우에 대한 화면
			
			// user01님 환영 합니다.
			
			// 이메일 수신 동의 여부 : O / X
			
			// (동의 O인 경우)
			// 수신할 이메일 : user01@naver.com
			
			out.printf("<h3>%s님 환영합니다.</h3>", inputId);
			
			// checkbox는 별도의 value가 없을 때
			// 체크 O : "on"
			// 체크 X : null
			
			if(agree != null) {
				out.println("<h3>이메일 동의 수신 여부 : O</h3>");
				
				out.printf("<h3>수신할 이메일 : %s</h3>", inputEmail);
				
			} else {
				out.println("<h3>이메일 동의 수신 여부 : X</h3>");
			}
			
			
		} else {
			out.println("<h1 style='color:red;'>비밀번호 불일치</h1>");
			
		}
		
		
		out.println("</body>");
		out.println("</html>");

		
	}

}