天择外汇模拟交易系统后端框架搭建
commit
7c16d404cc
@ -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/
|
@ -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
|
@ -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>
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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";
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -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}
|
@ -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@
|
@ -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() {
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue