Request, Response 객체를 이용한 요청 처리(1)
* 본 글은 뉴렉처(Newlecture) 채널의 서블릿, JSP 강의를 참고하여 작성되었습니다.
* 참고하면 좋을 글
패키지(3) java.io 의 입출력스트림 <InputStream, OutputStream, Reader, Writer>
데이터 흐름 ⇒ 단방향ex. 물 위→아래처럼) 파이프 개념사용자의 입력 데이터를 읽어드리는 통로 어떤 파일에 등록된 데이터/메시지를 입력 스트림으로 읽어들임⇒ 입력데이터(키보드)와 파일
velog.io
서블릿으로 응답용 html 문서 생성
브라우저를 통해 주소를 요청하게 되면 서버는 해당 요청을 받아 적절한 처리 후에 html 문서 형식으로 응답하게 된다.
요청을 받게 되면 톰캣은 서블릿의 service 메서드의 매개변수로 전달되는 request, response 객체를 생성한다.
(참고: https://ruugskc.tistory.com/5)
request 객체는 세부적으로 HttpServletRequest 클래스의 객체이며, HttpServletRequest 클래스는 사용자(브라우저)의 요청 정보를 저장하는 역할을 한다.
response 객체는 HttpServletResponse 클래스의 객체이며, HttpServletResponse 클래스는 내부 메서드를 사용해 html 문서를 작성하는 방식으로 브라우저에게 요청 결과를 응답하는 역할을 한다.
html 문서를 작성을 위한 두 개의 메서드
첫째, HttpServletResponse의 메서드 getOutputStream()이 반환하는 OutputStream 객체를 PrintStream 객체로 감싼 형태로 html 문서에 입력할 문자열을 전달할 수 있다.
즉, html 문서를 생성해 작성할 수 있다.
# PrintStream 클래스
- 문자열 전달에 필요한 클래스
- System.out 객체도 해당 클래스의 객체이며, 주요 메서드로는 print(), println(), printf() 등이 있다.
둘째, HttpServletResponse의 메서드 getWriter()가 반환하는 PrintWriter 객체를 이용하는 방법이 있다.
PrintWriter 객체는 PrintStream 객체와 동일하게 문자열을 전달하는 문자열 기반 스트림의 역할을 한다.
개인적으로, getWriter()를 쓸 때 getOutputStream()보다 코드 타이핑 양이 줄고 가독성이 좋아지기에 getWriter()를 사용하는 방법이 더 좋은 방법으로 보인다.
@WebServlet("/ex")
public class ExampleServlet extends HttpServlet {
@Override
public void service(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
int x = 3;
int y = 4;
// 응답으로 쓰일 html 문서 작성시 전달할 문자열 스트림 얻어오기
// 방법 1, 2 모두 java.io 패키지의 클래스를 사용하므로 import 필요
// 방법 1
OutputStream os = response.getOutputStream();
PrintStream out = new PrintStream(os, true);
// 방법 2
PrintWriter out = response.getWriter();
// 방법 1 또는 2로 구한 문자열 스트림인 out 객체 사용해 html 문서 작성
out.print("x와 y를 더한 값은 ");
out.print(x + y);
out.print("입니다.");
}
}
브라우저의 출력 형식 지정
각 브라우저마다 out.println()로 만들어진 문서를 출력하는 방식(컨텐츠 형식)이 다르다.
이를테면 크롬은 텍스트 파일로, 엣지는 html 문서로 해석하는 식이다.
이처럼 우리가 컨텐츠 형식을 브라우저에게 알려주지 않으면 브라우저는 자의적으로 문서를 해석하게 된다.
그래서 우리는 서버의 문자 인코딩 형식, 브라우저의 문자 해석 형식(문자셋-character set)을 모두 지정해야 어느 브라우저에서든 사이트가 똑같은 내용을 출력한다.
아래 코드를 보면 response 객체를 이용해 브라우저가 받을 문서 형식을 html로, 서버의 인코딩 형식과 브라우저의 문자셋을 UTF-8로 지정하고 있다.
// response는 서블릿의 매개변수로 전달되는 HttpServletResponse객체
// 서버(톰캣)의 인코딩 형식 지정
response.setCharacterEncoding("UTF-8");
// 브라우저의 문자셋 지정
response.setContentType("text/html; charset=UTF-8");
브라우저의 요청 방식과 request 객체
브라우저의 요청 방식에는 크게 GET과 POST 두 가지가 있으며, 그중 GET 요청이 빈번하게 쓰인다.
(그 외에도 http 방식에서 쓰이는 메서드는 여러 개가 있지만, 지금은 몰라도 될 것 같다.)
우리가 브라우저의 주소창에 주소를 치게 되면 서버에 대한 GET 요청이 실행된다.
주소만 입력하는 GET 요청으로 html 문서를 받을 수 있지만, 주소 뒤에 ?로 시작하는 쿼리 스트링(질의 문자열)을 통해 GET 요청과 함께 서버에 인자를 전달할 수 있다.
물음표로 쿼리 스트링을 시작하고 입력하는 인자의 형식은 파라미터명=값이다.
http://localhost:8080/hello : GET 요청
http://localhost:8080/hello?val=12 : GET 요청 - 쿼리 스트링을 이용해 인자(값이 12인 파라미터 val)를 서버에 전달
사용자가 쿼리 스트링을 통해 서버에 전달한 인자 정보는 request 객체에 저장되며, request 객체의 getParameter("파라미터명")를 통해 인자값을 String 형태로 얻어올 수 있다.
원하는 인자값을 제대로 활용하기 위해서는 String 형태에서 형변환을 한 뒤 사용해야 한다.
쿼리 스트링의 형태에 따라 파라미터의 전달 여부, 값의 유무가 달라지기도 한다.
아래 표는 이를 정리한 것이다.
(요청할 주소는 http://localhost:8080/exam, 파라미터 이름은 val로 가정)
쿼리 스트링의 형태 (http://localhost:8080 이후의 내용) |
서버로 파라미터가 전달 X | 전달은 되나 값이 X | ||
/exam | /exam? | /exam?val | /exam?val= | |
request.getParameter("val") | null | null | ""(빈 문자열) | ""(빈 문자열) |
따라서 아래 코드처럼 파라미터의 형태에 따른 예외 처리를 진행해야 요청 에러를 줄일 수 있다.
// 서블릿의 service 메서드 안이라고 가정
int x = request.getParameter("x"); // 안됨! int형 변수에 String 객체가 저장될 수 없음
// 형변환만 해줘도 나쁘지 않음
// 하지만 형변환 과정에서 예외가 발생할 수 있기에 따로 처리해주면 좋음
int x = Integer.parseInt(request.getParameter("x"));
// 파라미터 x가 없거나, x에 빈 문자열이 들어가는 경우를 따로 처리해준 코드
// 어느 정도 예외 처리가 됨
String _x = request.getParameter("x");
int x;
if(_x != null && _x != "")
x = Integer.parseInt(_x);