commit 8dc1824603583e04b9c61f8f49cd55d032e71d12
Author: ALEX <2604434353@qq.com>
Date: Tue Jul 15 11:37:42 2025 +0800
init full backend repo with src + deploy config
diff --git a/Jenkinsfile b/Jenkinsfile
new file mode 100644
index 0000000..42a9a3d
--- /dev/null
+++ b/Jenkinsfile
@@ -0,0 +1,33 @@
+pipeline {
+ agent any
+ environment {
+ SSH_CREDENTIALS_ID = 'alex-ssh-key'
+ REMOTE_HOST = '117.72.202.202'
+ REMOTE_USER = 'alex'
+ REMOTE_DIR = '/home/alex/alex-api'
+ }
+
+ stages {
+ stage('Build') {
+ steps {
+ sh 'mvn clean package -DskipTests'
+ }
+ }
+
+ stage('Deploy') {
+ steps {
+ sshagent([env.SSH_CREDENTIALS_ID]) {
+ sh """
+ scp target/alex-api-0.0.1-SNAPSHOT.jar ${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_DIR}/app/
+ ssh ${REMOTE_USER}@${REMOTE_HOST} '
+ cd ${REMOTE_DIR} &&
+ docker compose down &&
+ docker compose up -d --build
+ '
+ """
+ }
+ }
+ }
+ }
+}
+
diff --git a/app/Dockerfile b/app/Dockerfile
new file mode 100755
index 0000000..894c163
--- /dev/null
+++ b/app/Dockerfile
@@ -0,0 +1,12 @@
+# 使用轻量级 OpenJDK 运行环境作为基础镜像
+FROM openjdk:8-jdk
+# 作者信息(可选)
+LABEL maintainer="2604434353@qq.com"
+# 创建工作目录
+WORKDIR /app
+# 复制 jar 包到容器中
+COPY alex-api-0.0.1-SNAPSHOT.jar app.jar
+# 开放容器端口
+EXPOSE 8888
+# 启动命令
+ENTRYPOINT ["java", "-jar", "app.jar"]
diff --git a/app/alex-api-0.0.1-SNAPSHOT.jar b/app/alex-api-0.0.1-SNAPSHOT.jar
new file mode 100755
index 0000000..d66dfaf
Binary files /dev/null and b/app/alex-api-0.0.1-SNAPSHOT.jar differ
diff --git a/bin/post-steps.sh b/bin/post-steps.sh
new file mode 100755
index 0000000..7ea7259
--- /dev/null
+++ b/bin/post-steps.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+PORT=8888
+JAR_PATH="/home/alex/alex-api/app/alex-api-0.0.1-SNAPSHOT.jar"
+LOG_PATH="/home/alex/alex-api/logs/alex-api.log"
+
+# 检测端口是否被占用
+if netstat -tuln | grep -q ":$PORT"; then
+ echo "Port $PORT is already in use. Not starting application."
+ exit 0
+else
+ echo "Port $PORT is free. Starting application..."
+ nohup java -jar "$JAR_PATH" > "$LOG_PATH" 2>&1 &
+ echo "Application started with PID $!"
+fi
diff --git a/bin/pre-steps.sh b/bin/pre-steps.sh
new file mode 100755
index 0000000..b937659
--- /dev/null
+++ b/bin/pre-steps.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+pid=$(ps -ef | grep -w java | grep "alex-api-0.0.1-SNAPSHOT.jar" | grep -v grep | awk '{print $2}')
+
+echo "Found pid: $pid"
+
+if [ -z "$pid" ]; then
+ echo "Java application not running."
+else
+ sudo kill -9 $pid
+ echo "Java application (pid: $pid) stopping..."
+ sleep 2
+fi
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100755
index 0000000..6b388a7
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,70 @@
+name: alex-api-docker
+services:
+ mysql:
+ image: mysql:8.0
+ container_name: mysql
+ restart: always
+ environment:
+ MYSQL_ROOT_PASSWORD: ALEXzcz123456
+ MYSQL_DATABASE: test_alex
+ MYSQL_USER: alex
+ MYSQL_PASSWORD: ALEXzcz123456
+ ports:
+ - "3306:3306"
+ volumes:
+ - mysql-data:/var/lib/mysql
+ networks:
+ - alex-bridge-network
+
+ redis:
+ image: redis:6
+ container_name: redis
+ command: redis-server --requirepass "ALEXzcz123456"
+ ports:
+ - "6379:6379"
+ volumes:
+ - redis-data:/data
+ networks:
+ - alex-bridge-network
+
+ alex-api:
+ build:
+ context: /home/alex/alex-api/app
+ dockerfile: Dockerfile
+ image: alex-api-image
+ container_name: alex-api
+ restart: always
+ depends_on:
+ - mysql
+ - redis
+ ports:
+ - "8888:8888"
+ networks:
+ - alex-bridge-network
+
+ nginx:
+ image: nginx:latest
+ container_name: nginx
+ restart: always
+ ports:
+ - "80:80"
+ volumes:
+ - /etc/nginx/conf.d/alex-ui.conf:/etc/nginx/conf.d/alex-ui.conf
+ - /var/www/alex-ui:/var/www/alex-ui
+ - /var/log/nginx:/var/log/nginx
+ depends_on:
+ - alex-api
+ networks:
+ - alex-bridge-network
+
+# 声明命名数据卷
+volumes:
+ mysql-data:
+ external: true # 使用已有的 mysql-data 卷,不创建新卷
+ redis-data:
+ external: true
+
+# 创建自定义网络
+networks:
+ alex-bridge-network:
+ driver: bridge
diff --git a/logs/alex-api.log b/logs/alex-api.log
new file mode 100644
index 0000000..2ec3645
--- /dev/null
+++ b/logs/alex-api.log
@@ -0,0 +1,45 @@
+
+ . ____ _ __ _ _
+ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
+( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
+ \\/ ___)| |_)| | | | | || (_| | ) ) ) )
+ ' |____| .__|_| |_|_| |_\__, | / / / /
+ =========|_|==============|___/=/_/_/_/
+ :: Spring Boot :: (v2.6.13)
+
+2025-07-15 09:34:11.450 INFO 2719370 --- [ main] com.ctgu.alexapi.AlexApiApplication : Starting AlexApiApplication using Java 17.0.15 on server with PID 2719370 (/home/alex/alex-api/app/alex-api-0.0.1-SNAPSHOT.jar started by alex in /home/alex)
+2025-07-15 09:34:11.452 INFO 2719370 --- [ main] com.ctgu.alexapi.AlexApiApplication : The following 1 profile is active: "dev"
+2025-07-15 09:34:12.544 INFO 2719370 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Multiple Spring Data modules found, entering strict repository configuration mode
+2025-07-15 09:34:12.547 INFO 2719370 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data Redis repositories in DEFAULT mode.
+2025-07-15 09:34:12.590 INFO 2719370 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 20 ms. Found 0 Redis repository interfaces.
+2025-07-15 09:34:13.738 INFO 2719370 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8888 (http)
+2025-07-15 09:34:13.770 INFO 2719370 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
+2025-07-15 09:34:13.770 INFO 2719370 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.68]
+2025-07-15 09:34:13.950 INFO 2719370 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
+2025-07-15 09:34:13.950 INFO 2719370 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 2362 ms
+ _ _ |_ _ _|_. ___ _ | _
+| | |\/|_)(_| | |_\ |_)||_|_\
+ / |
+ 3.5.1
+2025-07-15 09:34:16.185 INFO 2719370 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8888 (http) with context path ''
+2025-07-15 09:34:16.204 INFO 2719370 --- [ main] com.ctgu.alexapi.AlexApiApplication : Started AlexApiApplication in 5.761 seconds (JVM running for 6.61)
+2025-07-15 09:45:02.685 INFO 2719370 --- [0.0-8888-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
+2025-07-15 09:45:02.686 INFO 2719370 --- [0.0-8888-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
+2025-07-15 09:45:02.687 INFO 2719370 --- [0.0-8888-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 1 ms
+2025-07-15 09:45:02.907 INFO 2719370 --- [0.0-8888-exec-1] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
+2025-07-15 09:45:03.268 INFO 2719370 --- [0.0-8888-exec-1] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
+2025-07-15 10:55:24.202 INFO 2719370 --- [0.0-8888-exec-3] o.apache.coyote.http11.Http11Processor : Error parsing HTTP request header
+ Note: further occurrences of HTTP request parsing errors will be logged at DEBUG level.
+
+java.lang.IllegalArgumentException: Invalid character found in method name [0x030x000x00/*0xe00x000x000x000x000x00Cookie: ]. HTTP method names must be tokens
+ at org.apache.coyote.http11.Http11InputBuffer.parseRequestLine(Http11InputBuffer.java:419) ~[tomcat-embed-core-9.0.68.jar!/:na]
+ at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:271) ~[tomcat-embed-core-9.0.68.jar!/:na]
+ at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.68.jar!/:na]
+ at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893) ~[tomcat-embed-core-9.0.68.jar!/:na]
+ at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1789) ~[tomcat-embed-core-9.0.68.jar!/:na]
+ at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.68.jar!/:na]
+ at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-embed-core-9.0.68.jar!/:na]
+ at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-9.0.68.jar!/:na]
+ at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.68.jar!/:na]
+ at java.base/java.lang.Thread.run(Thread.java:840) ~[na:na]
+
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..6a75b63
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,133 @@
+
+
+ 4.0.0
+ com.ctgu
+ alex-api
+ 0.0.1-SNAPSHOT
+ alex-api
+ alex-api
+
+ 1.8
+ UTF-8
+ UTF-8
+ 2.6.13
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ com.mysql
+ mysql-connector-j
+ runtime
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+ com.github.pagehelper
+ pagehelper-spring-boot-starter
+ 2.1.0
+
+
+
+ org.apache.logging.log4j
+ log4j-core
+ 2.19.0
+
+
+
+ org.apache.logging.log4j
+ log4j-slf4j2-impl
+ 2.19.0
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+ 2.7.6
+
+
+
+ org.mybatis.spring.boot
+ mybatis-spring-boot-starter
+ 2.3.0
+
+
+
+ org.springframework.boot
+ spring-boot-devtools
+ true
+
+
+ com.baomidou
+ mybatis-plus-boot-starter
+ 3.5.1
+
+
+ com.baomidou
+ mybatis-plus-generator
+ 3.5.1
+
+
+ com.google.code.gson
+ gson
+ 2.10.1
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-dependencies
+ ${spring-boot.version}
+ pom
+ import
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.8.1
+
+ 1.8
+ 1.8
+ UTF-8
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+ ${spring-boot.version}
+
+ com.ctgu.alexapi.AlexApiApplication
+
+
+
+
+ repackage
+
+ repackage
+
+
+
+
+
+
+
+
diff --git a/src/main/java/com/ctgu/alexapi/AlexApiApplication.java b/src/main/java/com/ctgu/alexapi/AlexApiApplication.java
new file mode 100644
index 0000000..c93cca9
--- /dev/null
+++ b/src/main/java/com/ctgu/alexapi/AlexApiApplication.java
@@ -0,0 +1,15 @@
+package com.ctgu.alexapi;
+
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+@MapperScan("com.ctgu.alexapi.mapper")
+public class AlexApiApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(AlexApiApplication.class, args);
+ }
+
+}
diff --git a/src/main/java/com/ctgu/alexapi/config/RedisConfig.java b/src/main/java/com/ctgu/alexapi/config/RedisConfig.java
new file mode 100644
index 0000000..7a49a6c
--- /dev/null
+++ b/src/main/java/com/ctgu/alexapi/config/RedisConfig.java
@@ -0,0 +1,42 @@
+package com.ctgu.alexapi.config;
+
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
+import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+
+@Configuration
+public class RedisConfig {
+
+ @Bean
+ public RedisConnectionFactory redisConnectionFactory(RedisProperties redisProperties) {
+ RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
+ config.setHostName(redisProperties.getHost());
+ config.setPort(redisProperties.getPort());
+ config.setPassword(redisProperties.getPassword());
+ config.setDatabase(0);
+ return new LettuceConnectionFactory(config);
+ }
+
+ @Bean(name = "redisTemplate")
+ public RedisTemplate redisTemplate(
+ @Qualifier("redisConnectionFactory")RedisConnectionFactory redisConnectionFactory
+ ) {
+ // 创建 RedisTemplate 对象
+ RedisTemplate redisTemplate = new RedisTemplate<>();
+ redisTemplate.setConnectionFactory(redisConnectionFactory);
+
+ // 设置默认的序列化器(String 类型)
+ redisTemplate.setKeySerializer(new StringRedisSerializer());
+ redisTemplate.setHashKeySerializer(new StringRedisSerializer());
+ redisTemplate.setValueSerializer(new StringRedisSerializer());
+ redisTemplate.setHashValueSerializer(new StringRedisSerializer());
+
+ return redisTemplate;
+ }
+}
diff --git a/src/main/java/com/ctgu/alexapi/controller/UsersController.java b/src/main/java/com/ctgu/alexapi/controller/UsersController.java
new file mode 100644
index 0000000..b12637a
--- /dev/null
+++ b/src/main/java/com/ctgu/alexapi/controller/UsersController.java
@@ -0,0 +1,36 @@
+package com.ctgu.alexapi.controller;
+
+import com.ctgu.alexapi.service.UsersService;
+import com.ctgu.alexapi.utils.ApiResult;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * @ClassName UserController
+ * @Author Alex2
+ * @Date 2025/7/2 14:43
+ **/
+@RestController
+@RequestMapping("/api/users")
+public class UsersController {
+ private final UsersService usersService;
+
+ @Autowired
+ public UsersController(UsersService usersService) {
+ this.usersService = usersService;
+ }
+
+ // http://localhost:8888/api/users/getAllUser?pageNum=1&pageSize=10
+ @GetMapping("/getAllUser")
+ public ApiResult getAllUser(
+ @RequestParam(value = "pageNum", defaultValue = "0", required = false) Integer pageNum,
+ @RequestParam(value = "pageSize", defaultValue = "10", required = false) Integer pageSize) {
+ return usersService.getAllUser(pageNum, pageSize);
+ }
+
+ // http://localhost:8888/api/users/1
+ @GetMapping("/{id}")
+ public ApiResult getUserById(@PathVariable("id") Integer id) {
+ return usersService.getUserById(id);
+ }
+}
diff --git a/src/main/java/com/ctgu/alexapi/entity/UsersEntity.java b/src/main/java/com/ctgu/alexapi/entity/UsersEntity.java
new file mode 100644
index 0000000..93c88a9
--- /dev/null
+++ b/src/main/java/com/ctgu/alexapi/entity/UsersEntity.java
@@ -0,0 +1,37 @@
+package com.ctgu.alexapi.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import lombok.Data;
+
+/**
+ *
+ * @TableName t_users
+ */
+@TableName(value ="t_users")
+@Data
+public class UsersEntity implements Serializable {
+ /**
+ * 主键
+ */
+ @TableId(value = "id", type = IdType.AUTO)
+ private Integer id;
+
+ /**
+ * 用户名
+ */
+ @TableField(value = "username")
+ private String username;
+
+ /**
+ * 密码
+ */
+ @TableField(value = "password")
+ private String password;
+
+ @TableField(exist = false)
+ private static final long serialVersionUID = 1L;
+}
\ No newline at end of file
diff --git a/src/main/java/com/ctgu/alexapi/mapper/UsersMapper.java b/src/main/java/com/ctgu/alexapi/mapper/UsersMapper.java
new file mode 100644
index 0000000..d475e7c
--- /dev/null
+++ b/src/main/java/com/ctgu/alexapi/mapper/UsersMapper.java
@@ -0,0 +1,18 @@
+package com.ctgu.alexapi.mapper;
+
+import com.ctgu.alexapi.entity.UsersEntity;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+* @author Alex2
+* @description 针对表【t_users】的数据库操作Mapper
+* @createDate 2025-07-02 14:37:56
+* @Entity com.ctgu.alexapi.entity.UsersEntity
+*/
+public interface UsersMapper extends BaseMapper {
+
+}
+
+
+
+
diff --git a/src/main/java/com/ctgu/alexapi/service/UsersService.java b/src/main/java/com/ctgu/alexapi/service/UsersService.java
new file mode 100644
index 0000000..7fe9695
--- /dev/null
+++ b/src/main/java/com/ctgu/alexapi/service/UsersService.java
@@ -0,0 +1,17 @@
+package com.ctgu.alexapi.service;
+
+import com.ctgu.alexapi.entity.UsersEntity;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ctgu.alexapi.utils.ApiResult;
+
+/**
+* @author Alex2
+* @description 针对表【t_users】的数据库操作Service
+* @createDate 2025-07-02 14:37:56
+*/
+public interface UsersService extends IService {
+
+ ApiResult getAllUser(Integer pageNum, Integer pageSize);
+
+ ApiResult getUserById(Integer id);
+}
diff --git a/src/main/java/com/ctgu/alexapi/service/impl/UsersServiceImpl.java b/src/main/java/com/ctgu/alexapi/service/impl/UsersServiceImpl.java
new file mode 100644
index 0000000..7443e13
--- /dev/null
+++ b/src/main/java/com/ctgu/alexapi/service/impl/UsersServiceImpl.java
@@ -0,0 +1,71 @@
+package com.ctgu.alexapi.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ctgu.alexapi.entity.UsersEntity;
+import com.ctgu.alexapi.service.UsersService;
+import com.ctgu.alexapi.mapper.UsersMapper;
+import com.ctgu.alexapi.utils.ApiResult;
+import com.ctgu.alexapi.utils.Tools;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import com.google.gson.Gson;
+import lombok.extern.log4j.Log4j2;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/**
+* @author Alex2
+* @description 针对表【t_users】的数据库操作Service实现
+* @createDate 2025-07-02 14:37:56
+*/
+@Log4j2
+@Service
+public class UsersServiceImpl extends ServiceImpl
+ implements UsersService{
+
+ private static final String TAG = UsersServiceImpl.class.getSimpleName();
+
+ @Autowired
+ private StringRedisTemplate redisTemplate;
+
+ private static final String USER_CACHE_PREFIX = "user:";
+
+ @Override
+ public ApiResult getAllUser(Integer pageNum, Integer pageSize) {
+ PageHelper.startPage(pageNum, pageSize);
+ List list = query().list();
+ PageInfo pageInfo = new PageInfo<>(list, 5);
+ return Tools.pageHelperResult(list, pageInfo, TAG);
+ }
+
+ @Override
+ public ApiResult getUserById(Integer userId) {
+ String key = USER_CACHE_PREFIX + userId;
+ // 1. 先从 Redis 取缓存
+ String cachedUserJson = redisTemplate.opsForValue().get(key);
+ if (cachedUserJson != null) {
+ // 有缓存,反序列化后返回
+ UsersEntity cachedUser = new Gson().fromJson(cachedUserJson, UsersEntity.class);
+ log.debug("{}: 从缓存获取用户成功 = {}", TAG, cachedUser);
+ return ApiResult.success("获取用户成功(缓存)", cachedUser);
+ }
+
+ // 2. 缓存没命中,从数据库查
+ UsersEntity usersEntity = lambdaQuery().eq(UsersEntity::getId, userId).one();
+ if (usersEntity == null) {
+ log.error("{}: 用户 Id = {} 不存在", TAG, userId);
+ return ApiResult.error("用户不存在");
+ }
+
+ // 3. 查到后写入缓存,设置过期时间,比如10分钟
+ String userJson = new Gson().toJson(usersEntity);
+ redisTemplate.opsForValue().set(key, userJson, 10, TimeUnit.MINUTES);
+
+ log.debug("{}: 获取用户成功 = {}", TAG, usersEntity);
+ return ApiResult.success("获取用户成功", usersEntity);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/ctgu/alexapi/utils/ApiResult.java b/src/main/java/com/ctgu/alexapi/utils/ApiResult.java
new file mode 100644
index 0000000..4050f6e
--- /dev/null
+++ b/src/main/java/com/ctgu/alexapi/utils/ApiResult.java
@@ -0,0 +1,100 @@
+package com.ctgu.alexapi.utils;
+
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.util.Optional;
+
+@Data
+@Builder
+@NoArgsConstructor
+public class ApiResult implements Serializable {
+
+ private static final long serialVersionUID = -8440958610795020343L;
+
+ public static final int CODE_SUCCESS = 200;
+ public static final int CODE_ERROR = 500;
+ public static final int CODE_WARNING = 501;
+ public static final int CODE_NOT_PERMISSION = 403;
+ public static final int CODE_NOE_LOGIN = 401;
+ public static final int CODE_INVALID_REQUEST = 400;
+
+ private int code;
+ private String msg;
+ private Object data;
+
+ // 构造方法
+ public ApiResult(int code, String msg, Object data) {
+ this.code = code;
+ this.msg = msg;
+ this.data = data;
+ }
+
+ // 静态构造方法
+ public static ApiResult success() {
+ return new ApiResult(CODE_SUCCESS, null, null);
+ }
+
+ public static ApiResult success(String msg) {
+ return new ApiResult(CODE_SUCCESS, msg, null);
+ }
+
+ public static ApiResult success(String msg, Object data) {
+ return new ApiResult(CODE_SUCCESS, msg, data);
+ }
+
+ public static ApiResult success(Object data) {
+ return new ApiResult(CODE_SUCCESS, null, data);
+ }
+
+ public static ApiResult error() {
+ return new ApiResult(CODE_ERROR, "出错了", null);
+ }
+
+ public static ApiResult error(String msg) {
+ return new ApiResult(CODE_ERROR, msg, null);
+ }
+
+ public static ApiResult error(String msg, Object data) {
+ return new ApiResult(CODE_ERROR, msg, data);
+ }
+
+ public static ApiResult notLogin() {
+ return new ApiResult(CODE_NOE_LOGIN, "未登录,请先进行登录", null);
+ }
+
+ public static ApiResult noPermissions() {
+ return new ApiResult(CODE_NOT_PERMISSION, "权限不足", null);
+ }
+
+ public static ApiResult build(int code, String msg) {
+ return new ApiResult(code, msg, null);
+ }
+
+ public static ApiResult getByBoolean(boolean b) {
+ return b ? success() : error();
+ }
+
+ public static ApiResult warning(String msg, Object data) {
+ return new ApiResult(CODE_WARNING, msg, data);
+ }
+
+ public static ApiResult warning(String msg) {
+ return new ApiResult(CODE_WARNING, msg, null);
+ }
+
+ public Optional getData(Class clazz) {
+ return Optional.ofNullable(clazz.cast(data));
+ }
+
+ @Override
+ public String toString() {
+ return "ApiResult{" +
+ "code=" + code +
+ ", msg='" + msg + '\'' +
+ ", data=" + (data != null ? data.toString() : "null") +
+ '}';
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/ctgu/alexapi/utils/PageData.java b/src/main/java/com/ctgu/alexapi/utils/PageData.java
new file mode 100644
index 0000000..67b06e0
--- /dev/null
+++ b/src/main/java/com/ctgu/alexapi/utils/PageData.java
@@ -0,0 +1,16 @@
+package com.ctgu.alexapi.utils;
+
+import lombok.Builder;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+@Builder
+public class PageData {
+ private Long totalNum; //总条数
+
+ private Integer totalPage; //总页数
+
+ private List data; //数据
+}
\ No newline at end of file
diff --git a/src/main/java/com/ctgu/alexapi/utils/Tools.java b/src/main/java/com/ctgu/alexapi/utils/Tools.java
new file mode 100644
index 0000000..cadb772
--- /dev/null
+++ b/src/main/java/com/ctgu/alexapi/utils/Tools.java
@@ -0,0 +1,46 @@
+package com.ctgu.alexapi.utils;
+
+import com.github.pagehelper.PageInfo;
+import lombok.extern.log4j.Log4j2;
+
+import java.util.Collections;
+import java.util.List;
+
+@Log4j2
+public class Tools {
+ public static ApiResult pageHelperResult(List list, PageInfo pageInfo, String TAG) {
+ if (list.isEmpty()) {
+ log.debug("{} : 获取列表为空 = {}", TAG, Collections.emptyList());
+ return ApiResult.success("获取列表为空", Collections.emptyList());
+ }
+ PageData.PageDataBuilder builder = PageData.builder();
+ log.debug("{} : 获取列表成功 = {}", TAG, list);
+ return ApiResult.success("获取列表成功", builder
+ .totalNum(pageInfo.getTotal())
+ .totalPage(pageInfo.getPages())
+ .data(list)
+ .build());
+ }
+
+ /**
+ * @Author: Alex
+ * @Description: 获取图片MD5
+ */
+ public static String getMd5(String url) {
+ if (url.contains("aliyuncs.com")) {
+ int lastSlash = url.lastIndexOf('/');
+ int lastDot = url.lastIndexOf('.');
+ if (lastSlash != -1 && lastDot != -1 && lastDot > lastSlash) {
+ return url.substring(lastSlash + 1, lastDot);
+ }
+ } else if (url.contains("/image/")) {
+ int startIndex = url.lastIndexOf("/image/") + "/image/".length();
+ int endIndex = url.indexOf("?", startIndex);
+ if (endIndex == -1) {
+ endIndex = url.length();
+ }
+ return url.substring(startIndex, endIndex);
+ }
+ return null;
+ }
+}
diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml
new file mode 100644
index 0000000..5e58b5a
--- /dev/null
+++ b/src/main/resources/application-dev.yml
@@ -0,0 +1,12 @@
+spring:
+ datasource:
+ type: com.zaxxer.hikari.HikariDataSource
+ driver-class-name: com.mysql.cj.jdbc.Driver
+ url: jdbc:mysql://localhost:3306/test_alex?characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true
+ username: root
+ password: ALEXzcz123456
+ redis:
+ host: localhost
+ password: ALEXzcz123456
+ port: 6379
+ database: 0
\ No newline at end of file
diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml
new file mode 100644
index 0000000..674c874
--- /dev/null
+++ b/src/main/resources/application-prod.yml
@@ -0,0 +1,12 @@
+spring:
+ datasource:
+ type: com.zaxxer.hikari.HikariDataSource
+ driver-class-name: com.mysql.cj.jdbc.Driver
+ url: jdbc:mysql://117.72.202.202:3306/test_alex?characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true
+ username: alex
+ password: ALEXzcz123456
+ redis:
+ host: 117.72.202.202
+ password: ALEXzcz123456
+ port: 6379
+ database: 0
\ No newline at end of file
diff --git a/src/main/resources/application-test.yml b/src/main/resources/application-test.yml
new file mode 100644
index 0000000..25e6375
--- /dev/null
+++ b/src/main/resources/application-test.yml
@@ -0,0 +1,12 @@
+spring:
+ datasource:
+ type: com.zaxxer.hikari.HikariDataSource
+ driver-class-name: com.mysql.cj.jdbc.Driver
+ url: jdbc:mysql://117.72.202.202:3306/test_alex?characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true
+ username: alex
+ password: ALEXzcz123456
+ redis:
+ host: 117.72.202.202
+ password: ALEXzcz123456
+ port: 6379
+ database: 0
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
new file mode 100644
index 0000000..e8e145a
--- /dev/null
+++ b/src/main/resources/application.yml
@@ -0,0 +1,41 @@
+server:
+ address: 0.0.0.0
+ port: 8888
+spring:
+ profiles:
+ active: dev # 默认激活开发环境
+#配置mybatis
+mybatis:
+ configuration:
+ auto-mapping-behavior: full
+ map-underscore-to-camel-case: true
+ log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl
+ type-aliases-package: com.anytrek.entity # 配置别名路径
+ mapper-locations: classpath:mapper/*.xml # 配置 XML 文件位置
+#配置mybatis-plus
+mybatis-plus:
+ configuration:
+ log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl
+ global-config:
+ db-config:
+ table-prefix: t_
+ id-type: auto
+#配置分页插件
+pagehelper:
+ helperDialect: mysql
+ params: count=countSql
+ reasonable: true
+ supportMethodsArguments: true
+#配置日志
+logging:
+ level:
+ root: INFO #根日志配置,整个应用程序的默认日志级别为 INFO
+ com.anytrek: DEBUG #com.anytrek 包下的类的日志级别设置为 DEBUG
+ org.apache.ibatis: INFO #MyBatis 日志级别设置为 INFO
+ com.zaxxer.hikari: INFO #HikariCP 的日志级别设置为 INFO
+ org.springframework.web.socket: DEBUG
+ org.springframework.web.socket.server.support: DEBUG
+ org:
+ springframework:
+ integration: DEBUG
+ messaging: DEBUG
\ No newline at end of file
diff --git a/src/main/resources/mapper/UsersMapper.xml b/src/main/resources/mapper/UsersMapper.xml
new file mode 100644
index 0000000..6de296e
--- /dev/null
+++ b/src/main/resources/mapper/UsersMapper.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+ id,username,password
+
+
diff --git a/src/test/java/com/ctgu/alexapi/AlexApiApplicationTests.java b/src/test/java/com/ctgu/alexapi/AlexApiApplicationTests.java
new file mode 100644
index 0000000..285e7bf
--- /dev/null
+++ b/src/test/java/com/ctgu/alexapi/AlexApiApplicationTests.java
@@ -0,0 +1,13 @@
+package com.ctgu.alexapi;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class AlexApiApplicationTests {
+
+ @Test
+ void contextLoads() {
+ }
+
+}