commit 7c16d404cc04e1b3fcc5291b342f717f7050f216
Author: 陈沅 <907037276@qq.com>
Date:   Tue Jun 20 20:58:07 2023 +0800

    天择外汇模拟交易系统后端框架搭建

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..549e00a
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,33 @@
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000..e69de29
diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..ca5ab4b
--- /dev/null
+++ b/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.7/apache-maven-3.8.7-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..756a523
--- /dev/null
+++ b/README.md
@@ -0,0 +1,46 @@
+
+# 天择外汇模拟交易系统
+
+## foreign_exchange_trading
+
+**构建**:\
+环境要求:JDK1.8及更高版本、Maven3.6+、postgresql。\
+若项目依赖构建失败,请确认本地环境版本。\
+JDK查看版本方式:win+R进入CMD界面输入java -version即可查看\
+Maven查看版本方式:win+R进入CMD界面输入输入mvn -v即可查看\
+maven构建:进入idea Terminal界面运行命令 mvn clean install.等待项目build完成,注:第一次构建系统可能耗时较长\
+完成以上既可进行开发
+
+
+**开发**:
+命名规范:类名采用大驼峰命名方式,方法名、变量名采用小驼峰方式.二者差异自行访问baidu.com查阅。\
+**注:代码注释需满足javadoc规范\** \
+系统目录及代码归属约束:\
+annotation:系统切面文件。全局日志切面管理及接口权限控制文件.\
+config:整个系统配置文件,如全局token校验,swagger配置,jpa配置及数据库方言配置.\
+controller:接口定义,对外开放的接口文件请放置在该包,注:每个模块有一个对应文件,如对某模块新增接口请
+放置到对应的controller文件内.\
+entity:实体类文件放置地址,与数据库表字段对应,调整数据库字段或新增表请移至改包,注:对应的模块属性请放置于对应的类中.\
+repository:整个系统与数据库交互的文件放置于该包下,如调整数据库语句请移至该包。注:建议复杂查询及多表联查才用JPA原生SQL查询
+简单查询请用Specification条件构造器.用法请参考service包下的子文件\
+service:子模块业务逻辑代码请放置于该包下。\
+util:系统用到的第三方工具文件请放置于该包,如Excel导入导出、几何数据操作,第三方API接入及结果解析、file文件处理,全局异常定义等.\
+**为防止系统结构混乱,开发准备阶段请详细阅读开发规则及java文件归属规则。**
+
+
+
+**运行**:
+设置ForeignExchangeTradingApplication为项目启动入口。Shift+F10启动. 注:必须完成上述开发节点下的项目构建工作才可启动,否则系统会报错
+
+**接口预览及调用**:
+默认地址为localhost:8800(端口号可自行更改)
+
+**测试**:
+后续团队将尽快整理和提供系统每一个子模块单元测试.
+
+**发布**:
+CMD进入系统目录,运行 mvn clean package命令,移至target目录复制plantingInspect.jar文件\
+windows发布:cmd界面运行 java -jar plantingInspect.jar.\
+linux发布:请自行查阅baidu.com
+
+
diff --git a/mvnw b/mvnw
new file mode 100644
index 0000000..e69de29
diff --git a/mvnw.cmd b/mvnw.cmd
new file mode 100644
index 0000000..e69de29
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..a3ff6fc
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,98 @@
+<?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.7.12</version>
+		<relativePath/> <!-- lookup parent from repository -->
+	</parent>
+	<groupId>com.sztzjy</groupId>
+	<artifactId>foreign_exchange_trading</artifactId>
+	<version>2.0-SNAPSHOT</version>
+	<name>foreign_exchange_trading</name>
+	<packaging>jar</packaging>
+
+	<properties>
+		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+		<java.version>1.8</java.version>
+	</properties>
+	<dependencies>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter</artifactId>
+		</dependency>
+
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-test</artifactId>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>cn.hutool</groupId>
+			<artifactId>hutool-all</artifactId>
+			<version>5.8.10</version>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-web</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.security</groupId>
+			<artifactId>spring-security-jwt</artifactId>
+			<version>1.1.1.RELEASE</version>
+		</dependency>
+		<dependency>
+			<groupId>com.nimbusds</groupId>
+			<artifactId>nimbus-jose-jwt</artifactId>
+			<version>9.26</version>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-data-jpa</artifactId>
+		</dependency>
+
+		<dependency>
+			<groupId>com.alibaba</groupId>
+			<artifactId>druid-spring-boot-starter</artifactId>
+			<version>1.2.18</version>
+		</dependency>
+
+		<dependency>
+			<groupId>com.github.xiaoymin</groupId>
+			<artifactId>knife4j-spring-boot-starter</artifactId>
+			<version>3.0.3</version>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.security.oauth</groupId>
+			<artifactId>spring-security-oauth2</artifactId>
+			<version>2.3.8.RELEASE</version>
+		</dependency>
+		<dependency>
+			<groupId>org.projectlombok</groupId>
+			<artifactId>lombok</artifactId>
+		</dependency>
+				<dependency>
+			<groupId>org.hibernate</groupId>
+			<artifactId>hibernate-spatial</artifactId>
+		</dependency>
+		<!-- MySQL连接驱动 -->
+		<dependency>
+			<groupId>mysql</groupId>
+			<artifactId>mysql-connector-java</artifactId>
+			<version>8.0.28</version>
+		</dependency>
+	</dependencies>
+
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.springframework.boot</groupId>
+				<artifactId>spring-boot-maven-plugin</artifactId>
+			</plugin>
+		</plugins>
+	</build>
+
+</project>
diff --git a/src/main/java/com/sztzjy/forex/trading_trading/ForeignExchangeTradingApplication.java b/src/main/java/com/sztzjy/forex/trading_trading/ForeignExchangeTradingApplication.java
new file mode 100644
index 0000000..729f258
--- /dev/null
+++ b/src/main/java/com/sztzjy/forex/trading_trading/ForeignExchangeTradingApplication.java
@@ -0,0 +1,13 @@
+package com.sztzjy.forex.trading_trading;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class ForeignExchangeTradingApplication {
+
+	public static void main(String[] args) {
+		SpringApplication.run(ForeignExchangeTradingApplication.class, args);
+	}
+
+}
diff --git a/src/main/java/com/sztzjy/forex/trading_trading/annotation/AnonymousAccess.java b/src/main/java/com/sztzjy/forex/trading_trading/annotation/AnonymousAccess.java
new file mode 100644
index 0000000..6247e52
--- /dev/null
+++ b/src/main/java/com/sztzjy/forex/trading_trading/annotation/AnonymousAccess.java
@@ -0,0 +1,16 @@
+package com.sztzjy.forex.trading_trading.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * 用于匿名访问配置, 使用时只需在Controller方法上使用此注解即能实现匿名访问
+ *
+ * @author 陈沅
+ */
+@Inherited
+@Documented
+@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface AnonymousAccess {
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/sztzjy/forex/trading_trading/config/Constant.java b/src/main/java/com/sztzjy/forex/trading_trading/config/Constant.java
new file mode 100644
index 0000000..f253b6b
--- /dev/null
+++ b/src/main/java/com/sztzjy/forex/trading_trading/config/Constant.java
@@ -0,0 +1,18 @@
+package com.sztzjy.forex.trading_trading.config;
+
+import org.springframework.stereotype.Component;
+
+/**
+ * 常量定义
+ */
+@Component
+public class Constant {
+    /**
+     * 请求头
+     */
+    public static final String AUTHORIZATION = "Authorization";
+    /**
+     * Basic 请求头
+     */
+    public static final String BASIC = "Basic";
+}
diff --git a/src/main/java/com/sztzjy/forex/trading_trading/config/SpringContextHolder.java b/src/main/java/com/sztzjy/forex/trading_trading/config/SpringContextHolder.java
new file mode 100644
index 0000000..b3289fe
--- /dev/null
+++ b/src/main/java/com/sztzjy/forex/trading_trading/config/SpringContextHolder.java
@@ -0,0 +1,79 @@
+package com.sztzjy.forex.trading_trading.config;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.DisposableBean;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.context.ApplicationEvent;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Service;
+
+@Slf4j
+@Service
+@Lazy(false)
+public class SpringContextHolder implements ApplicationContextAware, DisposableBean {
+
+    private static ApplicationContext applicationContext = null;
+
+    /**
+     * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> T getBean(String name) {
+        assertContextInjected();
+        return (T) applicationContext.getBean(name);
+    }
+
+    /**
+     * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
+     */
+    public static <T> T getBean(Class<T> requiredType) {
+        assertContextInjected();
+        return applicationContext.getBean(requiredType);
+    }
+
+    /**
+     * 检查ApplicationContext不为空.
+     */
+    private static void assertContextInjected() {
+        if (applicationContext == null) {
+            throw new IllegalStateException("applicaitonContext属性未注入, 请在applicationContext" +
+                    ".xml中定义SpringContextHolder或在SpringBoot启动类中注册SpringContextHolder.");
+        }
+    }
+
+    /**
+     * 清除SpringContextHolder中的ApplicationContext为Null.
+     */
+    private static void clearHolder() {
+        log.debug("清除SpringContextHolder中的ApplicationContext:"
+                + applicationContext);
+        applicationContext = null;
+    }
+
+    @Override
+    public void destroy(){
+        SpringContextHolder.clearHolder();
+    }
+
+    @Override
+    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+        if (SpringContextHolder.applicationContext != null) {
+            log.warn("SpringContextHolder中的ApplicationContext被覆盖, 原有ApplicationContext为:" + SpringContextHolder.applicationContext);
+        }
+        SpringContextHolder.applicationContext = applicationContext;
+    }
+
+    /**
+     * 发布事件
+     *
+     * @param event
+     */
+    public static void publishEvent(ApplicationEvent event) {
+        if (applicationContext == null) {
+            return;
+        }
+        applicationContext.publishEvent(event);
+    }
+}
diff --git a/src/main/java/com/sztzjy/forex/trading_trading/config/exception/UnAuthorizedException.java b/src/main/java/com/sztzjy/forex/trading_trading/config/exception/UnAuthorizedException.java
new file mode 100644
index 0000000..d1479d6
--- /dev/null
+++ b/src/main/java/com/sztzjy/forex/trading_trading/config/exception/UnAuthorizedException.java
@@ -0,0 +1,41 @@
+package com.sztzjy.forex.trading_trading.config.exception;
+
+/**
+ * 当用户访问受保护资源但不提供任何凭据时将抛出此异常
+ *
+ * @author 陈沅
+ * @version 1.0.0
+ */
+public class UnAuthorizedException extends RuntimeException {
+
+    /**
+     * Constructs a new runtime exception with the specified detail message.
+     * The cause is not initialized, and may subsequently be initialized by a
+     * call to {@link #initCause}.
+     *
+     * @param message the detail message. The detail message is saved for
+     *                later retrieval by the {@link #getMessage()} method.
+     */
+    public UnAuthorizedException(String message) {
+        super(message);
+    }
+
+    /**
+     * Constructs a new runtime exception with the specified detail message and
+     * cause.  <p>Note that the detail message associated with
+     * {@code cause} is <i>not</i> automatically incorporated in
+     * this runtime exception's detail message.
+     *
+     * @param message the detail message (which is saved for later retrieval
+     *                by the {@link #getMessage()} method).
+     * @param cause   the cause (which is saved for later retrieval by the
+     *                {@link #getCause()} method).  (A {@code null} value is
+     *                permitted, and indicates that the cause is nonexistent or
+     *                unknown.)
+     * @since 1.4
+     */
+    public UnAuthorizedException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+}
diff --git a/src/main/java/com/sztzjy/forex/trading_trading/config/exception/handler/CustomAccessDeniedHandler.java b/src/main/java/com/sztzjy/forex/trading_trading/config/exception/handler/CustomAccessDeniedHandler.java
new file mode 100644
index 0000000..6226f21
--- /dev/null
+++ b/src/main/java/com/sztzjy/forex/trading_trading/config/exception/handler/CustomAccessDeniedHandler.java
@@ -0,0 +1,32 @@
+package com.sztzjy.forex.trading_trading.config.exception.handler;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.security.web.access.AccessDeniedHandler;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+/**
+ * 权限不足异常拦截
+ * 当用户在没有授权的情况下访问受保护的REST资源时,将调用此方法发送403 Forbidden响应
+ *
+ * @author 陈沅
+ */
+@Component
+public class CustomAccessDeniedHandler implements AccessDeniedHandler {
+
+    @Override
+    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException {
+        response.setCharacterEncoding("UTF-8");
+        response.setStatus(HttpStatus.FORBIDDEN.value());
+        response.addHeader("Access-Control-Allow-Origin", "*");
+        response.addHeader("Content-Type", "application/json");
+        PrintWriter printWriter = response.getWriter();
+        printWriter.write("{\"code\":" + HttpStatus.FORBIDDEN.value() + ", \"msg\": \"权限不足\"}");
+        printWriter.flush();
+    }
+}
diff --git a/src/main/java/com/sztzjy/forex/trading_trading/config/exception/handler/CustomAuthenticationEntryPoint.java b/src/main/java/com/sztzjy/forex/trading_trading/config/exception/handler/CustomAuthenticationEntryPoint.java
new file mode 100644
index 0000000..22c5c9f
--- /dev/null
+++ b/src/main/java/com/sztzjy/forex/trading_trading/config/exception/handler/CustomAuthenticationEntryPoint.java
@@ -0,0 +1,39 @@
+package com.sztzjy.forex.trading_trading.config.exception.handler;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
+import org.springframework.security.web.AuthenticationEntryPoint;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+/**
+ * token异常拦截
+ * 当用户尝试访问安全的REST资源而不提供任何凭据时,将调用此方法发送401 响应
+ *
+ * @author 陈沅
+ */
+@Component
+public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {
+
+    @Override
+    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException {
+        // 当用户尝试访问安全的REST资源而不提供任何凭据时,将调用此方法发送401 响应
+        response.setCharacterEncoding("UTF-8");
+        response.setStatus(HttpStatus.UNAUTHORIZED.value());
+        response.addHeader("Access-Control-Allow-Origin", "*");
+        response.addHeader("Content-Type", "application/json");
+        Throwable cause = authException.getCause();
+        PrintWriter printWriter = response.getWriter();
+        if (cause instanceof InvalidTokenException) {
+            printWriter.write("{\"code\":" + HttpStatus.UNAUTHORIZED.value() + ",\"msg\":\"身份认证失败,无效或过期token\"}");
+        } else {
+            printWriter.write("{\"code\":" + HttpStatus.UNAUTHORIZED.value() + ",\"msg\":\"身份认证失败\"}");
+        }
+        printWriter.flush();
+    }
+}
diff --git a/src/main/java/com/sztzjy/forex/trading_trading/config/exception/handler/GlobalExceptionHandler.java b/src/main/java/com/sztzjy/forex/trading_trading/config/exception/handler/GlobalExceptionHandler.java
new file mode 100644
index 0000000..e7799bc
--- /dev/null
+++ b/src/main/java/com/sztzjy/forex/trading_trading/config/exception/handler/GlobalExceptionHandler.java
@@ -0,0 +1,79 @@
+package com.sztzjy.forex.trading_trading.config.exception.handler;
+
+import com.sztzjy.forex.trading_trading.config.exception.UnAuthorizedException;
+import com.sztzjy.forex.trading_trading.util.ResultEntity;
+import com.sztzjy.forex.trading_trading.util.ThrowableUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpStatus;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.validation.FieldError;
+import org.springframework.validation.ObjectError;
+import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+
+/**
+ * 全局异常处理
+ */
+@Slf4j
+@RestControllerAdvice
+public class GlobalExceptionHandler {
+
+    @ExceptionHandler(IllegalArgumentException.class)
+    public ResultEntity<String> illegalArgumentException(IllegalArgumentException e) {
+        log.error(ThrowableUtil.getStackTrace(e));
+        return new ResultEntity<>(HttpStatus.BAD_REQUEST, e.getMessage());
+    }
+
+    @ExceptionHandler(AccessDeniedException.class)
+    public ResultEntity<String> accessDeniedException(AccessDeniedException e) {
+        log.error(ThrowableUtil.getStackTrace(e));
+        return new ResultEntity<>(HttpStatus.FORBIDDEN, e.getMessage());
+    }
+
+    @ExceptionHandler(UnAuthorizedException.class)
+    public ResultEntity<String> UnAuthorizedException(UnAuthorizedException e) {
+        log.error(ThrowableUtil.getStackTrace(e));
+        return new ResultEntity<>(HttpStatus.UNAUTHORIZED, e.getMessage());
+    }
+
+    /**
+     * 处理所有接口数据验证异常
+     */
+    @ExceptionHandler(MethodArgumentNotValidException.class)
+    public ResultEntity<String> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
+        log.error(ThrowableUtil.getStackTrace(e));
+        ObjectError objectError = e.getBindingResult().getAllErrors().get(0);
+        String message = objectError.getDefaultMessage();
+        if (objectError instanceof FieldError) {
+            message = ((FieldError) objectError).getField() + ": " + message;
+        }
+        return new ResultEntity<>(HttpStatus.BAD_REQUEST, message);
+    }
+
+    /**
+     * 处理所有不可知的异常
+     *
+     * @param e 未知异常
+     * @return /
+     */
+    @ExceptionHandler(Throwable.class)
+    public ResultEntity<String> nullPointerException(Throwable e) {
+        log.error(ThrowableUtil.getStackTrace(e));
+        return new ResultEntity<>(HttpStatus.BAD_REQUEST, e.getMessage());
+    }
+
+    /**
+     * BadCredentialsException
+     */
+    @ExceptionHandler(BadCredentialsException.class)
+    public ResultEntity<String> badCredentialsException(BadCredentialsException e) {
+        // 打印堆栈信息
+        String message = "坏的凭证".equals(e.getMessage()) ? "用户名或密码不正确" : e.getMessage();
+        log.error(message);
+        return new ResultEntity<>(HttpStatus.BAD_REQUEST, message);
+    }
+
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/sztzjy/forex/trading_trading/config/security/AuthenticationFilter.java b/src/main/java/com/sztzjy/forex/trading_trading/config/security/AuthenticationFilter.java
new file mode 100644
index 0000000..25e3773
--- /dev/null
+++ b/src/main/java/com/sztzjy/forex/trading_trading/config/security/AuthenticationFilter.java
@@ -0,0 +1,91 @@
+package com.sztzjy.forex.trading_trading.config.security;
+
+import cn.hutool.extra.servlet.ServletUtil;
+import com.sztzjy.forex.trading_trading.config.Constant;
+import com.sztzjy.forex.trading_trading.config.exception.UnAuthorizedException;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.util.AntPathMatcher;
+import org.springframework.util.PathMatcher;
+import org.springframework.util.StringUtils;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.time.LocalDateTime;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * 系统登陆认证拦截
+ *
+ *  @author 陈沅
+ */
+public class AuthenticationFilter extends OncePerRequestFilter {
+    private final PathMatcher matcher = new AntPathMatcher();
+    private final TokenProvider tokenProvider;
+    public AuthenticationFilter(TokenProvider tokenProvider) {
+        this.tokenProvider = tokenProvider;
+    }
+
+    @Override
+    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
+        String requestRri = request.getRequestURI();
+        if (requestRri.equals("/")) {
+            response.sendRedirect("/doc.html");
+            return;
+        }
+        if (!isExclude(request)) {
+            System.out.println("--------------------------------->>>  " + LocalDateTime.now() + " ---ip:" + ServletUtil.getClientIP(request) + " requestUri:" + requestRri);
+        }
+        String token = request.getHeader(Constant.AUTHORIZATION);
+
+        if (token == null || token.equals("undefined") || token.equals("") || token.equals("null")) {
+            filterChain.doFilter(request, response);
+            return;
+        }
+
+        if (!StringUtils.startsWithIgnoreCase(token, "Bearer ")) {
+            throw new UnAuthorizedException("令牌错误: 缺失Bearer..");
+        }
+        JwtUser currentUser = tokenProvider.getClaims(token);
+        Authentication authentication = new UsernamePasswordAuthenticationToken(currentUser, "****", currentUser.getAuthorities());
+        request.getUserPrincipal();
+        SecurityContextHolder.getContext().setAuthentication(authentication);
+        filterChain.doFilter(request, response);
+    }
+
+
+    /**
+     * 排除的请求路径匹配
+     */
+    private final static List<String> patterns = Arrays.asList(
+            "/swagger-resources/**",
+            "/doc.html",
+            "/webjars/**",
+            "/v2/**",
+            "/favicon.ico",
+            "/login",
+            "/druid/**"
+    );
+
+    /**
+     * 判断请求路径是否是在排除之外
+     *
+     * @param request /
+     * @return true-是排除的
+     */
+    private boolean isExclude(HttpServletRequest request) {
+        String requestURI = request.getRequestURI();
+        for (String pattern : patterns) {
+            if (matcher.match(pattern, requestURI)) {
+                return true;
+            }
+        }
+        return false;
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/com/sztzjy/forex/trading_trading/config/security/JwtUser.java b/src/main/java/com/sztzjy/forex/trading_trading/config/security/JwtUser.java
new file mode 100644
index 0000000..e39b532
--- /dev/null
+++ b/src/main/java/com/sztzjy/forex/trading_trading/config/security/JwtUser.java
@@ -0,0 +1,48 @@
+package com.sztzjy.forex.trading_trading.config.security;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.userdetails.UserDetails;
+
+import java.util.Collection;
+
+/**
+ * jwt用户对象
+ */
+@Getter
+@Setter
+public class JwtUser implements UserDetails {
+    private String username;
+    private String password;
+    private String name;
+    private String userId;
+    private int roleId;
+    private int schoolId;
+    private int classId;
+
+    @Override
+    public Collection<? extends GrantedAuthority> getAuthorities() {
+        return null;
+    }
+
+    @Override
+    public boolean isAccountNonExpired() {
+        return false;
+    }
+
+    @Override
+    public boolean isAccountNonLocked() {
+        return false;
+    }
+
+    @Override
+    public boolean isCredentialsNonExpired() {
+        return false;
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return false;
+    }
+}
diff --git a/src/main/java/com/sztzjy/forex/trading_trading/config/security/TokenProvider.java b/src/main/java/com/sztzjy/forex/trading_trading/config/security/TokenProvider.java
new file mode 100644
index 0000000..2538577
--- /dev/null
+++ b/src/main/java/com/sztzjy/forex/trading_trading/config/security/TokenProvider.java
@@ -0,0 +1,20 @@
+package com.sztzjy.forex.trading_trading.config.security;
+
+import org.springframework.stereotype.Component;
+
+@Component
+public class TokenProvider {
+
+    /**
+     * 解析jwtToken
+     *
+     * @param jwtToken jwtToken
+     * @return jwt解析对象
+     */
+
+    public JwtUser getClaims(String jwtToken) {
+      //todo 解析用户token
+        return null;
+    }
+
+}
diff --git a/src/main/java/com/sztzjy/forex/trading_trading/config/security/WebConfigurerAdapter.java b/src/main/java/com/sztzjy/forex/trading_trading/config/security/WebConfigurerAdapter.java
new file mode 100644
index 0000000..fa53b0b
--- /dev/null
+++ b/src/main/java/com/sztzjy/forex/trading_trading/config/security/WebConfigurerAdapter.java
@@ -0,0 +1,62 @@
+package com.sztzjy.forex.trading_trading.config.security;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.support.ReloadableResourceBundleMessageSource;
+import org.springframework.http.converter.HttpMessageConverter;
+import org.springframework.http.converter.StringHttpMessageConverter;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+import org.springframework.web.servlet.config.annotation.EnableWebMvc;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+import javax.annotation.Resource;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+
+/**
+ * 系统配置
+ */
+@Configuration
+@EnableWebMvc
+public class WebConfigurerAdapter implements WebMvcConfigurer {
+    @Resource
+    private StringHttpMessageConverter stringHttpMessageConverter;
+
+
+    @Bean
+    public CorsFilter corsFilter() {
+        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+        CorsConfiguration config = new CorsConfiguration();
+        config.setAllowCredentials(true);
+        config.addAllowedOriginPattern("*");
+        config.addAllowedMethod("*");
+        config.addAllowedHeader("*");
+        source.registerCorsConfiguration("/**", config);
+        return new CorsFilter(source);
+    }
+
+    @Bean
+    public ReloadableResourceBundleMessageSource messageSource() {
+        ReloadableResourceBundleMessageSource reloadableResourceBundleMessageSource = new ReloadableResourceBundleMessageSource();
+        reloadableResourceBundleMessageSource.setBasename("classpath:messages");
+        return reloadableResourceBundleMessageSource;
+    }
+
+    @Override
+    public void addResourceHandlers(ResourceHandlerRegistry registry) {
+        registry.addResourceHandler("/**").addResourceLocations("classpath:/META-INF/resources/").setCachePeriod(0);
+    }
+
+    @Override
+    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
+        for (int i = 0; i < converters.size(); i++) {
+            if (converters.get(i) instanceof StringHttpMessageConverter) {
+                stringHttpMessageConverter.setDefaultCharset(StandardCharsets.UTF_8);
+                converters.set(i, stringHttpMessageConverter);
+            }
+        }
+    }
+}
diff --git a/src/main/java/com/sztzjy/forex/trading_trading/config/security/WebSecurityConfig.java b/src/main/java/com/sztzjy/forex/trading_trading/config/security/WebSecurityConfig.java
new file mode 100644
index 0000000..f3c64ca
--- /dev/null
+++ b/src/main/java/com/sztzjy/forex/trading_trading/config/security/WebSecurityConfig.java
@@ -0,0 +1,112 @@
+package com.sztzjy.forex.trading_trading.config.security;
+
+import com.sztzjy.forex.trading_trading.annotation.AnonymousAccess;
+import com.sztzjy.forex.trading_trading.config.SpringContextHolder;
+import com.sztzjy.forex.trading_trading.config.exception.handler.CustomAccessDeniedHandler;
+import com.sztzjy.forex.trading_trading.config.exception.handler.CustomAuthenticationEntryPoint;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+import org.springframework.web.method.HandlerMethod;
+import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
+import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
+
+import javax.annotation.Resource;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * secret配置
+ */
+@Configuration
+@EnableWebSecurity
+@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
+public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
+
+    @Resource
+    private TokenProvider tokenProvider;
+    @Resource
+    private CustomAccessDeniedHandler customAccessDeniedHandler;
+    @Resource
+    private CustomAuthenticationEntryPoint customAuthenticationEntryPoint;
+
+
+    @Bean
+    public PasswordEncoder passwordEncoder() {
+        return new BCryptPasswordEncoder();
+    }
+
+
+    @Override
+    protected void configure(HttpSecurity http) throws Exception {
+        RequestMappingHandlerMapping handlerMapping = SpringContextHolder.getBean("requestMappingHandlerMapping");
+        Map<RequestMappingInfo, HandlerMethod> handlerMethods = handlerMapping.getHandlerMethods();
+        Set<String> anonymousUrls = discoveryAnonymousUrls(handlerMethods);
+        http
+                .addFilterBefore(new AuthenticationFilter(tokenProvider), UsernamePasswordAuthenticationFilter.class)
+                // 禁用 CSRF
+                .csrf().disable()
+                .exceptionHandling()
+                .authenticationEntryPoint(customAuthenticationEntryPoint)
+                .accessDeniedHandler(customAccessDeniedHandler)
+                // 防止iframe 造成跨域
+                .and().headers().frameOptions().disable()
+                // 不创建会话
+                .and()
+                .sessionManagement()
+                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
+                .and()
+                // 所有请求都需要认证
+                .authorizeRequests()
+                .antMatchers("/swagger-resources/**").permitAll()
+                .antMatchers("/doc.html").permitAll()
+                .antMatchers("/webjars/**").permitAll()
+                .antMatchers("/v2/**").permitAll()
+                .antMatchers("/test/**").permitAll()
+                .antMatchers(anonymousUrls.toArray(new String[]{})).permitAll()
+                .anyRequest().authenticated();
+    }
+
+    /**
+     * 认证相关的核心接口
+     *
+     * @return {@link AuthenticationManager}
+     * @throws Exception /
+     */
+    @Bean
+    public AuthenticationManager authenticationManager() throws Exception {
+        return super.authenticationManager();
+    }
+
+
+
+    /**
+     * 根据注解发现需要匿名访问的请求路径
+     *
+     * @param handlerMethodMap ?
+     * @return 匿名Mapping patterns
+     */
+    private Set<String> discoveryAnonymousUrls(Map<RequestMappingInfo, HandlerMethod> handlerMethodMap) {
+        Set<String> patterns = new HashSet<>();
+        for (Map.Entry<RequestMappingInfo, HandlerMethod> infoEntry : handlerMethodMap.entrySet()) {
+            HandlerMethod handlerMethod = infoEntry.getValue();
+            AnonymousAccess anonymousAccess = handlerMethod.getMethodAnnotation(AnonymousAccess.class);
+            if (Objects.nonNull(anonymousAccess)) {
+                assert infoEntry.getKey().getPatternsCondition() != null;
+                patterns.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());
+            }
+        }
+        return patterns;
+    }
+
+}
diff --git a/src/main/java/com/sztzjy/forex/trading_trading/config/swagger/Swagger2Config.java b/src/main/java/com/sztzjy/forex/trading_trading/config/swagger/Swagger2Config.java
new file mode 100644
index 0000000..b79d7e5
--- /dev/null
+++ b/src/main/java/com/sztzjy/forex/trading_trading/config/swagger/Swagger2Config.java
@@ -0,0 +1,104 @@
+package com.sztzjy.forex.trading_trading.config.swagger;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.models.auth.In;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.web.context.WebServerInitializedEvent;
+import org.springframework.context.ApplicationListener;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.service.*;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spi.service.contexts.SecurityContext;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+import javax.annotation.Resource;
+import java.net.Inet4Address;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * swagger 3.0接口文档配置类
+ *
+ * @author 陈沅
+ */
+@EnableSwagger2
+@Configuration
+@Profile({"dev", "pro", "test"})
+public class Swagger2Config implements ApplicationListener<WebServerInitializedEvent> {
+    @Resource
+    private SwaggerProperties swaggerProperties;
+
+    @Bean
+    public Docket docket() {
+        return new Docket(DocumentationType.SWAGGER_2)
+                .enable(swaggerProperties.getEnable())
+                .apiInfo(apiInfo())
+                .select()
+                .apis(RequestHandlerSelectors.withClassAnnotation(Api.class))
+                .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
+                .paths(PathSelectors.any())
+//                 .globalRequestParameters(requestParameters())
+                .build()
+                .securitySchemes(securitySchemes())
+                .securityContexts(securityContexts());
+    }
+
+    private ApiInfo apiInfo() {
+        return new ApiInfoBuilder().title(swaggerProperties.getTitle())
+                .description(swaggerProperties.getDescription())
+                .contact(new Contact(swaggerProperties.getContactName(), swaggerProperties.getContactAddress(), swaggerProperties.getContactEmail()))
+                .version(swaggerProperties.getVersion())
+                .build();
+    }
+
+    /**
+     * 设置全局安全策略
+     *
+     * @return /
+     */
+    private List<SecurityScheme> securitySchemes() {
+        List<SecurityScheme> schemes = new ArrayList<>();
+        SecurityScheme scheme = new ApiKey(swaggerProperties.getTokenHeader(), swaggerProperties.getTokenHeader(), In.HEADER.toValue());
+        schemes.add(scheme);
+        return schemes;
+    }
+
+    /**
+     * 授权信息全局应用
+     */
+    private List<SecurityContext> securityContexts() {
+        SecurityContext securityContext = SecurityContext.builder()
+                .securityReferences(Collections.singletonList(new SecurityReference(swaggerProperties.getTokenHeader(), new AuthorizationScope[]{new AuthorizationScope("global", "")})))
+                .build();
+        return Collections.singletonList(securityContext);
+
+    }
+
+    @Override
+    public void onApplicationEvent(WebServerInitializedEvent webServerInitializedEvent) {
+        try {
+            Logger logger = LoggerFactory.getLogger(Swagger2Config.class);
+
+            //获取IP
+            String hostAddress = Inet4Address.getLocalHost().getHostAddress();
+            //获取端口号
+            int port = webServerInitializedEvent.getWebServer().getPort();
+            //获取应用名
+            String applicationName = webServerInitializedEvent.getApplicationContext().getApplicationName();
+            logger.info("项目启动成功!接口文档地址: http://" + hostAddress + ":" + webServerInitializedEvent.getWebServer().getPort() + applicationName + "/doc.html#");
+        } catch (UnknownHostException e) {
+            e.printStackTrace();
+        }
+    }
+
+}
diff --git a/src/main/java/com/sztzjy/forex/trading_trading/config/swagger/SwaggerProperties.java b/src/main/java/com/sztzjy/forex/trading_trading/config/swagger/SwaggerProperties.java
new file mode 100644
index 0000000..27d3bcd
--- /dev/null
+++ b/src/main/java/com/sztzjy/forex/trading_trading/config/swagger/SwaggerProperties.java
@@ -0,0 +1,115 @@
+package com.sztzjy.forex.trading_trading.config.swagger;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author 陈沅
+ */
+@Component
+@ConfigurationProperties(prefix = "swagger")
+public class SwaggerProperties {
+    /**
+     * 是否开启swagger,生产环境一般关闭
+     */
+    private Boolean enable;
+    /**
+     * 授权KEY
+     */
+    private String tokenHeader;
+
+    /**
+     * 标题
+     */
+    private String title;
+
+    /**
+     * 描述
+     */
+    private String description;
+
+    /**
+     * 联系人姓名
+     */
+    private String contactName;
+
+    /**
+     * 联系人地址
+     */
+    private String contactAddress;
+
+    /**
+     * 联系人邮箱
+     */
+    private String contactEmail;
+
+    /**
+     * 版本
+     */
+    private String version;
+
+    public Boolean getEnable() {
+        return enable;
+    }
+
+    public void setEnable(Boolean enable) {
+        this.enable = enable;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public String getContactName() {
+        return contactName;
+    }
+
+    public void setContactName(String contactName) {
+        this.contactName = contactName;
+    }
+
+    public String getContactAddress() {
+        return contactAddress;
+    }
+
+    public void setContactAddress(String contactAddress) {
+        this.contactAddress = contactAddress;
+    }
+
+    public String getContactEmail() {
+        return contactEmail;
+    }
+
+    public void setContactEmail(String contactEmail) {
+        this.contactEmail = contactEmail;
+    }
+
+    public String getVersion() {
+        return version;
+    }
+
+    public void setVersion(String version) {
+        this.version = version;
+    }
+
+    public String getTokenHeader() {
+        return tokenHeader;
+    }
+
+    public void setTokenHeader(String tokenHeader) {
+        this.tokenHeader = tokenHeader;
+    }
+}
+
diff --git a/src/main/java/com/sztzjy/forex/trading_trading/util/ResultDataEntity.java b/src/main/java/com/sztzjy/forex/trading_trading/util/ResultDataEntity.java
new file mode 100644
index 0000000..fc5c05b
--- /dev/null
+++ b/src/main/java/com/sztzjy/forex/trading_trading/util/ResultDataEntity.java
@@ -0,0 +1,55 @@
+package com.sztzjy.forex.trading_trading.util;
+
+import lombok.Getter;
+import org.springframework.http.HttpStatus;
+
+/**
+ * 出参对象统一封装
+ */
+@Getter
+public class ResultDataEntity<T> {
+    /**
+     * 状态码
+     */
+    private final Integer code;
+    /**
+     * 异常提示
+     */
+//    @JsonInclude(JsonInclude.Include.NON_NULL)
+    private String msg = null;
+    /**
+     * 返回体对象
+     */
+//    @JsonInclude(JsonInclude.Include.NON_NULL)
+    private T data = null;
+
+    public ResultDataEntity(T data) {
+        this.code = HttpStatus.OK.value();
+        this.data = data;
+    }
+
+    public ResultDataEntity(HttpStatus status, T data) {
+        this.code = status.value();
+        this.data = data;
+    }
+
+    public ResultDataEntity(HttpStatus status, String msg, T data) {
+        this.code = status.value();
+        this.msg = msg;
+        this.data = data;
+    }
+
+    public ResultDataEntity(String msg) {
+        this.code = HttpStatus.OK.value();
+        this.msg = msg;
+    }
+
+    public ResultDataEntity(HttpStatus status, String msg) {
+        this.code = status.value();
+        this.msg = msg;
+    }
+
+    public ResultDataEntity(HttpStatus status) {
+        this.code = status.value();
+    }
+}
diff --git a/src/main/java/com/sztzjy/forex/trading_trading/util/ResultEntity.java b/src/main/java/com/sztzjy/forex/trading_trading/util/ResultEntity.java
new file mode 100644
index 0000000..f89acba
--- /dev/null
+++ b/src/main/java/com/sztzjy/forex/trading_trading/util/ResultEntity.java
@@ -0,0 +1,38 @@
+package com.sztzjy.forex.trading_trading.util;
+
+import io.swagger.annotations.ApiModel;
+import lombok.Getter;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+
+/**
+ * 对ResponseEntity做了简单包装
+ *
+ */
+@ApiModel("API返回对象")
+@Getter
+public class ResultEntity<T> extends ResponseEntity<ResultDataEntity<T>> {
+    public ResultEntity(T data) {
+        super(new ResultDataEntity<>(HttpStatus.OK, data), HttpStatus.OK);
+    }
+
+    public ResultEntity(HttpStatus status, T data) {
+        super(new ResultDataEntity<>(status, data), status);
+    }
+
+    public ResultEntity(HttpStatus status, String msg, T data) {
+        super(new ResultDataEntity<>(status, msg, data), status);
+    }
+
+    public ResultEntity(String msg) {
+        super(new ResultDataEntity<>(HttpStatus.OK, msg), HttpStatus.OK);
+    }
+
+    public ResultEntity(HttpStatus status, String msg) {
+        super(new ResultDataEntity<>(status, msg), status);
+    }
+
+    public ResultEntity(HttpStatus status) {
+        super(new ResultDataEntity<>(status), status);
+    }
+}
diff --git a/src/main/java/com/sztzjy/forex/trading_trading/util/ThrowableUtil.java b/src/main/java/com/sztzjy/forex/trading_trading/util/ThrowableUtil.java
new file mode 100644
index 0000000..0b1e831
--- /dev/null
+++ b/src/main/java/com/sztzjy/forex/trading_trading/util/ThrowableUtil.java
@@ -0,0 +1,23 @@
+package com.sztzjy.forex.trading_trading.util;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+/**
+ * 异常工具
+ *
+ * 陈沅
+ */
+public class ThrowableUtil {
+
+    /**
+     * 获取堆栈信息
+     */
+    public static String getStackTrace(Throwable throwable) {
+        StringWriter sw = new StringWriter();
+        try (PrintWriter pw = new PrintWriter(sw)) {
+            throwable.printStackTrace(pw);
+            return sw.toString();
+        }
+    }
+}
diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml
new file mode 100644
index 0000000..3e38a98
--- /dev/null
+++ b/src/main/resources/application-dev.yml
@@ -0,0 +1,8 @@
+spring:
+  datasource:
+    druid:
+      db-type: com.alibaba.druid.pool.DruidDataSource
+      driverClassName: com.mysql.cj.jdbc.Driver
+      url: jdbc:mysql://${DB_HOST:118.31.7.2}:${DB_PORT:3306}}/${DB_NAME:foreign_trading_system}?useSSL=false&serverTimezone=UTC
+      username: ${DB_USER:root}
+      password: ${DB_PWD:sztzjy2017}
\ No newline at end of file
diff --git a/src/main/resources/application-pro.yml b/src/main/resources/application-pro.yml
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/resources/application-test.yml b/src/main/resources/application-test.yml
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
new file mode 100644
index 0000000..6a4c421
--- /dev/null
+++ b/src/main/resources/application.yml
@@ -0,0 +1,82 @@
+server:
+  port: 8800
+  servlet:
+    context-path: /
+
+spring:
+  application:
+    name: trading_system
+  profiles:
+    active: dev
+  mvc:
+    pathmatch:
+      matching-strategy: ant_path_matcher
+  jackson:
+    time-zone: GMT+8
+  datasource:
+    druid:
+      # 初始连接数
+      initial-size: 5
+      # 最小连接数
+      min-idle: 15
+      # 最大连接数
+      max-active: 500
+      # 获取连接超时时间
+      max-wait: 5000
+      # 连接有效性检测时间
+      time-between-eviction-runs-millis: 60000
+      # 连接在池中最小生存的时间
+      min-evictable-idle-time-millis: 300000
+      # 连接在池中最大生存的时间
+      max-evictable-idle-time-millis: 900000
+      # 指明连接是否被空闲连接回收器(如果有)进行检验.如果检测失败,则连接将被从池中去除
+      test-while-idle: true
+      # 指明是否在从池中取出连接前进行检验,如果检验失败, 则从池中去除连接并尝试取出另一个
+      test-on-borrow: false
+      # 是否在归还到池中前进行检验
+      test-on-return: false
+      # 检测连接是否有效
+      validation-query: select 'X'
+      # 配置监控统计
+      webStatFilter:
+        enabled: true
+      stat-view-servlet:
+        allow:
+        enabled: true
+        # 控制台管理用户名和密码
+        url-pattern: /druid/*
+        reset-enable: false
+        login-username: admin
+        login-password: 2023inspect
+      filter:
+        stat:
+          enabled: true
+          # 记录慢SQL
+          log-slow-sql: false
+          slow-sql-millis: 1000
+          merge-sql: true
+        wall:
+          config:
+            multi-statement-allow: true
+    #配置 Jpa
+    jpa:
+      hibernate:
+        ddl-auto: update
+      open-in-view: true
+      show-sql: true
+      properties:
+        hibernate:
+          format_sql: true
+          dialect: org.hibernate.dialect.MySQL8Dialect
+        temp:
+          use_jdbc_metadata_defaults: false
+      database: mysql
+
+swagger:
+  enable: true
+  tokenHeader: Authorization
+  title: 天择外汇模拟交易 • 接口文档
+  description: 天择外汇模拟交易WebAPI接口文档
+  contactName: 深圳天择教育科技有限公司
+  contactAddress: www.sztzjy.com
+  version: @project.version@
diff --git a/src/test/java/com/sztzjy/foreign_exchange_trading/ForeignExchangeTradingApplicationTests.java b/src/test/java/com/sztzjy/foreign_exchange_trading/ForeignExchangeTradingApplicationTests.java
new file mode 100644
index 0000000..b44314f
--- /dev/null
+++ b/src/test/java/com/sztzjy/foreign_exchange_trading/ForeignExchangeTradingApplicationTests.java
@@ -0,0 +1,13 @@
+package com.sztzjy.foreign_exchange_trading;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class ForeignExchangeTradingApplicationTests {
+
+	@Test
+	void contextLoads() {
+	}
+
+}