- 웹 서비스를 위한 자바 클래스 (자바를 이용하여 웹을 만들기 위해 필요한 기술)
- 웹 프로그래밍에서 클라이언트의 요청(Request)을 처리하고 그 결과를 다시 클라이언트에게 응답(Response)하는 Servlet 클래스의 구현 규칙을 지킨 자바 프로그래밍 기술
특별한 라이브러리나 도구를 의미하는 것이 아닌 별도로 제작된 웹 서버와 프로그램 간의 교환 방식
즉, Servlet은 자바 어플리케이션 코딩을 하듯 웹 브라우저용 출력 화면(HTML) 을 만드는 방법이다!
클라이언트의 요청에 대해 동적으로 작동하는 웹 애플리케이션 컴포넌트
-> 클라이언트 요청에 대한 서버 응답 시 미리 만들어 둔 화면(정적)이 아닌, 요청을 받을 때마다 알맞은 화면을 만들어(동적) 응답함
HTML을 사용하여 요청에 응답함
java thread를 이용하여 동작함 (요청마다 별도 thread가 생성됨)
MVC Model2 패턴에서 Controller로 이용함
서블릿 코드를 작성할 클래스는 반드시 javax.servlet.http.HttpServlet 클래스
를 상속받아 메소드를 구현해야 함
-> doGet() / doPost()를 필요한 형태로 오버라이딩 진행
javax.servlet.Servlet 인터페이스
ㄴ javax.servlet.GenericServlet 추상클래스
ㄴ javax.servlet.http.HttpServlet 클래스
웹 클라이언트의 요청 방식 | 응답 방식 |
---|---|
GET 방식 | doGet() 메소드 |
POST 방식 | doPost() 메소드 |
반드시 doGet()메소드와 doPost()메소드는 오버라이딩 해 주어야 한다.
사용자(클라이언트)가 URL(Uniform Resource Locator)을 클릭하면 HTTP Request(요청)를 Servlet Container로 전송
Http Request를 전송 받은 Servlet Container는 아래 두 객체를 생성
HttpServletRequest(클라이언트 + 요청 정보가 담긴 객체)
HttpServletResponse(서버가 클라이언트한테 응답하는 방법을 제공하는 객체)
DD (배포서술자, Deployment Descriptor) = web.xml은 사용자가 요청한 URL을 분석하여 어떤 서블릿 클래스에 요청 내용을 전달할지 찾음
해당 서블릿에서 init() 메소드를 먼저 호출한 후 service() 메소드를 호출하여
클라이언트로부터 전송 받은 방식인 GET, POST 여부에 따라 해당 메소드(doXXX())를 호출함
doGet() / doPost() 메소드는 동적 페이지를 생성 후 HttpServletResponse
객체에 응답을 보냄
응답 종료 시 HttpServletRequest, HttpServletResponse
객체 소멸
- Servlet : 어떤 역할을 수행하는 정의서
- Servlet Container : 정의된 Servlet을 보고 수행
-> 클라이언트의 요청을 받을 때마다 새로운 자바 스레드(Thread)를 만들어 요청을 처리하고 응답을 해 줌
배포를 위한 포트 연결, 웹 서버 통신을 위한 소켓, 입/출력 스트림을 생성하는 역할을 함
Java로 웹 애플리케이션을 만들기 위해 JSP(Java Server Page)나 서블릿(Servlet)을 사용해 서버와 통신하기 위해서는 서버가 구축이 되어 있어야 함
톰캣이 처리할 수 없는 정적 페이지 처리를 위하여 아파치의 일부 기능을 가져와 함께 제공하는 서버
- 다운로드 링크
http://tomcat.apache.org/
-> 왼쪽 탭 Download -> Tomcat 9 -> 9.0.xx -> Core -> OS에 맞는 tomcat 다운로드
내부에 작성된 input 태그의 값을 지정된 서버 또는 페이지로 제출(전달)하는 역할
-> 이때, 어떤 input 태그에 작성된 값이 제출된 건지 알 수 있도록 input태그에 name 속성을 반드시 작성한다!
action
input 태그 값을 전달할 서버 또는 페이지 주소를 작성하는 속성
method
데이터 전달 방식 지정 속성(get / post)
http://localhost:8080 /ServletProject1/
- http://아이피:포트번호 : 통신 규약, 서버 컴퓨터 위치를 지정(고정)
- /ServletProject1/ : 요청하고자 하는 내용을 나타내는 주소
요청하는 주소 뒤에 전달하려는 값(input 태그에 작성된 값)을 문자열 형태로 붙여서 서버로 전달하는 방식
- form태그, a태그, 주소창 직접 입력하는 모든 것이 GET방식
- form태그, method 속성 기본값
단순함, 캐싱 가능(요청 저장 가능 == 북마크, 즐겨찾기)
보안에 취약함(눈에 다 보임)
GET 방식 요청을 처리하는 메소드
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {...}
요청 시 전달된 input 태그의 값
요청 시 전달된 input 태그 값(== Parameter)을 얻어오는 방법
같은 name이 여러 개면 String[]로 반환
서버가 클라이언트에게 응답할 수 있는 출력 전용 스트림을 얻어옴
Write : 서버가 클라이언트에게 쓰다 == 출력
스트림을 통해서 그냥 문자열을 내보내면 정상 출력되지 않는 문제가 발생한다.
따라서 전달되는 응답 데이터가 어떤 형식인지, 문자 인코딩은 어떤 건지를 지정해 줘야 한다.
요청에 따라서 응답되는 화면(HTML)을 실시간으로 만들어내서(동적) 클라이언트에게 응답하는 프로젝트
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>index라는 이름이 붙은 파일은 메인 페이지 역할을 합니다.</h1>
<hr>
<h3>테스트 1</h3>
<pre>
form 태그 :
내부에 작성된 input 태그의 값을 지정된 서버 또는 페이지로
제출(전달)하는 역할
* 이때, 어떤 input 태그에 작성된 값이 제출된 건지 알 수 있도록
input태그에 name 속성을 반드시 작성한다!!
* form 태그 속성
- action : input 태그 값을 전달할 서버 또는 페이지 주소를 작성하는 속성
- method : 데이터 전달 방식 지정 속성(get / post)
</pre>
<!-- http://localhost:8080 /ServletProject1/
- http://아이피:포트번호 : 통신 규약, 서버 컴퓨터 위치를 지정(고정)
- /ServletProject1/ : 요청하고자 하는 내용을 나타내는 주소
-->
<form action="/ServletProject1/example1.do">
<!-- ServletProject1 프로젝트에 example.do 라는 요청을 전달한다
-> 예제 1번을 수행해서 결과를 응답할 예정
-->
이름 : <input type="text" name="inputName"><br>
나이 : <input type="text" name="inputAge"><br>
<button type="submit">서버로 제출하기</button>
</form>
<hr>
<h3>GET방식 요청 및 응답</h3>
<pre>
GET방식 : 요청하는 주소 뒤에
전달하려는 값(input 태그에 작성된 값)을
문자열 형태로 붙여서 서버로 전달하는 방식
- 장점 : 단순함, 캐싱 가능(요청 저장 가능 == 북마크, 즐겨찾기)
- 단점 : 보안에 취약함(눈에 다 보임)
* form태그, a태그, 주소창 직접 입력하는 모든 것이 GET방식
* form태그, method 속성 기본값
</pre>
<form action="/ServletProject1/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>
<?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>ServletProject1</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>
<!-- ============================================================ -->
<!-- 클래스르 Servlet으로 등록하고 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>
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{
// /ServletProject1/example1.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.getParameter("inputName");
String inputAge = req.getParameter("inputAge");
System.out.println(inputName);
System.out.println(inputAge);
}
}
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;
// Servlet 클래스를 만들 때는
// 반드시 HttpServlet을 상속받아야 한다.
public class ServletEx2 extends HttpServlet{
// Get 방식 요청을 처리하는(do) 메소드
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 파라미터(Parameter) == 요청 시 전달된 input 태그의 값
String orderer = req.getParameter("orderer");
// -> getParameter()는 전달된 iput태그의 name이 하나일 때만 가능
// -> 같은 name이 여러 개면 String[]로 반환하는
// getParameterValues()를 사용
String[] coffee = req.getParameterValues("coffee");
// 체크박스에 체크된 메뉴들이 모두 배열에 담김
// --> 체크가 안 되면 배열에 하나도 담기지 않음
if(coffee != null) { // 체크된 메뉴가 있는지 검사
// 향상된 for문
for(String c : coffee) {
System.out.println( c );
}
}
System.out.println("주문자 : " + orderer);
// HttpServletRequest : 클라이언트 정보 + 전달된 값
// HttpSErvletResponse : 서버가 클라이언트에게 응답할 방법을 제공
// Write : 서버가 클라이언트에게 쓰다 == 출력
// resp.getWriter() : 서버가 클라이언트에게 응답할 수 있는
// 출력 전용 스트림을 얻어옴
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>");
}
}
웹 화면
Eclipse 내부 콘솔창
-> System.out.println(inputName)과 System.out.println(inputAge)로 인해 콘솔에 이름과 나이가 출력되는 모습을 볼 수 있다.
웹 화면
'주문서 제출하기' 버튼을 클릭했을 때
-> 주문자 이름이 title에, 주문한 메뉴 목록이 body에 보여지는 모습이다.