sk_fems_apigw commit

This commit is contained in:
unknown
2025-07-12 15:03:31 +09:00
parent b6841161e1
commit c7414f013c
24 changed files with 1739 additions and 0 deletions

View File

@ -0,0 +1,32 @@
package com.lsitc.fems.SpringCloudGateway;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.config.GlobalCorsProperties;
import org.springframework.cloud.gateway.handler.FilteringWebHandler;
import org.springframework.cloud.gateway.handler.RoutePredicateHandlerMapping;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.core.env.Environment;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
public class PassCorsRoutePredicateHandlerMapping extends RoutePredicateHandlerMapping {
private static final Logger logger = LoggerFactory.getLogger(PassCorsRoutePredicateHandlerMapping.class);
public PassCorsRoutePredicateHandlerMapping(FilteringWebHandler webHandler, RouteLocator routeLocator,
GlobalCorsProperties globalCorsProperties, Environment environment) {
super(webHandler, routeLocator, globalCorsProperties, environment);
}
@Override
public Mono<Object> getHandler(ServerWebExchange exchange) {
logger.info("[PassCorsRoutePredicateHandlerMapping] getHandler");
return getHandlerInternal(exchange).map(handler -> {
logger.info(exchange.getLogPrefix() + "Mapped to " + handler);
// CORS 체크 로직 제거
return handler;
});
}
}

View File

@ -0,0 +1,28 @@
package com.lsitc.fems.SpringCloudGateway;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.gateway.config.GlobalCorsProperties;
import org.springframework.cloud.gateway.handler.FilteringWebHandler;
import org.springframework.cloud.gateway.handler.RoutePredicateHandlerMapping;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.core.env.Environment;
@SpringBootApplication
public class SpringCloudGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(SpringCloudGatewayApplication.class, args);
}
@Bean
@Primary
public RoutePredicateHandlerMapping passCorsRoutePredicateHandlerMapping(
FilteringWebHandler webHandler, RouteLocator routeLocator,
GlobalCorsProperties globalCorsProperties, Environment environment) {
return new PassCorsRoutePredicateHandlerMapping(webHandler, routeLocator,
globalCorsProperties, environment);
}
}

View File

