먼저 Spring Webflux Annotated Controller 방식에서 client ip를 가져와볼게요.
그 다음 MVC 방식에서는 어떻게 설정하면 되는지도 다뤄볼게요.
@ClientIp 어노테이션을 만들어서 비즈니스 로직 단에서는 매우 간단하게 처리하고
IP를 받아오는 로직은 Resolver에 존재하도록 하겠습니다.
일단 목표는 Controller에서 아래와 같이 사용하는 거에요.
Controller
@RestController
@RequiredArgsConstructor
@Slf4j
public class BookController {
private final BookService bookService;
@GetMapping("/books/{bookId}")
public Mono<BookResponse> getBook(@PathVariable String bookId,
@ClientIp String clientIp) {
log.info(clientIp);
return bookService.getBook(bookId);
}
}
@ClientIp
어노테이션을 하나 만들어줍니다.
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface ClientIp {
}
ClientIpArgumentResolver
IP 받아오는 부분을 아주 간단하게 작성하였습니다.
혹시 IP가 이상하게 나올 경우나, 기타 상황에 따라 맞게 IP 받아오는 로직 잘 수정하시면 됩니다.
import org.springframework.core.MethodParameter;
import org.springframework.web.reactive.BindingContext;
import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolver;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.net.InetAddress;
import java.net.InetSocketAddress;
public class ClientIpArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.getParameterType().equals(String.class) &&
parameter.hasParameterAnnotation(ClientIp.class);
}
@Override
public Mono<Object> resolveArgument(MethodParameter parameter,
BindingContext bindingContext,
ServerWebExchange exchange) {
InetSocketAddress remoteAddress = exchange.getRequest().getRemoteAddress();
if (remoteAddress != null) {
InetAddress address = remoteAddress.getAddress();
return Mono.just(address.getHostAddress());
}
return Mono.empty();
}
}
CustomWebFluxConfigurer
위의 ClientIpArgumentResolver를 추가해줍니다.
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.config.WebFluxConfigurer;
import org.springframework.web.reactive.result.method.annotation.ArgumentResolverConfigurer;
@Configuration
public class CustomWebFluxConfigurer implements WebFluxConfigurer {
@Override
public void configureArgumentResolvers(ArgumentResolverConfigurer configurer) {
configurer.addCustomResolver(new ClientIpArgumentResolver());
WebFluxConfigurer.super.configureArgumentResolvers(configurer);
}
}
MVC
MVC Controller에서도 비슷하게 구현할 수 있습니다.
위에서 사용한 HandlerMethodArgumentResolver와 WebFluxConfigurer가 reactive 패키지에 있는 인터페이스인데요.
이걸 MVC 환경에서 동일한 걸 찾아서 똑같은 방식으로 메서드 오버라이드하여 구현하시면 됩니다.
HandlerMethodArgumentResolver
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
WebMvcConfigurer
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
'Backend > Spring' 카테고리의 다른 글
Spring Boot ReactiveRedisTemplate<String, Integer> (0) | 2021.08.14 |
---|---|
Spring Boot MongoDB multi-document transactions (0) | 2021.08.14 |
Spring Boot Reactive Mongo Data QueryDSL (2) | 2021.07.31 |
Spring Boot logback.xml 설정 (2) | 2020.08.29 |
Spring Boot Logging 간단 설정 (application.yml) (0) | 2020.08.27 |