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() { + } + +}