스프링이 자동으로 내 패키지를 포함한 모든 하위패키지에 있는 서플릿을 찾아 자동으로 서플릿 등록을 해주기 위해 @ServletComponentScan 어노테이션을 추가한다.
@ServletComponentScan // 서블릿 자동 등록
public class ServletApplication {

서플릿 등록하기
@WebServlet 어노테이션 추가한다. // name: 서블릿 이름, urlPatterns: URL 매핑
// "/hello" 이 호출되면 서블릿 컨테이너는 해당 메서드 실행
@WebServlet(name = "helloServlet", urlPatterns = "/hello")
서비스 메서드 추가
ctrl + O 단축키를 누르면 쉽게 생성할 수 있음.
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
퀴리 파라미터로 request 요청을 받기
--> 쿼리 파라미터를 읽는 코드를 작성한다.
String username = request.getParameter("username");
http://localhost:8080/hello?username=kim 에 들어가고 쿼리 파라미터로 받은 값을 출력해보면 정상적으로 쿼리 파라미터 값을 받은 것을 확인할 수 있다.

response 응답 메세지
response.setContentType("text/plain");
response.setCharacterEncoding("utf-8");
response.getWriter().write("hello " + username); // HTTP 메시지 바디에 write
서플릿 컨테이너 동작 방식

HTTP 요청 메시지를 파싱한 결과를 HttpServletRequest 객체에 담아 제공하여, HTTP 요청 메시지를 편리하게 조회할 수 있다.
HTTP 요청 메시지
POST /save HTTP/1.1
Host: localhost:8080
Content-Type: application/x-www-form-urlencoded
username=kim&age=20
HttpServletRequest의 부가기능
임시 저장소 기능 세션 관리 기능
세션 관리 기능
서블릿 어노테이션을 추가한다
@WebServlet(name = "requestHeaderServlet", urlPatterns = "/request-header")
public class RequestHeaderServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
START LINE 정보
request.getMethod() // 메서드
request.getProtocol() // 프로트콜
request.getScheme() // 스키마
request.getRequestURL() // 요청 url
request.getRequestURI() // 요청 uri
request.getQueryString() // 쿼리 파라미터
request.isSecure() // 보안(https)

헤더 정보
HTTP 요청 메시지의 모든 헤더의 내용을 출력하기 위한 메서드를 만들어 내용을 확인한다.
request.getHeaderNames().asIterator().forEachRemaining(headerName -> System.out.println(headerName + " : " + headerName)));
모든 정보 말고도 원하는 헤더의 내용을 확인할 수 있다.
request.getServerName() // 이름
request.getServerPort() // 포트
request.getLocales().asIterator() // 언어
.forEachRemaining(locale -> System.out.println("locale = " + locale));
request.getLocale()
if (request.getCookies() != null) { // 쿠키
for (Cookie cookie : request.getCookies()) {
System.out.println(cookie.getName() + ": " + cookie.getValue());
}
}
request.getContentType() // content 타입
request.getContentLength() // content 길이
request.getCharacterEncoding() // 인코딩

기타 정보
네트워크 커넥션등에 대한 정보
request.getRemoteHost()
request.getRemoteAddr()
request.getRemotePort()
request.getLocalName()
request.getLocalAddr()
request.getLocalPort()
주로 3가지 방법을 사용한다
1. GET - 쿼리 파라미터
2. POST - HTML Form

3. HTTP message body에 데이터를 직접 담아서 요청
전달 데이터
메시지 바디 없이 URL의 쿼리 파라미터를 사용해서 데이터를 전달해보자
쿼리파라미터는 URL에 다음과 같이
?를 시작으로 보낼 수 있으며,
추가 파라미터는&로 구분하면 된다.
http://localhost:8080/request-param?username=hello&age=20
서버에서는 HttpServletRequest가 제공하는 다음 메서들을 통해 쿼리 파라미터를 편리하게 조회할 수 있다.
System.out.println("[전체 파라미터 조회] - start");
request.getParameterNames().asIterator().forEachRemaining(paramName ->
System.out.println(paramName + " : " + request.getParameter(paramName)));
System.out.println("[전체 파라미터 조회] - end");
System.out.println("[단일 파라미터 조회] - start");
String username = request.getParameter("username");
String age = request.getParameter("age");
System.out.println("username = " + username);
System.out.println("age = " + age);
System.out.println("[이름이 같은 복수 파라미터 조회] - start");
String[] usernames = request.getParameterValues("username");
for (String name : usernames) {
System.out.println("name = " + name);
}
복수 파라미터에서 단일 파라미터 조회
username=hello&username=kim과 같이 파라미터 이름은 하나인데, 값이 중복이면 어떻게 될까?
--> request.getParameter()는 하나의 파라미터 이름에 대해서 단 하나의 값만 있을 때 사용해야 한다.
지금처럼 중복일 때에는 request.getParamValues()를 사용해야 한다.
참고) 중복일 때, request.getParameter()를 사용하면, request.getParameterValue()의 첫번째 값을 반환한다.
이번에는 HTML의 Form을 사용해서 클라이언트에서 서버로 데이터를 전송해보자
주로 회원 가입, 상품 주문 등에서 사용하는 방식이다
특징
username=hello&age=20hello-form.html 생성

실행해보자

