Commit e1e4ab6a authored by huangcb's avatar huangcb

Init

parents
*.class
*.iml
*.log
/*.fo
/*.iml
/.idea/
/log/
/logs/
*/target/
/target/
#!/bin/bash
#这里可替换为你自己的执行程序,其他代码无需更改
APP_NAME=datacenter-gateway-service.jar
#日志文件,与logback-spring.xml的日志文件保持一致
LOG_FILE=./logs/datacenter-gateway-service.log
#日志配置文件
LOG_CONFIG_FILE=./logback-spring.xml
#使用说明,用来提示输入参数
usage() {
echo "Usage: sh 脚本名.sh [start|stop|restart|status]"
exit 1
}
#检查程序是否在运行
is_exist(){
pid=`ps -ef|grep $APP_NAME|grep -v grep|awk '{print $2}' `
#如果不存在返回1,存在返回0
if [ -z "${pid}" ]; then
return 1
else
return 0
fi
}
#启动方法
start(){
is_exist
if [ $? -eq "0" ]; then
echo "${APP_NAME} is already running. pid=${pid} ."
else
nohup java -Xmx128m -Xms128m -Dlogging.config=$LOG_CONFIG_FILE -jar $APP_NAME >> /dev/null 2>&1 &
date
tail -f $LOG_FILE
fi
}
#停止方法
stop(){
is_exist
if [ $? -eq "0" ]; then
kill -9 $pid
else
echo "${APP_NAME} is not running"
fi
}
#输出运行状态
status(){
is_exist
if [ $? -eq "0" ]; then
echo "${APP_NAME} is running. Pid is ${pid}"
else
echo "${APP_NAME} is NOT running."
fi
}
#重启
restart(){
stop
start
}
#根据输入参数,选择执行对应方法,不输入则执行使用说明
case "$1" in
"start")
start
;;
"stop")
stop
;;
"status")
status
;;
"restart")
restart
;;
*)
usage
;;
esac
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
</parent>
<groupId>com.esv.datacenter</groupId>
<artifactId>datacenter-gateway-service</artifactId>
<version>1.0.0-SNAPSHOT</version>
<name>datacenter-gateway-service</name>
<description>datacenter-gateway-service</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
<docker.image.prefix>springio</docker.image.prefix>
<spring-cloud.version>Greenwich.SR1</spring-cloud.version>
<alibaba-nacos-discovery.version>2.1.1.RELEASE</alibaba-nacos-discovery.version>
<alibaba-nacos-config.version>2.1.1.RELEASE</alibaba-nacos-config.version>
<alibaba-fastjson.version>1.2.70</alibaba-fastjson.version>
<apache-commons-lang3.version>3.7</apache-commons-lang3.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>${alibaba-nacos-discovery.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>${alibaba-nacos-config.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${alibaba-fastjson.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${apache-commons-lang3.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
</dependency>
<dependency>
<groupId>com.esv.platform</groupId>
<artifactId>gateway-common</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<profiles>
<profile>
<id>develop</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>release</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<excludes>
<exclude>*.yml</exclude>
<exclude>*.properties</exclude>
<exclude>logback-spring.xml</exclude>
</excludes>
<filtering>true</filtering>
</resource>
</resources>
</build>
</profile>
</profiles>
<build>
<finalName>datacenter-gateway-service</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<includeSystemScope>true</includeSystemScope>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<nonFilteredFileExtensions>
<nonFilteredFileExtension>woff</nonFilteredFileExtension>
<nonFilteredFileExtension>woff2</nonFilteredFileExtension>
<nonFilteredFileExtension>eot</nonFilteredFileExtension>
<nonFilteredFileExtension>ttf</nonFilteredFileExtension>
<nonFilteredFileExtension>svg</nonFilteredFileExtension>
</nonFilteredFileExtensions>
</configuration>
</plugin>
<!-- docker打包插件 -->
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>1.3.6</version>
<configuration>
<repository>${docker.image.prefix}/${project.artifactId}</repository>
<buildArgs>
<JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
</buildArgs>
</configuration>
</plugin>
</plugins>
</build>
</project>
package com.esv.datacenter.gateway;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.web.context.request.RequestContextListener;
import javax.annotation.PostConstruct;
import java.util.TimeZone;
/**
* @description:
* @author: 黄朝斌
* @email: huangchaobin@esvtek.com
* @createTime: 2020/06/29 19:33
* @version:1.0
*/
@SpringBootApplication
@EnableDiscoveryClient
@EnableZuulProxy
@EnableFeignClients({"com.esv.datacenter.gateway.feign"})
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
@Bean
public RequestContextListener requestContextListener(){
return new RequestContextListener();
}
@PostConstruct
void setDefaultTimezone() {
TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai"));
}
}
package com.esv.datacenter.gateway.common.component;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
/**
* @description:
* @author: 黄朝斌
* @email: huangchaobin@esvtek.com
* @createTime: 2020/05/28 14:33
* @version:1.0
*/
@Slf4j
@Component
public class ApplicationLoadRunner implements ApplicationRunner {
@Value("${spring.application.name}")
private String applicationName;
@Override
public void run(ApplicationArguments var) {
log.info("-------------------- [{}]初始化完成 --------------------", applicationName);
}
}
\ No newline at end of file
package com.esv.datacenter.gateway.common.component;
import com.alibaba.fastjson.JSONObject;
import com.esv.datacenter.gateway.util.LogUtils;
import com.netflix.client.ClientException;
import com.netflix.hystrix.exception.HystrixTimeoutException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.netflix.zuul.filters.route.FallbackProvider;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Component;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.SocketTimeoutException;
/**
* @description: 服务熔断降级处理
* @author: 黄朝斌
* @email: huangchaobin@esvtek.com
* @createTime: 2020/07/01 13:43
* @version:1.0
*/
@Component
@Slf4j
public class ServiceFallbackProvider implements FallbackProvider {
/**
* getRoute方法的返回值就是要监听的挂掉的微服务的名字
* 如果需要所有服务都走这个熔断回退,则return "*" 或 return null
**/
@Override
public String getRoute() {
return null;
}
/**
* 当服务无法执行的时候,返回托底信息
**/
@Override
public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
return new ClientHttpResponse() {
/**
* ClientHttpResponse的fallback的状态码
*/
@Override
public HttpStatus getStatusCode() throws IOException {
return HttpStatus.OK;
}
/**
* ClientHttpResponse的fallback的状态码
*/
@Override
public int getRawStatusCode() throws IOException {
return this.getStatusCode().value();
}
/**
* ClientHttpResponse的fallback的状态码
*/
@Override
public String getStatusText() throws IOException {
return this.getStatusCode().getReasonPhrase();
}
/**
* Close this response, freeing any resources created.
*/
@Override
public void close() {
}
/**
* 设置响应体
*/
@Override
public InputStream getBody() throws IOException {
Throwable causeLevel2 = cause.getCause();
Throwable causeLevel3 = (null == causeLevel2) ? null : causeLevel2.getCause();
// Log输出cause层级信息
log.info(cause.toString());
if (null != causeLevel2) {
log.info(causeLevel2.toString());
}
if (null != causeLevel3) {
log.info(causeLevel3.toString());
}
String message;
if (cause instanceof ClientException) {
message = "网关未路由到服务[" + route + "],请稍后再试";
if (null != causeLevel2 && causeLevel2 instanceof RuntimeException) {
if (causeLevel3 instanceof SocketTimeoutException || causeLevel3 instanceof HystrixTimeoutException) {
message = "服务[" + route + "]响应超时";
}
}
} else if (cause instanceof HystrixTimeoutException) {
message = "服务[" + route + "]响应超时";
} else {
message = "网关未定义错误[" + cause.toString() + "]";
}
JSONObject json = new JSONObject();
json.put("code", 500);
json.put("responseTime", System.currentTimeMillis());
json.put("message", message);
json.put("logId", LogUtils.getThreadTraceId());
return new ByteArrayInputStream(json.toJSONString().getBytes());
}
/**
* 设置响应头信息
*/
@Override
public HttpHeaders getHeaders() {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
return headers;
}
};
}
}
package com.esv.datacenter.gateway.common.constants;
/**
* @description: 全局常量
* @author: 黄朝斌
* @email: huangchaobin@esvtek.com
* @createTime: 2020/07/17 16:17
* @version:1.0
*/
public class CommonConstants {
/**
* 操作系统:windows
**/
public static final String SYSTEM_WINDOWS = "windows";
/**
* 访问端来源:1-浏览器端、2-Android端、3-iOS端、4-后台服务端
**/
public static final String REQ_SOURCE_TYPE_KEY = "Source-Type";
public static final String REQ_SOURCE_TYPE_WEB = "1";
public static final String REQ_SOURCE_TYPE_ANDROID = "2";
public static final String REQ_SOURCE_TYPE_IOS = "3";
public static final String REQ_SOURCE_TYPE_SERVICE = "4";
/**
* Feign调用返回参数
**/
public static final String FEIGN_RESULT_CODE = "code";
public static final String FEIGN_RESULT_MESSAGE = "message";
public static final String FEIGN_RESULT_DATA = "data";
public static final int FEIGN_RESULT_SUCCESS = 200;
/**
* 日志ID
**/
public static final String LOG_TRACE_ID = "traceId";
/**
* 字符串"null"
**/
public static final String NULL_STRING = "null";
/**
* 字符串"unknown"
**/
public static final String UNKNOWN_STRING = "unknown";
/**
* 默认字符编码
**/
public static final String DEFAULT_CHARACTER_ENCODING = "utf-8";
/**
* Http请求方式
**/
public static final String HTTP_REQUEST_METHOD_GET = "GET";
public static final String HTTP_REQUEST_METHOD_POST = "POST";
/**
* Http请求头
**/
public static final String HTTP_HEADER_X_FORWARDED_FOR = "x-forwarded-for";
public static final String HTTP_HEADER_PROXY_CLIENT_IP = "Proxy-Client-IP";
public static final String HTTP_HEADER_WL_PROXY_CLIENT_IP = "WL-Proxy-Client-IP";
}
package com.esv.datacenter.gateway.common.exception;
/**
* @description:
* @author: 黄朝斌
* @email: huangchaobin@esvtek.com
* @createTime: 2020/06/24 14:41
* @version:1.0
*/
public class EException extends RuntimeException {
private static final long serialVersionUID = 1L;
private String msg;
private int code = 500;
public EException(String msg) {
super(msg);
this.msg = msg;
}
public EException(String msg, Throwable e) {
super(msg, e);
this.msg = msg;
}
public EException(String msg, int code) {
super(msg);
this.msg = msg;
this.code = code;
}
public EException(String msg, int code, Throwable e) {
super(msg, e);
this.msg = msg;
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
}
package com.esv.datacenter.gateway.common.response;
/**
* @description:
* @author: 黄朝斌
* @email: huangchaobin@esvtek.com
* @createTime: 2020/06/24 14:42
* @version:1.0
*/
public class ECode {
public static final ECode SUCCESS = new ECode(200, "success");
public static final ECode ACCESS_DENIED = new ECode(401, "没有访问权限");
public static final ECode SERVER_ERROR = new ECode(500, "服务内部错误");
public static final ECode PARAM_ERROR = new ECode(600, "参数不合法");
public static final ECode TOKEN_INVALID = new ECode(601, "无效的Token");
public static final ECode TOKEN_EXPIRED = new ECode(602, "Token已过期");
public ECode(int code, String message) {
this.code = code;
this.message = message;
}
private int code;
private String message;
public int code() {
return code;
}
public String message() {
return message;
}
}
package com.esv.datacenter.gateway.common.response;
import com.esv.datacenter.gateway.util.LogUtils;
import com.fasterxml.jackson.annotation.JsonInclude;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import java.io.Serializable;
/**
* @description:
* @author: 黄朝斌
* @email: huangchaobin@esvtek.com
* @createTime: 2020/06/24 14:42
* @version:1.0
*/
public class EResponse<T> implements Serializable {
private static final long serialVersionUID = 1L;
private int code;
private String message;
private long responseTime;
private String logId;
private T data;
private EResponse() {
this.responseTime = System.currentTimeMillis();
this.logId = LogUtils.getThreadTraceId();
}
private EResponse(int code, String message) {
this();
this.code = code;
this.message = message;
}
private EResponse(int code, String message, T data) {
this();
this.code = code;
this.message = message;
this.data = data;
}
private EResponse(ECode eCode) {
this(eCode.code(), eCode.message());
}
private EResponse(T data) {
this(ECode.SUCCESS);
this.data = data;
}
/**
* description 成功返回
* param []
* return com.esv.common.response.EResponse
* author chenfm
* createTime 2020/3/6 14:50
**/
public static EResponse ok() {
return new EResponse(ECode.SUCCESS);
}
/**
* description 成功返回(带数据)
* param [data] 返回数据
* return com.esv.common.response.EResponse<T>
* author chenfm
* createTime 2020/3/6 14:50
**/
public static<T> EResponse<T> ok(T data) {
return new EResponse<T>(data);
}
/**
* description 返回默认系统异常
* param []
* return com.esv.springcloud.template.common.response.EResponse
* author Administrator
* createTime 2020/03/13 15:36
**/
public static EResponse error() {
return error(ECode.SERVER_ERROR);
}
/**
* description 返回自定义code、message异常
* param []
* return com.esv.common.response.EResponse
* author chenfm
* createTime 2020/3/9 13:32
*
* @param code
* @param message*/
public static EResponse error(int code, String message) {
return new EResponse(code, message);
}
/**
* description 返回自定义code、message、data异常
* param [code, message, data]
* return com.esv.htwl.customer.common.response.EResponse<T>
* author HuangChaobin
* createTime 2020/07/09 15:04
**/
public static<T> EResponse<T> error(int code, String message, T data) {
return new EResponse(code, message, data);
}
/**
* description 异常返回
* param [rCode] 异常码
* return com.esv.common.response.EResponse
* author chenfm
* createTime 2020/3/6 14:50
**/
public static EResponse error(ECode eCode) {
return new EResponse(eCode);
}
/**
* description 判断返回是否成功
* param []
* return boolean
* author chenfm
* createTime 2020/3/6 14:51
**/
public boolean success() {
return this.code == ECode.SUCCESS.code();
}
/**
* description 修改提示信息
* param [message] 提示信息
* return void
* author chenfm
* createTime 2020/3/6 17:44
**/
public EResponse message(String message) {
this.message = message;
return this;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public long getResponseTime() {
return responseTime;
}
public void setResponseTime(long responseTime) {
this.responseTime = responseTime;
}
public String getLogId() {
return logId;
}
public void setLogId(String logId) {
this.logId = logId;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE);
}
}
\ No newline at end of file
package com.esv.datacenter.gateway.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import java.util.Arrays;
/**
* @description: 跨域配置
* @author: 黄朝斌
* @email: huangchaobin@esvtek.com
* @createTime: 2020/06/30 9:18
* @version:1.0
*/
@Configuration
public class CorsConfig {
@Bean
public CorsFilter corsFilter() {
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
final CorsConfiguration config = new CorsConfiguration();
// 是否允许请求带有验证信息
config.setAllowCredentials(true);
// 允许向该服务器提交请求的URI,*表示全部允许。这里尽量限制来源域,比如http://test.com:8080 ,以降低安全风险
config.setAllowedOrigins(Arrays.asList("*"));
// 允许访问的头信息,*表示全部
config.setAllowedHeaders(Arrays.asList("*"));
// 预检请求的缓存时间(秒),即在这个时间段里,对于相同的跨域请求不会再预检了
config.setMaxAge(3600L);
// 允许提交请求的方法,*表示全部允许,也可以单独设置GET、POST等
config.setAllowedMethods(Arrays.asList("*"));
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}
package com.esv.datacenter.gateway.config;
import com.esv.datacenter.gateway.filter.AccessFilter;
import com.esv.datacenter.gateway.filter.AuthRoutingFilter;
import com.esv.datacenter.gateway.filter.LogBackPreFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @description: 注册Filter
* @author: 黄朝斌
* @email: huangchaobin@esvtek.com
* @createTime: 2020/06/29 20:05
* @version:1.0
*/
@Configuration
public class FilterConfig {
@Bean
public LogBackPreFilter getLogBackPreFilter() {
LogBackPreFilter filter = new LogBackPreFilter();
return filter;
}
@Bean
public AuthRoutingFilter getAuthRoutingFilter() {
AuthRoutingFilter filter = new AuthRoutingFilter();
return filter;
}
@Bean
public AccessFilter getAccessFilter() {
AccessFilter filter = new AccessFilter();
return filter;
}
}
package com.esv.datacenter.gateway.feign;
import com.esv.datacenter.gateway.common.response.EResponse;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
/**
* @description:
* @author: 黄朝斌
* @email: huangchaobin@esvtek.com
* @createTime: 2020/06/24 14:44
* @version:1.0
*/
@FeignClient("${app.service.cc.name}")
public interface AuthFeignClient {
@PostMapping({"/cc/auth/webReqAuth"})
EResponse<WebReqAuthRes> webReqAuth(@RequestHeader("gateway_traceid") String var1, @RequestBody WebReqAuthReq var2);
}
package com.esv.datacenter.gateway.feign;
import lombok.Data;
/**
* @description:
* @author: 黄朝斌
* @email: huangchaobin@esvtek.com
* @createTime: 2020/06/24 14:44
* @version:1.0
*/
@Data
public class WebReqAuthReq {
private String reqUrl;
private String token;
private String menuCode;
}
package com.esv.datacenter.gateway.feign;
import lombok.Data;
/**
* @description:
* @author: 黄朝斌
* @email: huangchaobin@esvtek.com
* @createTime: 2020/06/24 14:44
* @version:1.0
*/
@Data
public class WebReqAuthRes {
private String systemCode;
private Integer dataPerm;
private Long userId;
private String account;
private Long tenantId;
private Long departmentId;
private String departmentChildren;
}
package com.esv.datacenter.gateway.filter;
import lombok.extern.slf4j.Slf4j;
import javax.servlet.*;
import java.io.IOException;
/**
* @description:
* @author: 黄朝斌
* @email: huangchaobin@esvtek.com
* @createTime: 2020/07/01 11:09
* @version:1.0
*/
@Slf4j
public class AccessFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
}
}
package com.esv.datacenter.gateway.filter;
import com.esv.datacenter.gateway.common.response.EResponse;
import com.esv.datacenter.gateway.feign.AuthFeignClient;
import com.esv.datacenter.gateway.feign.WebReqAuthReq;
import com.esv.datacenter.gateway.feign.WebReqAuthRes;
import com.esv.datacenter.gateway.util.LogUtils;
import com.esv.datacenter.gateway.util.RequestUriUtils;
import com.esv.datacenter.gateway.util.ResponseUtils;
import com.esv.gateway.common.GatewayHeaders;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.util.Objects;
/**
* @description:
* @author: 黄朝斌
* @email: huangchaobin@esvtek.com
* @createTime: 2020/06/30 9:59
* @version:1.0
*/
@Slf4j
@RefreshScope
@Component
public class AuthRoutingFilter extends ZuulFilter {
@Value("${zuul.prefix}")
private String prefix;
@Value("${management.endpoints.web.base-path}")
private String actuatorBasePath;
private static final String AUTH_HEADER_KEY = "Union-Authorization";
private static final String MENU_CODE_HEADER_KEY = "Union-Menu-Code";
@Autowired
private AuthFeignClient authFeignClient;
@Override
public String filterType() {
return "route";
}
@Override
public int filterOrder() {
return 0;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
RequestContext context = RequestContext.getCurrentContext();
HttpServletRequest request = context.getRequest();
String uri = request.getRequestURI();
uri = uri.replaceFirst(prefix, "");
// 端点监控uri直接放行
if (uri.contains(actuatorBasePath)) {
return null;
}
// 手机APP uri直接放行
if (uri.startsWith("/app")) {
return null;
}
String token = StringUtils.trimToEmpty(request.getHeader(AUTH_HEADER_KEY));
String menuCode = StringUtils.trimToEmpty(request.getHeader(MENU_CODE_HEADER_KEY));
// 访问鉴权
WebReqAuthReq webReqAuthReq = new WebReqAuthReq();
webReqAuthReq.setReqUrl(uri);
webReqAuthReq.setToken(token);
webReqAuthReq.setMenuCode(menuCode);
EResponse<WebReqAuthRes> eResponse = authFeignClient.webReqAuth(LogUtils.getThreadTraceId(), webReqAuthReq);
if (eResponse.success()) {
WebReqAuthRes webReqAuthRes = eResponse.getData();
Integer dataPerm = webReqAuthRes.getDataPerm();
Long userId = webReqAuthRes.getUserId();
String account = webReqAuthRes.getAccount();
Long tenantId = webReqAuthRes.getTenantId();
Long departmentId = webReqAuthRes.getDepartmentId();
String departmentChildren = webReqAuthRes.getDepartmentChildren();
// 添加header
context.addZuulRequestHeader(GatewayHeaders.SYSTEM_CODE, RequestUriUtils.getSystemCode(uri));
if (Objects.nonNull(dataPerm)) {
context.addZuulRequestHeader(GatewayHeaders.DATA_PERM, String.valueOf(dataPerm));
}
if (Objects.nonNull(userId)) {
context.addZuulRequestHeader(GatewayHeaders.USER_ID, String.valueOf(userId));
}
if (Objects.nonNull(account)) {
context.addZuulRequestHeader(GatewayHeaders.USER_ACCOUNT, account);
}
if (Objects.nonNull(tenantId)) {
context.addZuulRequestHeader(GatewayHeaders.TENANT_ID, String.valueOf(tenantId));
}
if (Objects.nonNull(departmentId)) {
context.addZuulRequestHeader(GatewayHeaders.DEPARTMENT_ID, String.valueOf(departmentId));
}
if (Objects.nonNull(departmentChildren)) {
context.addZuulRequestHeader(GatewayHeaders.DEPARTMENT_CHILDREN, departmentChildren);
}
} else {
ResponseUtils.failureResponse(eResponse);
}
return null;
}
}
package com.esv.datacenter.gateway.filter;
import com.esv.datacenter.gateway.common.constants.CommonConstants;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import java.util.UUID;
/**
* @description:
* @author: 黄朝斌
* @email: huangchaobin@esvtek.com
* @createTime: 2020/06/29 19:48
* @version:1.0
*/
@Slf4j
public class LogBackPreFilter extends ZuulFilter {
/**
* pre:主要用在路由映射的阶段是寻找路由映射表的
* route:具体的路由转发过滤器是在routing路由器,具体的请求转发的时候会调用
* error:一旦前面的过滤器出错了,会调用error过滤器
* post:当routing,error运行完后才会调用该过滤器,是在最后阶段
*
**/
@Override
public String filterType() {
return "pre";
}
/**
* 自定义过滤器执行的顺序,数值越大越靠后执行,越小就越先执行
**/
@Override
public int filterOrder() {
return -10;
}
/**
* 控制过滤器生效不生效(是否执行run()方法),可以在里面写一串逻辑来控制,true是生效
**/
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
RequestContext context = RequestContext.getCurrentContext();
String traceId = UUID.randomUUID().toString().replace("-", "");
MDC.put(CommonConstants.LOG_TRACE_ID, traceId);
context.addZuulRequestHeader("gateway_traceid", traceId);
return null;
}
}
package com.esv.datacenter.gateway.util;
import com.esv.datacenter.gateway.common.constants.CommonConstants;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.MDC;
import java.util.UUID;
/**
* @description:
* @author: huangchaobin@esvtek.com
* @createTime: 2020/07/21 18:41
* @version:1.0
*/
public class LogUtils {
/**
* @description 获取当前线程设置日志traceId
* @return String
* @author huangChaobin@esvtek.com
* @createTime 2020/07/21 18:43
**/
public static String getThreadTraceId() {
String traceId = MDC.get(CommonConstants.LOG_TRACE_ID);
if (StringUtils.isBlank(traceId)) {
traceId = UUID.randomUUID().toString().replaceAll("-", "");
}
return traceId;
}
}
package com.esv.datacenter.gateway.util;
/**
* @description:
* @author: 黄朝斌
* @email: huangchaobin@esvtek.com
* @createTime: 2020/06/30 10:08
* @version:1.0
*/
public class RequestUriUtils {
public static String getSystemCode(String url) {
if (url.startsWith("/")) {
url = url.substring(1);
}
return url.split("/")[0];
}
public static String getPermsUrl(String url) {
if (url.startsWith("/")) {
url.substring(1);
}
return url.split("/")[1];
}
}
package com.esv.datacenter.gateway.util;
import com.esv.datacenter.gateway.common.response.EResponse;
import com.netflix.zuul.context.RequestContext;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
/**
* @description:
* @author: 黄朝斌
* @email: huangchaobin@esvtek.com
* @createTime: 2020/06/30 10:55
* @version:1.0
*/
public class ResponseUtils {
public static void failureResponse(EResponse eResponse) {
RequestContext context = RequestContext.getCurrentContext();
context.setSendZuulResponse(false);
context.setResponseStatusCode(HttpStatus.OK.value());
context.getResponse().setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
context.setResponseBody(eResponse.toString());
}
}
management:
endpoints:
web:
exposure:
# "*"开放所有监控端点,指定监控端点,用逗号分隔
include: health,loggers
base-path: /esvActuator
endpoint:
health:
show-details: always
app:
service:
cc:
name: datacenter-cc-service
# 负载均衡设置
ribbon:
# http建立socket超时时间,毫秒
ConnectTimeout: 2000
# http读取响应socket超时时间
ReadTimeout: 10000
# 同一台实例最大重试次数,不包括首次调用
MaxAutoRetries: 0
# 重试负载均衡其他的实例最大重试次数,不包括首次server
MaxAutoRetriesNextServer: 1
# 是否所有操作都重试,POST请求注意多次提交错误。默认false,设定为false的话,只有get请求会重试
OkToRetryOnAllOperations: true
# 熔断设置
hystrix:
command:
default:
execution:
timeout:
enabled: true
isolation:
thread:
timeoutInMilliseconds: 25000
zuul:
ribbon:
eager-load.enabled: true
ignored-services: '*'
prefix: /dataCenterApi
host:
max-total-connections: 200
max-per-route-connections: 20
routes:
cc-service:
path: /cc/**
service-id: datacenter-cc-service
stripPrefix: false
\ No newline at end of file
management:
endpoints:
web:
exposure:
# "*"开放所有监控端点,指定监控端点,用逗号分隔
include: health,loggers
base-path: /esvActuator
endpoint:
health:
show-details: always
app:
service:
cc:
name: datacenter-cc-service
# 负载均衡设置
ribbon:
# http建立socket超时时间,毫秒
ConnectTimeout: 2000
# http读取响应socket超时时间
ReadTimeout: 10000
# 同一台实例最大重试次数,不包括首次调用
MaxAutoRetries: 0
# 重试负载均衡其他的实例最大重试次数,不包括首次server
MaxAutoRetriesNextServer: 1
# 是否所有操作都重试,POST请求注意多次提交错误。默认false,设定为false的话,只有get请求会重试
OkToRetryOnAllOperations: true
# 熔断设置
hystrix:
command:
default:
execution:
timeout:
enabled: true
isolation:
thread:
timeoutInMilliseconds: 25000
zuul:
ribbon:
eager-load.enabled: true
ignored-services: '*'
prefix: /dataCenterApi
host:
max-total-connections: 200
max-per-route-connections: 20
routes:
cc-service:
path: /cc/**
service-id: datacenter-cc-service
stripPrefix: false
\ No newline at end of file
management:
endpoints:
web:
exposure:
# "*"开放所有监控端点,指定监控端点,用逗号分隔
include: health,loggers
base-path: /esvActuator
endpoint:
health:
show-details: always
app:
service:
cc:
name: datacenter-cc-service
# 负载均衡设置
ribbon:
# http建立socket超时时间,毫秒
ConnectTimeout: 2000
# http读取响应socket超时时间
ReadTimeout: 10000
# 同一台实例最大重试次数,不包括首次调用
MaxAutoRetries: 0
# 重试负载均衡其他的实例最大重试次数,不包括首次server
MaxAutoRetriesNextServer: 1
# 是否所有操作都重试,POST请求注意多次提交错误。默认false,设定为false的话,只有get请求会重试
OkToRetryOnAllOperations: true
# 熔断设置
hystrix:
command:
default:
execution:
timeout:
enabled: true
isolation:
thread:
timeoutInMilliseconds: 25000
zuul:
ribbon:
eager-load.enabled: true
ignored-services: '*'
prefix: /dataCenterApi
host:
max-total-connections: 200
max-per-route-connections: 20
routes:
cc-service:
path: /cc/**
service-id: datacenter-cc-service
stripPrefix: false
\ No newline at end of file
server:
port: 8085
servlet:
context-path: /
nacos:
url: 192.168.31.248:8848
namespace: 1697ea67-be4c-4d38-b00d-39392b9dee8f
group: DEFAULT_GROUP
spring:
application:
name: datacenter-gateway-service
profiles:
active: local
cloud:
nacos:
discovery:
server-addr: ${nacos.url}
namespace: ${nacos.namespace}
group: ${nacos.group}
config:
server-addr: ${nacos.url}
namespace: ${nacos.namespace}
group: ${nacos.group}
file-extension: yml
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds">
<include resource="org/springframework/boot/logging/logback/base.xml"/>
<springProperty scope="context" name="LOG_FILE_NAME" source="spring.application.name"/>
<!-- 日志存储目录 -->
<property name="LOG_FILE_PATH" value="./logs/" />
<!-- 日志文件大小 -->
<property name="MAX_FILE_SIZE" value="100MB" />
<!-- 日志最大的历史(单位:天) -->
<property name="MAX_HISTORY" value="90" />
<!-- 格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度,%msg:日志消息,%n:换行符-->
<property name="LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread-%X{traceId}] %-5level %logger{50}.%M[%line]:%msg%n" />
<!-- 控制台输出 -->
<appender name="CONSOLE_APPENDER" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>debug</level>
</filter>
<encoder>
<Pattern>${LOG_PATTERN}</Pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- 滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件 -->
<appender name="FILE_APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_FILE_PATH}${LOG_FILE_NAME}.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_FILE_PATH}${LOG_FILE_NAME}-%d{yyyy-MM-dd}-%i.log</fileNamePattern>
<maxHistory>${MAX_HISTORY}</maxHistory>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>${MAX_FILE_SIZE}</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${LOG_PATTERN}</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- mybatis sql日志 日志的级别需要是DEBUG -->
<!-- 日志打印的包的范围,及分类日志文件存储 -->
<logger name="com.esv" level="DEBUG" additivity="false">
<appender-ref ref="CONSOLE_APPENDER" />
<appender-ref ref="FILE_APPENDER" />
</logger>
<logger name="com.esv.freight.customer.config.mybatis" level="INFO" additivity="false">
<appender-ref ref="CONSOLE_APPENDER" />
<appender-ref ref="FILE_APPENDER" />
</logger>
<logger name="com.deepoove.poi" level="ERROR" additivity="false">
<appender-ref ref="CONSOLE_APPENDER" />
<appender-ref ref="FILE_APPENDER" />
</logger>
<!--控制台和日志文件输出级别-->
<root level="INFO" additivity="false">
<appender-ref ref="CONSOLE_APPENDER" />
<appender-ref ref="FILE_APPENDER" />
</root>
</configuration>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment