13693261870
2025-06-20 58bef650d244447c65d0b6b7e632443b5bc27ac3
初始化代码~
已添加20个文件
已修改1个文件
1300 ■■■■■ 文件已修改
.gitignore 52 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pom.xml 193 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
se-gateway/pom.xml 93 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
se-gateway/src/main/java/com/terra/gateway/SeGatewayApplication.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
se-gateway/src/main/java/com/terra/gateway/config/GatewayConfig.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
se-gateway/src/main/java/com/terra/gateway/config/SpringDocConfig.java 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
se-gateway/src/main/java/com/terra/gateway/config/properties/IgnoreWhiteProperties.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
se-gateway/src/main/java/com/terra/gateway/config/properties/XssProperties.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
se-gateway/src/main/java/com/terra/gateway/filter/AuthFilter.java 128 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
se-gateway/src/main/java/com/terra/gateway/filter/BlackListUrlFilter.java 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
se-gateway/src/main/java/com/terra/gateway/filter/XssFilter.java 128 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
se-gateway/src/main/java/com/terra/gateway/handler/GatewayExceptionHandler.java 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
se-gateway/src/main/java/com/terra/gateway/handler/SentinelFallbackHandler.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
se-gateway/src/main/resources/banner.txt 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
se-gateway/src/main/resources/bootstrap.yml 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
se-gateway/src/main/resources/logback.xml 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
se-system/pom.xml 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
se-system/src/main/java/com/terra/system/SeSystemApplication.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
se-system/src/main/resources/banner.txt 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
se-system/src/main/resources/bootstrap.yml 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
se-system/src/main/resources/logback.xml 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.gitignore
@@ -1,12 +1,46 @@
*.class
######################################################################
# Build Tools
# Mobile Tools for Java (J2ME)
.mtj.tmp/
.gradle
/build/
!gradle/wrapper/gradle-wrapper.jar
# Package Files #
*.jar
*.war
*.ear
target/
!.mvn/wrapper/maven-wrapper.jar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
######################################################################
# IDE
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### JRebel ###
rebel.xml
### NetBeans ###
nbproject/private/
build/*
nbbuild/
dist/
nbdist/
.nb-gradle/
######################################################################
# Others
*.log
*.xml.versionsBackup
*.swp
!*/build/*.java
!*/build/*.html
!*/build/*.xml
pom.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,193 @@
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.terra</groupId>
    <artifactId>terra</artifactId>
    <version>1.0.2</version>
    <name>terra</name>
    <url>https://www.smartearth.cn/</url>
    <description>微服务系统</description>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-boot.version>2.7.18</spring-boot.version>
        <spring-cloud.version>2021.0.9</spring-cloud.version>
        <spring-cloud-alibaba.version>2021.0.6.1</spring-cloud-alibaba.version>
        <spring-boot-admin.version>2.7.16</spring-boot-admin.version>
        <tobato.version>1.27.2</tobato.version>
        <kaptcha.version>2.3.3</kaptcha.version>
        <pagehelper.boot.version>2.0.0</pagehelper.boot.version>
        <druid.version>1.2.23</druid.version>
        <dynamic-ds.version>4.3.1</dynamic-ds.version>
        <commons.io.version>2.19.0</commons.io.version>
        <velocity.version>2.3</velocity.version>
        <fastjson.version>2.0.57</fastjson.version>
        <jjwt.version>0.9.1</jjwt.version>
        <minio.version>8.2.2</minio.version>
        <poi.version>4.1.2</poi.version>
        <springdoc.version>1.6.9</springdoc.version>
        <transmittable-thread-local.version>2.14.4</transmittable-thread-local.version>
        <!-- override dependency version -->
        <tomcat.version>9.0.106</tomcat.version>
        <logback.version>1.2.13</logback.version>
        <spring-framework.version>5.3.39</spring-framework.version>
    </properties>
    <!-- ä¾èµ–声明 -->
    <dependencyManagement>
        <dependencies>
            <!-- è¦†ç›–SpringFramework的依赖配置-->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-framework-bom</artifactId>
                <version>${spring-framework.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- SpringCloud å¾®æœåŠ¡ -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- SpringCloud Alibaba å¾®æœåŠ¡ -->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- SpringBoot ä¾èµ–配置 -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- è¦†ç›–logback的依赖配置-->
            <dependency>
                <groupId>ch.qos.logback</groupId>
                <artifactId>logback-core</artifactId>
                <version>${logback.version}</version>
            </dependency>
            <dependency>
                <groupId>ch.qos.logback</groupId>
                <artifactId>logback-classic</artifactId>
                <version>${logback.version}</version>
            </dependency>
            <!-- è¦†ç›–tomcat的依赖配置-->
            <dependency>
                <groupId>org.apache.tomcat.embed</groupId>
                <artifactId>tomcat-embed-core</artifactId>
                <version>${tomcat.version}</version>
            </dependency>
            <dependency>
                <groupId>org.apache.tomcat.embed</groupId>
                <artifactId>tomcat-embed-el</artifactId>
                <version>${tomcat.version}</version>
            </dependency>
            <dependency>
                <groupId>org.apache.tomcat.embed</groupId>
                <artifactId>tomcat-embed-websocket</artifactId>
                <version>${tomcat.version}</version>
            </dependency>
            <!-- JSON è§£æžå™¨å’Œç”Ÿæˆå™¨ -->
            <dependency>
                <groupId>com.alibaba.fastjson2</groupId>
                <artifactId>fastjson2</artifactId>
                <version>${fastjson.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <modules>
        <module>se-gateway</module>
        <module>se-system</module>
    </modules>
    <packaging>pom</packaging>
    <dependencies>
        <!-- bootstrap å¯åЍ噍 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <encoding>${project.build.sourceEncoding}</encoding>
                </configuration>
            </plugin>
        </plugins>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <version>${spring-boot.version}</version>
                    <executions>
                        <execution>
                            <goals>
                                <goal>repackage</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
    <repositories>
        <repository>
            <id>public</id>
            <name>aliyun nexus</name>
            <url>https://maven.aliyun.com/repository/public</url>
            <releases>
                <enabled>true</enabled>
            </releases>
        </repository>
    </repositories>
    <pluginRepositories>
        <pluginRepository>
            <id>public</id>
            <name>aliyun nexus</name>
            <url>https://maven.aliyun.com/repository/public</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>
</project>
se-gateway/pom.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,93 @@
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <groupId>com.terra</groupId>
        <artifactId>terra</artifactId>
        <version>1.0.2</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>se-gateway</artifactId>
    <description>
        ç½‘关模块
    </description>
    <dependencies>
        <!-- SpringCloud Gateway -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <!-- SpringCloud Alibaba Nacos -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!-- SpringCloud Alibaba Nacos Config -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
        <!-- SpringCloud Alibaba Sentinel -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
        <!-- SpringCloud Alibaba Sentinel Gateway -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
        </dependency>
        <!-- Sentinel Datasource Nacos -->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
        </dependency>
        <!-- SpringBoot Actuator -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!-- SpringCloud Loadbalancer -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-loadbalancer</artifactId>
        </dependency>
        <!-- Springdoc -->
        <dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-webflux-ui</artifactId>
            <version>${springdoc.version}</version>
        </dependency>
    </dependencies>
    <build>
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>
se-gateway/src/main/java/com/terra/gateway/SeGatewayApplication.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,20 @@
package com.terra.gateway;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
/**
 * ç½‘关启动程序
 *
 * @author admin
 */
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class })
public class SeGatewayApplication
{
    public static void main(String[] args)
    {
        SpringApplication.run(SeGatewayApplication.class, args);
        System.out.println("----------网关模块启动成功----------  \n");
    }
}
se-gateway/src/main/java/com/terra/gateway/config/GatewayConfig.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,23 @@
package com.terra.gateway.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import com.terra.gateway.handler.SentinelFallbackHandler;
/**
 * ç½‘关限流配置
 *
 * @author admin
 */
