Filter는 Servlet이 제공하는 기능
Intercepter는 Spring이 제공하는 기능
게시글 작성 Controller에서 로그인 여부를 체크하는 Logic을 작성하면?
- 실제로는 수정, 삭제, 조회 등 모든 컨트롤러에 공통으로 로그인 여부를 체크해야 한다.
- 로그인 로직이 변경될 때 마다 로그인 여부를 체크하는 Logic 또한 변경될 가능성이 높다.
@Controller
@RequestMapping("/post")
public class PostController {
@PostMapping("/")
public void create(CreateRequestDto requestDto) {
// 로그인 여부 확인 로직
}
@PutMapping("/")
public void update(UpdateRequestDto requestDto) {
// 로그인 여부 확인 로직
}
@DeleteMapping("/")
public void delete(DeleteRequestDto requestDto) {
// 로그인 여부 확인 로직
}
}
여러가지 로직에서 공통으로 관심이 있는 부분(로그인 등)을 공통 관심사라고 한다
Servlet Filter
- 보안, 로깅, 인코딩, 인증/인가 등 다양한 작업을 처리하기 위해 사용
1. 공통 관심사 로직 -> 중앙 집중적인 로직 구현
2. HTTP 요청, 응답을 중간에 필터링할 수 있다
3. Filter Chain -> 여러 개의 필터가 순차적으로 적용될 수 있다
- filterChain.doFilter(request, response); 다음 필터로 제어를 전달한다
4. doFilter -> 실제 필터링 작업을 수행하는 주요 메소드
Filter 적용후
- Filter를 적용하면 Servlet이 호출되기 이전에 Filter를 항상 거치게된다.
- 공통 관심사를 필터에만 적용하면 모든 요청 or 응답에 적용된다 .
- Filter는 특정 URL Pattern에 적용할 수 있다.
- ex) /* : 모든 요청 필터
- Spring을 사용하는 경우 Servlet은 Dispatcher Servlet이다.
Filter Chain
- Filter는 Chain 형식으로 구성된다.
- Filter는 개발자가 자유롭게 추가할 수 있다.
- Filter는 순서를 지정하여 추가할 수 있다.
Filter Interface
package jakarta.servlet;
import java.io.IOException;
public interface Filter {
// default
public default void init(FilterConfig filterConfig) {
}
public void doFilter(
SevletRequest request,
SevletResponse response,
FilterChain chain
) throws IOException, ServletException;
// default
public default void destroy() {
}
}
Filter Interface를 Implements하여 구현하고 등록하면 Servlet Container가 Filter를 Singleton 객체로 생성 및 관리한다
- doFilter()
- Client에서 요청이 올 때 마다 doFilter() 메서드가 호출된다.
- doFilter() 내부에 필터 로직(공통 관심사 로직)을 구현하면 된다.
- WAS에서 doFilter() 를 호출해주고 하나의 필터의 doFilter()가 통과된다면
- Filter Chain에 따라서 순서대로 doFilter() 를 호출한다.
- 더이상 doFilter() 를 호출할 Filter가 없으면 Servlet이 호출된다.
- Client에서 요청이 올 때 마다 doFilter() 메서드가 호출된다.
- init()
- Filter를 초기화하는 메서드이다.
- Servlet Container가 생성될 때 호출된다.
- default method이기 때문에 implements 후 구현하지 않아도 된다.
- destroy()
- 필터를 종료하는 메서드이다.
- Servlet Container가 종료될 때 호출된다.
- default method이기 때문에 implements 후 구현하지 않아도 된다.
Servlet Filter 구현
Filter 구현체
@Slf4j
public class CustomFilter implements Filter {
@Override
public void doFilter(
ServletRequest request,
ServletResponse response,
FilterChain chain
) throws IOException, ServletException {
// Filter에서 수행할 Logic
HttpServletRequest httpRequest = (HttpServletRequest) request;
String requestURI = httpRequest.getRequestURI();
try {
log.info("request URI={}", requestURI);
chain.doFilter(request, response); // chain 이 없으면 Servlet을 바로 호출
} catch(Exception e) {
throw e;
}
}
}
servletRequest는 기능이 별로없고 대부분 기능이 많은 HttpServletRequest 를 사용한다
Filter 등록
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Bean
public FilterRegistrationBean customFilter() {
FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>();
filterRegistrationBean.setFilter(new CustomFilter()); // Filter 등록
filterRegistrationBean.setOrder(1); // Filter 순서 설정
filterRegistrationBean.addUrlPatterns("/*"); // 전체 URL에 Filter 적용
return filterRegistrationBean;
}
}
Postman 호출
GET http://localhost:8080/test
filterRegistrationBean.addUrlPatterns("/*")
- 모든 Request는 Custom Filter를 항상 지나간다
정리
1. Filter를 사용하려면 Filter Interface를 Implements 하여 구현해야 한다.
2. HTTP 요청이 오면 doFilter()메서드가 호출된다
-> ServletRequest는 기능이 별로 없으니 HttpServletRequest로 다운캐스팅 해야한다
chain.doFilter(request, response)
- (순서를 설정해둔)다음 필터가 있으면 Filter를 호출한다
- 다음 실행할 필터가 없으면 Servlet을 호출한다
- 해당 메서드를 호출하지 않으면 다음 단계로 진행되지 않는다
- > 다음 필터나 Servlet을 호출하지 않는다
Filter를 등록하는 방법은 여러가지가 있다. SpringBoot의 경우
FilterRegistrationBean 사용
setFilter()
- > 등록할 필터를 파라미터로 전달하면 된다
setOrder()
- Filter는 Chain 형태로 동작한다.
- 즉, 실행될 Filter들의 순서가 필요하다.
- 파라미터로 전달될 숫자에 따라 우선순위가 정해진다.
- 숫자가 낮을수록 우선순위가 높다.
addUrlPatterns()
- 필터를 적용할 URL 패턴을 지정한다.
- 여러개 URL 패턴을 한번에 지정할 수 있다.
- 규칙은 Servlet url-pattern과 같다.
코끼리를 냉장고에 넣는 방법 :: [서블릿/JSP] 서블릿 맵핑시 url-pattern 규칙 (tistory.com)
[서블릿/JSP] 서블릿 맵핑시 url-pattern 규칙
서블릿(Servlet) 맵핑시 url-pattern 규칙 구현한 서블릿은 특정 URL에 맵핑을 시켜주어야 합니다. 그래야 클라이언트에서 해당 URL로 요청시 해당 서블릿이 요청을 처리할 수 있기 때문입니다. URL 맵핑
dololak.tistory.com
'Springboot' 카테고리의 다른 글
AWS # Identity and Access Management (0) | 2024.07.05 |
---|---|
QueryDSL, Auditing, Dynamic Insert/Update (0) | 2024.07.01 |
테이블 객체 만들기 (0) | 2024.06.28 |
쿼리 파일 만들기 (QueryMapper) (0) | 2024.06.28 |
데이터베이스 연결(Driver) (0) | 2024.06.27 |