TIL/Servlet

[Servlet] response, exception-handler

yndev 2022. 3. 7. 08:55

서블릿이 하는 역할은 크게 3가지라고 볼 수 있다.

1. 요청 받기(HTTP method GET/POST 요청에 따른 parameter로 전달 받은 데이터를 꺼내올 수 있다)

2. 비즈니스 로직 처리(DB 접속과 CRUD에 대한 로직 처리 -> 서비스를 호출하는 쪽으로 해결(MVC))

3. 응답하기 (문자열로 동적인 웹(HTML 태그)페이지를 만들어서 스트림을 이용하여 내보내기)

 

사용자 브라우저에 응답하기 위해 HttpServletResponse가 가지는 getWriter() 메소드로 PrintWriter 인스턴스를 반환 받는다.

PrintWriter는 BufferedWriter와 형제격인 클래스이지만 더 많은 형태의 생성자를 제공하고 있어서 실제로는 범용성으로 인해 더 많이 사용 된다.

 

문자열을 이용해 사용자에게 내보내기를 할 페이지를 작성한다.

 

스트림을 이용해 내보내기

 

버퍼에 잔류한 데이터를 강제로 내보내고 스트림을 닫아준다.

 

'안녕' 부분이 출력이 안됐다.

 

기본 값은 text/plain이지만 html 태그를 사용하면 요청 시 text/html도 응답으로 수락 가능하도록 헤더 설정이 되어 있기 때문에 text/html로 인식을 하게 된다.
하지만 명시적으로 text/plain으로 설정하게 되면 html 태그를 태그로 인식하지 않고 문자열로 인식하게 된다.

응답 시에도 별도로 인코딩을 지정하지 않으면 기본적으로 설정 된 인코딩 방식을 따르게 된다. (ISO-8859-1)
 따라서 한글로 페이지를 응답하는 경우 글씨가 깨져서 나오게 된다.

 

이 때 응답할 인코딩 방식이 UTF-8임을 응답 헤더에 알려주게 되면 브라우저가 이를 해석할 때 UTF-8로 인식하고 해석하게 된다.
 즉, 한글 값이 깨지지 않게 된다. 
 주의할 점은 반드시 getWriter()로 스트림을 얻어오기 전에 설정해야 한다. 

 

참고로 위 두개의 설정을 한번에 설정할 수 있다.

 

전체코드

package com.greedy.section01.response;

import java.io.IOException;
import java.io.PrintWriter;

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("/response")
public class ResponseTestServlet extends HttpServlet {

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		//response.setContentType("text/plain");
		response.setContentType("text/html");
		
		System.out.println("default response encoding : " + response.getCharacterEncoding());
		
		response.setCharacterEncoding("UTF-8");
		System.out.println("changed response encoding : " + response.getCharacterEncoding());
		
		//response.setContentType("text/html; charset=UTF-8");
		
		PrintWriter out = response.getWriter();
		
		StringBuilder responseBuilder = new StringBuilder();
		responseBuilder.append("<!doctype html>\n")
						.append("<html>\n")
					    .append("<head>\n")
					    .append("</head>\n")
					    .append("<body>\n")
					    .append("<h1>안녕 servlet response</h1>\n")
					    .append("</body>\n")
					    .append("</html>");
		
		out.print(responseBuilder.toString());
		
		out.flush();
		
		out.close();
		
	}

}

 

 

request header 출력

 

request.getHeader()에 name값을 전달해서 값을 가져올 수 있다.

 

요청에 따라서 밀리세컨을 보여주고있다.

 

response header 출력

 

1초에 한번씩 새로고침한다. (응답헤더쪽에 리프레시라는 속성을 1이라고 전달했기 때문)

전체 코드

package com.greedy.section02.headers;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;

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("/headers")
public class HeaderPrintServlet extends HttpServlet {

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		Enumeration<String> headerNames = request.getHeaderNames();
		while(headerNames.hasMoreElements()) {
			System.out.println(headerNames.nextElement());
		}
		
		System.out.println("accept : " + request.getHeader("accept"));
		System.out.println("host : " + request.getHeader("host"));
		
		response.setContentType("text/html; charset=UTF-8");
		//response.setHeader("Refresh", "1");
		
		PrintWriter out = response.getWriter();
		
		long currentTime = System.currentTimeMillis();
		
		out.print("<h1>" + currentTime + "</h1>");
		
		out.close();
		
		
		Collection<String> responseHeaders = response.getHeaderNames();
		Iterator<String> iter = responseHeaders.iterator();
		while(iter.hasNext()) {
			String headerName = iter.next();
			System.out.println(headerName + " : " + response.getHeader(headerName));
		}
		
	}

}

exception-handler

 

기본적으로 tomcat에서 404 오류 화면을 보여주는 것

 

메시지를 추가하면 메시지 확인이 가능하다.

 

500번 오류페이지도 확인 가능

위의 화면을 그대로 내보내는 것이 좋지는 않다. 커스터마이징한 화면을 내보내는 것이 보기 좋다.

깃허브에서도 404 오류페이지를 커스터마이징한 페이지로 내보낸다.

 

400번 오류페이지 서블릿

 

500번 오류페이지 서블릿

 

web.xml에 404, 500오류가 일어나면 showErrorPage(또 다른 서블릿)로 넘어가도록 작성해준다.

 

또다른 showErrorPage 서블릿을 만들어준다.

톰캣에서 설정한 기본 오류페이지가 안 뜬다.

위의 값을 출력해보자.

 

응답 페이지에서 바로 출력해내는 코드

 

전체코드

showErrorPage서블릿

package com.greedy.section01.exception;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;

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("/showErrorPage")
public class ExceptionHandlerServlet extends HttpServlet {

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		Enumeration<String> attrName = request.getAttributeNames();
		while(attrName.hasMoreElements()) {
			System.out.println(attrName.nextElement());
		}
		
		String forwardRequestURI = (String) request.getAttribute("javax.servlet.forward.request_uri");
		String contextPath = (String) request.getAttribute("javax.servlet.forward.context_path");
		String servletPath = (String) request.getAttribute("javax.servlet.forward.servlet_path");
		Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
		String errorMessage = (String) request.getAttribute("javax.servlet.error.message");
		String servletName = (String) request.getAttribute("javax.servlet.error.servlet_name");
		String errorRequestURI = (String) request.getAttribute("javax.servlet.error.request_uri");
		
		System.out.println("forwardRequestURI : " + forwardRequestURI);
		System.out.println("contextPath : " + contextPath);
		System.out.println("servletPath : " + servletPath);
		System.out.println("statusCode : " + statusCode);
		System.out.println("errorMessage : " + errorMessage);
		System.out.println("servletName : " + servletName);
		System.out.println("errorRequestURI : " + errorRequestURI);
		
		StringBuilder errorPage = new StringBuilder();
		errorPage.append("<!doctype html>\n")
				.append("<html>\n")
				.append("<head>\n")
				.append("</head>\n")
				.append("<body>\n")
				.append("<h1 align='center'>")
				.append(statusCode)
				.append(" - ")
				.append(errorMessage)
				.append("</h1>")
				.append("</body>\n")
				.append("</body>\n")
				.append("</html>\n");
		
		response.setContentType("text/html; charset=UTF-8");
		PrintWriter out = response.getWriter();
		
		out.print(errorPage.toString());
		
		out.flush();
		out.close();
	}

}