@Configuration
public class GatewayConfig
{
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public SentinelFallbackHandler sentinelGatewayExceptionHandler()
    {
        return new SentinelFallbackHandler();
    }
}
se-gateway/src/main/java/com/terra/gateway/config/SpringDocConfig.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,94 @@
package com.terra.gateway.config;
import java.util.Set;
import java.util.stream.Collectors;
import org.springdoc.core.AbstractSwaggerUiConfigProperties;
import org.springdoc.core.SwaggerUiConfigProperties;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.context.annotation.Configuration;
import com.alibaba.nacos.client.naming.event.InstancesChangeEvent;
import com.alibaba.nacos.common.notify.Event;
import com.alibaba.nacos.common.notify.NotifyCenter;
import com.alibaba.nacos.common.notify.listener.Subscriber;
import javax.annotation.Resource;
/**
 * SpringDoc配置类
 *
 * @author admin
 */
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(value = "springdoc.api-docs.enabled", matchIfMissing = true)
public class SpringDocConfig implements InitializingBean
{
    @Autowired
    private SwaggerUiConfigProperties swaggerUiConfigProperties;
    @Autowired
    private DiscoveryClient discoveryClient;
    /**
     * åœ¨åˆå§‹åŒ–后调用的方法
     */
    @Override
    public void afterPropertiesSet()
    {
        NotifyCenter.registerSubscriber(new SwaggerDocRegister(swaggerUiConfigProperties, discoveryClient));
    }
}
/**
 * Swagger文档注册器
 */
