[JAVA] Servlet 시작하기/Servlet을 사용해보자
서블릿 시작하기
서블릿이란?
서블릿(Servlet)은 Java 언어를 기반으로 웹 애플리케이션을 개발하기 위한 서버 사이드 컴포넌트이다. 서블릿은 웹 서버에서 동작하며, 클라이언트의 요청에 대해 동적으로 처리하고 응답을 생성하는 역할을 한다. 자바 코드 내에 html을 내장한 형식이다.
서블릿 시작하기
* 이클립스의 경우 상단의 source탭 누르면 오버라이딩, 게터, 세터 등 생성 가능
통신 방식
GET 방식
- url에 요청 파라미터가 나타난다. ex) https://localhost:9000/aaa/index.html?name=값&나이=값
- 보안성이 떨어진다
- post 방식에 비해 전송 속도가 빠르다.
- 전송 데이터의 길이 제한이 존재한다.(255로 제한)
POST 방식
- url의 뒤에 파라미터가 보이지 않는다.
- GET 방식에 비해 보안성이 강화된다.
- 캐싱이 불가능하다.
- get 방식에 비해 전송 속도가 느리다.
- 전송 데이터의 길이 제한이 없다.
이클립스를 기준으로 쉽게 서블릿 프로젝트를 시작하는 방법을 기술한다.
- WEB-INF → new → other → XML파일 → 파일이름 : web.xml 생성
- webapp → index.html 생성
- 아파치 톰캣 서버 생성 및 실행
폴더 및 파일 구성
패키지 내에 서블릿 클래스 생성 (extends HttpServlet으로 상속 받은 후, 상단의 source탭에서 오버라이딩 쉽게 가능)
java Resources/sampl1/HelloServlet
public class HelloServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Do get");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Do Post");
}
}
- doGet : HTTP GET 요청을 처리
- doPost : HTTP POST 요청을 처리
web.xml내에 클래스 등록
(패키지 우클릭 → Java EE tools → Generate Deployement Descriptor Stub클릭시 자동 생성)
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
version="6.0">
<servlet>
<servlet-name>Hello</servlet-name>
<servlet-class>sample1.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Hello</servlet-name>
<url-pattern>/Hello</url-pattern>
</servlet-mapping>
</web-app>
- : 서블릿 구성 파일의 루트 요소
- xmlns="https://jakarta.ee/xml/ns/jakartaee : 기본 네임스페이스 지정
- xsi:schemaLocation… : 스키마 위치 지정
- : 서블릿 이름 지정. 즉 sampl1 패키지의 HelloServlet은 web.xml에서 Hello라는 이름으로 사용된다.
- : 서블릿 클래스의 전체 경로를 지정. 여기서는 "sample1.HelloServlet" 클래스를 사용
- : 서블릿 매핑 정의
- : 서블릿 URL 지정. /Hello로 설정되어 해당 url로 들어오는 요청은 앞에서 정의한 “HelloServlet”에 매핑. 즉 의 name과 의 name을 일치시켜 작동시킴
+ web.xml이란?
- Java 웹 애플리케이션에서 사용되는 배치(설정) 파일
- 웹 애플리케이션의 구성 요소와 동작 방식을 정의하며, 서블릿, 필터, 리스너 등의 구성 요소와 그들의 설정을 포함
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title</title>
</head>
<body>
<!--post 방식-->
<form action="Hello" method="get">
<input type="submit" value="Hello Servlet GET">
</form>
<form action="Hello" method="post">
<input type="submit" value="Hello Servlet POST">
</form>
</body>
</html>
위쪽 버튼을 클릭하면 GET을 날리고 아래 버튼을 누르면 POST를 날린다.
클릭시 HelloServlet클래스에서 요청을 받아 처리한다. 즉, 콘솔에 각각 Do get 혹은 Do post가 뜬다.
클라이언트에서 데이터 받기
서블릿에서 클라이언트로 데이터를 넘길 때는 PrinterWriter를 사용한다.
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>fsd</title>
</head>
<body>
<form action="hello" method="get">
name:<input type="text" name="name"><br>
age:<input type="text" name="age">
<input type="submit" value="Hello!"/>
</form>
</body>
</html>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="https://jakarta.ee/xml/ns/jakartaee" xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd" version="6.0">
<display-name>sample3</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>hello</servlet-name>
<servlet-class>sample3.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
HelloServlet.java
package sample3;
import java.io.IOException;
import java.io.PrintWriter;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String name = req.getParameter("name");
int age = Integer.parseInt(req.getParameter("age"));//파라미터 값은 항상 스트링으로 받는다
resp.setContentType("text/html; charset=utf-8");
PrintWriter pw = resp.getWriter();
pw.println("<html>");
pw.println("<head>");
pw.println("</head>");
pw.println("<body>");
pw.println("<h1>Hello servlet</h1>");
pw.println("<p>이름 : " + name + "</p>");
pw.println("<p>나이 : " + age + "</p>");
pw.println("</body>");
pw.println("</html>");
//doProc(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
String name = req.getParameter("name");
int age = Integer.parseInt(req.getParameter("age"));//파라미터 값은 항상 스트링으로 받는다
resp.setContentType("text/html; charset=utf-8");
PrintWriter pw = resp.getWriter();
pw.println("<html>");
pw.println("<head>");
pw.println("</head>");
pw.println("<body>");
pw.println("<h1>Hello servlet</h1>");
pw.println("<p>이름 : " + name + "</p>");
pw.println("<p>나이 : " + age + "</p>");
pw.println("</body>");
pw.println("</html>");
//doProc
}
protected void doProc(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("doProc 실행!");//post, get에서 호출시 동일하게 처리 가능
}
}
req는 HttpServletRequest 객체이다.
- 하나의 값 받기 : String val = req.getParameter(”name”);
- 여러 값 받기 : String val[] = req.getParameterValues("name")
get의 url : http://localhost:9000/sample3/hello?name=홍길동&age=12
post의 rul : http://localhost:9000/sample3/hello
여러 값 받기
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="hello" method="get">
<h3>과일</h3>
<input type="radio" name="fruit" value="사과" checked>appel
<input type="radio" name="fruit" value="배">pear
<input type="radio" name="fruit" value="바나나">banana
<h3>취미</h3>
<input type="checkbox" name="hobby" value="그림 그리기"/>picture
<input type="checkbox" name="hobby" value="게임"/>game
<input type="checkbox" name="hobby" value="영화"/>movie
<h3>좋아하는 포털</h3>
<select name="url" multiple>
<option value="네이버">네이버</option>
<option value="구글" >google</option>
<option value="구글">zum</option>
</select>
<button>이동</button>
</form>
</body>
</html>
HelloServlet.js
package sample4;
import java.io.IOException;
import java.io.PrintWriter;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
public class HelloServelt extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doProc(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doProc(req, resp);
}
protected void doProc(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html; charset=utf-8");
PrintWriter pw = resp.getWriter();
다수의 값을 받기 위해 아래 코드를 사용하였다.
- String hobbys[] = req.getParameterValues("hobby");
- String url[] = req.getParameterValues("url");
서블릿간 통신
Forwarding 방식으로 서블릿간 통신을 정리한다.
포워딩은 하나의 서블릿에서 다른 서블릿으로 제어를 전달하는 방법이다. 이를 위해RequestDispatcher
를 사용한다. 포워딩은 클라이언트의 브라우저에게는 보이지 않고 서버 내부에서 처리되므로 클라이언트에게 직접적으로 응답을 보내지 않고도 서블릿 간의 데이터 공유 가능하다.
파일 구조
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="https://jakarta.ee/xml/ns/jakartaee" xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd" version="6.0">
<display-name>sample4</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>hello</servlet-name>
<servlet-class>sample4.HelloServelt</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>sample</servlet-name>
<servlet-class>sample4.SampleServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>sample</servlet-name>
<url-pattern>/sample</url-pattern>
</servlet-mapping>
</web-app>
index.html
- 조건 검사를 위해 간단한 제이쿼리를 사용하였다.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
</head>
<body>
<form action="hello" id="frm" method="post">
이름: <input type="text" name="name" id="name"/><br>
나이 : <input type="text" name="age" id="age"/><br>
주소 : <input type="text" name="address" id="address"/><br>
<button type="button" class="btn">이동</button>
</form>
</body>
</html>
<script>
$(".btn").click(()=>{
if($("#name").val() == ""){
alert("이름 입력해요!");
return;
}
if($("#age").val() == ""){
alert("나이 입력해요!");
return;
}
if($("#address").val() == ""){
alert("주소 입력해요!");
return;
}
$("#frm").submit();
});
</script>
Human.java
package sample4;
public class Human {
private String name;
private int age;
private String address;
public Human(String name, int age, String address) {
this.name = name;
this.age = age;
this.address = address;
}
public String toString() {
return "이름: " + name + "</br>나이: " + age + "</br>주소: " + address;
}
}
HelloServelt.java
package sample4;
import java.io.IOException;
import java.io.PrintWriter;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
public class HelloServelt extends HttpServlet{
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html; charset=utf-8");
req.setCharacterEncoding("utf-8");
String name = req.getParameter("name");
int age = Integer.parseInt(req.getParameter("age"));
String address = req.getParameter("address");
Human human = new Human(name, age, address);
req.setAttribute("human", human);
req.getRequestDispatcher("sample").forward(req, resp);
}
}
HelloServelet은 클라이언트로부터 데이터를 받아 sample 서블렛으로 데이터를 전송하는 역할을 한다.
setAttribute는 요청에 속성 값을 부여한다. 위 코드에서 req.setAttribute("human", human);는 요청에 human이라는 이름으로 객체를 속성으로 부여하였다.
추후 req.getAttribute(”human”);으로 속성에 접근하여 값인 human객체를 받아올 수 있다.
package sample4;
import java.io.IOException;
import java.io.PrintWriter;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
public class SampleServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html; charset=utf-8");
Human human = (Human)req.getAttribute("human");
PrintWriter pw = resp.getWriter();
pw.println("<html>");
pw.println("<head>");
pw.println("</head>");
pw.println("<body>");
pw.println("<h1>Sample servlet</h1>");
pw.println("<p>" + human.toString() + "</p>");
pw.println("</body>");
pw.println("</html>");
}
}
HelloServelet으로부터 데이터를 받아와 처리한다.
어노테이션으로 매핑
아래의 코드는 /hello로 들어온 url에 대한 처리가 가능하다. 서블릿 버전을 상위 버전으로 맞추면 web.xml이 없어도 정상적으로 매핑되어 동작한다.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="hello">
<input type="text" name="val" />
<button>버튼</button>
</form>
</body>
</html>
@WebServlet("/hello")
public class FirstServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String val = req.getParameter("val");
System.out.println(val);
}
}
세션 만들고 사용하기
서블릿에서는 공유 가능한 세션을 만들고 읽고 수정하는 등의 작업을 할 수 있다. 세션을 조작하기 위해 아래의 메서드들을 사용한다.
HttpSession session = request.getSession(); //세션 객체 만들기
session.setAttribute("속성명",속성값); //세션 생성
String sessionS=(String) session.getAttribut("속성명"); //세션 받아오기
session.removeAttribute("속성명");//세션 내 속성 삭제
session.invalidate();//세션 삭제
session.setMaxInactiveInterval(value)//세션 유효기간 설정 ex) 60 * 30는 30분이다.