diff --git a/test05/USER_ROLE_GUIDE.md b/test05/USER_ROLE_GUIDE.md
new file mode 100644
index 0000000..33cd103
--- /dev/null
+++ b/test05/USER_ROLE_GUIDE.md
@@ -0,0 +1,130 @@
+# 用户角色访问控制指南
+
+## 用户名格式规则
+
+- **管理员**: `a_<姓名>` (例如: `a_admin`, `a_zhangsan`)
+- **老师**: `t_<姓名>` (例如: `t_teacher`, `t_lisi`)
+- **学生**: `s_<姓名>` (例如: `s_student`, `s_wangwu`)
+
+## 权限说明
+
+### 管理员权限
+- 可以访问所有API端点
+- 可以创建老师用户
+- 可以创建学生用户
+- 可以创建管理员用户
+
+### 老师权限
+- 可以访问老师端API (`/teacherAction/**`)
+- 可以访问学生端API (`/studentAction/**`)
+- 可以创建学生用户
+- 不能创建老师或管理员用户
+
+### 学生权限
+- 只能访问学生端API (`/studentAction/**`)
+- 不能创建任何用户
+
+## API端点
+
+### 用户管理API (`/userManagementAction/**`)
+
+#### 创建老师用户
+```
+POST /userManagementAction/createTeacher
+参数: username, password
+权限: 仅管理员
+```
+
+#### 创建学生用户
+```
+POST /userManagementAction/createStudent
+参数: username, password
+权限: 管理员和老师
+```
+
+#### 创建管理员用户
+```
+POST /userManagementAction/createAdmin
+参数: username, password
+权限: 仅管理员
+```
+
+### 课程管理API示例 (`/courseAction/**`)
+
+#### 选课API (学生端)
+```
+POST /courseAction/selectCourse
+参数: courseId
+权限: 学生
+状态: 待实现
+```
+
+#### 创建课程API (老师端)
+```
+POST /courseAction/createCourse
+参数: courseName, courseDescription
+权限: 老师
+状态: 待实现
+```
+
+#### 获取课程列表
+```
+GET /courseAction/getCourses
+参数: page, pageSize
+权限: 所有用户
+状态: 待实现
+```
+
+## 使用示例
+
+### 1. 管理员登录
+```bash
+# 假设已存在管理员用户 a_admin
+POST /userAction/login
+{
+ "username": "a_admin",
+ "password": "password"
+}
+```
+
+### 2. 管理员创建老师用户
+```bash
+POST /userManagementAction/createTeacher
+Headers: token: <登录返回的JWT>
+{
+ "username": "t_zhangsan",
+ "password": "password123"
+}
+```
+
+### 3. 老师创建学生用户
+```bash
+POST /userManagementAction/createStudent
+Headers: token: <老师登录返回的JWT>
+{
+ "username": "s_lisi",
+ "password": "password123"
+}
+```
+
+## 注意事项
+
+1. 所有API调用都需要在请求头中包含有效的JWT token
+2. 用户名必须严格按照格式要求,否则会被拒绝
+3. 拦截器会自动验证用户角色权限
+4. 课程相关API目前只是空实现,需要创建相应的数据库表后才能完成功能
+
+## 数据库表需求
+
+为了完整实现课程功能,需要创建以下表:
+
+1. **课程表** (courses)
+ - id, course_name, course_description, teacher_id, create_time, etc.
+
+2. **选课表** (student_courses)
+ - id, student_id, course_id, select_time, etc.
+
+3. **课程老师映射表** (如果需要多对多关系)
+ - id, course_id, teacher_id, etc.
+
+这些表创建后,就可以完成课程管理API的具体实现了。
\ No newline at end of file
diff --git a/test05/pom.xml b/test05/pom.xml
index dadd0ae..4f1336d 100644
--- a/test05/pom.xml
+++ b/test05/pom.xml
@@ -1,148 +1,231 @@
-
4.0.0
+
+
org.springframework.boot
spring-boot-starter-parent
- 3.4.0
-
+ 3.5.0
+
+
+
top.awin-x
test05
0.0.1-SNAPSHOT
test05
- test05
-
+ Test project for Spring Boot (JDK 25)
+ https://github.com/awin-x/test05
+
+
-
+
+ Apache License, Version 2.0
+ http://www.apache.org/licenses/LICENSE-2.0.txt
+ repo
+
+
+
-
+
+ awin-x
+ awin-x
+ awin-x@example.com
+
+ Developer
+
+ +8
+
+
+
-
-
-
-
+ scm:git:https://github.com/awin-x/test05.git
+ scm:git:git@github.com:awin-x/test05.git
+ https://github.com/awin-x/test05
+ HEAD
+
+
- 21
+ 25
+ UTF-8
+ UTF-8
+
+
+ 3.0.4
+ 1.2.24
+ 3.46.1.0
+ 8.4.0
+ 0.12.6
+ 2.0.53
+ 1.18.38
-
-
-
-
+
org.springframework.boot
spring-boot-starter-web
+
org.mybatis.spring.boot
mybatis-spring-boot-starter
- 3.0.4
+ ${mybatis-spring-boot.version}
+
+
+ com.alibaba
+ druid-spring-boot-3-starter
+ ${druid.version}
+
+
+
+
+ org.xerial
+ sqlite-jdbc
+ ${sqlite-jdbc.version}
+
+
+
+
+ com.mysql
+ mysql-connector-j
+ ${mysql-connector.version}
+ runtime
+
+
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+ true
+
+
+
+
+ io.jsonwebtoken
+ jjwt
+ ${jjwt.version}
+
+
+
+
+ com.alibaba.fastjson2
+ fastjson2
+ ${fastjson2.version}
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-aop
+
+
+
org.springframework.boot
spring-boot-starter-test
test
+
org.mybatis.spring.boot
mybatis-spring-boot-starter-test
- 3.0.4
+ ${mybatis-spring-boot.version}
test
-
-
- com.alibaba
- druid-spring-boot-3-starter
- 1.2.24
-
-
-
- org.xerial
- sqlite-jdbc
- 3.47.1.0
-
-
-
- mysql
- mysql-connector-java
- 8.0.33
-
-
-
- org.projectlombok
- lombok
- true
-
-
-
- io.jsonwebtoken
- jjwt
- 0.12.3
-
-
-
- com.alibaba.fastjson2
- fastjson2
- 2.0.53
-
-
- org.springframework.boot
- spring-boot-starter-aop
-
-
-
- org.realityforge.org.jetbrains.annotations
- org.jetbrains.annotations
- 1.7.0
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
org.springframework.boot
spring-boot-maven-plugin
+
+
+
+ dev
+
+
+
+
+ org.projectlombok
+ lombok
+
+
+
+
+
org.apache.maven.plugins
maven-compiler-plugin
- 3.11.0
+ 3.14.1
- 25
- 25
+ ${java.version}
+ ${java.version}
+ ${project.build.sourceEncoding}
+
org.projectlombok
lombok
- 1.18.24
+ ${lombok.version}
+
+
+
+ org.mybatis.spring.boot
+ mybatis-spring-boot-starter
+ ${mybatis-spring-boot.version}
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 3.3.1
+
+ false
+ false
+
+
+
+
diff --git a/test05/src/main/java/test05/config/WebConfig.java b/test05/src/main/java/test05/config/WebConfig.java
index 78fcf91..ac6b897 100644
--- a/test05/src/main/java/test05/config/WebConfig.java
+++ b/test05/src/main/java/test05/config/WebConfig.java
@@ -2,21 +2,59 @@ package test05.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
+import org.springframework.core.env.Environment;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import test05.interceptor.LoginCheckInterceptor;
+
+/**
+ * 配置类
+ */
@Configuration
public class WebConfig implements WebMvcConfigurer {
private final LoginCheckInterceptor loginCheckInterceptor;
+ private final Environment environment;
+ // 构造函数注入,登陆检查拦截器
@Autowired
- WebConfig(LoginCheckInterceptor loginCheckInterceptor){
+ WebConfig(LoginCheckInterceptor loginCheckInterceptor, Environment environment){
this.loginCheckInterceptor = loginCheckInterceptor;
+ this.environment = environment;
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
- registry.addInterceptor(loginCheckInterceptor).addPathPatterns("/*Action/**").excludePathPatterns("/userAction/login");
+ registry.addInterceptor(loginCheckInterceptor)
+ .addPathPatterns("/*Action/**")
+ .excludePathPatterns("/userAction/login", "/userAction/logout");
+ }
+
+ @Override
+ public void addCorsMappings(org.springframework.web.servlet.config.annotation.CorsRegistry registry) {
+ // 仅在开发环境启用跨域
+ String[] activeProfiles = environment.getActiveProfiles();
+ boolean isDev = false;
+
+ if (activeProfiles.length == 0) {
+ // 如果没有指定profile,默认使用dev
+ isDev = true;
+ } else {
+ for (String profile : activeProfiles) {
+ if ("dev".equals(profile) || "development".equals(profile) || "test".equals(profile)) {
+ isDev = true;
+ break;
+ }
+ }
+ }
+
+ if (isDev) {
+ registry.addMapping("/**") // 允许所有路径
+ .allowedOriginPatterns("*") // 允许所有来源
+ .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") // 允许的HTTP方法
+ .allowedHeaders("*") // 允许所有请求头
+ .allowCredentials(true) // 允许发送cookie
+ .maxAge(3600); // 预检请求的有效期
+ }
}
}
diff --git a/test05/src/main/java/test05/controller/CourseManagementController.java b/test05/src/main/java/test05/controller/CourseManagementController.java
new file mode 100644
index 0000000..af1fa24
--- /dev/null
+++ b/test05/src/main/java/test05/controller/CourseManagementController.java
@@ -0,0 +1,63 @@
+package test05.controller;
+
+import jakarta.servlet.http.HttpServletRequest;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import test05.pojo.Result;
+
+/**
+ * 课程管理控制器 - 提供示例API
+ */
+@RestController
+@RequestMapping("/courseAction")
+public class CourseManagementController {
+
+ /**
+ * 选课API - 学生端API示例
+ * 注意:这是空实现,因为还没有选课表
+ */
+ @RequestMapping("/selectCourse")
+ public Result selectCourse(Integer courseId, HttpServletRequest request) {
+ // TODO: 实现选课功能
+ // 需要创建选课表和相关的映射关系表
+ return Result.success("选课功能待实现 - 课程ID: " + courseId);
+ }
+
+ /**
+ * 创建课程API - 老师端API示例
+ * 注意:这是空实现,因为还没有课程表和老师用户映射关系表
+ */
+ @RequestMapping("/createCourse")
+ public Result createCourse(String courseName, String courseDescription, HttpServletRequest request) {
+ // TODO: 实现创建课程功能
+ // 需要创建课程表和课程与老师的映射关系表
+ return Result.success("创建课程功能待实现 - 课程名称: " + courseName);
+ }
+
+ /**
+ * 获取课程列表API - 公共API示例
+ */
+ @RequestMapping("/getCourses")
+ public Result getCourses(Integer page, Integer pageSize) {
+ // TODO: 实现获取课程列表功能
+ return Result.success("获取课程列表功能待实现");
+ }
+
+ /**
+ * 删除课程API - 老师端API示例
+ */
+ @RequestMapping("/deleteCourse")
+ public Result deleteCourse(Integer courseId, HttpServletRequest request) {
+ // TODO: 实现删除课程功能
+ return Result.success("删除课程功能待实现 - 课程ID: " + courseId);
+ }
+
+ /**
+ * 更新课程API - 老师端API示例
+ */
+ @RequestMapping("/updateCourse")
+ public Result updateCourse(Integer courseId, String courseName, String courseDescription, HttpServletRequest request) {
+ // TODO: 实现更新课程功能
+ return Result.success("更新课程功能待实现 - 课程ID: " + courseId);
+ }
+}
\ No newline at end of file
diff --git a/test05/src/main/java/test05/controller/TeacherController.java b/test05/src/main/java/test05/controller/TeacherController.java
new file mode 100644
index 0000000..7a1a118
--- /dev/null
+++ b/test05/src/main/java/test05/controller/TeacherController.java
@@ -0,0 +1,56 @@
+package test05.controller;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import test05.pojo.Result;
+import test05.pojo.Teacher;
+import test05.service.TeacherService;
+
+@RestController
+@RequestMapping("/teacherAction")
+public class TeacherController {
+ private final TeacherService teacherService;
+ @Autowired
+ public TeacherController(TeacherService teacherService) {
+ this.teacherService = teacherService;
+ }
+
+ @RequestMapping("/get")
+ public Result get(Teacher teacher, Integer page, Integer pageSize) {
+ if (pageSize == null) {
+ pageSize = 10;
+ }
+ if (page == null) {
+ page = 1;
+ }
+ int offset = Math.max(0, (page - 1)) * pageSize;
+ return teacherService.getTeacher(teacher, offset, pageSize);
+ }
+
+ @RequestMapping("/add")
+ public Result add(Teacher teacher) {
+ if (teacher == null || teacher.getId() != -1) {
+ return Result.error("bad request");
+ }else{
+ return teacherService.addTeacher(teacher);
+ }
+ }
+
+ @RequestMapping("/edit")
+ public Result edit(Teacher teacher) {
+ if (teacher == null || teacher.getId() == -1) {
+ return Result.error("bad request");
+ }
+ return teacherService.updateTeacher(teacher);
+ }
+
+ @RequestMapping("/delete")
+ public Result delete(Teacher teacher) {
+ if (teacher == null || teacher.getId() <= 0) {
+ return Result.error("bad request");
+ }
+ return teacherService.deleteTeacher(teacher);
+ }
+}
diff --git a/test05/src/main/java/test05/controller/UserManagementController.java b/test05/src/main/java/test05/controller/UserManagementController.java
new file mode 100644
index 0000000..b271092
--- /dev/null
+++ b/test05/src/main/java/test05/controller/UserManagementController.java
@@ -0,0 +1,106 @@
+package test05.controller;
+
+import jakarta.servlet.http.HttpServletRequest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import test05.enums.UserRole;
+import test05.pojo.Result;
+import test05.pojo.User;
+import test05.service.UserService;
+import test05.utils.UserRoleUtils;
+
+/**
+ * 用户管理控制器 - 处理用户创建功能
+ */
+@RestController
+@RequestMapping("/userManagementAction")
+public class UserManagementController {
+ private final UserService userService;
+
+ @Autowired
+ public UserManagementController(UserService userService) {
+ this.userService = userService;
+ }
+
+ /**
+ * 创建老师用户 - 仅管理员可访问
+ */
+ @RequestMapping("/createTeacher")
+ public Result createTeacher(String username, String password, HttpServletRequest request) {
+ String token = request.getHeader("token");
+ UserRole creatorRole = UserRoleUtils.getUserRoleFromToken(token);
+
+ // 检查权限
+ if (!UserRoleUtils.canCreateUser(creatorRole, UserRole.TEACHER)) {
+ return Result.error("access denied");
+ }
+
+ // 验证用户名格式
+ if (!username.startsWith(UserRole.TEACHER.getPrefix())) {
+ return Result.error("teacher username must start with 't_'");
+ }
+
+ if (!UserRole.isValidUsername(username)) {
+ return Result.error("invalid username format");
+ }
+
+ // 创建用户
+ User newUser = new User(username, password);
+ return userService.addUser(newUser);
+ }
+
+ /**
+ * 创建学生用户 - 管理员和老师可访问
+ */
+ @RequestMapping("/createStudent")
+ public Result createStudent(String username, String password, HttpServletRequest request) {
+ String token = request.getHeader("token");
+ UserRole creatorRole = UserRoleUtils.getUserRoleFromToken(token);
+
+ // 检查权限
+ if (!UserRoleUtils.canCreateUser(creatorRole, UserRole.STUDENT)) {
+ return Result.error("access denied");
+ }
+
+ // 验证用户名格式
+ if (!username.startsWith(UserRole.STUDENT.getPrefix())) {
+ return Result.error("student username must start with 's_'");
+ }
+
+ if (!UserRole.isValidUsername(username)) {
+ return Result.error("invalid username format");
+ }
+
+ // 创建用户
+ User newUser = new User(username, password);
+ return userService.addUser(newUser);
+ }
+
+ /**
+ * 创建管理员用户 - 仅管理员可访问
+ */
+ @RequestMapping("/createAdmin")
+ public Result createAdmin(String username, String password, HttpServletRequest request) {
+ String token = request.getHeader("token");
+ UserRole creatorRole = UserRoleUtils.getUserRoleFromToken(token);
+
+ // 只有管理员可以创建管理员
+ if (creatorRole != UserRole.ADMIN) {
+ return Result.error("access denied");
+ }
+
+ // 验证用户名格式
+ if (!username.startsWith(UserRole.ADMIN.getPrefix())) {
+ return Result.error("admin username must start with 'a_'");
+ }
+
+ if (!UserRole.isValidUsername(username)) {
+ return Result.error("invalid username format");
+ }
+
+ // 创建用户
+ User newUser = new User(username, password);
+ return userService.addUser(newUser);
+ }
+}
\ No newline at end of file
diff --git a/test05/src/main/java/test05/enums/UserRole.java b/test05/src/main/java/test05/enums/UserRole.java
new file mode 100644
index 0000000..11794c9
--- /dev/null
+++ b/test05/src/main/java/test05/enums/UserRole.java
@@ -0,0 +1,73 @@
+package test05.enums;
+
+/**
+ * 用户角色枚举
+ */
+public enum UserRole {
+ ADMIN("a_", "管理员"),
+ TEACHER("t_", "老师"),
+ STUDENT("s_", "学生");
+
+ private final String prefix;
+ private final String description;
+
+ UserRole(String prefix, String description) {
+ this.prefix = prefix;
+ this.description = description;
+ }
+
+ public String getPrefix() {
+ return prefix;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ /**
+ * 根据用户名获取角色
+ */
+ public static UserRole getRoleByUsername(String username) {
+ if (username == null || username.isEmpty()) {
+ return null;
+ }
+
+ if (username.startsWith(ADMIN.getPrefix())) {
+ return ADMIN;
+ } else if (username.startsWith(TEACHER.getPrefix())) {
+ return TEACHER;
+ } else if (username.startsWith(STUDENT.getPrefix())) {
+ return STUDENT;
+ }
+
+ return null;
+ }
+
+ /**
+ * 检查用户名格式是否有效
+ */
+ public static boolean isValidUsername(String username) {
+ return getRoleByUsername(username) != null;
+ }
+
+ /**
+ * 检查角色是否有权限访问指定路径
+ */
+ public boolean hasAccessToPath(String path) {
+ if (path == null) return false;
+
+ switch (this) {
+ case ADMIN:
+ // 管理员可以访问所有API
+ return true;
+ case TEACHER:
+ // 老师可以访问老师端API
+ return path.contains("/teacherAction/") || path.contains("/studentAction/");
+ case STUDENT:
+ // 学生只能访问学生端API
+ return path.contains("/studentAction/");
+ default:
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/test05/src/main/java/test05/interceptor/LoginCheckInterceptor.java b/test05/src/main/java/test05/interceptor/LoginCheckInterceptor.java
index 9635433..a3f082d 100644
--- a/test05/src/main/java/test05/interceptor/LoginCheckInterceptor.java
+++ b/test05/src/main/java/test05/interceptor/LoginCheckInterceptor.java
@@ -3,20 +3,35 @@ package test05.interceptor;
import com.alibaba.fastjson2.JSONObject;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
-import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
+import test05.enums.UserRole;
import test05.pojo.Result;
import test05.utils.JwtUtils;
+import test05.utils.UserRoleUtils;
@Component
public class LoginCheckInterceptor implements HandlerInterceptor {
@Override
- public boolean preHandle(HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler) throws Exception {
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response,Object handler) throws Exception {
String token = request.getHeader("token");
try{
JwtUtils.parseJwt(token);
+
+ // 检查角色权限
+ UserRole userRole = UserRoleUtils.getUserRoleFromToken(token);
+ if (userRole == null) {
+ response.getWriter().print(JSONObject.toJSONString(Result.error("invalid user role")));
+ return false;
+ }
+
+ String requestURI = request.getRequestURI();
+ if (!userRole.hasAccessToPath(requestURI)) {
+ response.getWriter().print(JSONObject.toJSONString(Result.error("access denied")));
+ return false;
+ }
+
}catch(Exception e){
response.getWriter().print(JSONObject.toJSONString(Result.error("not login")));
return false;
@@ -24,11 +39,11 @@ public class LoginCheckInterceptor implements HandlerInterceptor {
return true;
}
@Override
- public void postHandle(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler, ModelAndView modelAndView) {
+ public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
}
@Override
- public void afterCompletion(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler, Exception ex) {
+ public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
}
}
diff --git a/test05/src/main/java/test05/mapper/TeacherMapper.java b/test05/src/main/java/test05/mapper/TeacherMapper.java
index 136bedb..83636d3 100644
--- a/test05/src/main/java/test05/mapper/TeacherMapper.java
+++ b/test05/src/main/java/test05/mapper/TeacherMapper.java
@@ -7,7 +7,8 @@ import java.util.List;
@Mapper
public interface TeacherMapper {
- List selectTeacher(Teacher teacher);
+ List selectTeacher(Teacher teacher, int offset, int pageSize);
+ int selectTeacherCount(Teacher teacher);
int insertTeacher(Teacher teacher);
int updateTeacher(Teacher teacher);
int deleteTeacher(Teacher teacher);
diff --git a/test05/src/main/java/test05/pojo/Teacher.java b/test05/src/main/java/test05/pojo/Teacher.java
index d6e8058..72fee46 100644
--- a/test05/src/main/java/test05/pojo/Teacher.java
+++ b/test05/src/main/java/test05/pojo/Teacher.java
@@ -10,18 +10,24 @@ import lombok.NonNull;
@NoArgsConstructor
public class Teacher {
@NonNull
- Integer N_TEACHER_ID=-1;
+ // Integer N_TEACHER_ID=-1;
+ Integer id = -1;
@NonNull
- String VC_TEACHER_NAME="";
+ // String VC_TEACHER_NAME="";
+ String name = "";
@NonNull
- Integer N_SEX=-1;
+ // Integer N_SEX=-1;
+ Integer sex = -1;
@NonNull
- String VC_BIRTH="";
+ // String VC_BIRTH="";
+ String birth = "";
@NonNull
- Integer N_EDUC=-1;
+ // Integer N_EDUC=-1;
+ Integer educ = -1;
@NonNull
- Integer N_TITLE=-1;
+ // Integer N_TITLE=-1;
+ Integer title = -1;
public Teacher(int id){
- N_TEACHER_ID = id;
+ this.id = id;
}
}
diff --git a/test05/src/main/java/test05/service/TeacherService.java b/test05/src/main/java/test05/service/TeacherService.java
new file mode 100644
index 0000000..2bc8da6
--- /dev/null
+++ b/test05/src/main/java/test05/service/TeacherService.java
@@ -0,0 +1,11 @@
+package test05.service;
+
+import test05.pojo.Result;
+import test05.pojo.Teacher;
+
+public interface TeacherService {
+ Result getTeacher(Teacher teacher, int page, int pageSize);
+ Result addTeacher(Teacher teacher);
+ Result updateTeacher(Teacher teacher);
+ Result deleteTeacher(Teacher teacher);
+}
diff --git a/test05/src/main/java/test05/service/UserService.java b/test05/src/main/java/test05/service/UserService.java
index 256979b..9fb412b 100644
--- a/test05/src/main/java/test05/service/UserService.java
+++ b/test05/src/main/java/test05/service/UserService.java
@@ -10,4 +10,11 @@ public interface UserService {
* @return 登录结果
*/
Result login(User user);
+
+ /**
+ * 添加用户服务
+ * @param user 要添加的用户
+ * @return 添加结果
+ */
+ Result addUser(User user);
}
diff --git a/test05/src/main/java/test05/service/impl/TeacherServiceImpl.java b/test05/src/main/java/test05/service/impl/TeacherServiceImpl.java
new file mode 100644
index 0000000..a2d3b90
--- /dev/null
+++ b/test05/src/main/java/test05/service/impl/TeacherServiceImpl.java
@@ -0,0 +1,53 @@
+package test05.service.impl;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import test05.mapper.TeacherMapper;
+import test05.pojo.Result;
+import test05.pojo.Teacher;
+import test05.service.TeacherService;
+
+@Service
+public class TeacherServiceImpl implements TeacherService{
+ private final TeacherMapper teacherMapper;
+
+ @Autowired
+ public TeacherServiceImpl(TeacherMapper teacherMapper) {
+ this.teacherMapper = teacherMapper;
+ }
+
+ @Override
+ public Result getTeacher(Teacher teacher, int page, int pageSize) {
+ try{
+ int offset = Math.max(0, (page - 1)) * pageSize;
+ List list = teacherMapper.selectTeacher(teacher, offset, pageSize);
+ int total = teacherMapper.selectTeacherCount(teacher);
+ return Result.success(list, total);
+ }catch (Exception e){
+ return Result.error(e.getMessage());
+ }
+ }
+
+ @Override
+ public Result addTeacher(Teacher teacher) {
+ // TODO:校验数据
+ int count = teacherMapper.insertTeacher(teacher);
+ return Result.success(count>0);
+ }
+
+ @Override
+ public Result updateTeacher(Teacher teacher) {
+ int count = teacherMapper.updateTeacher(teacher);
+ return Result.success(count>0);
+ }
+
+ @Override
+ public Result deleteTeacher(Teacher teacher) {
+ int count = teacherMapper.deleteTeacher(teacher);
+ return Result.success(count>0);
+ }
+
+}
diff --git a/test05/src/main/java/test05/service/impl/UserServiceImpl.java b/test05/src/main/java/test05/service/impl/UserServiceImpl.java
index 5cc5b16..d2d2287 100644
--- a/test05/src/main/java/test05/service/impl/UserServiceImpl.java
+++ b/test05/src/main/java/test05/service/impl/UserServiceImpl.java
@@ -34,4 +34,21 @@ public class UserServiceImpl implements UserService {
return Result.error("password incorrect");
}
}
+
+ @Override
+ public Result addUser(User user) {
+ // 检查用户名是否已存在
+ User existingUser = userMapper.selectUserByName(user.getName());
+ if (existingUser != null) {
+ return Result.error("username already exists");
+ }
+
+ // 插入新用户
+ int result = userMapper.insertUser(user);
+ if (result > 0) {
+ return Result.success("user created successfully");
+ } else {
+ return Result.error("failed to create user");
+ }
+ }
}
diff --git a/test05/src/main/java/test05/utils/UserRoleUtils.java b/test05/src/main/java/test05/utils/UserRoleUtils.java
new file mode 100644
index 0000000..ff94cb6
--- /dev/null
+++ b/test05/src/main/java/test05/utils/UserRoleUtils.java
@@ -0,0 +1,113 @@
+package test05.utils;
+
+import java.util.Map;
+
+import com.alibaba.fastjson2.JSONObject;
+
+import test05.enums.UserRole;
+
+/**
+ * 用户角色工具类
+ */
+public class UserRoleUtils {
+
+ /**
+ * 从JWT token中提取用户名并获取角色
+ */
+ public static UserRole getUserRoleFromToken(String token) {
+ try {
+ if (token == null || token.isEmpty()) {
+ return null;
+ }
+
+ // 解析JWT token获取用户信息
+ Map claims_map = test05.utils.JwtUtils.parseJwt(token);
+ com.alibaba.fastjson2.JSONObject claims = new JSONObject(claims_map) ;
+ if (claims == null || !claims.containsKey("data")) {
+ return null;
+ }
+
+ Object dataObj = claims.get("data");
+ if (dataObj == null) {
+ return null;
+ }
+
+ com.alibaba.fastjson2.JSONObject data;
+ if (dataObj instanceof com.alibaba.fastjson2.JSONObject) {
+ data = (com.alibaba.fastjson2.JSONObject) dataObj;
+ } else {
+ data = com.alibaba.fastjson2.JSONObject.parseObject(dataObj.toString());
+ }
+
+ if (!data.containsKey("name")) {
+ return null;
+ }
+
+ String username = data.getString("name");
+ return UserRole.getRoleByUsername(username);
+
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ /**
+ * 从JWT token中提取用户名
+ */
+ public static String getUsernameFromToken(String token) {
+ try {
+ if (token == null || token.isEmpty()) {
+ return null;
+ }
+
+ com.alibaba.fastjson2.JSONObject claims = new JSONObject(test05.utils.JwtUtils.parseJwt(token));
+ if (claims == null || !claims.containsKey("data")) {
+ return null;
+ }
+
+ Object dataObj = claims.get("data");
+ if (dataObj == null) {
+ return null;
+ }
+
+ com.alibaba.fastjson2.JSONObject data;
+ if (dataObj instanceof com.alibaba.fastjson2.JSONObject) {
+ data = (com.alibaba.fastjson2.JSONObject) dataObj;
+ } else {
+ data = com.alibaba.fastjson2.JSONObject.parseObject(dataObj.toString());
+ }
+
+ if (!data.containsKey("name")) {
+ return null;
+ }
+
+ return data.getString("name");
+
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ /**
+ * 检查用户是否有权限创建指定角色的用户
+ */
+ public static boolean canCreateUser(UserRole creatorRole, UserRole targetRole) {
+ if (creatorRole == null || targetRole == null) {
+ return false;
+ }
+
+ switch (creatorRole) {
+ case ADMIN:
+ // 管理员可以创建老师和用户
+ return targetRole == UserRole.TEACHER || targetRole == UserRole.STUDENT;
+ case TEACHER:
+ // 老师可以创建学生
+ return targetRole == UserRole.STUDENT;
+ case STUDENT:
+ // 学生不能创建用户
+ return false;
+ default:
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/test05/src/main/resources/application-dev.properties b/test05/src/main/resources/application-dev.properties
new file mode 100644
index 0000000..2ad4be7
--- /dev/null
+++ b/test05/src/main/resources/application-dev.properties
@@ -0,0 +1,16 @@
+# 开发环境配置
+
+# 开发环境数据库配置
+spring.datasource.url=jdbc:mysql://www.awin-x.top:63306/db_student
+spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
+spring.datasource.username=admin
+spring.datasource.password=3131313xY
+
+spring.datasource.druid.validation-query=SELECT 1
+
+mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
+
+# 开发环境特定配置
+logging.level.root=INFO
+logging.level.test05=DEBUG
+spring.devtools.restart.enabled=true
\ No newline at end of file
diff --git a/test05/src/main/resources/application-prod.properties b/test05/src/main/resources/application-prod.properties
new file mode 100644
index 0000000..6fca755
--- /dev/null
+++ b/test05/src/main/resources/application-prod.properties
@@ -0,0 +1,16 @@
+# 生产环境配置
+
+# 生产环境数据库配置(请根据实际情况修改)
+spring.datasource.url=jdbc:mysql://your-prod-db-host:3306/db_student
+spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
+spring.datasource.username=prod_user
+spring.datasource.password=prod_password
+
+spring.datasource.druid.validation-query=SELECT 1
+
+# 生产环境关闭SQL日志输出
+mybatis.configuration.log-impl=org.apache.ibatis.logging.nologging.NoLoggingImpl
+
+# 生产环境特定配置
+logging.level.root=WARN
+spring.devtools.restart.enabled=false
\ No newline at end of file
diff --git a/test05/src/main/resources/application.properties b/test05/src/main/resources/application.properties
index b5f8ffa..08e6a4f 100644
--- a/test05/src/main/resources/application.properties
+++ b/test05/src/main/resources/application.properties
@@ -1,15 +1,7 @@
spring.application.name=test05
-#\u4F7F\u7528\u672C\u5730\u6D4B\u8BD5\u6570\u636E\u5E93
-#spring.datasource.driver-class-name=org.sqlite.JDBC
-spring.datasource.url=jdbc:mysql://www.awin-x.top:63306/db_student
-#spring.datasource.url=jdbc:sqlite::resource:db/db_student.db
-##\u4F7F\u7528mysql\u6570\u636E\u5E93
-spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
-#spring.datasource.url=jdbc:mysql://localhost:3306/db_student.db
-spring.datasource.username=admin
-spring.datasource.password=3131313xY
+# 默认激活开发环境profile
+spring.profiles.active=dev
+# 公共配置(可被各环境覆盖)
spring.datasource.druid.validation-query=SELECT 1
-
-mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
diff --git a/test05/src/main/resources/test05/mapper/StudentMapper.xml b/test05/src/main/resources/test05/mapper/StudentMapper.xml
index 4c56441..1352c9a 100644
--- a/test05/src/main/resources/test05/mapper/StudentMapper.xml
+++ b/test05/src/main/resources/test05/mapper/StudentMapper.xml
@@ -22,7 +22,7 @@
AND (VC_DETAIL LIKE CONCAT('%', #{student.detail}, '%')
OR (#{student.detail} = '' AND VC_DETAIL IS NULL))
ORDER BY N_STUDENT_ID DESC
- LIMIT #{offset},#{pageSize}
+ LIMIT #{offset},#{pageSize};