class SwaggerDocRegister extends Subscriber<InstancesChangeEvent>
{
    @Resource
    private SwaggerUiConfigProperties swaggerUiConfigProperties;
    @Resource
    private DiscoveryClient discoveryClient;
    private final static String[] EXCLUDE_ROUTES = new String[] { "se-gateway", "se-auth", "se-file", "se-monitor", "se-system" };
    public SwaggerDocRegister(SwaggerUiConfigProperties swaggerUiConfigProperties, DiscoveryClient discoveryClient)
    {
        this.swaggerUiConfigProperties = swaggerUiConfigProperties;
        this.discoveryClient = discoveryClient;
    }
    /**
     * äº‹ä»¶å›žè°ƒæ–¹æ³•,处理InstancesChangeEvent事件
     * @param event äº‹ä»¶å¯¹è±¡
     */
    @Override
    public void onEvent(InstancesChangeEvent event)
    {
        Set<AbstractSwaggerUiConfigProperties.SwaggerUrl> swaggerUrlSet = discoveryClient.getServices()
            .stream()
            .flatMap(serviceId -> discoveryClient.getInstances(serviceId).stream())
            //.filter(instance -> !StringUtils.equalsAnyIgnoreCase(instance.getServiceId(), EXCLUDE_ROUTES))
            .map(instance -> {
                AbstractSwaggerUiConfigProperties.SwaggerUrl swaggerUrl = new AbstractSwaggerUiConfigProperties.SwaggerUrl();
                swaggerUrl.setName(instance.getServiceId());
                swaggerUrl.setUrl(String.format("/%s/v3/api-docs", instance.getServiceId()));
                return swaggerUrl;
            })
            .collect(Collectors.toSet());
        swaggerUiConfigProperties.setUrls(swaggerUrlSet);
    }
    /**
     * è®¢é˜…类型方法,返回订阅的事件类型
     * @return è®¢é˜…的事件类型
     */
    @Override
    public Class<? extends Event> subscribeType()
    {
        return InstancesChangeEvent.class;
    }
}
se-gateway/src/main/java/com/terra/gateway/config/properties/IgnoreWhiteProperties.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,33 @@
package com.terra.gateway.config.properties;
import java.util.ArrayList;
import java.util.List;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Configuration;
/**
 * æ”¾è¡Œç™½åå•配置
 *
 * @author admin
 */
@Configuration
@RefreshScope
@ConfigurationProperties(prefix = "security.ignore")
public class IgnoreWhiteProperties
{
    /**
     * æ”¾è¡Œç™½åå•配置,网关不校验此处的白名单
     */
    private List<String> whites = new ArrayList<>();
    public List<String> getWhites()
    {
        return whites;
    }
    public void setWhites(List<String> whites)
    {
        this.whites = whites;
    }
}
se-gateway/src/main/java/com/terra/gateway/config/properties/XssProperties.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,48 @@
package com.terra.gateway.config.properties;
import java.util.ArrayList;
import java.util.List;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Configuration;
/**
 * XSS跨站脚本配置
 *
 * @author admin
 */
@Configuration
@RefreshScope
@ConfigurationProperties(prefix = "security.xss")
public class XssProperties
{
    /**
     * Xss开关
     */
    private Boolean enabled;
    /**
     * æŽ’除路径
     */
    private List<String> excludeUrls = new ArrayList<>();
    public Boolean getEnabled()
    {
        return enabled;
    }
    public void setEnabled(Boolean enabled)
    {
        this.enabled = enabled;
    }
    public List<String> getExcludeUrls()
    {
        return excludeUrls;
    }
    public void setExcludeUrls(List<String> excludeUrls)
    {
        this.excludeUrls = excludeUrls;
    }
}
se-gateway/src/main/java/com/terra/gateway/filter/AuthFilter.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,128 @@
package com.terra.gateway.filter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import com.terra.gateway.config.properties.IgnoreWhiteProperties;
import reactor.core.publisher.Mono;
import javax.annotation.Resource;
/**
 * ç½‘关鉴权
 *
 * @author admin
 */
