@ControllerAdvice를 사용해 404 에러 페이지를 커스텀하려 했습니다.
그러나 NoHandlerFoundException
가 @ControllerAdvice를 적용한 인스턴스에서 잡히지 않는 이슈가 발생했습니다.
static/error/404.html 경로에 html 파일을 위치시키는 방법으로 에러 페이지를 커스터마이징 할 수 있었지만, NoHandlerFoundException
이 잡히지 않는 이유가 궁금해 해결을 시도했습니다.
아직 처리되지 않은 에러를 처리해주는 GlobalExceptionHandler 객체입니다. 해당 클래스는 공통 에러가 발생했을 때 커스텀한 에러 페이지를 반환하는 역할을 합니다.
package org.kimtaehoondev.jpcollector.web.controller;
import lombok.RequiredArgsConstructor;
import org.kimtaehoondev.jpcollector.config.AdminProperties;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.NoHandlerFoundException;
@ControllerAdvice
@RequiredArgsConstructor
public class GlobalExceptionHandler {
private final AdminProperties properties;
@ExceptionHandler(Exception.class)
public String unexpected(Exception e, Model model) {
model.addAttribute("adminEmail", properties.getEmail());
return "view/error/500.html";
}
@ExceptionHandler(NoHandlerFoundException.class)
public String notFound(Exception e) {
return "view/error/404.html";
}
}
application.yml에 다음 설정이 필요합니다.
spring:
mvc:
throw-exception-if-no-handler-found: true
web:
resources:
add-mappings: false
핸들러가 존재하지 않아도 스프링은 NoHandlerFoundException
을 발생시키지 않습니다. 해당 에러를 발생시키기 위해 "application.yml" 에 throw-exception-if-no-handler-found
을 true로 변경합니다.
1285번쨰 줄을 확인하면 throwExceptionIfNoHandlerFound 라는 필드가 존재합니다. 해당 필드가 true일 때만 throw new NoHandlerFoundException 코드가 실행됩니다.
위 설정은 해당 필드를 true로 바꾸는 설정입니다.
다음 설정은 정적 리소스들에 대한 매핑을 끄는 설정입니다.
스프링은 존재하지 않는 핸들러가 들어왔을 때 자동으로 404 기본 에러 페이지를 매핑해줍니다.
따라서, 에러가 발생해도 스프링이 매핑을 하지 못하도록 정적 리소스들에 대한 설정을 꺼야 합니다.
spring:
web:
resources:
add-mappings: false
404 에러 페이지는 커스텀한 화면으로 출력되는 걸 확인했지만, css가 적용되지 않는 이슈를 확인했습니다.
앞서 정적 리소스들의 매핑을 껐으니, 필요한 정적 리소스들을 수동으로 매핑해줘야 합니다.
WebMvcConfigurer에 /static 경로로 들어왔을 때 classpath:/static/으로 매핑되도록 설정해줬습니다.
package org.kimtaehoondev.jpcollector.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class StaticConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**")
.addResourceLocations("classpath:/static/");
}
}
좋은 글 감사합니다. 자주 올게요 :)