@ -0,0 +1,229 @@
/*
* 상기 프로그램에 대한 저작권을 포함한 지적재산권은 LS ITC에 있으며,
* LS와 명시적으로 허용하지 않은 사용, 복사, 변경, 제3자에의 공개, 배포는 엄격히 금지되며,
* LS의 지적재산권 침해에 해당됩니다.
* (Copyright ⓒ 2021 LS ITC. All Rights Reserved| Confidential)
*
* You are strictly prohibited to copy, disclose, distribute, modify, or use
* this program in part or as a whole without the prior written consent of
* LS. LS owns the intellectual property rights in
* and to this program.
* (Copyright ⓒ 2021 LS. All Rights Reserved| Confidential)
* Created : 2021.04.06
*/
package com.lsitc.fems.SpringCloudGateway.filter;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.CharBuffer;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseCookie;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.client.ClientResponse;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.server.ServerWebExchange;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@SuppressWarnings("rawtypes")
@Component
public class AuthFilter extends AbstractGatewayFilterFactory<Map> {
private Logger logger = LoggerFactory.getLogger(AuthFilter.class);
private String authServiceUrl = "";
private String loginUrl = "";
private String cookieId = "";
private final WebClient webClient = WebClient.create();
public AuthFilter() {
super(Map.class);
}
@Override
public GatewayFilter apply(Map config) {
authServiceUrl = config.get("authAPI").toString();
cookieId = config.get("cookieId").toString();
loginUrl = config.get("loginUrl").toString();
return (exchange, chain) -> {
ServerHttpRequest request = exchange.getRequest();
// 로그인 및 권한 Check 호출
Mono<ClientResponse> authServiceResponse = callAuthService(request);
// 후처리
Mono<Void> middleService = authServiceResponse.flatMap(r -> processAuthResponse(exchange, chain, request, r));
return middleService.then();
};
}
/**
* @methodName : resolveBodyFromRequest
* @date : 2021.05.06
* @desc : requestBody를 String으로 변환하여 반환한다.
* @param serverHttpRequest
* @return
*/
private String resolveBodyFromRequest(ServerHttpRequest serverHttpRequest) {
// Get the request body
Flux<DataBuffer> body = serverHttpRequest.getBody();
AtomicReference<String> bodyRef = new AtomicReference<>();
body.subscribe(buffer -> {
CharBuffer charBuffer = StandardCharsets.UTF_8.decode(buffer.asByteBuffer());
DataBufferUtils.release(buffer);
bodyRef.set(charBuffer.toString());
});
// Get request body
return bodyRef.get();
}
/**
*
* @methodName : callAuthService
* @date : 2021.04.15
* @desc : 로그인 및 권한 check API 호출
* @param inputRequest
* @return
*/
private Mono<ClientResponse> callAuthService(ServerHttpRequest inputRequest) {
logger.info("requestURI : {}", inputRequest.getPath());
Map<String, String> params = new HashMap<>();
params.put("requestURI", inputRequest.getPath().toString());
if( inputRequest.getMethod().matches("POST") ) {
//POST는 header에서
List<String> menuId = inputRequest.getHeaders().get("X-Fems-MenuId");
logger.info("X-Fems-MenuId : {}", menuId);
params.put("menuId", menuId.get(0));
// String requestBodyStr = resolveBodyFromRequest(inputRequest);
// ObjectMapper mapper = new ObjectMapper();
// JsonNode actualObj;
// try {
// //requestBody
// actualObj = mapper.readTree(requestBodyStr);
// //menuId
// params.put("menuId", actualObj.get("params").get("menuId") != null ? actualObj.get("params").get("menuId").asText() : "2");
// } catch (Exception e) {
// }
} else {
//POST는 queryString에서(e.g. menu)
params.put("menuId", inputRequest.getQueryParams().getFirst("$menuId"));
}
System.out.println("getHeaders" + inputRequest.getHeaders());
System.out.println("authServiceUrl : " + authServiceUrl);
System.out.println("cookieId : " + cookieId);
System.out.println("getCookies : " + inputRequest.getCookies().toString());
System.out.println("getFirst(cookieId) : " + inputRequest.getCookies().getFirst(cookieId));
WebClient.RequestBodySpec request = webClient.method(HttpMethod.POST).uri(authServiceUrl)
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)
.cookie(cookieId,
inputRequest.getCookies().getFirst(cookieId) != null
? inputRequest.getCookies().getFirst(cookieId).getValue()
: "");
request.bodyValue(params);
return request.exchange();
}
/**
*
* @methodName : processMiddleResponse
* @date : 2021.04.15
* @desc :
* @param exchange
* @param chain
* @param request
* @param middleServiceResponse
* @return
*/
private Mono<Void> processAuthResponse(ServerWebExchange exchange, GatewayFilterChain chain,
ServerHttpRequest request, ClientResponse authServiceResponse) {
if (authServiceResponse.statusCode().is2xxSuccessful()) {
// 로그인 및 권한 체크 결과 정상이면 새로 발급된 쿠키를 담아준다.
ServerHttpRequest modifiedRequest = request.mutate().headers((httpHeaders) -> {
httpHeaders.set("Cookie",
authServiceResponse.cookies().get(cookieId) != null
? authServiceResponse.cookies().get(cookieId).get(0).toString()
: "");
}).build();
ServerWebExchange modifiedExchange = exchange.mutate().request(modifiedRequest).build();
ResponseCookie cookie = authServiceResponse.cookies().get(cookieId).get(0);
exchange.getResponse().addCookie(cookie);
System.out.println("exchange.getResponse is2xxSuccessful" + exchange.getResponse());
// authServiceResponse.bodyToMono(Map.class).subscribe(m -> {
//// logger.info("retnCd :: {}", m.get("retnCd"));
// });
return chain.filter(modifiedExchange);
} else {
System.out.println("exchange.getResponse else is2xxSuccessful" + exchange.getResponse().getHeaders());
System.out.println("exchange.getResponse else is2xxSuccessful" + exchange.getResponse().getCookies());
if (exchange.getRequest().getHeaders().getAccept().contains(MediaType.APPLICATION_JSON)) {
ObjectMapper objectMapper = new ObjectMapper();
exchange.getResponse().getHeaders().setContentType(MediaType.APPLICATION_JSON);
exchange.getResponse().setStatusCode(HttpStatus.OK);
DataBufferFactory bufferFactory = exchange.getResponse().bufferFactory();
DataBuffer dataBuffer = null;
try {
dataBuffer = bufferFactory
.wrap(objectMapper.writeValueAsBytes(new HttpError("-1", "문제가 발생하였습니다. 관리자에게 문의하세요.")));
} catch (JsonProcessingException e) {
dataBuffer = bufferFactory.wrap("".getBytes());
}
return exchange.getResponse().writeWith(Mono.just(dataBuffer));
} else {
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.MOVED_TEMPORARILY);
try {
response.getHeaders().setLocation(new URI(loginUrl));
} catch (URISyntaxException e) {
// TODO Auto-generated catch block
}
return Mono.empty();
}
}
}
public class HttpError {
private String rtnCd;
private String message;
HttpError(String rtnCd, String message) {
this.rtnCd = rtnCd;
this.message = message;
}
public String getMessage() {
return message;
}
public String getRtnCd() {
return rtnCd;
}
}
}