@Component
public class AuthFilter implements GlobalFilter, Ordered
{
    private static final Logger log = LoggerFactory.getLogger(AuthFilter.class);
    // æŽ’除过滤的 uri åœ°å€ï¼Œnacos自行添加
    @Resource
    private IgnoreWhiteProperties ignoreWhite;
    //@Resource
    //private RedisService redisService;
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain)
    {
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpRequest.Builder mutate = request.mutate();
        String url = request.getURI().getPath();
        /*// è·³è¿‡ä¸éœ€è¦éªŒè¯çš„路径
        if (StringUtils.matches(url, ignoreWhite.getWhites()))
        {
            return chain.filter(exchange);
        }
        String token = getToken(request);
        if (StringUtils.isEmpty(token))
        {
            return unauthorizedResponse(exchange, "令牌不能为空");
        }
        Claims claims = JwtUtils.parseToken(token);
        if (claims == null)
        {
            return unauthorizedResponse(exchange, "令牌已过期或验证不正确!");
        }
        String userkey = JwtUtils.getUserKey(claims);
        boolean islogin = redisService.hasKey(getTokenKey(userkey));
        if (!islogin)
        {
            return unauthorizedResponse(exchange, "登录状态已过期");
        }
        String userid = JwtUtils.getUserId(claims);
        String username = JwtUtils.getUserName(claims);
        if (StringUtils.isEmpty(userid) || StringUtils.isEmpty(username))
        {
            return unauthorizedResponse(exchange, "令牌验证失败");
        }
        // è®¾ç½®ç”¨æˆ·ä¿¡æ¯åˆ°è¯·æ±‚
        addHeader(mutate, SecurityConstants.USER_KEY, userkey);
        addHeader(mutate, SecurityConstants.DETAILS_USER_ID, userid);
        addHeader(mutate, SecurityConstants.DETAILS_USERNAME, username);
        // å†…部请求来源参数清除
        removeHeader(mutate, SecurityConstants.FROM_SOURCE);*/
        return chain.filter(exchange.mutate().request(mutate.build()).build());
    }
    private void addHeader(ServerHttpRequest.Builder mutate, String name, Object value)
    {
        if (value == null)
        {
            return;
        }
        String valueStr = value.toString();
        //String valueEncode = ServletUtils.urlEncode(valueStr);
        //mutate.header(name, valueEncode);
    }
    private void removeHeader(ServerHttpRequest.Builder mutate, String name)
    {
        mutate.headers(httpHeaders -> httpHeaders.remove(name)).build();
    }
    private Mono<Void> unauthorizedResponse(ServerWebExchange exchange, String msg)
    {
        log.error("[鉴权异常处理]请求路径:{},错误信息:{}", exchange.getRequest().getPath(), msg);
        //return ServletUtils.webFluxResponseWriter(exchange.getResponse(), msg, HttpStatus.UNAUTHORIZED);
        return null;
    }
    /**
     * èŽ·å–ç¼“å­˜key
     */
    private String getTokenKey(String token)
    {
        return null; //return CacheConstants.LOGIN_TOKEN_KEY + token;
    }
    /**
     * èŽ·å–è¯·æ±‚token
     */
    private String getToken(ServerHttpRequest request)
    {
//        String token = request.getHeaders().getFirst(SecurityConstants.AUTHORIZATION_HEADER);
//        // å¦‚果前端设置了令牌前缀,则裁剪掉前缀
//        if (StringUtils.isNotEmpty(token) && token.startsWith(TokenConstants.PREFIX))
//        {
//            token = token.replaceFirst(TokenConstants.PREFIX, StringUtils.EMPTY);
//        }
//        return token;
        return null;
    }
    @Override
    public int getOrder()
    {
        return -200;
    }
}
se-gateway/src/main/java/com/terra/gateway/filter/BlackListUrlFilter.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,64 @@
package com.terra.gateway.filter;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.stereotype.Component;
/**
 * é»‘名单过滤器
 *
 * @author admin
 */
