프로젝트 생성
Hello 서블릿
@ServletComponentScan
:스프링이 자동으로 현재 패키지 내 하위 패키지를 모두 뒤져서 서블릿을 찾고, 자동으로 서블릿을 등록 및 실행가능
@WebServlet : 서블릿 애노테이션
name: 서블릿 이름
urlPatterns: URL 매핑
HTTP 요청을 통해 매핑이된 URL이 호출되면 서블릿 컨테이너가 아래 메서드 (서비스메서드) 실행
String username = request.getParameter("username");
getParameter 로 요청받은 쿼리 파라미터 (?username=) 값을 읽을 수 있다.
== 참고 ==
서버가 받은 HTTP 요청 메시지가 콘솔창에 또한 출력된다.
스프링부트 실행 -> 내장톰캣서버(내부에 서블릿 컨테이너 기능을 갖고있다) 띄워줌 -> 서블릿 생성(helloServlet)
HTTP요청이 들어오면 서버는 request, respons 객체를 만든 후 싱글톤으로 떠있는 helloServlet을 호출해준다. -> service 메서드를 호출 -> request, respons를 넘겨준다
-> respons 객체에 원하는 정보를 입력한다 -> WAS 서버가 응답정보를 바탕으로 HTTP 응답 메시지를 만들어서 반환 -> 웹 브라우저에서 HelloWorld 볼 수 있다.
HttpServletRequest - 개요
START LINE
HTTP 메소드
URL
쿼리 스트링
스키마, 프로토콜
ex) POST /save HTTP/1.1
헤더
헤더 조회
ex) Host, Content-Type
바디
form 파라미터 형식 조회
message body 데이터 직접 조회
ex) 헤더 밑 부분
username=kim&age=20 과 같은 정보가 오면
request.getParameter 로 편리하게 읽을 수 있도록 지원한다
메세지 바디에 JSON 이 많이 들어가도, 메세지를 통으로 읽어들이는 기능도 지원한다.
(JSON을 parsing하려면 라이브러리가 필요함 -> 뒤에서 설명)
HttpServletRequest의 기능
1.임시 저장소 기능
- 자주 사용된다
저장: request.setAttribute(name,value)
조회: request.getAttribute(name)
2.세션 관리 기능
session? -> 로그인햇다 or 안했다 정보 유지 기능을 제공
HttpServletRequest - 기본 사용법
start-line 정보
헤더 정보
Enumeration<String> headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
System.out.println(headerName + ": " + request.getHeader(headerName));
getHeaderNames(): HTTP 요청 메세지에 있는 모든 헤더 정보를 전부 꺼내서 출력 가능
요즘은 위 코드 말고 아래코드 처럼 간략하게 사용
request.getHeaderNames().asIterator()
.forEachRemaining(headerName ->
System.out.println("headerName = " + headerName));
Header 편리한 조회
기타 정보
a-7a27b7ba3101/image.png)
HTTP 요청 데이터 - 개요
위 세가지 방식 잘 알아둬야 나중에 헷갈리지 않음
GET - 일반 구글 검색시 나오는 엄청 긴 쿼리 파라미터
POST - content-type: 어떤 바디인지 설명 해준다.
HTTP message body에 데이터를 직접 담아서 요청
HTTP 요청 데이터 - GET 쿼리 파라미터
전달 데이터
username=hello
age=20
메시지 바디 없이, URL의 쿼리파라미터(? 과 &)를 사용해서 데이터를 전달하자
전체 파라미터 조회
단일 파라미터 조회
이름이 같은 복수 파라미터 조회 (username=kim&username=you)
(if) value 값이 중복인데 request.getParameterValues(username)을 사용하지 않고
request.getParameter(username)를 사용하면 values 배열의 값들 중 가장 첫 번째 값을 반환한다.
HTTP 요청 데이터 - POST HTML Form
특징
message body가 존재하기 때문에 content-type : 'application/x-www-form-urlencoded' 가 존재한다.
GET 방식과 마찬가지로 message body에 쿼리 파라미터 형식으로 데이터를 전달한다.
request.getParameter()
1. GET 형식 (parameter)
2. POST 형식 (message body, form)
둘 다 모두 조회할 수 있다.
즉, 클라이언트 입장에서는 두 방식이 다르지만
서버 입장에서는 둘의 형식이 동일하다
정리 => request.getParameter() 는 GET URL 쿼리 파라미터 형식도 지원하고, POST HTML Form 형식도 둘 다 지원한다.
HTTP 요청 데이터 - API 메시지 바디 - 단순 테스트
HTTP message body에 데이터를 직접 담아서 요청
HTTP API에서 주로 사용, JSON, XML ,TEXT
데이터 형식은 주로 JSON 사용
ServletInputStream inputStream = request.getInputStream();
String messageBody = StreamUtils.copyToString(inputStream,
StandardCharsets.UTF_8);
HTTP 메시지 바디의 데이터를 InputStream으로 사용해서 "바이트코드"로 직접 읽을 수 있다.
읽은 "바이트코드"의 데이터를 spring에서 지원해주는 StreamUtils를 통해 문자열로 바꿀 수 있다
바이트 코드 <-> 문자열 인코딩 필수
HTTP 요청 데이터 - API 메시지 바디 - JSON
JSON 형식으로 파싱할 수 있게 객체 생성
@Getter @Setter // lombok 으로 get,set 메서드 생략 가능
public class HelloData {
private String username;
private int age;
}
JSON 결과를 파싱해서 자바 객체로 변환하기 위해 JSON 라이브러리 사용
(Spring boot로 Spring MVC를 선택해서 Jackson 라이브러리 함께 제공)
private ObjectMapper objectMapper = new ObjectMapper();
(참고) 전에 했던 두번째 방식인 HTML form 데이터도 결국에는 메시지 바디를 통해 전송되므로 직접 읽을 수 있다.
하지만 request.getParameter() 기능이 있으므로 그냥 파라미터 조회 기능을 사용하면 된다.
HttpServletResponse - 기본 사용법
HTTP 응답 메시지 생성
편의 기능 제공
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//[status-line]
response.setStatus(HttpServletResponse.SC_OK); //직접 200 적는거보다 이 방식이 낫다.
//[respons-header]
response.setHeader("Content-Type", "text/plain;charset=utf-8");
response.setHeader("Cache-Control", "no-cache,no-store,must-revalidate");
response.setHeader("Pragma", "no-cache");
response.setHeader("my-header", "hello"); //내가 원하는 헤더 만들기
//[Header 편의 메서드]
// content(response);
// cookie(response);
// redirect(response);
PrintWriter writer = response.getWriter();
writer.println("ok");
}
private void content(HttpServletResponse response) {
//Content-Type: text/plain;charset=utf-8
//Content-Length: 2 // println() 시에는 엔터가 들어가서 글자수 + 1 이 출력
//response.setHeader("Content-Type", "text/plain;charset=utf-8");
// response.setContentType("text/plain");
// response.setCharacterEncoding("utf-8");
// response.setContentLength(2); // (생략시 자동 생성)
}
private void cookie(HttpServletResponse response) {
//Set-Cookie: myCookie=good; Max-Age=600;
//response.setHeader("Set-Cookie", "myCookie=good; Max-Age=600");
Cookie cookie = new Cookie("myCookie", "good");
cookie.setMaxAge(600); //600초
response.addCookie(cookie);
}
private void redirect(HttpServletResponse response) throws IOException {
//Status Code 302
//Location: /basic/hello-form.html
// response.setStatus(HttpServletResponse.SC_FOUND); //302
// response.setHeader("Location", "/basic/hello-form.html");
response.sendRedirect("/basic/hello-form.html"); //위에 두 줄과 동일
}
HTTP 응답 데이터 - 단순 텍스트, HTML
** HTTP 응답 메시지는 주로 다음 내용을 담아서 전달한다.
HTTP 응답으로 HTML을 반환할 때는 content-type을 text/html 로 지정해야 한다.
//Conter-Type: text/html;charset=utf-8
response.setContentType("text/html"); //웹 브라우저가 html 렌더링 하기 위함 (출력은 안되지만 소스보기하면 html 태그가 보임)
response.setCharacterEncoding("utf-8");
응답 데이터 - API JSON
응답은 크게 세 가지
1. 단순 텍스트
2. HTML
3. message body에 직접 JSON 보내기
// json도 그냥 문자이기 때문에 형태 JSON문자로 바꿔줘야 한다
private ObjectMapper objectMapper = new ObjectMapper();
//{"username":"kim","age":20}
String result = objectMapper.writeValueAsString(data);
HTTP응답으로 JSON을 반환할 때는 Content-Type을 application/json으로 지정해야 한다.
Jackson 라이브러리가 제공하는 objectMapper.writeVaueAsString() 메서드를 사용해서 JSON문자로 변경할 수 있다.
정리
클라이언트 -> 서버
1. GET 방식 (메세지 바디 데이터 X, 단순 URL)
2. POST - HTML Form
위 두 방식의 파라미터와 URL이 (/url ? username=hello&age=20)이 보낼때는 다르지만
서버입장에서는 똑같기 때문에 그냥 요청파라미터를 읽는다고 퉁침
HTML Form 데이터를 전송할 때는 POST 방식만 가능
(단, 스프링에서는 PUT, PATCH로도 가능하게 해주긴 함) (???)
Reference
김영한 님 - 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술