View File

@ -0,0 +1,58 @@
/*
* 상기 프로그램에 대한 저작권을 포함한 지적재산권은 LS ITC에 있으며,
* LS와 명시적으로 허용하지 않은 사용, 복사, 변경, 제3자에의 공개, 배포는 엄격히 금지되며,
* LS의 지적재산권 침해에 해당됩니다.
* (Copyright ⓒ 2021 LS ITC. All Rights Reserved| Confidential)
*
* You are strictly prohibited to copy, disclose, distribute, modify, or use
* this program in part or as a whole without the prior written consent of
* LS. LS owns the intellectual property rights in
* and to this program.
* (Copyright ⓒ 2021 LS. All Rights Reserved| Confidential)
* Created : 2021.05.06
*/
package com.lsitc.fems.SpringCloudGateway.filter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@Component
public class CacheRequestBodyGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
if (exchange.getRequest().getHeaders().getContentType() == null || exchange.getRequest().getMethod().matches("GET")) {
return chain.filter(exchange);
} else {
return DataBufferUtils.join(exchange.getRequest().getBody())
.flatMap(dataBuffer -> {
DataBufferUtils.retain(dataBuffer);
Flux<DataBuffer> cachedFlux = Flux
.defer(() -> Flux.just(dataBuffer.slice(0, dataBuffer.readableByteCount())));
ServerHttpRequest mutatedRequest = new ServerHttpRequestDecorator(
exchange.getRequest()) {
@Override
public Flux<DataBuffer> getBody() {
return cachedFlux;
}
};
return chain.filter(exchange.mutate().request(mutatedRequest).build());
});
}
}
@Override
public int getOrder() {
return 0;
}
}

View File