@Component
public class BlackListUrlFilter extends AbstractGatewayFilterFactory<BlackListUrlFilter.Config>
{
    @Override
    public GatewayFilter apply(Config config)
    {
        return (exchange, chain) -> {
            String url = exchange.getRequest().getURI().getPath();
            if (config.matchBlacklist(url))
            {
                //return ServletUtils.webFluxResponseWriter(exchange.getResponse(), "请求地址不允许访问");
            }
            return chain.filter(exchange);
        };
    }
    public BlackListUrlFilter()
    {
        super(Config.class);
    }
    public static class Config
    {
        private List<String> blacklistUrl;
        private List<Pattern> blacklistUrlPattern = new ArrayList<>();
        public boolean matchBlacklist(String url)
        {
            return !blacklistUrlPattern.isEmpty() && blacklistUrlPattern.stream().anyMatch(p -> p.matcher(url).find());
        }
        public List<String> getBlacklistUrl()
        {
            return blacklistUrl;
        }
        public void setBlacklistUrl(List<String> blacklistUrl)
        {
            this.blacklistUrl = blacklistUrl;
            this.blacklistUrlPattern.clear();
            this.blacklistUrl.forEach(url -> {
                this.blacklistUrlPattern.add(Pattern.compile(url.replaceAll("\\*\\*", "(.*?)"), Pattern.CASE_INSENSITIVE));
            });
        }
    }
}
se-gateway/src/main/java/com/terra/gateway/filter/XssFilter.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,128 @@
package com.terra.gateway.filter;
import java.nio.charset.StandardCharsets;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
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.DataBufferFactory;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
import org.springframework.core.io.buffer.NettyDataBufferFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
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 com.terra.gateway.config.properties.XssProperties;
import io.netty.buffer.ByteBufAllocator;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
/**
 * è·¨ç«™è„šæœ¬è¿‡æ»¤å™¨
 *
 * @author admin
 */
@Component
@ConditionalOnProperty(value = "security.xss.enabled", havingValue = "true")
public class XssFilter implements GlobalFilter, Ordered
{
    // è·¨ç«™è„šæœ¬çš„ xss é…ç½®ï¼Œnacos自行添加
    @Autowired
    private XssProperties xss;
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain)
    {
        ServerHttpRequest request = exchange.getRequest();
        // xss开关未开启 æˆ– é€šè¿‡nacos关闭,不过滤
        if (!xss.getEnabled())
        {
            return chain.filter(exchange);
        }
        // GET DELETE ä¸è¿‡æ»¤
        HttpMethod method = request.getMethod();
        if (method == null || method == HttpMethod.GET || method == HttpMethod.DELETE)
        {
            return chain.filter(exchange);
        }
        // éžjson类型,不过滤
        if (!isJsonRequest(exchange))
        {
            return chain.filter(exchange);
        }
        // excludeUrls ä¸è¿‡æ»¤
        String url = request.getURI().getPath();
//        if (StringUtils.matches(url, xss.getExcludeUrls()))
//        {
//            return chain.filter(exchange);
//        }
        ServerHttpRequestDecorator httpRequestDecorator = requestDecorator(exchange);
        return chain.filter(exchange.mutate().request(httpRequestDecorator).build());
    }
    private ServerHttpRequestDecorator requestDecorator(ServerWebExchange exchange)
    {
        ServerHttpRequestDecorator serverHttpRequestDecorator = new ServerHttpRequestDecorator(exchange.getRequest())
        {
            @Override
            public Flux<DataBuffer> getBody()
            {
                Flux<DataBuffer> body = super.getBody();
                return body.buffer().map(dataBuffers -> {
                    DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory();
                    DataBuffer join = dataBufferFactory.join(dataBuffers);
                    byte[] content = new byte[join.readableByteCount()];
                    join.read(content);
                    DataBufferUtils.release(join);
                    String bodyStr = new String(content, StandardCharsets.UTF_8);
                    // é˜²xss攻击过滤
                    //bodyStr = EscapeUtil.clean(bodyStr);
                    // è½¬æˆå­—节
                    byte[] bytes = bodyStr.getBytes(StandardCharsets.UTF_8);
                    NettyDataBufferFactory nettyDataBufferFactory = new NettyDataBufferFactory(ByteBufAllocator.DEFAULT);
                    DataBuffer buffer = nettyDataBufferFactory.allocateBuffer(bytes.length);
                    buffer.write(bytes);
                    return buffer;
                });
            }
            @Override
            public HttpHeaders getHeaders()
            {
                HttpHeaders httpHeaders = new HttpHeaders();
                httpHeaders.putAll(super.getHeaders());
                // ç”±äºŽä¿®æ”¹äº†è¯·æ±‚体的body,导致content-length长度不确定,因此需要删除原先的content-length
                httpHeaders.remove(HttpHeaders.CONTENT_LENGTH);
                httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked");
                return httpHeaders;
            }
        };
        return serverHttpRequestDecorator;
    }
    /**
     * æ˜¯å¦æ˜¯Json请求
     *
     * @param exchange HTTP请求
     */
    public boolean isJsonRequest(ServerWebExchange exchange)
    {
        String header = exchange.getRequest().getHeaders().getFirst(HttpHeaders.CONTENT_TYPE);
        //return StringUtils.startsWithIgnoreCase(header, MediaType.APPLICATION_JSON_VALUE);
        return true;
    }
    @Override
    public int getOrder()
    {
        return -100;
    }
}
se-gateway/src/main/java/com/terra/gateway/handler/GatewayExceptionHandler.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,56 @@
package com.terra.gateway.handler;
import org.springframework.cloud.gateway.support.NotFoundException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ResponseStatusException;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
/**
 * ç½‘关统一异常处理
 *
 * @author admin
 */
