系统基本构成
This commit is contained in:
parent
c8f71d1d25
commit
26e1b92726
23
pom.xml
23
pom.xml
@ -7,6 +7,7 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<!--<version>2.3.5.RELEASE</version>-->
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
<groupId>club.joylink</groupId>
|
||||
@ -51,13 +52,19 @@
|
||||
<artifactId>fastjson2-extension-spring6</artifactId>
|
||||
<version>2.0.25</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Swagger UI -->
|
||||
<dependency>
|
||||
<groupId>org.springdoc</groupId>
|
||||
<artifactId>springdoc-openapi-ui</artifactId>
|
||||
<version>1.6.15</version>
|
||||
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
|
||||
<version>2.0.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springdoc</groupId>
|
||||
<artifactId>springdoc-openapi-security</artifactId>
|
||||
<version>1.7.0</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- mybatis-plus -->
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
@ -114,6 +121,16 @@
|
||||
<artifactId>protobuf-java</artifactId>
|
||||
<version>3.23.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt</artifactId>
|
||||
<version>0.9.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>31.1-jre</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
@ -1,13 +1,18 @@
|
||||
package club.joylink.xiannccda;
|
||||
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableCaching
|
||||
@MapperScan("club.joylink.xiannccda.mapper")
|
||||
public class XianNccDaApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(XianNccDaApplication.class, args);
|
||||
}
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(XianNccDaApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,37 @@
|
||||
package club.joylink.xiannccda.config;
|
||||
|
||||
import java.util.Arrays;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.cors.CorsConfigurationSource;
|
||||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
|
||||
|
||||
/**
|
||||
* @author Walker-sheng
|
||||
*/
|
||||
@Configuration
|
||||
public class ServerCorsConfiguration {
|
||||
|
||||
private CorsConfiguration buildConfig() {
|
||||
CorsConfiguration corsConfiguration = new CorsConfiguration();
|
||||
corsConfiguration.addAllowedOriginPattern("*");
|
||||
corsConfiguration.addAllowedHeader("*");
|
||||
corsConfiguration.addAllowedMethod("*");
|
||||
corsConfiguration.setAllowCredentials(true);
|
||||
// 暴露 header 中的其他属性给客户端应用程序
|
||||
corsConfiguration.setExposedHeaders(
|
||||
Arrays.asList("Authorization", "Access-Control-Allow-Origin",
|
||||
"Access-Control-Allow-Credentials"));
|
||||
return corsConfiguration;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public CorsConfigurationSource corsConfigurationSource() {
|
||||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||||
source.registerCorsConfiguration("/**", buildConfig());
|
||||
return source;
|
||||
}
|
||||
}
|
@ -0,0 +1,145 @@
|
||||
package club.joylink.xiannccda.config;
|
||||
|
||||
import com.nimbusds.jose.jwk.JWK;
|
||||
import com.nimbusds.jose.jwk.JWKSet;
|
||||
import com.nimbusds.jose.jwk.RSAKey;
|
||||
import com.nimbusds.jose.jwk.source.ImmutableJWKSet;
|
||||
import com.nimbusds.jose.jwk.source.JWKSource;
|
||||
import com.nimbusds.jose.proc.SecurityContext;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.security.config.Customizer;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
|
||||
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.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer;
|
||||
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.oauth2.jwt.JwtDecoder;
|
||||
import org.springframework.security.oauth2.jwt.JwtEncoder;
|
||||
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
|
||||
import org.springframework.security.oauth2.jwt.NimbusJwtEncoder;
|
||||
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
|
||||
import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter;
|
||||
import org.springframework.security.oauth2.server.resource.web.BearerTokenAuthenticationEntryPoint;
|
||||
import org.springframework.security.oauth2.server.resource.web.access.BearerTokenAccessDeniedHandler;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.web.cors.CorsConfigurationSource;
|
||||
|
||||
/**
|
||||
* 安全、权限相关配置
|
||||
*
|
||||
* @author Walker-sheng
|
||||
*/
|
||||
@Configuration
|
||||
@EnableMethodSecurity
|
||||
@EnableWebSecurity
|
||||
public class SpringSecurityConfiguration {
|
||||
|
||||
@Autowired
|
||||
CorsConfigurationSource corsConfigurationSource;
|
||||
|
||||
static List<RequestMatcher> AuthWhiteList = new ArrayList<>();
|
||||
|
||||
static {
|
||||
AuthWhiteList.add(AntPathRequestMatcher.antMatcher(HttpMethod.POST, "/api/userInfo/register"));
|
||||
AuthWhiteList.add(AntPathRequestMatcher.antMatcher("/error"));
|
||||
AuthWhiteList.add(AntPathRequestMatcher.antMatcher("/swagger-ui/**"));
|
||||
AuthWhiteList.add(AntPathRequestMatcher.antMatcher("/api-docs/**"));
|
||||
AuthWhiteList.add(AntPathRequestMatcher.antMatcher("/swagger-ui.html"));
|
||||
AuthWhiteList.add(AntPathRequestMatcher.antMatcher("/test"));
|
||||
AuthWhiteList.add(AntPathRequestMatcher.antMatcher("/test2"));
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||
// @formatter:off
|
||||
http
|
||||
.authorizeHttpRequests((authorize) -> {
|
||||
authorize.requestMatchers("/favicon.ico","/js2/**","/swagger-resources/configuration/security","/swagger-resources/configuration/ui","/swagger-resources/**","/upload/**","/v2/**","/swagger-ui.html","/webjars/**","/img/**","/css/**","/js/**","/image/**").permitAll();
|
||||
AuthWhiteList.forEach(matcher -> authorize.requestMatchers(matcher).permitAll());
|
||||
authorize.requestMatchers(HttpMethod.OPTIONS).permitAll();
|
||||
authorize.anyRequest().authenticated();
|
||||
}
|
||||
)
|
||||
.cors(corsConfig -> corsConfig.configurationSource(corsConfigurationSource))
|
||||
.csrf((csrf) -> csrf.disable())
|
||||
.httpBasic(Customizer.withDefaults())
|
||||
.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt)
|
||||
.sessionManagement(
|
||||
(session) -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
|
||||
.exceptionHandling((exceptions) -> exceptions
|
||||
.authenticationEntryPoint(new BearerTokenAuthenticationEntryPoint())
|
||||
// .defaultAuthenticationEntryPointFor(new MyBasicAuthenticationEntryPoint(),
|
||||
// new AntPathRequestMatcher("/api/auth/token", null))
|
||||
.defaultAuthenticationEntryPointFor(new BearerTokenAuthenticationEntryPoint(),
|
||||
new AntPathRequestMatcher("/api/**", null))
|
||||
.accessDeniedHandler(new BearerTokenAccessDeniedHandler())
|
||||
);
|
||||
// @formatter:on
|
||||
return http.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public JwtAuthenticationConverter jwtAuthenticationConverter() {
|
||||
JwtGrantedAuthoritiesConverter grantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
|
||||
//取消jwt的默认前缀SCOPE_
|
||||
grantedAuthoritiesConverter.setAuthorityPrefix("");
|
||||
|
||||
JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();
|
||||
jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(grantedAuthoritiesConverter);
|
||||
return jwtAuthenticationConverter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Spring Security用户username/password认证使用的password编码器
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public PasswordEncoder passwordEncoder() {
|
||||
return new BCryptPasswordEncoder(13);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * JWT解码器
|
||||
// *
|
||||
// * @return
|
||||
// */
|
||||
// @Bean
|
||||
// public JwtDecoder jwtDecoder() {
|
||||
// return NimbusJwtDecoder.withPublicKey(this.rsaKeys.publicKey).build();
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * JWT编码器
|
||||
// *
|
||||
// * @return
|
||||
// */
|
||||
// @Bean
|
||||
// public JwtEncoder jwtEncoder() {
|
||||
// JWK jwk = new RSAKey.Builder(this.rsaKeys.publicKey).privateKey(this.rsaKeys.privateKey)
|
||||
// .build();
|
||||
// JWKSource<SecurityContext> jwks = new ImmutableJWKSet<>(new JWKSet(jwk));
|
||||
// return new NimbusJwtEncoder(jwks);
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * 自定义方法安全授权处理器
|
||||
// * PS:此方法必须是static的,以确保Spring在初始化Spring Security的方法Security@Configuration类之前发布它
|
||||
// */
|
||||
// @Bean
|
||||
// static MethodSecurityExpressionHandler methodSecurityExpressionHandler() {
|
||||
// DefaultMethodSecurityExpressionHandler handler = new DefaultMethodSecurityExpressionHandler();
|
||||
// handler.setDefaultRolePrefix(""); // 原本SpringSecurity默认角色前缀为'ROLE_'
|
||||
// return handler;
|
||||
// }
|
||||
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package club.joylink.xiannccda.config;
|
||||
|
||||
import io.swagger.v3.oas.models.Components;
|
||||
import io.swagger.v3.oas.models.OpenAPI;
|
||||
import io.swagger.v3.oas.models.info.Info;
|
||||
import io.swagger.v3.oas.models.security.SecurityScheme;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class SwaggerConfig {
|
||||
|
||||
@Bean
|
||||
public OpenAPI customOpenAPI() {
|
||||
return new OpenAPI()
|
||||
.components(new Components()
|
||||
// 设置 spring security jwt accessToken 认证的请求头 Authorization: Bearer xxx.xxx.xxx
|
||||
.addSecuritySchemes("authScheme", new SecurityScheme()
|
||||
.type(SecurityScheme.Type.HTTP)
|
||||
.bearerFormat("JWT")
|
||||
.scheme("bearer")))
|
||||
.info(new Info()
|
||||
.title("My API")
|
||||
.description("My API description")
|
||||
.version("1.0.0")
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
package club.joylink.xiannccda.controller;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@RequestMapping()
|
||||
@Tag(name = "这是一个测试api名称", description = "接口描述")
|
||||
public class TestController {
|
||||
|
||||
@GetMapping("test")
|
||||
@Operation(summary = "测试", description = "测试接口")
|
||||
@ApiResponse(description = "返回字符串")
|
||||
public String d() {
|
||||
return "aaaaaaaaaaaaaaaa";
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("test2")
|
||||
@Operation(summary = "测试接口2", description = "测试接口描述")
|
||||
@ApiResponse(description = "返回test对象")
|
||||
public TestData test2(
|
||||
@Parameter(name = "name", description = "这是一个那么参数") @RequestParam(name = "name") String name) {
|
||||
return new TestData("name", "psss");
|
||||
}
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Schema(name = "返回对象数据", description = "返回对象数据描述")
|
||||
public static class TestData {
|
||||
|
||||
@Schema(name = "name", description = "属性描述")
|
||||
private String name;
|
||||
private String passwd;
|
||||
}
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
package club.joylink.xiannccda.controller.advice;
|
||||
|
||||
|
||||
import club.joylink.xiannccda.exception.BusinessException;
|
||||
import club.joylink.xiannccda.vo.CommonJsonResponse;
|
||||
import club.joylink.xiannccda.vo.ResponseConsts;
|
||||
import com.google.protobuf.AbstractMessageLite;
|
||||
import java.util.List;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.server.ServerHttpRequest;
|
||||
import org.springframework.http.server.ServerHttpResponse;
|
||||
import org.springframework.validation.ObjectError;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.MissingServletRequestParameterException;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
|
||||
|
||||
@ControllerAdvice
|
||||
@Slf4j
|
||||
public class CommonResponseBody implements ResponseBodyAdvice {
|
||||
|
||||
@Override
|
||||
public boolean supports(MethodParameter returnType, Class converterType) {
|
||||
return returnType.getMethod() != null && !returnType.getMethod().getReturnType().getSimpleName()
|
||||
.equals("CommonJsonResponse");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object beforeBodyWrite(Object body, MethodParameter returnType,
|
||||
MediaType selectedContentType,
|
||||
Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
|
||||
//byte[]
|
||||
if (body instanceof byte[]) {
|
||||
response.getHeaders().setContentType(MediaType.APPLICATION_OCTET_STREAM);
|
||||
return body;
|
||||
}
|
||||
//byte[]
|
||||
if (body instanceof AbstractMessageLite) {
|
||||
response.getHeaders().setContentType(MediaType.APPLICATION_OCTET_STREAM);
|
||||
final AbstractMessageLite proto = (AbstractMessageLite) body;
|
||||
return proto.toByteArray();
|
||||
}
|
||||
if (body instanceof CommonJsonResponse) {
|
||||
return body;
|
||||
}
|
||||
if (request.getURI().getPath().startsWith("/swagger")) {
|
||||
return body;
|
||||
}
|
||||
if (request.getURI().getPath().startsWith("/api-docs")) {
|
||||
return body;
|
||||
}
|
||||
if (request.getURI().getPath().equals("/api/userinfo/ifRegisted")) {
|
||||
return body;
|
||||
}
|
||||
if (request.getURI().getPath().equals("/api/userinfo/identity")) {
|
||||
return body;
|
||||
}
|
||||
CommonJsonResponse commonJsonResponse = CommonJsonResponse.newSuccessResponse(body);
|
||||
if (returnType.getMethod().getReturnType().equals(String.class) || body instanceof String) {
|
||||
return commonJsonResponse.toJSONString();
|
||||
}
|
||||
return commonJsonResponse;
|
||||
}
|
||||
|
||||
|
||||
@ExceptionHandler({Exception.class})
|
||||
@ResponseBody
|
||||
public CommonJsonResponse handleException(Exception e) {
|
||||
if (e instanceof MethodArgumentNotValidException) {
|
||||
// 参数验证异常处理
|
||||
MethodArgumentNotValidException validException = (MethodArgumentNotValidException) e;
|
||||
List<ObjectError> errorList = validException.getBindingResult().getAllErrors();
|
||||
StringBuffer sb = new StringBuffer();
|
||||
errorList.forEach(error ->
|
||||
sb.append(error.getDefaultMessage()).append(";"));
|
||||
log.error("【参数校验异常】{}", e);
|
||||
return CommonJsonResponse.newErrorResponse(ResponseConsts.VALIDATE_ERROR.getCode(),
|
||||
sb.toString());
|
||||
}
|
||||
if (e instanceof BusinessException) {
|
||||
BusinessException be = (BusinessException) e;
|
||||
log.error("【业务异常】{}", e);
|
||||
return CommonJsonResponse.newErrorResponse(be.getCode(), be.getVoMessage());
|
||||
} else if (e instanceof MissingServletRequestParameterException) {
|
||||
log.error("【接口参数异常】", e);
|
||||
return CommonJsonResponse.newErrorResponse(ResponseConsts.VALIDATE_ERROR.getCode(),
|
||||
"接口参数异常");
|
||||
}/* else if (e instanceof SimulationException) {
|
||||
club.joylink.rtss.simulation.cbtc.exception.SimulationException simulationException = (club.joylink.rtss.simulation.cbtc.exception.SimulationException) e;
|
||||
log.error("【仿真系统异常】{}", e);
|
||||
return CommonJsonResponse.newErrorResponse(simulationException.getCode(),
|
||||
simulationException.getMessage());
|
||||
}*/
|
||||
|
||||
log.error("【系统异常】{}", e);
|
||||
return CommonJsonResponse.newErrorResponse();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package club.joylink.xiannccda.exception;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
public class BaseException extends RuntimeException {
|
||||
|
||||
private IExceptionMessage exceptionMessage;
|
||||
|
||||
public BaseException(IExceptionMessage exceptionMessage) {
|
||||
super(exceptionMessage.getMessage());
|
||||
this.exceptionMessage = exceptionMessage;
|
||||
}
|
||||
|
||||
public BaseException(IExceptionMessage exceptionMessage, String message) {
|
||||
super(message);
|
||||
this.exceptionMessage = exceptionMessage;
|
||||
}
|
||||
|
||||
public BaseException(IExceptionMessage exceptionMessage, Throwable cause) {
|
||||
super(exceptionMessage.getMessage(), cause);
|
||||
this.exceptionMessage = exceptionMessage;
|
||||
}
|
||||
|
||||
public BaseException(IExceptionMessage exceptionMessage, String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
this.exceptionMessage = exceptionMessage;
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return this.exceptionMessage.getCode();
|
||||
}
|
||||
|
||||
public String getVoMessage() {
|
||||
if (!StringUtils.isEmpty(super.getMessage())) {
|
||||
return super.getMessage();
|
||||
}
|
||||
return this.exceptionMessage.getMessage();
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package club.joylink.xiannccda.exception;
|
||||
|
||||
public class BusinessException extends BaseException {
|
||||
|
||||
public BusinessException(IExceptionMessage exceptionMessage) {
|
||||
super(exceptionMessage);
|
||||
}
|
||||
|
||||
public BusinessException(IExceptionMessage exceptionMessage, String message) {
|
||||
super(exceptionMessage, message);
|
||||
}
|
||||
|
||||
public BusinessException(IExceptionMessage exceptionMessage, Throwable cause) {
|
||||
super(exceptionMessage, cause);
|
||||
}
|
||||
|
||||
public BusinessException(IExceptionMessage exceptionMessage, String message, Throwable cause) {
|
||||
super(exceptionMessage, message, cause);
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package club.joylink.xiannccda.exception;
|
||||
|
||||
public interface BusinessExceptionAssert extends IExceptionMessage, ExceptionAssert {
|
||||
|
||||
default BaseException exception() {
|
||||
return new BusinessException(this);
|
||||
}
|
||||
|
||||
default BaseException exception(Throwable t) {
|
||||
return new BusinessException(this, t);
|
||||
}
|
||||
|
||||
default BaseException exception(String message) {
|
||||
return new BusinessException(this, message);
|
||||
}
|
||||
|
||||
default BaseException exception(String message, Throwable t) {
|
||||
return new BusinessException(this, message, t);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
package club.joylink.xiannccda.exception;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public enum BusinessExceptionAssertEnum implements BusinessExceptionAssert {
|
||||
INVALID_LICENSE(90000, "invalid license"),
|
||||
LICENSE_EXPIRED(90001, "license expired"),
|
||||
LICENSE_LOCAL_SAVE_FAILED(90002, "license local save failed"),
|
||||
LICENSE_LOCAL_LOAD_FAILED(90003, "license local load failed"),
|
||||
LICENSE_DECRYPT_FAILED(90004, "license decrypt failed"),
|
||||
LICENSE_NOT_EXIST(90005, "license not exist"),
|
||||
LICENSE_FILE_NOT_EXIST(90006, "license file not exist"),
|
||||
|
||||
|
||||
SYSTEM_EXCEPTION(10000, "system exception"),
|
||||
TRAINING_ROOM_SIMULATION_NOT_EXIST(10001, "training room simulation not exist"),
|
||||
SIMULATION_PERMISSION_ALREADY_GET(10002, "permission already get"),
|
||||
INSUFFICIENT_PERMISSIONS(10003, "insufficient permissions"),
|
||||
OPERATION_NOT_SUPPORTED(10004, "operation not supported"),
|
||||
INVALID_OPERATION(10005, "invalid operation"),
|
||||
TRAINING_ROOM_SIMULATION_LOAD_DEVICE_ERROR(10006, "training room simulation load device error"),
|
||||
DATA_NOT_EXIST(10007, "data not exist"),
|
||||
ARGUMENT_ILLEGAL(10008, "argument illegal"),
|
||||
SIMULATION_PERMISSION_USE_UP(10009, "simulation permission use up"),
|
||||
NAME_REPEAT(10010, "name repeat"),
|
||||
QUESTION_RULE_NOT_EXIST(10011, "question rule not exist"),
|
||||
DATA_ALREADY_EXIST(10012, "data already exist"),
|
||||
SIMULATION_PERMISSION_NOT_EXIST(10013, "simulation permission not exist"),
|
||||
SIMULATION_PERMISSION_NOT_AVAILABLE(10014, "simulation permission not available"),
|
||||
UNSUPPORTED_FILE_FORMAT(10015, "unsupported file format"),
|
||||
OPERATION_REPEAT(10016, "operation repeat"),
|
||||
SIMULATION_EXCEPTION_FOR_SHOW(10017, ""), //错误信息用于展示给仿真用户
|
||||
OPERATION_FAIL(10018, "操作失败"),
|
||||
STATION_DETAIL_NOT_FOUND_RD_PLAN_ITEM(10019, "站细卡控未找到对应的接发车计划"),
|
||||
|
||||
DATA_ERROR(11000, "data error"),
|
||||
REPEAT_RUN_PLAN_FROM_CTC_UPDATE_DATA(11200, "repeat run plan"),
|
||||
CI_GENERATE_ERROR(11001, "ci data generate error"),
|
||||
MAP_PASSENGER_FLOW_DATA_ERROR(11002, "map passenger flow data error"),
|
||||
DATA_UNIQUE_PROPERTY_REPEAT(11013, "data unique property repeat"),
|
||||
DATA_INVALID(11004, "data invalid"),
|
||||
DATA_BEEN_USED(11005, "data has been used"),
|
||||
DATA_STATE_INCORRECT(11007, "data state incorrect"),
|
||||
|
||||
// 运行图工具
|
||||
BEYOND_RECEPTION(101, "beyond station reception"),
|
||||
|
||||
// 仿真
|
||||
SIMULATION_NOT_EXIST(30001, "simulation not exist"),
|
||||
SIMULATION_OPERATION_FAILED(30002, "simulation operation failed"),
|
||||
|
||||
//
|
||||
LOGIN_INFO_ERROR(40003, "login info error"),
|
||||
LOGIN_EXPIRED(40004, "login expired"),
|
||||
NOT_LOGIN(40005, "not login"),
|
||||
WECHAT_CODE_EXPIRED(40029, "wechat code expired"),
|
||||
INVALID_CLIENT(40031, "invalid client"),
|
||||
INCORRECT_VERIFICATION_CODE(40051, "incorrect verification code"),
|
||||
THIRD_SERVICE_CALL_EXCEPTION(40071, "the third service call exception"),
|
||||
VOICE_COMMAND_PARSE_ERROR(40061, "voice command parse error"),
|
||||
VOICE_COMMAND_CONFIG_NULL(40062, "voice command config is null"),
|
||||
VOICE_COMMAND_DEVICE_UNDEFINED(40063, "device undefined"),
|
||||
VOICE_COMMAND_WORK_UNDEFINED(40064, "device work undefined"),
|
||||
|
||||
//支付异常
|
||||
PAY_ERROR(50000, "pay error"),
|
||||
WECHAT_NOTIFY_ERROR(401, "wechat notify error");
|
||||
|
||||
int code;
|
||||
|
||||
String message;
|
||||
|
||||
BusinessExceptionAssertEnum(int code, String message) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
}
|
||||
}
|
@ -0,0 +1,171 @@
|
||||
package club.joylink.xiannccda.exception;
|
||||
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
public interface ExceptionAssert {
|
||||
|
||||
BaseException exception();
|
||||
|
||||
BaseException exception(Throwable t);
|
||||
|
||||
BaseException exception(String message);
|
||||
|
||||
BaseException exception(String message, Throwable t);
|
||||
|
||||
default void fail() {
|
||||
throw exception();
|
||||
}
|
||||
|
||||
default void fail(String message) {
|
||||
throw exception(message);
|
||||
}
|
||||
|
||||
default void assertNotNull(Object object) {
|
||||
if (object == null) {
|
||||
throw exception();
|
||||
}
|
||||
}
|
||||
|
||||
default void assertNotNull(Object object, String message) {
|
||||
if (object == null) {
|
||||
throw exception(message);
|
||||
}
|
||||
}
|
||||
|
||||
default void assertNull(Object object) {
|
||||
if (object != null) {
|
||||
throw exception();
|
||||
}
|
||||
}
|
||||
|
||||
default void assertNull(Object object, String message) {
|
||||
if (object != null) {
|
||||
throw exception(message);
|
||||
}
|
||||
}
|
||||
|
||||
default void assertTrue(boolean expression) {
|
||||
if (!expression) {
|
||||
throw exception();
|
||||
}
|
||||
}
|
||||
|
||||
default void assertTrue(boolean expression, String message) {
|
||||
if (!expression) {
|
||||
throw exception(message);
|
||||
}
|
||||
}
|
||||
|
||||
default void assertNotTrue(boolean expression) {
|
||||
if (expression) {
|
||||
throw exception();
|
||||
}
|
||||
}
|
||||
|
||||
default void assertNotTrue(boolean expression, String message) {
|
||||
if (expression) {
|
||||
throw exception(message);
|
||||
}
|
||||
}
|
||||
|
||||
default void assertCollectionEmpty(Collection<?> collection) {
|
||||
if (!CollectionUtils.isEmpty(collection)) {
|
||||
throw exception();
|
||||
}
|
||||
}
|
||||
|
||||
default void assertCollectionEmpty(Collection<?> collection, String message) {
|
||||
if (!CollectionUtils.isEmpty(collection)) {
|
||||
throw exception(message);
|
||||
}
|
||||
}
|
||||
|
||||
default void assertCollectionNotEmpty(Collection<?> collection) {
|
||||
if (CollectionUtils.isEmpty(collection)) {
|
||||
throw exception();
|
||||
}
|
||||
}
|
||||
|
||||
default void assertCollectionNotEmpty(Collection<?> collection, String message) {
|
||||
if (CollectionUtils.isEmpty(collection)) {
|
||||
throw exception(message);
|
||||
}
|
||||
}
|
||||
|
||||
default void assertMapEmpty(Map<?, ?> map) {
|
||||
if (!CollectionUtils.isEmpty(map)) {
|
||||
throw exception();
|
||||
}
|
||||
}
|
||||
|
||||
default void assertMapEmpty(Map<?, ?> map, String message) {
|
||||
if (!CollectionUtils.isEmpty(map)) {
|
||||
throw exception(message);
|
||||
}
|
||||
}
|
||||
|
||||
default void assertMapNotEmpty(Map<?, ?> map) {
|
||||
if (CollectionUtils.isEmpty(map)) {
|
||||
throw exception();
|
||||
}
|
||||
}
|
||||
|
||||
default void assertMapNotEmpty(Map<?, ?> map, String message) {
|
||||
if (CollectionUtils.isEmpty(map)) {
|
||||
throw exception(message);
|
||||
}
|
||||
}
|
||||
|
||||
default void assertEquals(Object o1, Object o2) {
|
||||
if (!Objects.equals(o1, o2)) {
|
||||
throw exception();
|
||||
}
|
||||
}
|
||||
|
||||
default void assertEquals(Object o1, Object o2, String message) {
|
||||
if (!Objects.equals(o1, o2)) {
|
||||
throw exception(message);
|
||||
}
|
||||
}
|
||||
|
||||
default void assertNotEquals(Object o1, Object o2) {
|
||||
if (Objects.equals(o1, o2)) {
|
||||
throw exception();
|
||||
}
|
||||
}
|
||||
|
||||
default void assertNotEquals(Object o1, Object o2, String message) {
|
||||
if (Objects.equals(o1, o2)) {
|
||||
throw exception(message);
|
||||
}
|
||||
}
|
||||
|
||||
default void assertHasText(String str) {
|
||||
if (!StringUtils.hasText(str)) {
|
||||
throw exception();
|
||||
}
|
||||
}
|
||||
|
||||
default void assertHasText(String str, String message) {
|
||||
if (!StringUtils.hasText(str)) {
|
||||
throw exception(message);
|
||||
}
|
||||
}
|
||||
|
||||
default void assertNotHasText(String str) {
|
||||
if (StringUtils.hasText(str)) {
|
||||
throw exception();
|
||||
}
|
||||
}
|
||||
|
||||
default void assertNotHasText(String str, String message) {
|
||||
if (StringUtils.hasText(str)) {
|
||||
throw exception(message);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package club.joylink.xiannccda.exception;
|
||||
|
||||
public interface IExceptionMessage {
|
||||
|
||||
int getCode();
|
||||
|
||||
String getMessage();
|
||||
|
||||
}
|
110
src/main/java/club/joylink/xiannccda/vo/CommonJsonResponse.java
Normal file
110
src/main/java/club/joylink/xiannccda/vo/CommonJsonResponse.java
Normal file
@ -0,0 +1,110 @@
|
||||
package club.joylink.xiannccda.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonView;
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@NoArgsConstructor
|
||||
@JsonView(View.class)
|
||||
public class CommonJsonResponse<T> implements Serializable {
|
||||
|
||||
private Integer code;
|
||||
|
||||
private String message;
|
||||
|
||||
private T data;
|
||||
|
||||
/**
|
||||
* 构造一个没有数据的消息
|
||||
*/
|
||||
private CommonJsonResponse(ResponseConsts respConst) {
|
||||
this.code = respConst.getCode();
|
||||
this.message = respConst.getMsg();
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造成功返回数据对象
|
||||
*/
|
||||
private CommonJsonResponse(T data) {
|
||||
this.code = ResponseConsts.SUCCESS.getCode();
|
||||
this.message = ResponseConsts.SUCCESS.getMsg();
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public CommonJsonResponse(int code, String msg) {
|
||||
this.code = code;
|
||||
this.message = msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回通用成功对象
|
||||
*/
|
||||
public static CommonJsonResponse newSuccessResponse() {
|
||||
return new CommonJsonResponse(ResponseConsts.SUCCESS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 成功返回数据对象
|
||||
*/
|
||||
public static <T> CommonJsonResponse<T> newSuccessResponse(T data) {
|
||||
return new CommonJsonResponse<>(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回失败对象
|
||||
*/
|
||||
public static CommonJsonResponse newFaildResponse(ResponseConsts respConst) {
|
||||
return new CommonJsonResponse(respConst);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回通用异常对象
|
||||
*/
|
||||
public static CommonJsonResponse newErrorResponse() {
|
||||
return new CommonJsonResponse(ResponseConsts.ERROR);
|
||||
}
|
||||
|
||||
public static CommonJsonResponse newErrorResponse(int code, String msg) {
|
||||
return new CommonJsonResponse(code, msg);
|
||||
}
|
||||
|
||||
public Integer getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(Integer code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public Object getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(T data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CommonJsonResponse [code=" + code + ", message=" + message + ", data=" + data + "]";
|
||||
}
|
||||
|
||||
public String toJSONString() {
|
||||
if (Objects.isNull(data)) {
|
||||
return "{\"code\":" + code + ", \"message\":\"" + message + "\"}";
|
||||
} else {
|
||||
return "{\"code\":" + code + ", \"message\":\"" + message + "\", \"data\":\"" + data + "\"}";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
58
src/main/java/club/joylink/xiannccda/vo/RequestInfo.java
Normal file
58
src/main/java/club/joylink/xiannccda/vo/RequestInfo.java
Normal file
@ -0,0 +1,58 @@
|
||||
package club.joylink.xiannccda.vo;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class RequestInfo implements Serializable {
|
||||
|
||||
private String url;
|
||||
|
||||
private String methodType;
|
||||
|
||||
private String ip;
|
||||
|
||||
private String classMethod;
|
||||
|
||||
private String args;
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public String getMethodType() {
|
||||
return methodType;
|
||||
}
|
||||
|
||||
public void setMethodType(String methodType) {
|
||||
this.methodType = methodType;
|
||||
}
|
||||
|
||||
public String getIp() {
|
||||
return ip;
|
||||
}
|
||||
|
||||
public void setIp(String ip) {
|
||||
this.ip = ip;
|
||||
}
|
||||
|
||||
public String getClassMethod() {
|
||||
return classMethod;
|
||||
}
|
||||
|
||||
public void setClassMethod(String classMethod) {
|
||||
this.classMethod = classMethod;
|
||||
}
|
||||
|
||||
public String getArgs() {
|
||||
return args;
|
||||
}
|
||||
|
||||
public void setArgs(String args) {
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
}
|
26
src/main/java/club/joylink/xiannccda/vo/ResponseConsts.java
Normal file
26
src/main/java/club/joylink/xiannccda/vo/ResponseConsts.java
Normal file
@ -0,0 +1,26 @@
|
||||
package club.joylink.xiannccda.vo;
|
||||
|
||||
public enum ResponseConsts {
|
||||
|
||||
SUCCESS(200, "成功"),
|
||||
FAILD(300, "失败"),
|
||||
ERROR(500, "未知错误"),
|
||||
VALIDATE_ERROR(501, "");
|
||||
|
||||
private ResponseConsts(Integer code, String msg) {
|
||||
this.code = code;
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
private Integer code;
|
||||
|
||||
private String msg;
|
||||
|
||||
public Integer getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getMsg() {
|
||||
return msg;
|
||||
}
|
||||
}
|
5
src/main/java/club/joylink/xiannccda/vo/View.java
Normal file
5
src/main/java/club/joylink/xiannccda/vo/View.java
Normal file
@ -0,0 +1,5 @@
|
||||
package club.joylink.xiannccda.vo;
|
||||
|
||||
public interface View {
|
||||
|
||||
}
|
3
src/main/resources/app.pub
Normal file
3
src/main/resources/app.pub
Normal file
@ -0,0 +1,3 @@
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApNejr+YMt+as0M1VJL+OBUEiafsQ+93jIdDXhE026GeEickNwCH7zUAIk0rzQOpSmOIKT8Ur3nXZkTyG6dYFTOgis2RexFrOmUfVMTO0RAi65aBolUVL96ub27SMTDU8jC7C7XOfjxOmbL6HjhAFM17aD2V24NHp1n7P6n8VWhK93O64klxeUtA39IFLKrkRe/gjQHa9hhAzCY7RCpe6Q0ZPCLIjFabrqZn4ToUr3oit9elHNQ/IyyLoCh2etowDxl25CzC99ICCC1ihRRGS2m78NOH2VAiatNYo0W0cCyRvWfwJyFk5NYDHx/KCGXOUdLCN/PSBAGMoi/a9OI6AhQIDAQAB
|
||||
-----END PUBLIC KEY-----
|
@ -1,14 +1,9 @@
|
||||
server:
|
||||
port: 9071
|
||||
|
||||
spring:
|
||||
profiles:
|
||||
default: dev
|
||||
active: dev
|
||||
datasource:
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://192.168.3.233:3306/xian-ncc-da?useSSL=false&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
|
||||
username: root
|
||||
password: joylink0503
|
||||
hikari:
|
||||
minimum-idle: 5 # 连接池维护的最小空闲连接数
|
||||
maximum-pool-size: 10 #配置最大连接池大小
|
||||
@ -22,4 +17,22 @@ spring:
|
||||
oauth2:
|
||||
resource-server:
|
||||
jwt:
|
||||
public-key-location: classpath:app.pub
|
||||
public-key-location: classpath:app.pub
|
||||
springdoc:
|
||||
packages-to-scan: club.joylink.xiannccda.controller
|
||||
swagger-ui:
|
||||
enabled: true
|
||||
api-docs:
|
||||
enabled: true
|
||||
path: /api-docs
|
||||
logging:
|
||||
level:
|
||||
root: info
|
||||
mybatis-plus:
|
||||
# 映射文件的位置
|
||||
mapper-locations: classpath:mybatis/mapper/*.xml
|
||||
configuration:
|
||||
map-underscore-to-camel-case: true
|
||||
cache-enabled: false
|
||||
call-setters-on-nulls: true
|
||||
jdbc-type-for-null: 'null'
|
||||
|
@ -2,13 +2,18 @@ package club.joylink.xiannccda;
|
||||
|
||||
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
|
||||
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
|
||||
import com.baomidou.mybatisplus.generator.config.OutputFile;
|
||||
import com.baomidou.mybatisplus.generator.config.rules.DateType;
|
||||
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* baomidou 参考 https://www.baomidou.com/
|
||||
*/
|
||||
public class MybatisPlusGenerator {
|
||||
|
||||
public static final DataSourceConfig.Builder DataSourceConfigBuilder =
|
||||
@ -28,7 +33,9 @@ public class MybatisPlusGenerator {
|
||||
String baseDir =
|
||||
System.getProperty("user.dir") + File.separator + "src" + File.separator + "main";
|
||||
String javaBaseDir = baseDir + File.separator + "java";
|
||||
String mapperDir = baseDir + File.separator + "resources" + File.separator + "mapper";
|
||||
String mapperDir =
|
||||
baseDir + File.separator + "resources" + File.separator + "mybatis" + File.separator
|
||||
+ "mapper";
|
||||
System.out.println(javaBaseDir);
|
||||
System.out.println(mapperDir);
|
||||
FastAutoGenerator.create(DataSourceConfigBuilder)
|
||||
@ -38,9 +45,10 @@ public class MybatisPlusGenerator {
|
||||
.dateType(DateType.TIME_PACK)
|
||||
.outputDir(javaBaseDir))
|
||||
.packageConfig(builder ->
|
||||
builder.parent("club.joylink.rttp")
|
||||
builder.parent("club.joylink.xiannccda")
|
||||
.service("repository")
|
||||
.serviceImpl("repository.impl"))
|
||||
.serviceImpl("repository.impl").pathInfo(
|
||||
Collections.singletonMap(OutputFile.xml, mapperDir)))
|
||||
// .templateConfig(builder -> builder.entity())
|
||||
.strategyConfig(builder -> {
|
||||
builder.addExclude(ExcludeTableList);
|
||||
|
Loading…
Reference in New Issue
Block a user