.png%253FspaceId%253D7369a2e6-adff-489c-b6ec-00ea004de55c%3Ftable%3Dblock%26id%3D1deaf3cd-6c9b-8037-9e0d-e6dc24e9db8b%26cache%3Dv2&w=1920&q=75)
필터 라이브러리는 톰캣꺼 (스프링 밖에 잇으니께)
인터셉터는 디스패처서블릿을 실행
필터는 그 전에 작동?

1. 권장하지 않는 방법

filter가 스프링 앞에 있으니까 인식을 못하기 때문에 application에 @ServletComponentScan 을 걸어줘야 됨!

spring 들어가기 전에 하고 싶은 일 할 수 있음


아파트 입구의 경비원이 필터
아파트 동 = controller
경비원 통과하고 나니까 dispatcher servlet 만남
101동의 1302호 가고싶어요 ~ 하면 dispatcher servlet이 길을 알려줌
101동에 도착해서 입구 앞에 있음 1302호로 들어가기 직전에 interceptor가 간섭한다.
택배왔어용~
interceptor에서 prehandle을 하면서 혹시나 폭발물 검사ㅡㅡ
우리집 문 앞에서 AOP가 필요
AOP는 내가 집 안에 있으면 들어오라고 하고 없으면 문 앞에 두고 가세용
들고 온 물건은 내 상태와 상관없이 interceptor로 가능
AOP는 분석을 할수 있음 → 관점에 따라서 다르게 행동
집안에 들어가서 일처리하고 밖에 빠져나옴
엘베 타고 내려옴
나갈려고 하니까 afterhandle이 뭐 훔쳐가는거 없는지 interceptor가 확인
filter는 그냥 반복적인 일을 함
filter와 interceptor는 위치만 다르지 같은 일을 함
filter : 전역적 처리 가능 (아파트에 들어오는걸 한방에 처리 → 모든곳에서 통용되는 일 처리
→ 아파트 입주민인지 체킹 가능 (동마다 하면 경비원이 해야할 일이 늘어남)
interceptor : 동마다 처리 → 101동 사람인지만 체킹
aop : 관점에 따라서 다른 일을 함
filter에서는 db 접근 불가 = 스프링 들어가기 전이니까
interceptor는 db에서 꺼내서 체킹 가능
db 접근 = spring context부터 가능
filter에서 뭘 하는지가 중요X - 어디서 어떻게 동작하는지만 알면 뭐든 가능?!
spring이 실행되면
spring = 라이브러리 집합체 mvc만들어주는
was가 내가 짠 코드를 기반으로 filter 실행
filter와 spring은 따로 떠있음 (메모리에 올라와있음)
톰캣 - spring - mysql 세개가 떠있다!
요청하는 모든 정보를 request로, 빈 resonse 객체
톰캣이 request 객체를 만듦 - 아직 db 접근 안됨 (폴링기술 - 만들어져있던 객체 (50개) 가져다씀)
spring context로 들어가는 순간 - 동적으로 db 커넥션 객체 만ㄷ름 → read 커넥션 만듦
⇒ 지금부터 select치면 가능
db에서 조회해서 응답 → DS에서 filter로 빠져나오는 순간 db 커넥션이 끊김
repository 종료될때 db 커넥션 종료시키면 service에서 jpa에서 다시 select 못함 ⇒ serivce에서 끊지X
→ controller로 돌아오면 끊어도 되지 않을까? service는 한번만 호출
spring에서는 view에서 lazy로딩을 못하니까
getter로 호출하면 null이니까 select해서 채워넣어줌 = orm을 lazy하게
물리적인 선은 하나 존재
선에 접근할 수 있는 버퍼
- 아파트 입구의 경비원 = filter = WAS가 관리 → spring 내부가 아니니까 db 커넥션 열리지 X
- filter 통과해서 DS로 들어가는 순간 DB 커넥션을 연다
- DS가 controller를 찾는것 = 아파트의 동을 찾는 것
- 동마다 있는 경비 = interceptor
interceptor와 filter는 경비
- controller의 메서드는 아파트 동의 호수 (1302호)
- 1302호에 사람이 있으면 택배(request 객체) 직접 전달 / 사람 없으면 문 앞에 두고 간다
⇒ 관점에 따라 다르게 행동하는 AOP
- controller 이후는 비지니스 로직
- DB 커넥션은 DS에서 빠져나올 때 사라진다.
- filter는 DB 접근할 수 없다.
filter에서 DB 접근이 가능하면 request 객체 읽어서 로그인 처리도 가능할지도
spirng context 범위 늘리는 전략
delegate 패턴 (위임패턴)

→ filter에서 db 접근이 가능해짐!!!!!!!!!!

톰캣이 컴포넌트 스캔 webfilter 어노테이션 찾으면 new만 하는게 아니라
톰캣은 필터체인을 들고 있음
체인 = 비어있음
웹필터가 세개면 체인에 세개가 끼워짐 (필터 순서는 gpt한테 물어보면 다 알ㄹ줌)
request,response 객체 만들어지만 doFilter 호출하고 바로 응답
필터체인을 이용하면 다음체인의 dofilter를 호출 (req,resp 객체도 넘겨줘야됨!!)
마지막 doFilter에서는 DS로 간다!
2. 이제는 톰캣이 스캔을 안하는 방법@

톰캣이 메모리에 뜰 때에는 체인에 아무것도 없음
어차피 스프링이랑 톰캣이 서버 실행시 동시에 뜬다
톰캣 뜰때 하는 scan 막음
오른쪽 네모가 클래스를 하나만들건데 filterRegistrationBean를 만들어서
직접 new해서 필터 끼워넣을거임
전체 클래스를 IOC에 등록할거임
안에있는 자료구조?
0번지부터 모두 꺼내서 chain에 꼽힘
filter 타입이 아니니까 안꼽히는데 filter 타입으로 만들어서 꼽힘
⇒ spring context 안에서 논다!!!!
- A가 먹고싶은거 슈퍼에서 삿음
- B는 가전제품 삿음
- A가 앞 B가 뒤
- A : 친구들이 오면 먹을거 줌
- 가전제품 주려면 b에게 넘겨야
- B : 이제 내가 먹을거 살게
- B : 가전 + 먹을거
- B는 일만 시킴
- B는 객체 내꺼
- delegate 위임
- 지가 할 일을 위임X 내가 다 산거를 위임 → 일을 넘김
방식1

package shop.mtcoding.blog._core.filter;
import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebFilter("/*")
public class LogFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("진짜?--------------------------------------------------");
// HttpServletResponse resp = (HttpServletResponse) servletResponse; // ServletResponse = HttpServletResponse의 부모 -> 다운캐스팅
// servletResponse.getWriter().println("Hello World");
filterChain.doFilter(servletRequest, servletResponse); // 진짜?----- 찍고 넘겨준다.
}
}
package shop.mtcoding.blog;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
@ServletComponentScan
@SpringBootApplication
public class BlogApplication {
public static void main(String[] args) {
SpringApplication.run(BlogApplication.class, args);
}
}
DB를 만질 일이 생각보다 있어서 방식1 별루
로그인 필터에서 처리하면 조음~!
혹시나 회사에서 레거시 스프링을 쓸 경우
tomcat / conf/ 보면 xml 파일들 잇음
annotation과 application.properties
=
context.xml
server.xml = servlet.
web.xml
spring+was 실행되면 성을 만들엇다고함..
성 안의 구조(세모할지 높이 입구 등등) ex.포트번호 등 설정하는 것 = server.xml
-> 지금은 포트번호 application.properties
외부에서 req 요청(사람한명이 걸어들어오는데 짐이 있거나(뭔가 줄려고 Post) 없거나(그냥 select해서 가져가려는애 get)
8080 포트 입구 앞 문지기 = 문서(web.xml)를 보고 일을 함
web.xml에 필터링할 내용이 적혀있음 (web.xml에 가방에 총기 금지야~ 써져있으면 문지기가 문서를 보고 총기 반임 금지 시킴)
문지기 = 배포 서술자?
성과 문지기도 아니지만 연결되고 필요한..
성의 높이가 3m 밖에 안되서 위험 - 앞에 강이 있으면 좋겟지 = context.xml에서 설정
context.xml = 성의 남쪽에 강을 하나 둬라 (DB 커넥션 같은거 설정)
context.xml = 바깥의 DB를 spring+was에 연결해야 되는데 그거 설정
ex. 서버 8080 설정하면
server.xml에서 클래스로 만들고 new해서 객체를 띄움
Hello라는 클래스를 남이 만들었음 = 라이브러리
얘를(new가 아닌) IoC에 등록하려면 2가지 방법
- 추상화시켜서 클래스 띄워서 extends 하면됨
- MyHello 클래스 만들어서 extends Hello
- @Configuration
- IoC에 Hello 뜸
- 실제로 MyHello가 메모리에 떴지만 부모가 Hello니까 Hello와 MyHello 다른 클래스에서 사용가능 (다형성)
- 다른놈들이 만든거 다 띄울 OtherBean 만듦
- @Configuration
- 내부에 public Hello loadBean(){
- return new Hello(); } 메서드 만듦
- 메서드에 @Bean 붙이기
- 컴포넌트 스캔되면서 @Bean 이 있는지 reflection으로 분석
- 그리고 리턴되는 값 때려서 IoC에 등록함!
package shop.mtcoding.blog._core.config;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import shop.mtcoding.blog._core.filter.LogFilter;
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<LogFilter> loggingFilter() {
FilterRegistrationBean<LogFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new LogFilter()); // 이제는 톰캣이 관리안하므로 직접 new
registrationBean.addUrlPatterns("/*"); // 모든 요청에 적용
registrationBean.setOrder(1); // 필터 순서 설정
return registrationBean;
}
}- 컴포넌트 스캔되니까 빈 있고 → 메서드 때려서 리턴값을 IoC에 꽂는다!
- registrationBean이 필터들을 들고 있음
- 수동으로 스프링이 for문 돌려서 필터 들고 톰캣의 필터 체인에 넣어준다
public class LogFilter implements Filter { -> component scan이 안됨
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) servletRequest;
String uri = req.getRequestURI();
String ip = req.getRemoteAddr();
String userAgent = req.getHeader("User-Agent");
System.out.printf("[로그] %s | IP: %s | UA: %s\n", uri, ip, userAgent);
filterChain.doFilter(servletRequest, servletResponse);
}
}위의 버전에서는 component scan이 안됨
db 끌어다 쓰고 싶으면 밑에처럼
- @RequiredArgsConstructor @Configuration
- private final UserRepository userRepository;
- registrationBean.setFilter(new LogFilter(userRepository));
package shop.mtcoding.blog._core.config;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import shop.mtcoding.blog._core.filter.LogFilter;
import shop.mtcoding.blog.user.UserRepository;
@RequiredArgsConstructor
@Configuration
public class FilterConfig {
private final UserRepository userRepository;
@Bean
public FilterRegistrationBean<LogFilter> loggingFilter() {
FilterRegistrationBean<LogFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new LogFilter(userRepository));
registrationBean.addUrlPatterns("/*"); // 모든 요청에 적용
registrationBean.setOrder(1); // 필터 순서 설정
return registrationBean;
}
}package shop.mtcoding.blog._core.filter;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import shop.mtcoding.blog.user.UserRepository;
import java.io.IOException;
@RequiredArgsConstructor
public class LogFilter implements Filter {
private final UserRepository userRepository;
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) servletRequest;
String uri = req.getRequestURI();
String ip = req.getRemoteAddr();
String userAgent = req.getHeader("User-Agent");
System.out.printf("[로그] %s | IP: %s | UA: %s\n", uri, ip, userAgent);
filterChain.doFilter(servletRequest, servletResponse);
}
}원래 필터 단점
- db 연결 안됨
- throw가 안됨
⇒ FilterRegistrationBean으로 이제 db 연결은 되지만 throw는 직접 버퍼에 resp 객체에 json으로 뭐시기 다입혀서 내가 직접 제어해야됨 귀찮을뿐
AOP의 최대 단점
필드를 다 분석하기 때문에 reflection으로 인해 느려짐
과다하게 쓸 경우 엄청 느려짐
→ 판단해서 쓰면 됨!
BufferedReader 땡겨와서
while돌리면서(enter 키같은게있을수있ㅇ니까) 버퍼에있는거 읽으면서
input에 contains(”<script>”) exception400(ㅅ크립트를 전송할수없습ㄴ다) 가능
< → <> 문자로
라이브러리 적용해서 필터에서 하나하나씩 전부 막을 필요X
ex)네이버 - lucy-xss-servlet-filter
필터를 어떻게 쓰는지, 개념만 알면 됨
@Bean은 return값을 ?에 등록
Share article