@Order(-1)
@Configuration
public class GatewayExceptionHandler implements ErrorWebExceptionHandler
{
    private static final Logger log = LoggerFactory.getLogger(GatewayExceptionHandler.class);
    @Override
    public Mono<Void> handle(ServerWebExchange exchange, Throwable ex)
    {
        ServerHttpResponse response = exchange.getResponse();
        if (exchange.getResponse().isCommitted())
        {
            return Mono.error(ex);
        }
        String msg;
        if (ex instanceof NotFoundException)
        {
            msg = "服务未找到";
        }
        else if (ex instanceof ResponseStatusException)
        {
            ResponseStatusException responseStatusException = (ResponseStatusException) ex;
            msg = responseStatusException.getMessage();
        }
        else
        {
            msg = "内部服务器错误";
        }
        log.error("[网关异常处理]请求路径:{},异常信息:{}", exchange.getRequest().getPath(), ex.getMessage());
        //return ServletUtils.webFluxResponseWriter(response, msg);
        return Mono.error(ex);
    }
}
se-gateway/src/main/java/com/terra/gateway/handler/SentinelFallbackHandler.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,41 @@
package com.terra.gateway.handler;
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebExceptionHandler;
import reactor.core.publisher.Mono;
/**
 * è‡ªå®šä¹‰é™æµå¼‚常处理
 *
 * @author admin
 */