@ -0,0 +1,157 @@
package com.lsitc.fems.SpringCloudGateway.filter;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseCookie;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.client.ClientResponse;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.server.ServerWebExchange;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import reactor.core.publisher.Mono;
@SuppressWarnings("rawtypes")
@Component
public class MenuLogFilter extends AbstractGatewayFilterFactory<Map> {
private Logger logger = LoggerFactory.getLogger(MenuLogFilter.class);
private String menuLogServiceUrl = "";
private String loginUrl = "";
private String cookieId = "";
private final WebClient webClient = WebClient.create();
public MenuLogFilter() {
super(Map.class);
}
@Override
public GatewayFilter apply(Map config) {
menuLogServiceUrl = config.get("menuLogAPI").toString();
cookieId = config.get("cookieId").toString();
loginUrl = config.get("loginUrl").toString();
return (exchange, chain) -> {
ServerHttpRequest request = exchange.getRequest();
// 로그인 및 권한 Check 호출
Mono<ClientResponse> menuLogServiceResponse = callMenuLogService(request);
// 후처리
Mono<Void> middleService = menuLogServiceResponse.flatMap(r -> processMenuLogResponse(exchange, chain, request, r));
return middleService.then();
};
}
private Mono<ClientResponse> callMenuLogService(ServerHttpRequest inputRequest) {
logger.info("callMenuLogService : {}", inputRequest.getPath());
Map<String, String> params = new HashMap<>();
params.put("requestURI", inputRequest.getPath().toString());
if( inputRequest.getMethod().matches("POST") ) {
//POST는 header에서
List<String> menuId = inputRequest.getHeaders().get("X-Fems-MenuId");
logger.info("X-Fems-MenuId : {}", menuId);
params.put("menuId", menuId.get(0));
} else {
//POST는 queryString에서(e.g. menu)
String menuId = inputRequest.getQueryParams().getFirst("$menuId");
params.put("menuId", menuId == null?"0":menuId);
}
WebClient.RequestBodySpec request = webClient.method(HttpMethod.POST).uri(menuLogServiceUrl)
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)
.cookie(cookieId,
inputRequest.getCookies().getFirst(cookieId) != null
? inputRequest.getCookies().getFirst(cookieId).getValue()
: "");
request.bodyValue(params);
return request.exchange();
}
private Mono<Void> processMenuLogResponse(ServerWebExchange exchange, GatewayFilterChain chain,
ServerHttpRequest request, ClientResponse authServiceResponse) {
if (authServiceResponse.statusCode().is2xxSuccessful()) {
// 로그인 및 권한 체크 결과 정상이면 새로 발급된 쿠키를 담아준다.
ServerHttpRequest modifiedRequest = request.mutate().headers((httpHeaders) -> {
httpHeaders.set("Cookie",
authServiceResponse.cookies().get(cookieId) != null
? authServiceResponse.cookies().get(cookieId).get(0).toString()
: "");
}).build();
ServerWebExchange modifiedExchange = exchange.mutate().request(modifiedRequest).build();
ResponseCookie cookie = authServiceResponse.cookies().get(cookieId).get(0);
exchange.getResponse().addCookie(cookie);
// authServiceResponse.bodyToMono(Map.class).subscribe(m -> {
//// logger.info("retnCd :: {}", m.get("retnCd"));
// });
return chain.filter(modifiedExchange);
} else {
if (exchange.getRequest().getHeaders().getAccept().contains(MediaType.APPLICATION_JSON)) {
ObjectMapper objectMapper = new ObjectMapper();
exchange.getResponse().getHeaders().setContentType(MediaType.APPLICATION_JSON);
exchange.getResponse().setStatusCode(HttpStatus.OK);
DataBufferFactory bufferFactory = exchange.getResponse().bufferFactory();
DataBuffer dataBuffer = null;
try {
dataBuffer = bufferFactory
.wrap(objectMapper.writeValueAsBytes(new HttpError("-1", "문제가 발생하였습니다. 관리자에게 문의하세요.")));
} catch (JsonProcessingException e) {
dataBuffer = bufferFactory.wrap("".getBytes());
}
return exchange.getResponse().writeWith(Mono.just(dataBuffer));
} else {
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.MOVED_TEMPORARILY);
try {
response.getHeaders().setLocation(new URI(loginUrl));
} catch (URISyntaxException e) {
// TODO Auto-generated catch block
}
return Mono.empty();
}
}
}
public class HttpError {
private String rtnCd;
private String message;
HttpError(String rtnCd, String message) {
this.rtnCd = rtnCd;
this.message = message;
}
public String getMessage() {
return message;
}
public String getRtnCd() {
return rtnCd;
}
}
}

View File

