스프링 입문
[스프링 입문] 6.3 Filter - Intercepter 활용 (1)
코딩펭귄
2024. 1. 10. 02:45
Filter
- Web Application에서 관리되는 영역
- 가장 앞단에서 client의 요청이 들어오자마자 해당 request body / response body를 기록하는, 보안의 용도로 사용
- Spring Boot Framewor에서 Client로부터 오는 요청/응답에 대해 최조/최종 단계 위치에 존재함 -> 이를통해 요청/응답의 정보를 변경하거나, Spring에의해 데이터가 변환되기전의 순수한 Client의 요청/응답값을 확인할 수 있음
- 유일하게 ServeletRequest, ServeletResponse의 객체를 변환할 수 있음
- 주로 Spring Framework에서 request / response의 Logging용도로 활용하거나, 인증과 관련된 Logic들을 해당Filter에서 처리함
- 이를 선/후처리 함으로써 Service business logic과 분리시킴
- 라이프사이클 : Filter에서부터 시작되는것을 확인할 수 있음
이번 프로젝트부터는 LomBok도 사용한다
만약 프로젝트 생성시 롬복선택하는거 까먹었다면 그래들파일에서 아래 해당 부분 설정 해줘야됨
controller 패키지 : client가 request하는 post를 받아줄수있도록 하기위함
package com.example.filter.controller;
import com.example.filter.dto.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Slf4j // 롬복을 사용해서 시스템아웃이 아닌, 로그로 정보 찍음
@RestController
@RequestMapping("/api/user")
public class ApiController {
//body를 하나 받음
@PostMapping("")
public User user(@RequestBody User user){
log.info("User : {}, {}", user, user);
return user;
}
}
package com.example.filter.controller;
import com.example.filter.dto.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Slf4j // 롬복을 사용해서 시스템아웃이 아닌, 로그로 정보 찍음
@RestController
@RequestMapping("/api/temp")
public class ApiUserController {
//body를 하나 받음
@PostMapping("")
public User user(@RequestBody User user){
log.info("Temp : {}, {}", user, user);
return user;
}
}
dto패키지 - user
package com.example.filter.dto;
import lombok.*;
//@Getter // 아래 변수의 겟,셋메서드 생성해줌
//@Setter // 아래 변수의 겟,셋메서드 생성해줌
@Data // getter, setter, toString, 등등 전부 생성해줌
@NoArgsConstructor //기본생성자
@AllArgsConstructor
public class User {
private String name;
private int age;
}
filter 패키지 - GlobalFilter
package com.example.filter.filter;
import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.util.ContentCachingRequestWrapper;
import org.springframework.web.util.ContentCachingResponseWrapper;
import java.io.BufferedReader;
import java.io.IOException;
@Slf4j // 로그를 남기기 위함
@WebFilter(urlPatterns = "/api/user/*")
public class GlobalFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//전처리
// ContentCaching~~Wrapper = 몇번이고 계속 읽을 수 있도록 만들어줌
ContentCachingRequestWrapper httpServletRequest = new ContentCachingRequestWrapper((HttpServletRequest)request); //HttpServletRequest로 형변환 시켜서 request매개변수로 넘겨줌
ContentCachingResponseWrapper httpServletResponse = new ContentCachingResponseWrapper((HttpServletResponse)response);
// doFilter() 를 통해 실제 내부 스프링 안으로 들어가야 그 메소드가 실행됨
// -> request에 대한 내용이 byte array에 담김 -> 읽을 수 있음
chain.doFilter(httpServletRequest, httpServletResponse);
String url = httpServletRequest.getRequestURI();
//후처리
//req
String reqContent = new String(httpServletRequest.getContentAsByteArray());
log.info("respuest url : {}, resquest body : {}", url, reqContent);
String resContent = new String(httpServletResponse.getContentAsByteArray());
int httpStatus = httpServletResponse.getStatus();
//내가 읽었던 만큼 다시한번 복사해주는 메소드
// 이렇게 해야 실제 응답이 클라이언트로 전송될수있음
httpServletResponse.copyBodyToResponse(); //다시한번 body내용을 채워넣음
log.info("response status : {}, responseBody : {}", httpStatus, resContent);
}
}
main
package com.example.filter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
@SpringBootApplication
@ServletComponentScan
public class FilterApplication {
public static void main(String[] args) {
SpringApplication.run(FilterApplication.class, args);
}
}