添加了dockerfile,完成了refreshToken接口

Change-Id: I25885613a8e8c08e1e4a6216368b5b083af67817
diff --git a/dockerfile b/dockerfile
new file mode 100644
index 0000000..a4af905
--- /dev/null
+++ b/dockerfile
@@ -0,0 +1,26 @@
+################################################################################
+# Stage 1:使用 Maven 镜像编译 Spring Boot 项目
+################################################################################
+FROM maven:3.9.4-eclipse-temurin-17 AS build
+
+WORKDIR /app
+
+COPY pom.xml .
+RUN mvn dependency:go-offline -B
+
+COPY src ./src
+
+RUN mvn clean package -DskipTests
+
+################################################################################
+# Stage 2:运行时镜像
+################################################################################
+FROM eclipse-temurin:17-jdk-jammy
+
+WORKDIR /app
+
+COPY --from=build /app/target/*.jar app.jar
+
+EXPOSE 8080
+
+ENTRYPOINT ["java", "-jar", "app.jar"]
diff --git a/src/main/java/edu/bjtu/groupone/backend/api/UserController.java b/src/main/java/edu/bjtu/groupone/backend/api/UserController.java
index d510cee..46fb153 100644
--- a/src/main/java/edu/bjtu/groupone/backend/api/UserController.java
+++ b/src/main/java/edu/bjtu/groupone/backend/api/UserController.java
@@ -7,6 +7,8 @@
 import edu.bjtu.groupone.backend.utils.JwtUtils;
 import edu.bjtu.groupone.backend.domain.entity.Result;
 
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.ExpiredJwtException;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Parameter;
 import io.swagger.v3.oas.annotations.enums.ParameterIn;
@@ -318,4 +320,73 @@
     public Result<List<User>> getAllUsers() {
         return Result.success(userService.getAllUsers());
     }
+
+    /**
+     * 刷新 Token
+     */
+    @Operation(
+            summary = "刷新 JWT Token",
+            description = "客户端调用此接口提供旧的 JWT(可能已过期)," +
+                    "服务端会校验旧 token:如果仅仅是过期,则从中取出 Claims 并重新签发;" +
+                    "如果签名无效或格式错误,则返回 401。",
+            parameters = {
+                    @Parameter(
+                            in = ParameterIn.HEADER,
+                            name = "token",
+                            description = "旧的 JWT(在请求头中携带,即使已过期也可以)",
+                            required = true,
+                            schema = @Schema(type = "string", example = "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJ1c2VyMSIsImVtYWlsIjoidXNlcjFAZXhhbXBsZS5jb20iLCJpYXQiOjE2NTAwMDAwMDAsImV4cCI6MTY1MDAwMTIwMH0.XYZxyzXYZxyzXYZxyzXYZxyzXYZxyzXYZxyz")
+                    )
+            },
+            responses = {
+                    @ApiResponse(
+                            responseCode = "200",
+                            description = "刷新成功,返回新的 JWT",
+                            content = @Content(
+                                    schema = @Schema(implementation = Result.class),
+                                    examples = @ExampleObject(
+                                            name = "刷新成功示例",
+                                            value = "{\"code\":200,\"message\":\"操作成功\",\"data\":\"eyJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJ1c2VyMSIsImVtYWlsIjoidXNlcjFAZXhhbXBsZS5jb20iLCJpYXQiOjE2NTAwMDAwMDAsImV4cCI6MTY1MDAwMjAwMH0.ABCabcABCabcABCabcABCabcABCabcABCabc\"}"
+                                    )
+                            )
+                    ),
+                    @ApiResponse(
+                            responseCode = "401",
+                            description = "无效的 token(签名错误或格式不对)",
+                            content = @Content(
+                                    schema = @Schema(implementation = Result.class),
+                                    examples = @ExampleObject(
+                                            name = "签名错误示例",
+                                            value = "{\"code\":401,\"message\":\"无效的 token\",\"data\":null}"
+                                    )
+                            )
+                    )
+            }
+    )
+    @PostMapping("/refreshToken")
+    public Result<String> refreshToken(
+            @Parameter(in = ParameterIn.HEADER, description = "旧的 JWT 令牌", required = true)
+            @RequestHeader("token") String oldToken
+    ) {
+        Claims claims;
+        try {
+            // 尝试解析;如果尚未过期,parseJwt 会返回 Claims
+            claims = JwtUtils.parseJwt(oldToken);
+        } catch (ExpiredJwtException ex) {
+            // 如果已过期,则从异常中获取过期前的 Claims
+            claims = ex.getClaims();
+        } catch (Exception ex) {
+            // 其它解析错误(签名无效等)
+            return Result.error("无效的 token");
+        }
+
+        // 从原有的 Claims 中提取用户信息,重新生成新的 token
+        var payload = java.util.Map.<String, Object>of(
+                "id", claims.get("id"),
+                "username", claims.get("username"),
+                "email", claims.get("email")
+        );
+        String newToken = JwtUtils.generateJwt(payload);
+        return Result.success(newToken);
+    }
 }
\ No newline at end of file
diff --git a/src/main/java/edu/bjtu/groupone/backend/utils/JwtUtils.java b/src/main/java/edu/bjtu/groupone/backend/utils/JwtUtils.java
index 65e917a..45e736b 100644
--- a/src/main/java/edu/bjtu/groupone/backend/utils/JwtUtils.java
+++ b/src/main/java/edu/bjtu/groupone/backend/utils/JwtUtils.java
@@ -8,6 +8,8 @@
 
 public class JwtUtils {
 
+
+
     // 生成JWT// 生成JWT
     public static String generateJwt(Map<String,Object> claims) {
 
@@ -31,4 +33,4 @@
                 .getBody();
     }
 
-}
+}
\ No newline at end of file