@ -0,0 +1,241 @@
# 공통
spring:
application:
#업무명
name: apiGw
serverip: localhost
profiles:
#프로파일(local:로컬환경, dev:개발환경(추가환경개발), docker:운영 택1)
active: local
#로깅관련
logging:
loginLogEnable: true
menuCnctLogEnable: true
level:
root: DEBUG
#logging
config: classpath:logback_spring.xml
file:
path: logs
max-history: 30
max-size: 100MB
---
##############
####local#####
##############
#AuthFilter정의
AuthFilter: &AuthFilter
- name: AuthFilter
args:
authAPI: http://localhost:8080/isValidToken
cookieId: FEMS_SESSION
loginUrl: /login
MenuLogFilter: &MenuLogFilter
- name: MenuLogFilter
args:
menuLogAPI: http://localhost:8080/menuLogCont
cookieId: FEMS_SESSION
loginUrl: /login
#MenuLogFilter: &MenuLogFilter
# - name: MenuLogFilter
# args:
# menuLogAPI: http://localhost:9999/menuLogCont
# cookieId: FEMS_SESSION
# loginUrl: http://localhost:9999/login
spring:
profiles: local
main:
allow-bean-definition-overriding: true
cloud:
gateway:
globalcors:
corsConfigurations:
'[/**]':
allowedOrigins: "*"
#timeout관련 설정
httpclient:
connect-timeout: 300000 # 30초
response-timeout: 300s # 30초, 글로벌 설정시 seconds
pool:
max-idle-time: 300000 # 5분간 휴상태이면 회수 처리
#routing관련 설정
routes:
# withoutAuth
- id: withOutAuth #id
uri: http://localhost:8080/comm #forward url
predicates:
- Path= /loginChk, /logout, /isValidToken, /menuLogCont, /sso, /comm/SystemLogReadCtr/saveMenuCnctLog, /loginProc #, /login
# withOutEms
- id: withOutEms
uri: http://localhost:8082/
predicates:
- Path=/ems/effc/MdlDataSetCtr/selectMdlOpen
# vuePage
- id: vuePage
uri: http://localhost:3000/
filters:
- <<: *MenuLogFilter
predicates:
#라우팅할 path
- Path=/ems/**/*Page, /comm/**/*Page
# vue.js
- id: vue #id
uri: http://localhost:3000/ #forward url
predicates:
#라우팅할 path
- Path=/_nuxt/comm/**, /__webpack_hmr/**, /_loading/**, /favicon.ico, /login, /ems/*Page, /comm/*Page, /iframe/**, /
# vue sample
- id: vueSample #id
uri: http://localhost:3010/ #forward url
predicates:
#라우팅할 path
- Path=/_nuxt/sample/**, /sample/*Page
# comm
- id: comm #id
uri: http://localhost:8080 #forward url
filters:
- <<: *AuthFilter
predicates:
#라우팅할 path
- Path=/comm/** #, /
# ems
- id: ems #id
uri: http://localhost:8082 #forward url
filters:
- <<: *AuthFilter
predicates:
#라우팅할 path
- Path=/ems/base/**, /ems/api/** ,/ems/bala/**, /ems/effc/**
# ems_fopm
- id: ems_fopm #id
uri: http://localhost:8084 #forward url
filters:
- <<: *AuthFilter
predicates:
#라우팅할 path
- Path=/fopm/**
# drp
- id: drp #id
uri: http://localhost:8086 #forward url
filters:
- <<: *AuthFilter
predicates:
#라우팅할 path
- Path=/ems/drp/**
# cmms
- id: cmms #id
uri: http://localhost:8089 #forward url
filters:
- <<: *AuthFilter
predicates:
#라우팅할 path
- Path=/cmms/**
# sample
- id: sample #id
uri: http://localhost:8090 #forward url
filters:
- <<: *AuthFilter
predicates:
#라우팅할 path
- Path=/sample/**
management:
endpoints:
web:
exposure:
include: "gateway"
endpoint:
gateway:
enabled: true
server:
port: 9999
---
###############################
#### Cloud(Kube) #####
###############################
AuthFilter: &AuthFilter
- name: AuthFilter
args:
authAPI: http://skfems-comm:8080/isValidToken
cookieId: FEMS_SESSION
loginUrl: /login
MenuLogFilter: &MenuLogFilter
- name: MenuLogFilter
args:
menuLogAPI: http://skfems-comm:8080/menuLogCont
cookieId: FEMS_SESSION
loginUrl: /login
spring:
profiles: cloud_kube
main:
allow-bean-definition-overriding: true
cloud:
gateway:
globalcors:
corsConfigurations:
'[/**]':
allowedOrigins: "*"
#timeout관련 설정
httpclient:
connect-timeout: 300000 # 30초
response-timeout: 300s # 30초, 글로벌 설정시 seconds
pool:
max-idle-time: 300000 # 5분간 휴상태이면 회수 처리
#routing관련 설정
routes:
# withoutAuth
- id: withOutAuth #id
uri: http://skfems-comm:8080/ #forward url
predicates:
- Path= /loginChk, /logout, /isValidToken, /menuLogCont, /comm/base/SystemLogReadCtr/saveMenuCnctLog, /loginProc #, /login
# withOutEms
- id: withOutEms
uri: http://skfems-ems:8082/
predicates:
- Path=/ems/effc/MdlDataSetCtr/selectMdlOpen
# vueCommAuthPage
- id: vueCommAuthPage
uri: http://skfems-ui:3000/
filters:
- <<: *MenuLogFilter
predicates:
#라우팅할 path
- Path=/comm/**/*Page, /ems/**/*Page
# vue.js
- id: vue #id
uri: http://skfems-ui:3000/ #forward url
predicates:
#라우팅할 path
- Path=/_nuxt/comm/**, /__webpack_hmr/**, /_loading/**, /favicon.ico, /login, /iframe/**, /
# comm
- id: comm #id
uri: http://skfems-comm:8080 #forward url
filters:
- <<: *AuthFilter
predicates:
#라우팅할 path
- Path=/comm/**
# ems
- id: ems #id
uri: http://skfems-ems:8082 #forward url
filters:
- <<: *AuthFilter
predicates:
#라우팅할 path
- Path=/ems/**
# webHmi
- id: webHmi #id
uri: http://skfems-fuxa:1881 #forward url
predicates:
#라우팅할 path
- Path=/webHmi/**
management:
endpoints:
web:
exposure:
include: "gateway"
endpoint:
gateway:
enabled: true
server:
port: 9999

View File

@ -0,0 +1,66 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- 60초마다 설정 파일의 변경을 확인 하여 변경시 갱신 -->
<configuration scan="true" scanPeriod="60 seconds">
<!--springProfile 태그를 사용하면 logback 설정파일에서 복수개의 프로파일을 설정할 수 있다. -->
<springProperty scope="context" name="LOG_LEVEL" source="logging.level.root" />
<!-- log file path -->
<springProperty scope="context" name="LOG_PATH" source="logging.file.path"/>
<!-- log file name -->
<springProperty scope="context" name="LOG_FILE_NAME" source="spring.application.name"/>
<!-- log file size -->
<springProperty scope="context" name="LOG_MAX-SIZE" source="logging.file.max-size"/>
<!-- log history -->
<springProperty scope="context" name="LOG_MAX_HISTORY" source="logging.file.max-history"/>
<!-- pattern -->
<property name="LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss} [%-6level] [%logger{0}:%line] - %msg%n" />
<!-- Console Appender -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${LOG_PATTERN}</pattern>
</encoder>
</appender>
<!-- File Appender -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 파일경로 설정 -->
<file>${LOG_PATH}/${LOG_FILE_NAME}.log</file>
<!-- 출력패턴 설정 -->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${LOG_PATTERN}</pattern>
</encoder>
<!-- Rolling 정책 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- .gz,.zip 등을 넣으면 자동 일자별 로그파일 압축 -->
<fileNamePattern>${LOG_PATH}/${LOG_FILE_NAME}.%d{yyyy-MM-dd}_%i.log
</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<!-- 파일당 최고 용량 kb, mb, gb -->
<maxFileSize>${LOG_MAX-SIZE}</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!-- 일자별 로그파일 최대 보관주기(~일), 해당 설정일 이상된 파일은 자동으로 제거 -->
<maxHistory>${LOG_MAX_HISTORY}</maxHistory>
<!--<MinIndex>1</MinIndex> <MaxIndex>10</MaxIndex> -->
</rollingPolicy>
</appender>
<root level="${LOG_LEVEL}">
<appender-ref ref="CONSOLE" />
<appender-ref ref="FILE" />
</root>
<!-- log4jdbc 옵션 설정 -->
<logger name="jdbc" level="OFF" />
<!-- 커넥션 open close 이벤트를 로그로 남긴다. -->
<logger name="jdbc.connection" level="OFF" />
<!-- SQL문만을 로그로 남기며, PreparedStatement일 경우 관련된 argument 값으로 대체된 SQL문이 보여진다. -->
<logger name="jdbc.sqlonly" level="OFF" />
<!-- SQL문과 해당 SQL을 실행시키는데 수행된 시간 정보(milliseconds)를 포함한다. -->
<logger name="jdbc.sqltiming" level="DEBUG" />
<!-- ResultSet을 제외한 모든 JDBC 호출 정보를 로그로 남긴다. 많은 양의 로그가 생성되므로 특별히 JDBC 문제를 추적해야 할 필요가 있는 경우를 제외하고는 사용을 권장하지 않는다. -->
<logger name="jdbc.audit" level="OFF" />
<!-- ResultSet을 포함한 모든 JDBC 호출 정보를 로그로 남기므로 매우 방대한 양의 로그가 생성된다. -->
<logger name="jdbc.resultset" level="OFF" />
<!-- SQL 결과 조회된 데이터의 table을 로그로 남긴다. -->
<logger name="jdbc.resultsettable" level="OFF" />
</configuration>

View File

@ -0,0 +1,13 @@
package com.lsitc.fems.SpringCloudGateway;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class SpringCloudGatewayApplicationTests {
@Test
void contextLoads() {
}
}