public class SentinelFallbackHandler implements WebExceptionHandler
{
    private Mono<Void> writeResponse(ServerResponse response, ServerWebExchange exchange)
    {
        //return ServletUtils.webFluxResponseWriter(exchange.getResponse(), "请求超过最大数,请稍候再试");
        return null;
    }
    @Override
    public Mono<Void> handle(ServerWebExchange exchange, Throwable ex)
    {
        if (exchange.getResponse().isCommitted())
        {
            return Mono.error(ex);
        }
        if (!BlockException.isBlockException(ex))
        {
            return Mono.error(ex);
        }
        return handleBlockedRequest(exchange, ex).flatMap(response -> writeResponse(response, exchange));
    }
    private Mono<ServerResponse> handleBlockedRequest(ServerWebExchange exchange, Throwable throwable)
    {
        return GatewayCallbackManager.getBlockHandler().handleRequest(exchange, throwable);
    }
}
se-gateway/src/main/resources/banner.txt
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,10 @@
Spring Boot Version: ${spring-boot.version}
Spring Application Name: ${spring.application.name}
               _
              | |
  __ _   __ _ | |_   ___ __      __  __ _  _   _
 / _` | / _` || __| / _ \\ \ /\ / / / _` || | | |
| (_| || (_| || |_ |  __/ \ V  V / | (_| || |_| |
 \__, | \__,_| \__| \___|  \_/\_/   \__,_| \__, |
  __/ |                                     __/ |
 |___/                                     |___/
se-gateway/src/main/resources/bootstrap.yml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,42 @@
# Tomcat
server:
  port: 8080
# Spring
spring:
  application:
    # åº”用名称
    name: se-gateway
  profiles:
    # çŽ¯å¢ƒé…ç½®
    active: dev
  cloud:
    nacos:
      username: nacos
      password: nAcos_!9#_admIn
      discovery:
        # æœåŠ¡æ³¨å†Œåœ°å€
        server-addr: 127.0.0.1:8848
      config:
        # é…ç½®ä¸­å¿ƒåœ°å€
        server-addr: 127.0.0.1:8848
        # é…ç½®æ–‡ä»¶æ ¼å¼
        file-extension: yml
        # å…±äº«é…ç½®
        shared-configs:
          - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
    sentinel:
      # å–消控制台懒加载
      eager: true
      transport:
        # æŽ§åˆ¶å°åœ°å€
        dashboard: 127.0.0.1:8718
      # nacos配置持久化
      datasource:
        ds1:
          nacos:
            server-addr: 127.0.0.1:8848
            dataId: sentinel-se-gateway
            groupId: DEFAULT_GROUP
            data-type: json
            rule-type: gw-flow
se-gateway/src/main/resources/logback.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
    <!-- æ—¥å¿—存放路径 -->
    <property name="log.path" value="logs/se-gateway" />
   <!-- æ—¥å¿—输出格式 -->
    <property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
    <!-- æŽ§åˆ¶å°è¾“出 -->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>${log.pattern}</pattern>
        </encoder>
    </appender>
    <!-- ç³»ç»Ÿæ—¥å¿—输出 -->
    <appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${log.path}/info.log</file>
        <!-- å¾ªçŽ¯æ”¿ç­–ï¼šåŸºäºŽæ—¶é—´åˆ›å»ºæ—¥å¿—æ–‡ä»¶ -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- æ—¥å¿—文件名格式 -->
            <fileNamePattern>${log.path}/info.%d{yyyy-MM-dd}.log</fileNamePattern>
            <!-- æ—¥å¿—最大的历史 60天 -->
            <maxHistory>60</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>${log.pattern}</pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <!-- è¿‡æ»¤çš„级别 -->
            <level>INFO</level>
            <!-- åŒ¹é…æ—¶çš„æ“ä½œï¼šæŽ¥æ”¶ï¼ˆè®°å½•) -->
            <onMatch>ACCEPT</onMatch>
            <!-- ä¸åŒ¹é…æ—¶çš„æ“ä½œï¼šæ‹’绝(不记录) -->
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${log.path}/error.log</file>
        <!-- å¾ªçŽ¯æ”¿ç­–ï¼šåŸºäºŽæ—¶é—´åˆ›å»ºæ—¥å¿—æ–‡ä»¶ -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- æ—¥å¿—文件名格式 -->
            <fileNamePattern>${log.path}/error.%d{yyyy-MM-dd}.log</fileNamePattern>
            <!-- æ—¥å¿—最大的历史 60天 -->
            <maxHistory>60</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>${log.pattern}</pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <!-- è¿‡æ»¤çš„级别 -->
            <level>ERROR</level>
            <!-- åŒ¹é…æ—¶çš„æ“ä½œï¼šæŽ¥æ”¶ï¼ˆè®°å½•) -->
            <onMatch>ACCEPT</onMatch>
            <!-- ä¸åŒ¹é…æ—¶çš„æ“ä½œï¼šæ‹’绝(不记录) -->
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!-- ç³»ç»Ÿæ¨¡å—日志级别控制  -->
    <logger name="com.terra" level="info" />
    <!-- Spring日志级别控制  -->
    <logger name="org.springframework" level="warn" />
    <root level="info">
        <appender-ref ref="console" />
    </root>
    <!--系统操作日志-->
    <root level="info">
        <appender-ref ref="file_info" />
        <appender-ref ref="file_error" />
    </root>
</configuration>
se-system/pom.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,69 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://maven.apache.org/POM/4.0.0"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <groupId>com.terra</groupId>
        <artifactId>terra</artifactId>
        <version>1.0.2</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>se-system</artifactId>
    <description>
        ç³»ç»Ÿæ¨¡å—
    </description>
    <dependencies>
        <!-- SpringCloud Alibaba Nacos -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!-- SpringCloud Alibaba Nacos Config -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
        <!-- SpringCloud Alibaba Sentinel -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
        <!-- SpringBoot Actuator -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!-- Mysql Connector -->
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
        </dependency>
    </dependencies>
    <build>
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>
se-system/src/main/java/com/terra/system/SeSystemApplication.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,19 @@
package com.terra.system;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
 * ç³»ç»Ÿæ¨¡å—
 *
 * @author admin
 */
@SpringBootApplication
public class SeSystemApplication
{
    public static void main(String[] args)
    {
        SpringApplication.run(SeSystemApplication.class, args);
        System.out.println("----------系统模块启动成功----------  \n");
    }
}
se-system/src/main/resources/banner.txt
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,10 @@
Spring Boot Version: ${spring-boot.version}
Spring Application Name: ${spring.application.name}
                            _                           _
                           (_)                         | |
 _ __  _   _   ___   _   _  _  ______  ___  _   _  ___ | |_   ___  _ __ ___
| '__|| | | | / _ \ | | | || ||______|/ __|| | | |/ __|| __| / _ \| '_ ` _ \
| |   | |_| || (_) || |_| || |        \__ \| |_| |\__ \| |_ |  __/| | | | | |
|_|    \__,_| \___/  \__, ||_|        |___/ \__, ||___/ \__| \___||_| |_| |_|
                      __/ |                  __/ |
                     |___/                  |___/
