1. Filter & Interceptor 기본 개념
모든 사용자가 같이 필요한 기능
ex ) 로그인, 보안
일반적인 spring application의 모습
springboot는 tomcat이 둘러싸게 됨 = web container
1. Filter
보안을 구현하기 위해 filter 사용
- springboot 외부에 있는 기능
- 외부client과 dispatcher servlet 사이에 들어옴
- Filter : jakarta servlet api의 일부
- spring framework의 일부분이 아니라 java로 만든 웹서버에서 사용하게 되는 interface
- springapplication에 도달하기 전에 모든 요청 막아 낼 수 있음
- 한개의 함수만 존재
doFilter() 함수인자로 ServeletRequest , ServeltResponse , FilterChain 받음
- http servelet resquest response보다 한단계 더 위 -> serveletReques, response를 상속받는 개체들임
- 모호한 객체 사용 이유 : ServeletRequest, Response를 조작가능.
- FilterChain : 여러개의 filter중 chain이라는 FilterChain에 속해있는 doFilter 호출 -> 모든 filter들이 호출됨
2. Interceptor
- 내부에서 구현
- fullname = HandlerInterceptor : handler mapping에 대한 요청 처리위한 interceptor
- 3개의 함수 존재
preHandle()- controller로 요청 들어가기 전
- preHandle과 postHandle 사이에서 controller와 model에 대한 조작 일어남
postHandle()
- controller에서 응답 만들고 난뒤
- postHandle과 afterCompletion사이에서 요청의 전달 일어남
- 인자 ModelAndView : 추가적인 정보 더 넣어 줄 수 있음
afterCompletion()
- 응답을 client한테 보내고 난 뒤
- view가 랜더 되고 사용자한테 이미 전달이 된 뒤
3. 차이
둘다 java server, spring framework에서 제공하는 기능
- AOP : reflection = 함수의 이름을 실행중에 알아내서 그에 따른 행동을 바꿔주고 string으로 바꿔 비교가 가능하게 함
- Interceptor와 Filter : 요청과 응답이 오고가는 와중에 기능 적용할 interface에 불과
더 간단
예외처리 : 대부분 spring framework 안에서 작동
= interceptor에서 발생한 예외는 처리 가능한데 filter에서 발생하면 처리 불가능함
2. Filter 구현하기
1. 실습
package filter 만들기
1) TransactionLogFilter
어떤 요청이 들어오고 그 요청이 어떤 status 코드를 가지고 돌아갔는지 확인
servelet의 filter을 선택
public clas TransactionLogFilter implements Filter{
privat static final Logger logger = LoggerFactory.getLogger(TransactionFilter.class);
@Override
public void doFilter(
ServletRequest requet,
ServletResponse response,
FilterChain chain) throws IOException, ServletException{
String requestUUID = UUID.randomUUID().toString().split("-")[0]; //구분자
HttpServletRequest httpservletRequest = (HttpServletRequest) request;
logger.debug("[{}] start request : {} {}",
requestUUID,
httpServletRequest.getMethod(),
httpServletRequest.getRequestURI()
);
}
}
chain의 doFilter 호출하기 전까지의 상황 / filter의 요청이 spring으로 넘어가기 전
- request 확인하기
HttpServletRequest httpservletRequest = (HttpServletRequest) request;
3) chain의 doFilter 호출하기
@Component
public class TransactionLogFilter implements Filter {
private static final Logger logger = LoggerFactory.getLogger(TransactionLogFilter.class);
@Override
public void doFilter(
ServletRequest request,
ServletResponse response,
FilterChain chain) throws IOException, ServletException {
String requestUUID = UUID.randomUUID().toString().split("-")[0];
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
logger.debug("[{}] start request: {} {}",
requestUUID,
httpServletRequest.getMethod(),
httpServletRequest.getRequestURI()
);
logger.info("*response status code : {}", ((HttpServletResponse) response).getStatus());
chain.doFilter(request, response);
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
logger.info(" *response status code:{}", ((HttpServletResponse) response).getStatus());
logger.info("[{}], send response : {}",
requestUUID, httpServletResponse.getStatus());
}
}
3. HandlerInterceptor 구현하기
1. 실습
package interceptor 생성
1) HeaderLoggingInterceptor
@Component
public class HeaderLoggingInterceptor implements HandlerInterceptor {
private static final Logger logger = LoggerFactory.getLogger(HeaderLoggingInterceptor.class);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HandlerMethod handlerMethod = (HandlerMethod) handler; //형변환
logger.info("start processing of {}", handlerMethod.getMethod().getName()); //
Enumeration<String> headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
logger.trace("{}: {}", headerName, request.getHeader(headerName));
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
Collection<String> headerNames = response.getHeaderNames();
for (String headerName: headerNames) {
logger.trace("{}: {}", headerName, response.getHeader(headerName));
}
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
HandlerMethod handlerMethod = (HandlerMethod) handler;
logger.info("completed processing of {}", handlerMethod.getMethod().getName());
if (ex != null) logger.error("Exception occurred while processing", ex);
}
}
Enumeration
eterator와 비슷하게 작동 / hasMoreElements를 대신 사용
Collection
response의 interface는 enumeration이 아니라 collection
2) 등록하기
만들었다고 끝아님 configuration bean안에 등록해줌
DemoConfiguration
@Configuration
public class DemoConfiguration implements WebMvcConfigurer{
private static final Logger logger = LoggerFactory.getLogger(DemoConfiguration.class);
private final HeaderLoggingInterceptor headerLoggingInterceptor;
public DemoConfiguration(
@Autowired HeaderLoggingInterceptor headerLoggingInterceptor){
this.headerLoggingInterceptor = headerLoggingInterceptor;}
@Override
public void addInterceptors(InterceptorRegistry registry){
registry
.addInterceptor(headeLogginInterceptor)
.addPathPattterns("/post/**");
.excludePathPatterns("/except/**");
}
addInterceptors 함수
interceptor를 만들고 등록하고 싶을 때 사용하는 함수
하고 싶은 interceptor 오기
private final HeaderLoggingInterceptor headerLoggingInterceptor;
public DemoConfiguration(
@Autowired HeaderLoggingInterceptor headerLoggingInterceptor){
this.headerLoggingInterceptor = headerLoggingInterceptor;}
'SpringBoot' 카테고리의 다른 글
Exception Handling - 강의 정리 (0) | 2022.03.24 |
---|---|
Validation - 강의정리 (0) | 2022.03.22 |
Spring AOP -강의정리 (0) | 2022.03.22 |
Logging -강의 (0) | 2022.03.22 |
Spring Boot Properties - 강의 정리 (0) | 2022.03.22 |