61일차(2)/Spring Boot(11) : Error Controller, 에러 응답 기능 구현
- users 프로필이미지 저장경로 수정
- error controller, 에러 응답 페이지 생성
- users의 프로필이미지가 저장되는 경로 수정하기
updateform.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>/views/users/updateform.jsp</title>
<style>
/* 이미지 업로드 폼을 숨긴다 */
#imageForm{
display: none;
}
#profileImage{
width: 100px;
height: 100px;
border: 1px solid #cecece;
border-radius: 50%;
}
</style>
</head>
<body>
<div class="container">
<h3>회원 가입 수정 폼 입니다.</h3>
<a id="profileLink" href="javascript:">
<c:choose>
<c:when test="${ empty dto.profile }">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-person-circle" viewBox="0 0 16 16">
<path d="M11 6a3 3 0 1 1-6 0 3 3 0 0 1 6 0z"/>
<path fill-rule="evenodd" d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8zm8-7a7 7 0 0 0-5.468 11.37C3.242 11.226 4.805 10 8 10s4.757 1.225 5.468 2.37A7 7 0 0 0 8 1z"/>
</svg>
</c:when>
<c:otherwise>
<img id="profileImage" src="${pageContext.request.contextPath }/users/images/${dto.profile}">
</c:otherwise>
</c:choose>
</a>
<form action="${pageContext.request.contextPath}/users/update" method="post">
<input type="hidden" name="profile"
value="${ empty dto.profile ? 'empty' : dto.profile }"/>
<div>
<label for="id">아이디</label>
<input type="text" id="id" value="${dto.id}" disabled/>
</div>
<div>
<label for="email">이메일</label>
<input type="text" id="email" name="email" value="${dto.email}"/>
</div>
<button type="submit">수정확인</button>
<button type="reset">취소</button>
</form>
<form id="imageForm" action="${pageContext.request.contextPath}/users/profile_upload" method="post" enctype="multipart/form-data">
프로필 사진
<input type="file" id="image" name="image" accept=".jpg, .png, .gif"/>
<button type="submit">업로드</button>
</form>
</div>
<!-- sy_util.js 로딩 -->
<script src="${pageContext.request.contextPath }/resources/js/sy_util.js"></script>
<script>
//프로필 이미지 링크를 클릭하면
document.querySelector("#profileLink").addEventListener("click", function(){
// input type="file" 을 강제 클릭 시킨다.
document.querySelector("#image").click();
});
//프로필 이미지를 선택하면(바뀌면) 실행할 함수 등록
document.querySelector("#image").addEventListener("change", function(){
//ajax 전송할 폼의 참조값 얻어오기
const form=document.querySelector("#imageForm");
//gura_util.js 에 있는 함수를 이용해서 ajax 전송하기
ajaxFormPromise(form)
.then(function(response){
return response.json();
})
.then(function(data){
console.log(data);
// input name="profile" 요소의 value 값으로 이미지 경로 넣어주기
document.querySelector("input[name=profile]").value=data.imagePath;
// img 요소를 문자열로 작성한 다음
let img=`<img id="profileImage"
src="${pageContext.request.contextPath }/users/images/\${data.imagePath}">`;
//id 가 profileLink 인 요소의 내부(자식요소)에 덮어쓰기 하면서 html 형식으로 해석해 주세요 라는 의미
document.querySelector("#profileLink").innerHTML=img;
});
});
</script>
</body>
</html>
<c:otherwise>
<img id="profileImage"
src="${pageContext.request.contextPath}${dto.profile}"/>
</c:otherwise>
- 기존 뷰 페이지 응답 방식
- 이렇게 이미지를 저장할 경로를 수정해준다.
UsersServiceImpl
- @Value와 필드 추가
- getRealPath 대신 fileLocation 으로 수정
- 저장된 파일명만! 응답되도록 한다.
updateform.jsp
- imagePath를 json으로 응답받아서 화면에 출력하려면 javascript 부분도 이렇게 수정
- 위쪽에 출력하는 화면에서도 경로를 표시!
- 이미지를 응답하는 컨트롤러 메소드가 필요하다.
- GalleryController에서 메소드 복사해서 추가해주기!
@GetMapping(
value="/users/images/{imageName}",
produces = {MediaType.IMAGE_JPEG_VALUE, MediaType.IMAGE_PNG_VALUE, MediaType.IMAGE_GIF_VALUE}
)
@ResponseBody
public byte[] profileImage(@PathVariable("imageName") String imageName) throws IOException {
String absolutePath=fileLocation+File.separator+imageName;
//파일에서 읽어들일 InputStream
InputStream is=new FileInputStream(absolutePath);
//이미지 데이터(byte)를 읽어서 배열에 담아서 클라이언트에게 응답한다.
return IOUtils.toByteArray(is);
}
- 메소드명, 경로만 변경해서 사용 가능!
- 변경하면 콘솔 창에 이렇게 출력된다.
cafe/detail.jsp
- 댓글의 프로필 이미지 출력을 위해!
- users/images/ 경로를 추가해준다.
- include된 ajax_Comment_List 페이지에도 필요!!
WebConfig 에서 interceptor 추가
- 로그인하지 않아도 users/images/ 안의 이미지가 보이도록 exclude 처리시킨다.
- 이렇게 하면 기존 Legacy 프로젝트를 Spring Boot 프로젝트로 변경하는 것은 끝!
- 에러 응답 기능 추가하기!
- 만약 없는 페이지를 요청한다면? (error)
- 불가능한 요청 처리(없는 페이지) → 404 에 해당한다.
- 에러 상황 발생시 이런식으로 이미지가 나오도록 처리하려고 한다!
- Root 패키지에 클래스 생성
ErrorHandler
package com.sy.boot07;
import javax.servlet.RequestDispatcher;
import javax.servlet.http.HttpServletRequest;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
//ExceptionController에서 처리되지 않은 예외가 발생하면 여기로 실행 순서가 온다.
@Controller
public class ErrorHandler{
//application.properties에 server.error.path=/error 설정때문에 호출되는 컨트롤러 메소드
@GetMapping("/error")
public String handleError(HttpServletRequest request) {
//에러의 코드값을 읽어온다. 404,500,403 등
int code=(int)request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
if( code == HttpStatus.NOT_FOUND.value()) { //404
return "error/404";
}else if( code == HttpStatus.INTERNAL_SERVER_ERROR.value()){ //500
return "error/500";
}else {
return "error/info";
}
}
}
- ErrorHandler에서 ErrorController를 꼭 구현하지는 않아도 작동한다.
- 특정 요청을 처리할 수 있는 bean으로만 만들어주면 된다. (@Controller)
application.properties
server.error.path=/error
- 에러가 났을때 자동으로 /error 라는 경로가 요청되도록 한다. 리다이렉트 되는 것!
- ErrorController 를 구현한 클래스 작성
- 에러 코드를 request로 읽어와서 int로 변환하여 콘솔 창에 출력하게 해본다.
- 일단 기존에 만들어둔 error/info로 들어가도록 설정했다.
- 없는 페이지를 요청하면 콘솔 창에 404 가 찍힌다.
- 찍히는 코드에 따라서 if~else로 분기할 수도 있다!!
- 에러 코드가 404, 500번일 경우 별도의 페이지에서 응답하도록 처리해준다.
- 숫자로 그대로 넣는 대신 어떤 값을 상수화하여 정한 이름이 있다.(미리 저장되어있다)
- 숫자로 직접 써도 되고, 이렇게 상수값을 가져와서 value로 읽어서 사용해도 된다.
(상수를 사용하는 쪽이 가독성이 좋다)
- 이런 식으로 분기하면 에러 상황에 대한 세부적인 처리가 가능하다.
/views/error/404.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>/views/error/404.jsp</title>
</head>
<body>
<div class="container">
<h3>404</h3>
<p>
요청하신 페이지는 존재하지 않습니다.
<a href="${pageContext.request.contextPath}/">인덱스로</a>
</p>
</div>
</body>
</html>
- 404에러에 대해 클라이언트 브라우저에 이렇게 응답하게 할 수 있다.
- 경로생성, 경로요청을 처리할 컨트롤러(ErrorController를 구현)
- request 값에 에러 정보가 들어오면, 그것을 읽어내서
에러 코드가 몇번이냐에 따라 선택적으로 작업하여 응답한다.
- 서버내에서 연산/처리를 하다가 오류가 났을 때 500번 오류를 띄운다.
- exception에서 잡히지 않으면 error/info 페이지로 기본으로 들어감.
(미리 Exception Controller 에서 잡고 거기서 잡지 않는 것들을 이 ErrorHandler에서 처리
views/error/500.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>/views/error/500.jsp</title>
</head>
<body>
<div class="container">
<h3>500</h3>
<p>
서버 내부에서 에러가 발생했습니다. 조속히 복구하겠습니다.
<a href="${pageContext.request.contextPath}/">인덱스로</a>
</p>
</div>
</body>
</html>
- cafe/detail/ 을 하고, 요청하면서 파라미터 값을 전달해주지 않으면 이 에러가 발생한다.
- null 에러가 발생한다. 이것을 출력하는 대신 커스텀 에러 페이지를 출력한 것이다.
'국비교육(22-23)' 카테고리의 다른 글
63일차(1)/GitHub : Pull Request (0) | 2023.01.05 |
---|---|
62일차(1)/Spring Boot(12) : 로그인 폼 css추가, 로그인정보 저장 기능 구현 (1) | 2023.01.05 |
61일차(1)/Spring Boot(10) : file, gallery 게시판 파일 저장경로, 다운로드 기능 수정 / Boot 기능 활용 (0) | 2023.01.03 |
60일차(2)/Spring Boot(9) : 파일 저장경로 수정 / Boot 기능 활용 (0) | 2023.01.03 |
60일차(1)/Spring Boot(8) : Spring 프로젝트 Spring Boot로 이식하기 / Boot에서 war파일 생성(2) (0) | 2023.01.02 |