Backchus 2020. 5. 12. 04:46

읽지 않은 알림이 있는 경우 메인 네비게이션 바의 알림 아이콘을 색이 있는 아이콘으로 변경한다..

 

HandlerInterceptor (Spring Framework 5.2.6.RELEASE API)

Intercept the execution of a handler. Called after HandlerMapping determined an appropriate handler object, but before HandlerAdapter invokes the handler. DispatcherServlet processes a handler in an execution chain, consisting of any number of interceptors

docs.spring.io

노티 핸들러 인터셉터 적용 범위

  • 리다이렉트 요청에는 적용하지 않기.
  • static 리소스 요청에는 적용하지 않기.

핸들러 인터셉터 등록

  • 웹 MVC 설정 커스터마이징
@Configuration
@RequiredArgsConstructor
public class WebConfig implements WebMvcConfigurer{
	// ToDo 인터셉터 등록
}

타임리프 + 부트스트랩

  • th:if 조건문으로 읽지 않은 메시지가 있는지 확인.
  • text-info 클래스로 아이콘에 파란색 적용.

핸들러 처리 이후 및 뷰 렌더링 이전에 처리를 위한 인터셉터를 작성

package me.weekbelt.studyolle.modules.notification;

@RequiredArgsConstructor
@Component
public class NotificationInterceptor implements HandlerInterceptor {

    private final NotificationRepository notificationRepository;

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response,
                           Object handler, ModelAndView modelAndView) throws Exception {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (modelAndView != null && !isRedirectView(modelAndView) && authentication != null
                && authentication.getPrincipal() instanceof UserAccount) {
            Account account =  ((UserAccount) authentication.getPrincipal()).getAccount();
            long count = notificationRepository.countByAccountAndChecked(account, false);
            modelAndView.addObject("hasNotification", count > 0);
        }
    }

    private boolean isRedirectView(ModelAndView modelAndView) {
        return modelAndView.getViewName().startsWith("redirect:")
                || modelAndView.getView() instanceof RedirectView;
    }

}

 

확인하지 않은 알림의 숫자를 가져오기위해 NotificationRepository에서 countByAccountAndChecked메소드를 추가한다.

package me.weekbelt.studyolle.modules.notification;

public interface NotificationRepository extends JpaRepository<Notification, Long> {
    long countByAccountAndChecked(Account account, boolean checked);
}

 

생성한 인터셉터를 적용시킨다.

package me.weekbelt.studyolle.infra.config;

@RequiredArgsConstructor
@Configuration
public class WebConfig implements WebMvcConfigurer {

    private final NotificationInterceptor notificationInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        List<String> staticResourcesPath = Arrays.stream(StaticResourceLocation.values())
                .flatMap(StaticResourceLocation::getPatterns)
                .collect(Collectors.toList());
        staticResourcesPath.add("/node_modules/**");

        registry.addInterceptor(notificationInterceptor)
                .excludePathPatterns(staticResourcesPath);
    }
}

 

네비게이션 바를 보여주는 fragments.html에서 main-nav fragment의 벨부분을 수정해준다.

<nav th:fragment="main-nav" class="navbar navbar-expand-sm navbar-dark bg-dark">
   
   // .........
   
            <li class="nav-item" sec:authorize="isAuthenticated()">
                <a class="nav-link" th:href="@{/notifications}">
                    <i th:if="${!hasNotification}" class="fa fa-bell-o" aria-hidden="true"></i>
                    <span class="text-info" th:if="${hasNotification}" ><i class="fa fa-bell" aria-hidden="true"></i></span>
                </a>
            </li>
            
   // ........
</nav>

 

 

참고: https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-JPA-%EC%9B%B9%EC%95%B1#

 

스프링과 JPA 기반 웹 애플리케이션 개발 - 인프런

이 강좌에서 여러분은 실제로 운영 중인 서비스를 스프링, JPA 그리고 타임리프를 비롯한 여러 자바 기반의 여러 오픈 소스 기술을 사용하여 웹 애플리케이션을 개발하는 과정을 학습할 수 있습�

www.inflearn.com