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>");
}
}
'Sever' 카테고리의 다른 글
6. 이메일 중복 검사 및 인증번호 이메일 보내기 기능 구현하기 (0) | 2023.04.05 |
---|---|
5. 로그인 기능 구현하기 (1) | 2023.04.05 |
4. JDBC - 연결 생성부터 자원반환까지 (0) | 2023.04.04 |
3. JDBC의 흐름 및 JDBC Tamplate (0) | 2023.04.04 |
2. JSP? + AJAX? (0) | 2023.03.28 |