se-system/src/main/resources/bootstrap.yml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,29 @@
# Tomcat
server:
  port: 9201
# Spring
spring:
  application:
    # åº”用名称
    name: se-system
  profiles:
    # çŽ¯å¢ƒé…ç½®
    active: dev
  cloud:
    nacos:
      username: nacos
      password: nAcos_!9#_admIn
      discovery:
        # æœåŠ¡æ³¨å†Œåœ°å€
        server-addr: 127.0.0.1:8848
      config:
        # é…ç½®ä¸­å¿ƒåœ°å€
        server-addr: 127.0.0.1:8848
        # é…ç½®æ–‡ä»¶æ ¼å¼
        file-extension: yml
        # å…±äº«é…ç½®
        shared-configs:
          - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
        # å…è®¸åˆ·æ–°
        refresh-enabled: true
se-system/src/main/resources/logback.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
    <!-- æ—¥å¿—存放路径 -->
    <property name="log.path" value="logs/se-system" />
   <!-- æ—¥å¿—输出格式 -->
    <property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
    <!-- æŽ§åˆ¶å°è¾“出 -->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>${log.pattern}</pattern>
        </encoder>
    </appender>
    <!-- ç³»ç»Ÿæ—¥å¿—输出 -->
    <appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${log.path}/info.log</file>
        <!-- å¾ªçŽ¯æ”¿ç­–ï¼šåŸºäºŽæ—¶é—´åˆ›å»ºæ—¥å¿—æ–‡ä»¶ -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- æ—¥å¿—文件名格式 -->
            <fileNamePattern>${log.path}/info.%d{yyyy-MM-dd}.log</fileNamePattern>
            <!-- æ—¥å¿—最大的历史 60天 -->
            <maxHistory>60</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>${log.pattern}</pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <!-- è¿‡æ»¤çš„级别 -->
            <level>INFO</level>
            <!-- åŒ¹é…æ—¶çš„æ“ä½œï¼šæŽ¥æ”¶ï¼ˆè®°å½•) -->
            <onMatch>ACCEPT</onMatch>
            <!-- ä¸åŒ¹é…æ—¶çš„æ“ä½œï¼šæ‹’绝(不记录) -->
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${log.path}/error.log</file>
        <!-- å¾ªçŽ¯æ”¿ç­–ï¼šåŸºäºŽæ—¶é—´åˆ›å»ºæ—¥å¿—æ–‡ä»¶ -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- æ—¥å¿—文件名格式 -->
            <fileNamePattern>${log.path}/error.%d{yyyy-MM-dd}.log</fileNamePattern>
            <!-- æ—¥å¿—最大的历史 60天 -->
            <maxHistory>60</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>${log.pattern}</pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <!-- è¿‡æ»¤çš„级别 -->
            <level>ERROR</level>
            <!-- åŒ¹é…æ—¶çš„æ“ä½œï¼šæŽ¥æ”¶ï¼ˆè®°å½•) -->
            <onMatch>ACCEPT</onMatch>
            <!-- ä¸åŒ¹é…æ—¶çš„æ“ä½œï¼šæ‹’绝(不记录) -->
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!-- ç³»ç»Ÿæ¨¡å—日志级别控制  -->
    <logger name="com.terra" level="info" />
    <!-- Spring日志级别控制  -->
    <logger name="org.springframework" level="warn" />
    <root level="info">
        <appender-ref ref="console" />
    </root>
    <!--系统操作日志-->
    <root level="info">
        <appender-ref ref="file_info" />
        <appender-ref ref="file_error" />
    </root>
</configuration>