elevne's Study Note
HttpServletRequest, HttpServletResponse 본문
HttpServletRequest, HttpServletResponse 두 클래스는 Java Servlet API 에서 사용되는 클래스로, HTTP 요청과 응답을 처리하는데 사용된다. 여기서 Servlet 이란 클라이언트의 요청을 처리하고 결과를 응답해주는 자바 웹 프로그래밍 기술을 말한다.
HttpServletResponse 는 HTTP 요청 정보를 캡슐화한다. 이 클래스는 클라이언트가 서버에 보낸 HTTP 요청정보를 나타내는 것으로, Servlet 에서 이 정보가 사용된다.
getParameter(String name) | HTTP 요청의 매개변수 값을 가져온다. |
getParameterMap() | 모든 HTTP 요청 매개변수를 매개변수 이름과 값으로 나타내는 Map 객체를 반환한다. |
getHeader(String name) | HTTP 요청 헤더 값을 가져온다. |
getHeaderNames() | HTTP 요청 헤더 이름을 나타내는 Enumeration 객체를 반환한다. |
getMethod() | HTTP 요청 메서드(POST, GET 등)를 가져온다. |
getRequestURI() | HTTP 요청 URI 를 가져온다. |
getInputStream() | 클라이언트가 전송한 바이너리 데이터(파일 등)를 읽어온다. |
간단한 예시로, 클라이언트가 폼에 입력한 데이터를 전송하는 HTTP POST 요청을 처리하는 Servlet 은 아래와 같이 작성될 수 있다.
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String name = request.getParameter("name");
String email = request.getParameter("email");
// name과 email을 처리하는 로직
}
또, getInputStream() 메서드로 클라이언트가 POST 나 PUT 방식으로 전송한 요청의 Body 부분에 포함된 바이너리 데이터를 읽어볼 수 있다. 예를 들어, 브라우저에서 파일을 첨부하여 POST 방식으로 요청을 보낸 후, getInputStream() 메서드를 사용하여 파일의 데이터를 읽을 수 있다.
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 클라이언트가 보낸 요청의 바이너리 데이터 읽기
InputStream inputStream = request.getInputStream();
// 바이너리 데이터를 저장할 파일 생성
File file = new File("/path/to/file.txt");
// 바이너리 데이터를 파일에 저장
try (OutputStream outputStream = new FileOutputStream(file)) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
} catch (IOException e) {
e.printStackTrace();
}
}
우선 getInputStream() 메서드를 통해 요청의 바이너리 데이터를 읽어들인 후, 바이너리 데이터를 저장할 파일 객체를 생성한다. 그 다음으로 읽어온 데이터를 FileOutputStream 을 사용하여 파일에 저장한다. InputStream 객체에서 데이터를 읽어와 OutputStream 객체에 쓰는 것으로, 바이너리 데이터를 파일에 저장할 수 있다. (try-with-resources 구문을 사용하여 OutputStream 객체를 자동으로 close 하여 자원 누수를 막는다)
HttpServletResponse 클래스는 HTTP 응답 정보를 캡슐화한다. 이 클래스는 Servlet 에서 생성되어 클라이언트로 보내지는 HTTP 응답 정보를 나타낸다.
setContentType(String type) | HTTP 응답의 Content-Type 헤더 값을 설정한다. |
setStatus(int sc) | HTTP 응답 상태 코드를 설정한다. |
getOutputStream() | 출력스트림을 반환한다. 이 스트림을 사용하여 클라이언트로 데이터를 보낸다. |
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head><title>Hello, World!</title></head>");
out.println("<body>");
out.println("<h1>Hello, World!</h1>");
out.println("</body></html>");
out.close();
}
위 코드를 사용하여 HTTP 응답의 Content-Type 헤더를 "text/html" 로 설정하고, 출력스트림을 이용하여 HTML 코드를 생성하여 클라이언트로 보내는 것이 가능하다.
웹사이트가 클라이언트에게 보이는 과정은 다음과 같다. 우선 클라이언트는 호스트에게 원하는 웹 페이지를 보여달라고 요청한다. 사용자의 요청은 WAS 에 도착 (e.g., 톰캣) 하게 되고, WAS 에 등록되어있는 URL 매핑 중 일치하는 자원을 찾는다. 클라이언트의 요청이 올바른 요청이라면 해당 자원을 만들거나, 이미 있는 자원을 응답한다. 웹 서버에서 응답한 자원이 요청 보냈던 클라이언트의 웹 브라우저에 도착하고, 웹 브라우저는 응답받은 내용을 해석하여 사용자에게 보여준다.
위 이미지는 Servlet 의 동작 구조를 보여준다. 클라이언트 요청에 따라 서블릿 컨테이너는 service() 메서드를 호출하고, service() 메서드는 요청인 GET 인지 POST 인지 구분하여 각각 doGet(), doPost() 메서드를 호출하게 된다. (PUT, DELETE 등에 대해서 분기 처리를 진행하여 doPut, doDelete 등의 메서드를 실행시킬 수도 있다.) HttpServlet 을 상속받는 Servlet 클래스를 작성하여 각종 요청에 대한 처리를 해줄 수 있는 것이다. (이 때 @WebServlet, @MultipartConfig 등의 어노테이션이 사용될 수 있다) 아래는 파일 업로드 처리를 해주는 Servlet 클래스 예시이다.
@WebServlet("/upload")
@MultipartConfig
public class FileUploadServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Part filePart = request.getPart("file");
InputStream fileContent = filePart.getInputStream();
File file = new File("/path/to/save/file.txt");
OutputStream outputStream = new FileOutputStream(file);
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = fileContent.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
outputStream.close();
fileContent.close();
response.sendRedirect("/upload_success.jsp");
}
}
만약 Spring Controller 을 이용하여 파일 업로드와 다운로드를 작성해본다면 아래와 같이 간단하게 해볼 수 있을 것이다.
@Controller
public class FileUploadController {
@PostMapping("/upload")
public String uploadFile(@RequestParam("file") MultipartFile file) throws IOException {
// 업로드된 파일을 처리하기 위한 코드 작성
if (!file.isEmpty()) {
byte[] bytes = file.getBytes();
Path path = Paths.get("/path/to/save/file.txt");
Files.write(path, bytes);
}
// 파일 업로드 완료 후 페이지 이동
return "upload_success";
}
}
@Controller
public class FileDownloadController {
@GetMapping("/download")
public ResponseEntity<Resource> downloadFile() throws IOException {
// 다운로드할 파일을 읽어서 Resource 객체로 만듦
Path path = Paths.get("/path/to/file.txt");
ByteArrayResource resource = new ByteArrayResource(Files.readAllBytes(path));
// 다운로드할 파일의 이름 설정
HttpHeaders headers = new HttpHeaders();
headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=file.txt");
// ResponseEntity를 사용하여 파일을 반환
return ResponseEntity.ok()
.headers(headers)
.contentLength(resource.contentLength())
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.body(resource);
}
}
파일 다운로드 코드에서 사용된 ResponseEntity 는 HTTP 응답을 나타내는 Spring 의 클래스이다. HTTP 상태코드, 응답헤더 및 응답본문과 같은 HTTP 응답을 모두 포함할 수 있다. (이를 사용하면 Spring 은 반환 값을 HTTP 응답으로 자동 변환해준다) Resource 는 Spring 에서 파일 시스템, 클래스 경로 또는 웹 URL 에 있는 리소스를 나타내는 인터페이스이다. ByteArrayResource 는 Resource 의 구현 클래스 중 하나로 바이트 배열을 가진 Resource 를 생성하는데 사용된다. Resource 는 보통 파일 다운로드와 같은 경우에 사용된다고 한다.
Reference:
'Backend > Java' 카테고리의 다른 글
Java - Multi Thread (1) (0) | 2023.05.07 |
---|---|
Java 중첩클래스/인터페이스, 익명클래스 (0) | 2023.05.04 |
Java (try-with-resources) (0) | 2023.04.29 |
Java (Singleton, 접근제어, Annotation) (0) | 2023.04.26 |
Java (Primitive Type, Reference Type ~) (0) | 2023.04.25 |