목차
서블릿 클래스 만들기
서블릿 클래스는 HttpServlet을 반드시 상속받아야하며
@WebServlet 애노테이션을 작성해서 스프링에게 이 클래스가 웹 서블릿 클래스 라는 것을 알려주어야 한다.
그래야 ServletApplication의 @ComponentScan이 HelloServlet클래스를 서블릿으로 가져올 수 있다.
HttpServlet 클래스를 실행하면 자동으로 service메서드가 실행된다.
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
@ServletComponentScan //hello.servlet 하위의 서블릿을 모두 스프링컨테이너에 등록한다 : 서블릿 자동등록
@SpringBootApplication
public class ServletApplication {
public static void main(String[] args) {
SpringApplication.run(ServletApplication.class, args);
}
}
@WebServlet(name="서블릿명", urlPatterns="/요청받을 경로")
http://localhost:8080/hello를 주소창에 입력하면 helloServlet 서블릿이 실행된다.
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name="helloServlet", urlPatterns = "/hello")
public class HelloServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
서블릿에서 HTTP 요청받기
HttpServletRequest, HttpServletResponse는 interface이다.
여러 WAS(tomcat, jetty,...)들이 HttpServletRequest, HttpServletResponse interface를 구현한다.
그 구현체가 org.apache.catalina.connector.~~ 이다.
Query Parameter
주소창에 localhost:8080/hello?username=kim 입력 시 ?username=kim 이것을 query parameter라고 한다.
query parameter는 request.getParameter(String name); 으로 값을 읽어온다.
@WebServlet(name="helloServlet", urlPatterns = "/hello")
public class HelloServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("HelloServlet.service");
System.out.println("request = " + request);
System.out.println("response = " + response);
//HelloServlet.service
//request = org.apache.catalina.connector.RequestFacade@cbe2520
//response = org.apache.catalina.connector.ResponseFacade@a23bd9c
String username = request.getParameter("username");
System.out.println(username);
//username = kim
}
}
서블릿에서 HTTP 응답하기
@WebServlet(name="helloServlet", urlPatterns = "/hello")
public class HelloServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/plain");
//HTML HEADER부분에 응답메시지를 단순 문자열로 보낸다고 알려준다.
response.setCharacterEncoding("utf-8");
//HTML HEADER부분에 응답메시지의 인코딩 방식을 알려준다.
response.getWriter().write("hello "+username);
//HTML BODY부분에 응답메시지로 출력하는 내용을 알려준다.
}
}
localhost:8080/hello?username=Myname 입력 시 아래와 같이 출력된다.
HttpServletRequest
HTTP 요청 메시지를 개발자가 직접 파싱해서 사용해도 되지만, 매우 불편할 것이다.
서블릿은 개발자가 HTTP 요청 메시지를 편리하게 사용할 수 있도록 개발자 대신에 HTTP 요청 메시지를 파싱한다.
그리고 그 결과를 HttpServletRequest 객체에 담아서 제공한다.
HTTP 요청 메시지의 주소정보 출력하기
@WebServlet(name = "requestHeaderServlet", urlPatterns = "/request-header")
public class RequestHeaderServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/*
localhost:8080/request-header?username=hello 입력 시
request.getMethod() = GET
request.getProtocal() = HTTP/1.1
request.getRequestURL() = http://localhost:8080/request-header
request.getScheme() = http
request.getServerName() = localhost
request.getServerPort() = 8080
request.getRequestURI() = /request-header
request.getQueryString() = username=hello
*/
}
}
HTTP 요청 메시지의 데이터 출력하기
클라이언트에서 서버로 데이터를 전달하는 방법은 3가지가 있다.
content-type은 HTTP 메시지 BODY의 데이터 형식을나타낸다.
GET방식 | 쿼리 파라미터 사용 /url?username=hello&age=20 |
메시지 BODY 없이 URL의 쿼리파라미터에 데이터를 포함해서 전달한다. content-type : GET방식에서는 BODY를 사용하지 않으니 비어있는 것으로 출력된다. EX) 검색, 필터, 페이징 등에서 많이 사용한다. |
POST방식 | HTML FORM태그 사용 <form method="post" action="/전달주소"> <input type="text" name="username" /> <button type="submit">전송</button> </form> |
메시지 BODY에 쿼리파라미터 형식으로 전달한다. content-type : application/x-www-form-urlencoded content-type을 출력했을 때 위에처럼 나오면 POST방식으로 출력된 것이다. EX) 회원가입, 상품주문 등에서 많이 사용한다. |
HTTP Message Body에 데이터를 직접 담아서 요청 | 메시지 BODY 없이 URL의 쿼리파라미터 없이 데이터만 전달한다. JSON, XML, TEXT 등으로 데이터만 전달된다. |
GET 방식 : 쿼리파라미터 사용
쿼리파라미터는 URL 맨 끝에서 "?"로 시작하고, "&"로 각각을 연결한다.
http://localhost:8080/request-param?username=hello&age=20
파라미터 키로 값 조회 : String username = request.getParameter("username")
파라미터명 모두 조회 : Enumeration<String> parameterNames = request.getParameterNames();
@WebServlet(name = "requestParamServlet", urlPatterns = "/request-param")
public class RequestParamServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
System.out.println("username = " + username);
//단일 파라미터 조회
//username = hello
Enumeration<String> parameterNames = request.getParameterNames();
parameterNames.asIterator().forEachRemaining(paramName ->
System.out.println(paramName + "=" + request.getParameter(paramName)));
//파라미터 모두 조회
//username=hello
//age=20
}
}
http://localhost:8080/request-param?username=hello&age=20&username=hello2
파라미터 키에 값이 2개인 경우 : String[] usernames = request.getParameterValues("username")
@WebServlet(name = "requestParamServlet", urlPatterns = "/request-param")
public class RequestParamServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String[] usernames = request.getParameterValues("username");
for (String s : usernames) {
System.out.println("usernames = " + s);
}
//복수 파라미터 조회
//username = hello
//username = hello2
}
}
POST 방식 : FORM태그 사용
form태그의 method값에 post를 작성하면 post방식으로 서버에 값이 전달된다.
(method에 get이라고 작성할수도 있다. 그러면 get방식으로 값이 전달된다.)
<form action="/request-param"> 이면 @WebServlet(urlPatterns = "/request-param") 메서드로 값이 전달된다.
http://localhost:8080/basic/hello-form.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/request-param" method="post">
username: <input type="text" name="username" />
age: <input type="text" name="age" />
<button type="submit">전송</button>
</form>
</body>
</html>
@WebServlet(name = "requestParamServlet", urlPatterns = "/request-param")
public class RequestParamServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String age = request.getParameter("age");
//System.out.println("age = " + age);
//age = 22
//단일 파라미터 조회
}
}
HTTP Message Body에 데이터를 직접 담아서 요청 - 단순 데이터 출력
ServletInputStream inputStream = request.getInputStream();
//데이터를 Stream형식으로 가져온다.
String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
//Stream형식을 UTF-8로 인코딩하여 문자열로 변경한다.
@WebServlet(name = "requestBodyStringServlet", urlPatterns = "/request-body-string")
public class RequestBodyStringServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletInputStream inputStream = request.getInputStream();
String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
System.out.println("messageBOdy = "+messageBody);
//messageBOdy = plain text!
}
}
HTTP Message Body에 데이터를 직접 담아서 요청 - JSON 형식
JSON(JavaScript Object Notation)은 텍스트 기반의 데이터 교환 표준이다.
JSON 데이터 |
"데이터이름" : 값 | "name" : "kim" |
JSON 객체 |
{ "속성명" : 값, "속성명" : 값, "속성명" : 값... } |
{ "name": "식빵", "age": 1, "weight": 2.14 } |
JSON 배열 |
"배열명" : [ { "속성명" : 값, "속성명" : 값, "속성명" : 값, ... } { "속성명" : 값, "속성명" : 값, "속성명" : 값, ... } { "속성명" : 값, "속성명" : 값, "속성명" : 값, ... } ] |
"dog": [ {"name": "식빵", "age": 1, "weight": 2.14}, {"name": "콩콩", "age": 3, "weight": 2.5}, {"name": "젤리", "age": 7, "weight": 3.1} ] |
private ObjectMapper objectMapper = new ObjectMapper();
HelloData helloData = objectMapper.readValue(messageBody, HelloData.class);
// Jackson라이브러리가 json문자열을 HelloData 클래스 객체로 변경해주었다.
import lombok.Getter;
import lombok.Setter;
@Getter @Setter
public class HelloData {
private String username;
private int age;
}
import com.fasterxml.jackson.databind.ObjectMapper;
import hello.servlet.basic.HelloData;
import org.springframework.util.StreamUtils;
@WebServlet(name="requestBodyJsonServlet", urlPatterns = "/request-body-json")
public class RequestBodyJsonServlet extends HttpServlet {
//스프링부트에 기본으로 포함되어있는 jackson 라이브러리
//json 문자열을 클래스 객체로 변경할 수 있다.
private ObjectMapper objectMapper = new ObjectMapper();
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletInputStream inputStream = request.getInputStream();
String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
System.out.println("messageBody = " + messageBody);
//messageBody = {"username" : "kim", "age" : 20}
HelloData helloData = objectMapper.readValue(messageBody, HelloData.class);
System.out.println("helloData.username = " + helloData.getUsername());
System.out.println("helloData.age = " + helloData.getAge());
//helloData.username = kim
//helloData.age = 20
}
}
HttpServletResponse
HTTP 응답 메시지를 생성하는 역할을한다.
@WebServlet(name = "responseHeaderServlet", urlPatterns = "/response-header")
public class ResponseHeaderServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setStatus(200); //성공
response.setStatus(HttpServletResponse.SC_OK); //200과 같음. 성공
response.setHeader("Content-Type", "text/plain;charset=utf-8");
// = response.setContentType("text/plain");
// = response.setCharacterEncoding("utf-8");
//응답데이터의 데이터타입, 인코딩방법 설정
response.setHeader("my-header", "hello");
//임의의 header설정
response.sendRedirect("/basic/hello-form.html");
//페이지 이동
response.getWriter().write("ok");
//"ok"로 HTML BODY에 출력한다.
}
}
HTTP 응답 메시지 데이터 보내기
서버에서 클라이언트로 데이터를 전달하는 방법은 3가지가 있다.
단순 텍스트 응답 | response.getWriter().write("OK"); |
HTML 응답 | response.setContentType("text/html"); response.getWriter().println("<html><body>"); response.getWriter().println("<div>안녕?</div>"); response.getWriter().println("</body></html>"); |
HTTP Message Body에 데이터를 직접 담아서 응답 | 메시지 BODY 없이 URL의 쿼리파라미터 없이 데이터만 전달한다. JSON, XML, TEXT 등으로 데이터만 전달된다. |
단순 텍스트 응답, HTML 응답
HTML로 응답할 땐 setContentType을 반드시 "text/html" 로 지정해야한다.
@WebServlet(name = "responseHtmlServlet", urlPatterns = "/response-html")
public class ResponseHtmlServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
response.setCharacterEncoding("utf-8");
PrintWriter writer = response.getWriter();
writer.println("<html>");
writer.println("<body>");
writer.println("<div>안녕?</div>");
writer.println("</body>");
writer.println("</html>");
}
}
HTTP Message Body에 데이터를 직접 담아서 응답 - JSON형식
JSON으로 응답할 땐 setContentType을 반드시 "application/json" 로 지정해야한다.
private ObjectMapper objectMapper = new ObjectMapper();
String
result = objectMapper.writeValueAsString(helloData);
// Jackson라이브러리가 HelloData클래스 객체를 json문자열로 변경해주었다.
@WebServlet(name="responseJsonServlet", urlPatterns = "/response-json")
public class ResponseJsonServlet extends HttpServlet {
private ObjectMapper objectMapper = new ObjectMapper();
//클래스 객체를 Json데이터 형식으로 변환해준다.
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
HelloData helloData = new HelloData();
helloData.setUsername("kim");
helloData.setAge(30);
String result = objectMapper.writeValueAsString(helloData);
response.getWriter().write(result);
}
}
정리
서블릿 클래스
@WebServlet(name="서블릿명", urlPatterns = "/요청받을 경로")
public class HelloServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
Request객체
파라미터 키로 값 조회 : String username = request.getParameter("username")
파라미터 키에 값이 2개인 경우 : String[] usernames = request.getParameterValues("username")
파라미터명 모두 조회 : Enumeration<String> parameterNames = request.getParameterNames();
Response객체
응답상태 설정 : response.setStatus(HttpServletResponse.SC_OK);
페이지 이동 : response.sendRedirect("/basic/hello-form.html");
요청받기&응답하기
요청받기 | GET 방식 | Query Parameter 사용 ?username=kim&age=20 |
POST 방식 | FORM태그 사용 <form method="post" action="/전달주소"> |
|
JSON 데이터 | ServletInputStream inputStream = request.getInputStream(); String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8); private ObjectMapper objectMapper = new ObjectMapper(); HelloData helloData = objectMapper.readValue(messageBody, HelloData.class); |
|
응답하기 | 단순텍스트 응답 | response.getWriter().write("OK"); |
HTML 응답 | response.setContentType("text/html"); response.getWriter().println("<html><body>"); response.getWriter().println("<div>안녕?</div>"); response.getWriter().println("</body></html>"); |
|
JSON 데이터 | response.setContentType("application/json"); HelloData helloData = new HelloData(); helloData.setUsername("kim"); helloData.setAge(30); private ObjectMapper objectMapper = new ObjectMapper(); String result = objectMapper.writeValueAsString(helloData); response.getWriter().write(result); |
인프런 - 스프링MVC 백엔드 웹개발 핵심기술
'Backend' 카테고리의 다른 글
FrontController, View, Model, Adapter, Handler (0) | 2021.12.01 |
---|---|
서블릿, JSP, MVC패턴 (0) | 2021.11.25 |
웹 애플리케이션의 이해 (0) | 2021.11.23 |
SQL EXISTS, NOT EXISTS / IN, NOT IN (0) | 2021.11.15 |
Oracle Live SQL 사용하기 (DB설치없이 EMP, DEPT 테이블로 SQL실습하기) + 추가 : 기존작업 이어서하는방법 (0) | 2021.11.02 |