스프링 부트 서블릿 환경 구성
스프링 부트에서 서블릿을 직접 등록하여 사용할 수 있도록 @ServletComponentScan을 지원한다.
package hello.servlet;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
@ServletComponentScan
@SpringBootApplication
public class ServletApplication {
public static void main(String[] args) {
SpringApplication.run(ServletApplication.class, args);
}
}
다음과 같이 애노테이션을 추가하게 되면
스프링이 자동으로 현재 나의 패키지인 hello.servlet을 기점으로 하위의 모든 패키지를 검색하여 서블릿을 자동 등록한다.
서블릿 등록하기
실제로 서블릿을 다음과 같이 등록할 수 있다.
package hello.servlet.basic;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@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);
}
}
서블릿을 사용하기 위해서는 다음과 같은 내용을 알아야한다.
1. HttpServlet의 상속을 통해 서블릿을 사용할 수 있다.
2. WebServlet 애노테이션을 통해 서블릿의 이름과 urlPattern(매핑정보)의 설정이 가능하다.
- 단 중복을 허용하지 않는다.
3. protected된 service 메소드를 override하여야 한다.
- 이유
접근자가 public인 service의 파라미터는 HttpServlet으로 시작하지 않고 Servlet으로 시작하는 ServletRequest, ServletResponse이다. 이 두 파라미터는 HttpServletRequest의 메서드를 호출할 수 없다.
https://coderanch.com/t/621449/java/Difference-ServletRequest-HttpServletRequest
Difference between ServletRequest & HttpServletRequest [Solved] (Servlets forum at Coderanch)
coderanch.com
이전에 설명했던대로 요청이 들어오면 WAS는 Request, Response 객체를 생성하여 서블릿에 던져준다
(그래서 파라미터로 들어오는 것!, 참고로 두 파라미터 형식은 인터페이스, 구현체는 WAS가 가진다)
HttpServletRequest - 개요
HTTP 요청 메세지를 개발자가 직접 파싱해도 되지만, 매우 불편할 것이다.
그래서 서블릿은 편리하게 HTTP 요청문을 파싱할 수 있도록 편의 객체를 제공한다
서블릿이 이 HTTP 요청메세지를 파싱하여 HttpServletRequest 객체에 담아서 제공한다.
POST /save HTTP/1.1
HOST: localhost:8080
Content-Type: application/x-www-form-urlencoded
username=kim&age=20
- START LINE
- HTTP 메소드
- URL
- 쿼리스트링(?username=~)
- 스키마, 프로토콜(POST, HTTP/1.1)
- 헤더 조회
- 바디
- form 파라미터 형식 조회
- message body 데이터 직접 조회
HttpServletRequest 객체는 이뿐만 아니라 여러가지 부가기능을 제공한다!
-> 임시 저장소 기능
해당 HTTP 요청이 시작부터 끝날때까지 유지되는 임시 저장소기능에 해당한다
MVC 패턴에서 주로 사용하게 될텐데, 다음과 같은 형식을 갖는다
request.setAttribute(name, value) // 값 넣고
request.getAttribute(name) // 값 꺼냄
request.getSession(create: true) // 로그인과 같은 세션 관리기능
HttpServletRequest - 기본 사용법
1) Start-Line 정보를 출력하는 방법
private void printStartLine(HttpServletRequest request){
System.out.println("--- Request Line - Start ---");
System.out.println("request.getMethod() = " + request.getMethod());
System.out.println("request.getProtocol() = " + request.getProtocol());
System.out.println("request.getScheme() = " + request.getScheme());
System.out.println("request.getRequestURL() = " + request.getRequestURL());
System.out.println("request.getRequestURI() = " + request.getRequestURI());
System.out.println("request.getQueryString() = " + request.getQueryString());
System.out.println("request.isSecure() = " + request.isSecure());
System.out.println("--- Request-Line - end ---");
System.out.println();
}
request.getMethod() - GET
request.getProtocol() - HTTP/1.1
request.getScheme() - http
request.getURL() - http://localhost:8080/request-header
request.getURI() - /request-header
request.getQueryString - username = hi
request.isSecure() - https 사용 유무(true or false로 반환)
2) 헤더 정보를 출력하는 방법
private void printHeaders(HttpServletRequest request){
System.out.println("--- Headers - Start ---");
/* Deprecated (Old Ways)
Enumeration<String> headerNames = request.getHeaderNames();
while(headerNames.hasMoreElements()){
String headerName = headerNames.nextElement();
System.out.println(headerName +":" + request.getHeader(headerName));
}
*/
request.getHeaderNames().asIterator()
.forEachRemaining(headerName -> System.out.println(headerName +":" + request.getHeader(headerName)) );
System.out.println("--- Headers - end ---");
System.out.println();
}
다음과 같은 로그 세팅으로도 출력가능(ApplicationProperties 수정)
logging.level.org.apache.coyote.http11 = debug
Header 편의 조회
private void printHeaderUtils(HttpServletRequest request){
System.out.println("--- Header 편의 조회 - Start ---");
System.out.println("[HOST 편의 조회]");
System.out.println("request.getServerName() = " + request.getServerName());
System.out.println("request.getServerPort() = " + request.getServerPort());
System.out.println("[Accept-Language 편의 조회]");
request.getLocales().asIterator()
.forEachRemaining(locale->System.out.println("locale : " + locale));
System.out.println("[Cookie 편의 조회]");
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 ---");
}
현재 GET을 통한 Request 정보를 받아서 사용하고 있기 때문에 getContentLength와 getContentType의 값이 -1/null로 되어있다.
POSTMAN을 통해 POST 방식으로 특정 데이터를 전송하면 값이 제대로 출력된다.
그리고 다시 기억해야할 것이 Legacy적인 EUC-KR 말고 UTF-8을 사용한다.
기타 정보 조회
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();
}
Remote 정보 - 요청 대상에 대한 정보를 내포한다
Local 정보 - 나의 서버에 대한 정보를 내포한다
이때 로컬에서 테스트하면 IPV6 정보가 나오는데 IPV4를 보고 싶다면 VM option에 다음 인자를 넣자
-Djava.net.preferIPv4Stack=true
'스프링 공부 (인프런 김영한 선생님) > 스프링 MVC 1편' 카테고리의 다른 글
[스프링 웹 MVC 1편] 6. HTTPServletResponse - 기본 사용법 (0) | 2023.05.20 |
---|---|
[스프링 웹 MVC 1편] 6. HTTP 요청 데이터 (0) | 2023.05.20 |
[스프링 웹 MVC 1편] 4. Hello 서블릿 (0) | 2023.05.17 |
[스프링 웹 MVC 1편] 3. 동시요청 - 멀티스레드 (0) | 2023.05.17 |
[스프링 웹 MVC 1편] 2. 서블릿 / 서블릿 컨테이너 (0) | 2023.05.16 |