POST의 HTML Form을 전송하면 웹 브라우저는 다음 형식으로 HTTP 메시지를 만든다. (웹 브라우저 개발자 모드 확인)
application/x-www-form-urlencodedusername=hello&age=20application/x-www-form-urlencoded형식은 앞서 GET에서 살펴본 쿼리 파라미터 형식과 같다. 따라서 쿼리 파라미터 조회 메서드를 그대로 사용하면 된다.
클라이언트(웹 브라우저) 입장에서는 두 방식에 차이가 있지만, 서버 입장에서는 둘의 형식이 동일하므로, request.getParameter()로 편리하게 구분 없이 조회할 수 있다.
정리하자면,
request.getParameeter()는 GET URL 쿼리 파라미터 형식도 지원하고, POST HTML Form 형식 둘다 지원한다.
참고
content-type은 HTTP 메시지 바디의 데이터 형식을 지정한다.
GET URL 쿼리 파라미터 형식 으로 클라이언트에서 서버로 데이터를 전달할 때는 HTTP 메시지 바디를 사용하지 않기 때문에 content-type이 없다.
POST HTML Form 형식으로 데이터를 전달하면 HTTP 메시지 바디에 해당 데이터를 포함해서 보내기 때문에
바디에 포함된 데이터가 어떤 형식인지 content-type을 꼭 지정해야 한다. 이렇게 폼으로 데이터를 전송하는 형식을 application/x-www-form-urlencoded라 한다
간단한 테스트를 하기 위해선 Postman을 사용하자

를 입력하면
결과를 확인할 수 있다
먼저 가장 단순한 텍스트 메시지를 HTTP 메시지 바디에 담아서 전송하고 읽어보자
HTTP메시지 바디의 데이터를 inputStream을 사용해서 직접 읽을 수 있다.
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);
response.getWriter().write("OK");
}
Postman을 사용해서 테스트를 해보자


가 출력되는 것을 알 수 있다.
JSON 형식 파싱 추가
JSON 형식으로 파싱할 수 있게 객체를 하나 생성한다.

@WebServlet(name = "requestBodyJsonServlet", urlPatterns = "/request-body-json")
public class RequestBodyJsonServlet extends HttpServlet {
//JSON 결과를 파싱해서 객체로 변환하기 위해 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);
HelloData helloData = objectMapper.readValue(messageBody, HelloData.class);
System.out.println("helloData.getUsername() = " + helloData.getUsername());
System.out.println("helloData.getAge() = " + helloData.getAge());
}
}
private ObjectMapper objectMapper = new ObjectMapper();
HelloData helloData = objectMapper.readValue(messageBody, HelloData.class)


HttpServletResponse 역할
HTTP 응답 메시지에 넣을 값들을 작성한다
//[status -line]
response.setStatus(HttpServletResponse.SC_OK);
//[response-headers]
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");
http://localhost:8080/response-header 에 들어가면
위의 작성한 응답 데이터를 확인할 수 있다.

private void content(HttpServletResponse response) {
// response.setHeader("Content-type", "text/plain;charset=utf-8");
response.setContentType("text/plain");
response.setCharacterEncoding("utf-8");
}
private void cookie(HttpServletResponse response) {
//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 {
response.sendRedirect("/basic/hello-form.html");
}

@WebServlet(name = "responseHtmlServlet", urlPatterns = "/response-html")
public class ResponseHtmlServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//Content-Type: text/html;charset=utf-8;
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>");
}
}
응답 메시지의 헤더 값을 설정해둔다
response.setContentType("text/html");
respinse.setCharacterEncoding("utf-8");
message body로 HTML 응답을 보내준다
PrintWriter writer = response.getWriter();
writer.println("<html>");
writer.println("<body>");
writer.println(" <div>안녕?</div>");
writer.println("</body>");
writer.println("</html>");
http://localhost:8080/response-html 에 들어가면,

이렇게 응답 데이터가 정상적으로 보내진 것을 확인할 수 있다.
HTTP 응답으로 HTML을 반환할 떄, Content-type을 text/html로 지정하면 된다.
@WebServlet(name = "responseJsonServlet", urlPatterns = "/response-json")
public class ResponseJsonServlet extends HttpServlet {
private ObjectMapper objectMapper = new ObjectMapper();
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//Content-type : application/json
response.setContentType("application/json");
HelloData helloData = new HelloData();
helloData.setUsername("kim");
helloData.setAge(20);
//객체를 JSON 형식으로 변환하기 위해, JSON 변환 라이브러리 사용
//{"username":"kim","age":20}
String result = objectMapper.writeValueAsString(helloData);
response.getWriter().write(result);
}
}
헤더 값을 설정해준다
response.setContentType("application/json")
username, age를 넣어서 HelloData 객체를 만든다
HelloData helloData = new HelloData();
helloData.setUsername("kim");
helloData.setAge(20);
객체를 JSON 형식으로 변경하기 위해, JSON 변환 라이브러리인 ObjectMapper를 사용한다.
private ObjectMapper objectMapper = new ObjectMapper();
...
String result = objectMapper.writeValueAsString(helloData);
response.getWriter().write(result);
http://localhost:8080/response-json 에 들어가면

정상적인 응답 데이터가 보내진 것을 확인할 수 있다.