feat(chaos-api): 初始化项目基础结构

- 新增 ApiResult 类用于统一返回结果
- 添加应用配置文件和日志配置文件
- 配置 MyBatis-Plus 和 Druid 数据源
- 实现基本的安全配置,包括未授权和权限不足的处理
- 引入必要的依赖,如 lombok、fastjson2、MariaDB驱动等
This commit is contained in:
chaos
2025-07-18 15:11:16 +08:00
parent 1810632e60
commit baa8bb57d8
10 changed files with 249 additions and 1 deletions

View File

@@ -19,5 +19,15 @@
<maven.compiler.target>21</maven.compiler.target> <maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties> </properties>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
</dependency>
</dependencies>
</project> </project>

View File

@@ -0,0 +1,30 @@
package cn.nopj.chaos_api.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ApiResult<T> {
private int code;
private String msg;
private T data;
public static <T> ApiResult<T> success(T data) {
return new ApiResult<>(200, "success", data);
}
public static <T> ApiResult<T> success(String msg, T data) {
return new ApiResult<>(200, msg, data);
}
public static <T> ApiResult<T> failed(int code, String msg) {
return new ApiResult<>(code, msg, null);
}
public static <T> ApiResult<T> failed(String msg) {
return new ApiResult<>(500, msg, null);
}
}

View File

@@ -40,5 +40,15 @@
<groupId>com.mysql</groupId> <groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId> <artifactId>mysql-connector-j</artifactId>
</dependency> </dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mariadb.jdbc/mariadb-java-client -->
<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
<version>3.5.4</version>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@@ -0,0 +1,9 @@
package cn.nopj.chaos_api.config;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@MapperScan("cn.nopj.chaos_api.mapper")
public class MyBatisPlusConfig {
}

View File

@@ -0,0 +1,28 @@
package cn.nopj.chaos_api.config.sec;
import cn.nopj.chaos_api.model.ApiResult;
import com.alibaba.fastjson2.JSONObject;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import java.io.IOException;
@Component
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException {
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json");
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
ApiResult<Object> result = ApiResult.failed("未授权");
String string = JSONObject.toJSONString(result);
response.getWriter().print(string);
response.getWriter().flush();
}
}

View File

@@ -0,0 +1,29 @@
package cn.nopj.chaos_api.config.sec;
import cn.nopj.chaos_api.model.ApiResult;
import com.alibaba.fastjson2.JSONObject;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;
import java.io.IOException;
@Component
public class RestfulAccessDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException {
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json");
response.setStatus(HttpServletResponse.SC_FORBIDDEN); // 状态码 403
ApiResult<String> result = ApiResult.failed(HttpServletResponse.SC_FORBIDDEN, "权限不足,请联系管理员");
response.getWriter().println(JSONObject.toJSONString( result));
response.getWriter().flush();
}
}

View File

@@ -0,0 +1,40 @@
package cn.nopj.chaos_api.config.sec;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.AbstractHttpConfigurer;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
private final RestAuthenticationEntryPoint restAuthenticationEntryPoint;
private final RestfulAccessDeniedHandler restfulAccessDeniedHandler;
public SecurityConfig(RestAuthenticationEntryPoint restAuthenticationEntryPoint, RestfulAccessDeniedHandler restfulAccessDeniedHandler) {
this.restAuthenticationEntryPoint = restAuthenticationEntryPoint;
this.restfulAccessDeniedHandler = restfulAccessDeniedHandler;
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
// 允许所有对 /api/public/** 的匿名访问
.requestMatchers("/api/public/**").permitAll()
// 其他所有请求都需要认证
.anyRequest().authenticated()
)
// 禁用 CSRF因为现代前后端分离项目通常使用 Token
.csrf(AbstractHttpConfigurer::disable)
.exceptionHandling(e -> e
.authenticationEntryPoint(restAuthenticationEntryPoint)
.accessDeniedHandler(restfulAccessDeniedHandler))
;
return http.build();
}
}

View File

@@ -0,0 +1,28 @@
server:
port: 18888
spring:
application:
name: chaos-api
datasource:
driver-class-name: org.mariadb.jdbc.Driver
url: jdbc:mysql://10.91.3.23:3306/chaos?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&allowPublicKeyRetrieval=true&useSSL=false
username: chaos
password: zx123456..
type: com.alibaba.druid.pool.DruidDataSource
druid:
initial-size: 5
min-idle: 5
max-active: 20
max-wait: 60000
mybatis-plus:
mapper-locations: classpath*:/mapper/**/*.xml
type-aliases-package: cn.nopj.chaos_api_domain.entity
global-config:
db-config:
id-type: assign_id
configuration:
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

View File

@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
<RollingFile name="RollingFile"
fileName="logs/chaos-api.log"
filePattern="logs/chaos-api-%d{yyyy-MM-dd}-%i.log.gz">
<PatternLayout>
<Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n</Pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="10 MB"/>
</Policies>
<DefaultRolloverStrategy max="10"/>
</RollingFile>
</Appenders>
<Loggers>
<Logger name="org.springframework" level="info" additivity="false">
<AppenderRef ref="Console"/>
<AppenderRef ref="RollingFile"/>
</Logger>
<Logger name="cn.nopj" level="debug" additivity="false">
<AppenderRef ref="Console"/>
<AppenderRef ref="RollingFile"/>
</Logger>
<Root level="info">
<AppenderRef ref="Console"/>
<AppenderRef ref="RollingFile"/>
</Root>
</Loggers>
</Configuration>

26
pom.xml
View File

@@ -87,6 +87,32 @@
<artifactId>mybatis-plus</artifactId> <artifactId>mybatis-plus</artifactId>
<version>3.5.12</version> <version>3.5.12</version>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/druid-spring-boot-starter -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.25</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mariadb.jdbc/mariadb-java-client -->
<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
<version>3.5.4</version>
</dependency>
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.57</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.38</version>
</dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>
</project> </project>