김영한님의 스프링 MVC 1편 강의를 듣고 정리하는 글입니다
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-1/dashboard
1. 스프링부트 서블릿 환경 구성
@ServletComponentScan // 서블릿 자동 등록
@SpringBootApplication
public class ServletApplication {
public static void main(String[] args) {
SpringApplication.run(ServletApplication.class, args);
}
}
스프링 부트에서 서블릿을 등록해서 사용할 수 있도록 @ServletComponentScan을 지원해준다. @CoponentScan과 마찬가지로 탐색 패키지를 지정해줄 수 있으며 해당되는 패키지 하위의 모든 컴포넌트로 등록된 Servlet을 스캔하는 역할을 한다.
2. 서블릿 등록
@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);
String username = request.getParameter("username");
System.out.println("username = " + username);
response.setContentType("text/plain");
response.setCharacterEncoding("utf-8");
response.getWriter().write("hello " + username);
}
}
- 서블릿을 등록할 때 @WebServlet을 사용한다.
- name은 서블릿 이름이며, urlPatterns는 url을 지정할 때 사용한다.
- 브라우저에서 " http://localhost:8080/hello" 를 입력하면 service 메서드가 호출된다.
- HttpServletReponse는 HTTP 응답메시지를 만들 수 있도록 다양한 메서드를 제공한다.
3. HttpServletRequest 사용법
HttpServletRequest는 서블릿에서 HTTP 메시지를 파싱해서 객체로 제공하여 HTTP 메시지를 다룰 수 있는 다양한 메서드를 제공한다.
HTTP 에 요청할 때 주로 3가지 방법을 사용한다.
1. GET - 쿼리 파라미터
2. POST - HTML Form 사용
3. HTTP message body
3가지 request에 대해 처리하는 방법을 예제를 통해 정리하겠다.
a. 헤더 및 기타 정보 다루기
HTTP 메시지의 헤더 및 기타 정보를 다루기 위한 다양한 메서드를 제공한다.
메서드 | 설명 |
getMethod() | HTTP 요청 메서드 반환(GET, POST ..) |
getProtool() | 요청 프로토콜 반환(HTTP/1.1) |
getRequestURL() | 요청 URL 반환(http://localhost:8080/request-header) |
getRequestURI() | 요청 URI 반환(/request-header) |
getQueryString() | 요청 쿼리파라미터 반환(username=강&age=10&username=김) |
isSecure() | https 적용 여부 반환(true / false) |
getHeaderNames() | 요청 메시지의 모든 헤더 반한(Enumeration 반환하므로 반복자로 출력) |
getServerName() | 서버 host 정보(localhost) |
getServerPort() | 서버 port 정보(8080) |
getLocals() | 모든 Accept-Language 반환(Enumeration 반환하므로 반복자로 출력) |
getLocal() | Accept-Language 반환(우선순위 높은 language 반환) |
getCookies() | 모든 쿠기 반환(배열 형태로 반환) |
getContentType() | Content-Type 반환( application/json) |
getContentLength() | Content-Length 반환 (5) |
getCharacterEncoding() | 인코딩 정보 반환 (UTF-8) |
getRemoteHost() | 요청자 host 반환(0:0:0:0:0:0:0:1) |
getRemoteAddr() | 요청자 주소 반환(0:0:0:0:0:0:0:1) |
getRemotePort() | 요청자 port 반환(60408) |
getLocalName() | 로컬 이름 반환(0:0:0:0:0:0:0:1) |
getLocalAddr() | 로컬 주소 반환(0:0:0:0:0:0:0:1) |
getLocalPort() | 로컬 port 반환(8080) |
메서드 사용 예시
@WebServlet(name = "requestHeaderServlet", urlPatterns = "/request-header")
public class RequestHeaderServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
printStartLine(request);
printHeaders(request);
printHeaderUtils(request);
printEtc(request);
}
// start-line
private void printStartLine(HttpServletRequest request) {
System.out.println("--- REQUEST-LINE - start ---");
System.out.println("request.getMethod() = " + request.getMethod()); //GET
System.out.println("request.getProtocal() = " + request.getProtocol()); //HTTP/1.1
System.out.println("request.getScheme() = " + request.getScheme()); //http
// System.out.println("request.getRequestURL() = " + request.getRequestURL()); // /request-test
System.out.println("request.getRequestURI() = " + request.getRequestURI()); //username=hi
System.out.println("request.getQueryString() = " + request.getQueryString());
System.out.println("request.isSecure() = " + request.isSecure()); //https 사용 유무
System.out.println("--- REQUEST-LINE - end ---");
System.out.println();
}
//Header 모든 정보
private void printHeaders(HttpServletRequest request) {
System.out.println("--- Headers - start ---");
request.getHeaderNames().asIterator()
.forEachRemaining(headerName -> System.out.println(headerName + ": " + headerName));
System.out.println("--- Headers - end ---");
System.out.println();
}
private void printHeaderUtils(HttpServletRequest request) {
System.out.println("--- Header 편의 조회 start ---");
System.out.println("[Host 편의 조회]");
System.out.println("request.getServerName() = " + request.getServerName()); //Host 헤더
System.out.println("request.getServerPort() = " + request.getServerPort()); //Host 헤더
System.out.println();
System.out.println("[Accept-Language 편의 조회]");
request.getLocales().asIterator()
.forEachRemaining(locale -> System.out.println("locale = " + locale));
System.out.println("request.getLocale() = " + request.getLocale());
System.out.println();
System.out.println("[cookie 편의 조회]");
if (request.getCookies() != null) {
for (Cookie cookie : request.getCookies()) {
System.out.println(cookie.getName() + ": " + cookie.getValue());
}
}
System.out.println();
System.out.println("[Content 편의 조회]");
System.out.println("request.getContentType() = " + request.getContentType());
System.out.println("request.getContentLength() = " + request.getContentLength());
System.out.println("request.getCharacterEncoding() = " + request.getCharacterEncoding());
System.out.println("--- Header 편의 조회 end ---");
System.out.println();
}
//기타 정보
private void printEtc(HttpServletRequest request) {
System.out.println("--- 기타 조회 start ---");
System.out.println("[Remote 정보]");
System.out.println("request.getRemoteHost() = " + request.getRemoteHost()); //
System.out.println("request.getRemoteAddr() = " + request.getRemoteAddr()); //
System.out.println("request.getRemotePort() = " + request.getRemotePort()); //
System.out.println();
System.out.println("[Local 정보]");
System.out.println("request.getLocalName() = " + request.getLocalName()); //
System.out.println("request.getLocalAddr() = " + request.getLocalAddr()); //
System.out.println("request.getLocalPort() = " + request.getLocalPort()); //
System.out.println("--- 기타 조회 end ---");
System.out.println();
}
}
b. GET 쿼리파라미터 / POST Form 요청 다루기
GET 요청의 쿼리파라미터, HTML Form으로 POST 요청을 보낼 때 모두 getParameter()를 통해 값을 조회할 수 있다.
@WebServlet(name = "requestParamServlet", urlPatterns = "/request-param")
public class RequestParamServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// getParameter() 는 쿼리스트링(get), 메시지바디 내용을 꺼낼 때 모두 사용
System.out.println("[전체 파라미터 조회] - start");
request.getParameterNames().asIterator()
.forEachRemaining(paramName -> System.out.println(paramName + "=" + request.getParameter(paramName)));
System.out.println("[전체 파라미터 조회] - end");
System.out.println();
System.out.println("[단일 파라미터 조회]");
String username = request.getParameter("username");
String age = request.getParameter("age");
System.out.println("username = " + username);
System.out.println("age = " + age);
System.out.println();
System.out.println("[이름이 같은 복수 파라미터 조회]");
String[] usernames = request.getParameterValues("username");
for (String name : usernames) {
System.out.println("username = " + name);
}
response.getWriter().write("ok");
}
}
c. 단순 텍스트 요청 다루기
HttpServletRequest의 getInputStream()으로 HTTP 메시지 바디의 바이너리 데이터를 읽어와서 String으로 변환해서 문자열로 다룰 수 있다.
@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);
response.getWriter().write("ok");
}
}
d .JSON 형식 요청 다루기
API 통신할 때 주로 JSON 형식으로 주고 받는다. JSON도 단순 바이너리 데이터이기 때문에 String으로 변환 후 JSON 변환 라이브러리인 Jackson에서 제공해주는 ObjectMapper를 사용하여 JSON형식의 데이터를 객체로 변환할 수 있다.
@Getter
@Setter
public class HelloData {
private String username;
private int age;
}
@WebServlet(name = "requestBodyJsonServlet", urlPatterns = "/request-body-json")
public class RequestBodyJsonServlet extends HttpServlet {
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.username = " + helloData.getUsername());
System.out.println("helloData.age = " + helloData.getAge());
response.getWriter().write("ok");
}
}
4. HttpServletResponse 사용
HttpServletResponse는 HTTP 응답 메시지를 생성에 필요한 다양한 메서드를 제공한다.
a. 응답코드 지정
setStatus로 응답코드를 지정할 수 있다.
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// [status-line]
response.setStatus(HttpServletResponse.SC_OK); // 200
response.setStatus(HttpServletResponse.SC_BAD_REQUEST); // 400
response.setStatus(HttpServletResponse.SC_FOUND); // 302
}
b. 헤더 생성
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 헤더 설정 방법
response.setHeader("Content-Type", "text/plain;charset=utf-8");
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
response.setHeader("Pargma", "no-cache");
response.setHeader("my-header", "hello");
// content 정보, 인코딩 정보 - 헤더
response.setContentType("text/plain");
response.setCharacterEncoding("utf-8");
// 쿠키 설정 - 헤더
Cookie cookie = new Cookie("myCookie", "good");
cookie.setMaxAge(600); //600초
response.addCookie(cookie);
// 리다이엑트 설정 - 헤더
response.sendRedirect("/basic/hello-form.html");
}
c. 바디 생성
1. 단순 텍스트 응답 메시지
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// [message body]
PrintWriter writer = response.getWriter();
writer.println("ok");
}
2. HTML 응답 메시지
@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>");
}
3. JSON 응답 메시지
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// Content-Type: application/json
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
HelloData helloData = new HelloData();
helloData.setUsername("kim");
helloData.setAge(20);
// {"username":"kim", "age":20}
String result = objectMapper.writeValueAsString(helloData);
response.getWriter().write(result);
}
'Programming > Spring' 카테고리의 다른 글
[Spring] 스프링 MVC 1편(MVC 프레임워크 만들기) (4) | 2024.03.14 |
---|---|
[Spring] 스프링 MVC 1편(서블릿, JSP MVC 패턴) (1) | 2024.02.27 |
[Spring] 스프링 MVC 1편(웹 애플리케이션 이해) (0) | 2024.01.22 |
[Spring] 웹 스코프란? (1) | 2024.01.11 |
[Spring] 싱글톤과 프로토타입 스코프 (1) | 2024.01.10 |