From 94a7b1bc136d0681515b9d624690762cd971fa65 Mon Sep 17 00:00:00 2001 From: "Chester.X" <2931709855@qq.com> Date: Tue, 2 Jul 2024 16:40:45 +0800 Subject: [PATCH 01/14] 1 --- pom.xml | 23 ++------ .../org/cmh/backend/Config/CorsConfig.java | 8 +-- .../cmh/backend/Config/SecurityConfig.java | 54 +++++++++++++++++ .../controller/AuthenticationController.java | 38 +++++++++++- .../controller/UserController.java | 50 +++++++++++++--- .../backend/authentication/model/User.java | 43 ++++++-------- .../repository/UserRepository.java | 8 ++- .../service/AuthenticationService.java | 0 .../authentication/service/UserService.java | 20 +++---- .../service/UserServiceImpl.java | 58 +++++++++++++++++++ src/test/application-test.properties | 7 +++ .../cmh/backend/BackendApplicationTests.java | 7 +-- .../cmh/backend/TestBackendApplication.java | 7 ++- 13 files changed, 245 insertions(+), 78 deletions(-) create mode 100644 src/main/java/org/cmh/backend/Config/SecurityConfig.java delete mode 100644 src/main/java/org/cmh/backend/authentication/service/AuthenticationService.java create mode 100644 src/main/java/org/cmh/backend/authentication/service/UserServiceImpl.java create mode 100644 src/test/application-test.properties diff --git a/pom.xml b/pom.xml index 428b562..809654a 100644 --- a/pom.xml +++ b/pom.xml @@ -1,6 +1,6 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 org.springframework.boot @@ -50,10 +50,10 @@ org.springframework.boot spring-boot-starter-data-jpa - - - - + + org.springframework.boot + spring-boot-starter-security + org.springframework.boot spring-boot-starter-web @@ -62,27 +62,16 @@ org.springframework.boot spring-boot-starter-web-services - - - - - org.springframework.session spring-session-jdbc - org.springframework.boot spring-boot-devtools runtime true - - - - - com.mysql mysql-connector-j @@ -210,4 +199,4 @@ - + \ No newline at end of file diff --git a/src/main/java/org/cmh/backend/Config/CorsConfig.java b/src/main/java/org/cmh/backend/Config/CorsConfig.java index 7852636..d178880 100644 --- a/src/main/java/org/cmh/backend/Config/CorsConfig.java +++ b/src/main/java/org/cmh/backend/Config/CorsConfig.java @@ -1,5 +1,4 @@ package org.cmh.backend.Config; -// CorsConfig.java import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -14,13 +13,12 @@ public class CorsConfig { return new WebMvcConfigurer() { @Override public void addCorsMappings(CorsRegistry registry) { - registry.addMapping("/**") - .allowedOrigins("http://localhost:8080") + registry.addMapping("/api/**") + .allowedOrigins("http://localhost:3000") .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") .allowedHeaders("*") .allowCredentials(true); } }; } -} - +} \ No newline at end of file diff --git a/src/main/java/org/cmh/backend/Config/SecurityConfig.java b/src/main/java/org/cmh/backend/Config/SecurityConfig.java new file mode 100644 index 0000000..48dd95f --- /dev/null +++ b/src/main/java/org/cmh/backend/Config/SecurityConfig.java @@ -0,0 +1,54 @@ +package org.cmh.backend.Config; + +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.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.filter.CorsFilter; + +import java.util.List; + +@Configuration +@EnableWebSecurity +public class SecurityConfig { + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } + + @Bean + public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + http + .csrf(csrf -> csrf.disable()) + .cors(cors -> cors.configurationSource(corsConfigurationSource())) + .authorizeHttpRequests(authorize -> authorize + .requestMatchers("/api/auth/register", "/api/auth/login").permitAll() + .anyRequest().authenticated() + ); + + return http.build(); + } + + @Bean + public UrlBasedCorsConfigurationSource corsConfigurationSource() { + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + CorsConfiguration config = new CorsConfiguration(); + config.setAllowCredentials(true); + config.setAllowedOrigins(List.of("http://localhost:3000")); + config.setAllowedHeaders(List.of("*")); + config.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS")); + source.registerCorsConfiguration("/**", config); + return source; + } + + @Bean + public CorsFilter corsFilter() { + return new CorsFilter(corsConfigurationSource()); + } +} \ No newline at end of file diff --git a/src/main/java/org/cmh/backend/authentication/controller/AuthenticationController.java b/src/main/java/org/cmh/backend/authentication/controller/AuthenticationController.java index 8ec56df..974eed0 100644 --- a/src/main/java/org/cmh/backend/authentication/controller/AuthenticationController.java +++ b/src/main/java/org/cmh/backend/authentication/controller/AuthenticationController.java @@ -1,13 +1,45 @@ package org.cmh.backend.authentication.controller; +import org.cmh.backend.authentication.model.User; +import org.cmh.backend.authentication.service.UserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RestController; +import java.util.HashMap; +import java.util.Map; @RestController -class AuthenticationController { +@RequestMapping("/api/auth") +public class AuthenticationController { + + @Autowired + private UserService userService; + + @PostMapping("/register") + public User register(@RequestBody User user) { + return userService.register(user); + } + + @PostMapping("/login") + public ResponseEntity> login(@RequestBody User loginRequest) { + User user = userService.login(loginRequest.getUsername(), loginRequest.getPassword()); + if (user == null) { + throw new RuntimeException("Invalid username or password"); + } + Map response = new HashMap<>(); + response.put("userId", user.getId()); + response.put("user", user); + return ResponseEntity.ok(response); + } + @GetMapping("/hello") public String hello(){ return "Hello SpringBoot!"; } + + @PostMapping("/getVerificationCode") + public String getVerificationCode(@RequestBody String contact) { + return "Verification code sent to " + contact; + } } \ No newline at end of file diff --git a/src/main/java/org/cmh/backend/authentication/controller/UserController.java b/src/main/java/org/cmh/backend/authentication/controller/UserController.java index f4e6aae..a3a38c5 100644 --- a/src/main/java/org/cmh/backend/authentication/controller/UserController.java +++ b/src/main/java/org/cmh/backend/authentication/controller/UserController.java @@ -4,20 +4,52 @@ import org.cmh.backend.authentication.model.User; import org.cmh.backend.authentication.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/users") public class UserController { + @Autowired private UserService userService; - @GetMapping("/{username}") - public ResponseEntity getUser(@PathVariable String username) { - User user = userService.getUserByUsername(username); - return ResponseEntity.ok(user); + @CrossOrigin(origins = "http://localhost:3000") + @PostMapping("/register") + public ResponseEntity register(@RequestBody User user) { + User registeredUser = userService.register(user); + return ResponseEntity.ok(registeredUser); } -} + + @PostMapping("/login") + public ResponseEntity login(@RequestParam String username, @RequestParam String password) { + User user = userService.login(username, password); + if (user != null) { + return ResponseEntity.ok(user); + } + return ResponseEntity.status(401).build(); + } + + @PutMapping("/update") + public ResponseEntity updateUserInfo(@RequestBody User user) { + User updatedUser = userService.updateUserInfo(user); + return ResponseEntity.ok(updatedUser); + } + + @PutMapping("/changePassword") + public ResponseEntity changePassword(@RequestParam Long userId, @RequestParam String oldPassword, @RequestParam String newPassword) { + boolean isChanged = userService.changePassword(userId, oldPassword, newPassword); + if (isChanged) { + return ResponseEntity.ok("Password changed successfully"); + } + return ResponseEntity.status(400).body("Old password is incorrect"); + } + + @GetMapping("/{userId}") + public ResponseEntity getUserInfo(@PathVariable Long userId) { + User user = userService.findById(userId).orElse(null); + if (user != null) { + return ResponseEntity.ok(user); + } + return ResponseEntity.status(404).build(); + } +} \ No newline at end of file diff --git a/src/main/java/org/cmh/backend/authentication/model/User.java b/src/main/java/org/cmh/backend/authentication/model/User.java index ba9aa53..0a2900c 100644 --- a/src/main/java/org/cmh/backend/authentication/model/User.java +++ b/src/main/java/org/cmh/backend/authentication/model/User.java @@ -1,39 +1,34 @@ +// User.java package org.cmh.backend.authentication.model; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; +import lombok.Data; +import jakarta.persistence.*; +import java.time.LocalDateTime; + +@Data @Entity +@Table(name = "Chester") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + + @Column(nullable = false, unique = true) private String username; + + @Column(nullable = false) private String password; - public Long getId() { - return id; - } + @Column(nullable = false) + private String email; - public void setId(Long id) { - this.id = id; - } + @Column(nullable = false) + private String role; - public String getUsername() { - return username; - } + private String phoneNumber; + private String company; - public void setUsername(String username) { - this.username = username; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } + @Column(nullable = false) + private LocalDateTime createdDate; } \ No newline at end of file diff --git a/src/main/java/org/cmh/backend/authentication/repository/UserRepository.java b/src/main/java/org/cmh/backend/authentication/repository/UserRepository.java index 2c5116e..473bba9 100644 --- a/src/main/java/org/cmh/backend/authentication/repository/UserRepository.java +++ b/src/main/java/org/cmh/backend/authentication/repository/UserRepository.java @@ -2,7 +2,13 @@ package org.cmh.backend.authentication.repository; import org.cmh.backend.authentication.model.User; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +import java.util.Optional; + +@Repository public interface UserRepository extends JpaRepository { User findByUsername(String username); -} + Optional findById(Long id); + User save(User user); +} \ No newline at end of file diff --git a/src/main/java/org/cmh/backend/authentication/service/AuthenticationService.java b/src/main/java/org/cmh/backend/authentication/service/AuthenticationService.java deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/java/org/cmh/backend/authentication/service/UserService.java b/src/main/java/org/cmh/backend/authentication/service/UserService.java index 30e5134..3e2c708 100644 --- a/src/main/java/org/cmh/backend/authentication/service/UserService.java +++ b/src/main/java/org/cmh/backend/authentication/service/UserService.java @@ -1,16 +1,14 @@ package org.cmh.backend.authentication.service; import org.cmh.backend.authentication.model.User; -import org.cmh.backend.authentication.repository.UserRepository; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -@Service -public class UserService { - @Autowired - private UserRepository userRepository; +import java.util.Optional; - public User getUserByUsername(String username) { - return userRepository.findByUsername(username); - } -} +// UserService.java +public interface UserService { + User register(User user); + User login(String username, String password); + User updateUserInfo(User user); + boolean changePassword(Long userId, String oldPassword, String newPassword); + Optional findById(Long id); +} \ No newline at end of file diff --git a/src/main/java/org/cmh/backend/authentication/service/UserServiceImpl.java b/src/main/java/org/cmh/backend/authentication/service/UserServiceImpl.java new file mode 100644 index 0000000..ae8be9b --- /dev/null +++ b/src/main/java/org/cmh/backend/authentication/service/UserServiceImpl.java @@ -0,0 +1,58 @@ +package org.cmh.backend.authentication.service; + +import org.cmh.backend.authentication.model.User; +import org.cmh.backend.authentication.repository.UserRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.util.Optional; + +// UserServiceImpl.java +@Service +public class UserServiceImpl implements UserService { + + @Autowired + private UserRepository userRepository; + + @Autowired + private PasswordEncoder passwordEncoder; + + @Override + public User register(User user) { + user.setPassword(passwordEncoder.encode(user.getPassword())); + user.setCreatedDate(LocalDateTime.now()); + return userRepository.save(user); + } + + @Override + public User login(String username, String password) { + User user = userRepository.findByUsername(username); + if (user != null && passwordEncoder.matches(password, user.getPassword())) { + return user; + } + return null; + } + + @Override + public User updateUserInfo(User user) { + return userRepository.save(user); + } + + @Override + public boolean changePassword(Long userId, String oldPassword, String newPassword) { + User user = userRepository.findById(userId).orElse(null); + if (user != null && passwordEncoder.matches(oldPassword, user.getPassword())) { + user.setPassword(passwordEncoder.encode(newPassword)); + userRepository.save(user); + return true; + } + return false; + } + + @Override + public Optional findById(Long id) { + return userRepository.findById(id); + } +} \ No newline at end of file diff --git a/src/test/application-test.properties b/src/test/application-test.properties new file mode 100644 index 0000000..77d29e8 --- /dev/null +++ b/src/test/application-test.properties @@ -0,0 +1,7 @@ +spring.datasource.url=jdbc:h2:mem:testdb +spring.datasource.driverClassName=org.h2.Driver +spring.datasource.username=sa +spring.datasource.password=password +spring.jpa.database-platform=org.hibernate.dialect.H2Dialect +spring.jpa.hibernate.ddl-auto=update +spring.h2.console.enabled=true \ No newline at end of file diff --git a/src/test/java/org/cmh/backend/BackendApplicationTests.java b/src/test/java/org/cmh/backend/BackendApplicationTests.java index 8bc26ca..e490cdf 100644 --- a/src/test/java/org/cmh/backend/BackendApplicationTests.java +++ b/src/test/java/org/cmh/backend/BackendApplicationTests.java @@ -2,14 +2,11 @@ package org.cmh.backend; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.context.annotation.Import; -@Import(TestcontainersConfiguration.class) @SpringBootTest -class BackendApplicationTests { +public class BackendApplicationTests { @Test void contextLoads() { } - -} +} \ No newline at end of file diff --git a/src/test/java/org/cmh/backend/TestBackendApplication.java b/src/test/java/org/cmh/backend/TestBackendApplication.java index a752147..52bb0ff 100644 --- a/src/test/java/org/cmh/backend/TestBackendApplication.java +++ b/src/test/java/org/cmh/backend/TestBackendApplication.java @@ -1,11 +1,12 @@ package org.cmh.backend; import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +@SpringBootApplication public class TestBackendApplication { public static void main(String[] args) { - SpringApplication.from(BackendApplication::main).with(TestcontainersConfiguration.class).run(args); + SpringApplication.run(TestBackendApplication.class, args); } - -} +} \ No newline at end of file From ef100673450f8df4614eff7ac9ae840702d5075a Mon Sep 17 00:00:00 2001 From: "Chester.X" <2931709855@qq.com> Date: Thu, 4 Jul 2024 21:21:46 +0800 Subject: [PATCH 02/14] 2 --- pom.xml | 5 - .../controller/CourseController.java | 67 +++++++++++++ .../controller/FileController.java | 35 +++++++ .../CourseManagement/model/Course.java | 22 +++++ .../repository/CourseRepository.java | 9 ++ .../service/CourseService.java | 96 +++++++++++++++++++ .../controller/AuthenticationController.java | 45 --------- .../controller/UserController.java | 51 ++++++---- .../authentication/dto/LoginRequest.java | 11 +++ .../authentication/dto/LoginResponse.java | 13 +++ .../authentication/dto/ProfileResponse.java | 19 ++++ .../authentication/dto/RegisterResponse.java | 12 +++ .../authentication/dto/UpdateRequest.java | 15 +++ .../repository/UserRepository.java | 2 - .../authentication/service/UserService.java | 72 ++++++++++++-- .../service/UserServiceImpl.java | 58 ----------- src/test/application-test.properties | 7 -- .../cmh/backend/BackendApplicationTests.java | 12 --- .../cmh/backend/TestBackendApplication.java | 12 --- .../backend/TestcontainersConfiguration.java | 25 ----- .../backend/Utils/JwtVerifyAspectTest.java | 88 ----------------- 21 files changed, 394 insertions(+), 282 deletions(-) create mode 100644 src/main/java/org/cmh/backend/CourseManagement/controller/CourseController.java create mode 100644 src/main/java/org/cmh/backend/CourseManagement/controller/FileController.java create mode 100644 src/main/java/org/cmh/backend/CourseManagement/model/Course.java create mode 100644 src/main/java/org/cmh/backend/CourseManagement/repository/CourseRepository.java create mode 100644 src/main/java/org/cmh/backend/CourseManagement/service/CourseService.java delete mode 100644 src/main/java/org/cmh/backend/authentication/controller/AuthenticationController.java create mode 100644 src/main/java/org/cmh/backend/authentication/dto/LoginRequest.java create mode 100644 src/main/java/org/cmh/backend/authentication/dto/LoginResponse.java create mode 100644 src/main/java/org/cmh/backend/authentication/dto/ProfileResponse.java create mode 100644 src/main/java/org/cmh/backend/authentication/dto/RegisterResponse.java create mode 100644 src/main/java/org/cmh/backend/authentication/dto/UpdateRequest.java delete mode 100644 src/main/java/org/cmh/backend/authentication/service/UserServiceImpl.java delete mode 100644 src/test/application-test.properties delete mode 100644 src/test/java/org/cmh/backend/BackendApplicationTests.java delete mode 100644 src/test/java/org/cmh/backend/TestBackendApplication.java delete mode 100644 src/test/java/org/cmh/backend/TestcontainersConfiguration.java delete mode 100644 src/test/java/org/cmh/backend/Utils/JwtVerifyAspectTest.java diff --git a/pom.xml b/pom.xml index 39cc9bb..9c4b479 100644 --- a/pom.xml +++ b/pom.xml @@ -93,11 +93,6 @@ runtime true - - - - - com.mysql mysql-connector-j diff --git a/src/main/java/org/cmh/backend/CourseManagement/controller/CourseController.java b/src/main/java/org/cmh/backend/CourseManagement/controller/CourseController.java new file mode 100644 index 0000000..3602384 --- /dev/null +++ b/src/main/java/org/cmh/backend/CourseManagement/controller/CourseController.java @@ -0,0 +1,67 @@ +package org.cmh.backend.CourseManagement.controller; + +import org.cmh.backend.CourseManagement.model.Course; +import org.cmh.backend.CourseManagement.service.CourseService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.http.HttpStatus; + +import java.util.List; + +@RestController +@RequestMapping("/course") +public class CourseController { + + @Autowired + private CourseService courseService; + + @PostMapping("/create") + public ResponseEntity createCourse( + @RequestParam("name") String name, + @RequestParam("description") String description, + @RequestParam("author") String author, + @RequestParam("sortOrder") String sortOrder, + @RequestParam("coverImage") MultipartFile coverImage, + @RequestParam("video") MultipartFile video) { + + Course createdCourse = courseService.createCourse(name, description, author, sortOrder, coverImage, video); + if (createdCourse == null) { + return new ResponseEntity<>("课程已存在", HttpStatus.BAD_REQUEST); + } + return new ResponseEntity<>("课程创建成功", HttpStatus.OK); + } + + @PutMapping("/edit/{id}") + public ResponseEntity updateCourse( + @PathVariable Long id, + @RequestParam("name") String name, + @RequestParam("description") String description, + @RequestParam("author") String author, + @RequestParam("sortOrder") String sortOrder, + @RequestParam(value = "coverImage", required = false) MultipartFile coverImage, + @RequestParam(value = "video", required = false) MultipartFile video) { + + Course updatedCourse = courseService.updateCourse(id, name, description, author, sortOrder, coverImage, video); + if (updatedCourse == null) { + return new ResponseEntity<>("课程未找到", HttpStatus.NOT_FOUND); + } + return new ResponseEntity<>("课程修改成功", HttpStatus.OK); + } + + @DeleteMapping("/delete/{id}") + public ResponseEntity deleteCourse(@PathVariable Long id) { + boolean isDeleted = courseService.deleteCourse(id); + if (!isDeleted) { + return new ResponseEntity<>("课程未找到", HttpStatus.NOT_FOUND); + } + return new ResponseEntity<>("课程删除成功", HttpStatus.OK); + } + + @GetMapping("/getAll") + public ResponseEntity> getAllCourses() { + List courses = courseService.getAllCourses(); + return new ResponseEntity<>(courses, HttpStatus.OK); + } +} \ No newline at end of file diff --git a/src/main/java/org/cmh/backend/CourseManagement/controller/FileController.java b/src/main/java/org/cmh/backend/CourseManagement/controller/FileController.java new file mode 100644 index 0000000..99d9350 --- /dev/null +++ b/src/main/java/org/cmh/backend/CourseManagement/controller/FileController.java @@ -0,0 +1,35 @@ +package org.cmh.backend.CourseManagement.controller; + +import org.springframework.core.io.UrlResource; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.core.io.Resource; + + +import java.nio.file.Path; +import java.nio.file.Paths; + +public class FileController { + private static final String UPLOAD_DIR = "uploads/"; + + @GetMapping("/files/{filename}") + public ResponseEntity getFile(@PathVariable String filename) { + try { + Path filePath = Paths.get(UPLOAD_DIR).resolve(filename).normalize(); + Resource resource = new UrlResource(filePath.toUri()); + + if (resource.exists() && resource.isReadable()) { + return ResponseEntity.ok() + .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"") + .body(resource); + } else { + return new ResponseEntity<>(HttpStatus.NOT_FOUND); + } + } catch (Exception e) { + return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); + } + } +} diff --git a/src/main/java/org/cmh/backend/CourseManagement/model/Course.java b/src/main/java/org/cmh/backend/CourseManagement/model/Course.java new file mode 100644 index 0000000..caa9186 --- /dev/null +++ b/src/main/java/org/cmh/backend/CourseManagement/model/Course.java @@ -0,0 +1,22 @@ +package org.cmh.backend.CourseManagement.model; + +import jakarta.persistence.*; +import lombok.Data; + +@Data +@Entity +@Table(name = "courses") +public class Course { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + private String name; + private String description; + private String author; + private String sortOrder; + private String coverImagePath; + private String videoPath; + + // getters and setters +} \ No newline at end of file diff --git a/src/main/java/org/cmh/backend/CourseManagement/repository/CourseRepository.java b/src/main/java/org/cmh/backend/CourseManagement/repository/CourseRepository.java new file mode 100644 index 0000000..ce25b61 --- /dev/null +++ b/src/main/java/org/cmh/backend/CourseManagement/repository/CourseRepository.java @@ -0,0 +1,9 @@ +package org.cmh.backend.CourseManagement.repository; + +import org.cmh.backend.CourseManagement.model.Course; +import org.springframework.data.jpa.repository.JpaRepository; +import java.util.Optional; + +public interface CourseRepository extends JpaRepository { + Optional findByName(String name); +} \ No newline at end of file diff --git a/src/main/java/org/cmh/backend/CourseManagement/service/CourseService.java b/src/main/java/org/cmh/backend/CourseManagement/service/CourseService.java new file mode 100644 index 0000000..f49676f --- /dev/null +++ b/src/main/java/org/cmh/backend/CourseManagement/service/CourseService.java @@ -0,0 +1,96 @@ +package org.cmh.backend.CourseManagement.service; + +import org.cmh.backend.CourseManagement.model.Course; +import org.cmh.backend.CourseManagement.repository.CourseRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import java.util.Optional; + +@Service +public class CourseService { + + @Autowired + private CourseRepository courseRepository; + + public Course createCourse(String name, String description, String author, String sortOrder, MultipartFile coverImage, MultipartFile video) { + Optional existingCourse = courseRepository.findByName(name); + if (existingCourse.isPresent()) { + return null; + } + + Course course = new Course(); + course.setName(name); + course.setDescription(description); + course.setAuthor(author); + course.setSortOrder(sortOrder); + + try { + if (coverImage != null && !coverImage.isEmpty()) { + String coverImagePath = saveFile(coverImage); + course.setCoverImagePath(coverImagePath); + } + if (video != null && !video.isEmpty()) { + String videoPath = saveFile(video); + course.setVideoPath(videoPath); + } + } catch (IOException e) { + e.printStackTrace(); + return null; + } + + return courseRepository.save(course); + } + + public Course updateCourse(Long id, String name, String description, String author, String sortOrder, MultipartFile coverImage, MultipartFile video) { + return courseRepository.findById(id) + .map(course -> { + course.setName(name); + course.setDescription(description); + course.setAuthor(author); + course.setSortOrder(sortOrder); + + try { + if (coverImage != null && !coverImage.isEmpty()) { + String coverImagePath = saveFile(coverImage); + course.setCoverImagePath(coverImagePath); + } + if (video != null && !video.isEmpty()) { + String videoPath = saveFile(video); + course.setVideoPath(videoPath); + } + } catch (IOException e) { + e.printStackTrace(); + return null; + } + + return courseRepository.save(course); + }).orElse(null); + } + + private String saveFile(MultipartFile file) throws IOException { + String filename = System.currentTimeMillis() + "_" + file.getOriginalFilename(); + Path filePath = Paths.get("uploads", filename); + Files.createDirectories(filePath.getParent()); + Files.write(filePath, file.getBytes()); + return filePath.toString(); + } + + public boolean deleteCourse(Long id) { + return courseRepository.findById(id) + .map(course -> { + courseRepository.delete(course); + return true; + }).orElse(false); + } + + public List getAllCourses() { + return courseRepository.findAll(); + } +} \ No newline at end of file diff --git a/src/main/java/org/cmh/backend/authentication/controller/AuthenticationController.java b/src/main/java/org/cmh/backend/authentication/controller/AuthenticationController.java deleted file mode 100644 index 974eed0..0000000 --- a/src/main/java/org/cmh/backend/authentication/controller/AuthenticationController.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.cmh.backend.authentication.controller; - -import org.cmh.backend.authentication.model.User; -import org.cmh.backend.authentication.service.UserService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; - -import java.util.HashMap; -import java.util.Map; - -@RestController -@RequestMapping("/api/auth") -public class AuthenticationController { - - @Autowired - private UserService userService; - - @PostMapping("/register") - public User register(@RequestBody User user) { - return userService.register(user); - } - - @PostMapping("/login") - public ResponseEntity> login(@RequestBody User loginRequest) { - User user = userService.login(loginRequest.getUsername(), loginRequest.getPassword()); - if (user == null) { - throw new RuntimeException("Invalid username or password"); - } - Map response = new HashMap<>(); - response.put("userId", user.getId()); - response.put("user", user); - return ResponseEntity.ok(response); - } - - @GetMapping("/hello") - public String hello(){ - return "Hello SpringBoot!"; - } - - @PostMapping("/getVerificationCode") - public String getVerificationCode(@RequestBody String contact) { - return "Verification code sent to " + contact; - } -} \ No newline at end of file diff --git a/src/main/java/org/cmh/backend/authentication/controller/UserController.java b/src/main/java/org/cmh/backend/authentication/controller/UserController.java index a3a38c5..c53f329 100644 --- a/src/main/java/org/cmh/backend/authentication/controller/UserController.java +++ b/src/main/java/org/cmh/backend/authentication/controller/UserController.java @@ -1,55 +1,64 @@ package org.cmh.backend.authentication.controller; +import org.cmh.backend.Utils.JwtUtil; +import org.cmh.backend.authentication.dto.*; import org.cmh.backend.authentication.model.User; import org.cmh.backend.authentication.service.UserService; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @RestController -@RequestMapping("/users") public class UserController { @Autowired private UserService userService; - @CrossOrigin(origins = "http://localhost:3000") @PostMapping("/register") - public ResponseEntity register(@RequestBody User user) { + public ResponseEntity register(@RequestBody User user) { User registeredUser = userService.register(user); - return ResponseEntity.ok(registeredUser); + if (registeredUser == null) { + return new ResponseEntity<>(new RegisterResponse("用户已存在"),HttpStatus.BAD_REQUEST); + } + return new ResponseEntity<>(new RegisterResponse("注册成功"),HttpStatus.OK); } @PostMapping("/login") - public ResponseEntity login(@RequestParam String username, @RequestParam String password) { - User user = userService.login(username, password); + public ResponseEntity login(@RequestBody LoginRequest request) { + User user = userService.login(request.getUsername(), request.getPassword()); if (user != null) { - return ResponseEntity.ok(user); + return new ResponseEntity<>(new LoginResponse("登录成功", JwtUtil.generateToken(user.getUsername())), HttpStatus.OK); } - return ResponseEntity.status(401).build(); + return new ResponseEntity<>(new LoginResponse("登录失败", null), HttpStatus.UNAUTHORIZED); } - @PutMapping("/update") - public ResponseEntity updateUserInfo(@RequestBody User user) { - User updatedUser = userService.updateUserInfo(user); - return ResponseEntity.ok(updatedUser); + @PostMapping("/update") + public ResponseEntity updateUserInfo(@RequestBody UpdateRequest user) { + userService.updateUserInfo(user); + return ResponseEntity.ok().build(); } - @PutMapping("/changePassword") - public ResponseEntity changePassword(@RequestParam Long userId, @RequestParam String oldPassword, @RequestParam String newPassword) { - boolean isChanged = userService.changePassword(userId, oldPassword, newPassword); + @PostMapping("/changePassword") + public ResponseEntity changePassword(@RequestParam String username, @RequestParam String oldPassword, @RequestParam String newPassword) { + boolean isChanged = userService.changePassword(username, oldPassword, newPassword); if (isChanged) { return ResponseEntity.ok("Password changed successfully"); } return ResponseEntity.status(400).body("Old password is incorrect"); } - @GetMapping("/{userId}") - public ResponseEntity getUserInfo(@PathVariable Long userId) { - User user = userService.findById(userId).orElse(null); - if (user != null) { - return ResponseEntity.ok(user); + @PostMapping("/getVerificationCode") + public String getVerificationCode(@RequestBody String contact) { + return "Verification code sent to " + contact; + } + + @GetMapping("/profile") + public ResponseEntity getUserInfo(@RequestParam String token) { + if (!JwtUtil.isTokenValid(token)) { + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); } - return ResponseEntity.status(404).build(); + String username = JwtUtil.extractUsername(token); + return new ResponseEntity<>(userService.getUserInfo(username),HttpStatus.OK); } } \ No newline at end of file diff --git a/src/main/java/org/cmh/backend/authentication/dto/LoginRequest.java b/src/main/java/org/cmh/backend/authentication/dto/LoginRequest.java new file mode 100644 index 0000000..c0ae6fc --- /dev/null +++ b/src/main/java/org/cmh/backend/authentication/dto/LoginRequest.java @@ -0,0 +1,11 @@ +package org.cmh.backend.authentication.dto; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class LoginRequest { + private String username; + private String password; +} diff --git a/src/main/java/org/cmh/backend/authentication/dto/LoginResponse.java b/src/main/java/org/cmh/backend/authentication/dto/LoginResponse.java new file mode 100644 index 0000000..c7b0256 --- /dev/null +++ b/src/main/java/org/cmh/backend/authentication/dto/LoginResponse.java @@ -0,0 +1,13 @@ +package org.cmh.backend.authentication.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@AllArgsConstructor +public class LoginResponse { + private String message; + private String token; +} diff --git a/src/main/java/org/cmh/backend/authentication/dto/ProfileResponse.java b/src/main/java/org/cmh/backend/authentication/dto/ProfileResponse.java new file mode 100644 index 0000000..d60fed8 --- /dev/null +++ b/src/main/java/org/cmh/backend/authentication/dto/ProfileResponse.java @@ -0,0 +1,19 @@ +package org.cmh.backend.authentication.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +import java.time.LocalDateTime; + +@Getter +@Setter +@AllArgsConstructor +public class ProfileResponse { + private String username; + private String email; + private String role; + private String phoneNumber; + private String company; + private LocalDateTime createdDate; +} diff --git a/src/main/java/org/cmh/backend/authentication/dto/RegisterResponse.java b/src/main/java/org/cmh/backend/authentication/dto/RegisterResponse.java new file mode 100644 index 0000000..10d7dd2 --- /dev/null +++ b/src/main/java/org/cmh/backend/authentication/dto/RegisterResponse.java @@ -0,0 +1,12 @@ +package org.cmh.backend.authentication.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@AllArgsConstructor +public class RegisterResponse { + private String message; +} diff --git a/src/main/java/org/cmh/backend/authentication/dto/UpdateRequest.java b/src/main/java/org/cmh/backend/authentication/dto/UpdateRequest.java new file mode 100644 index 0000000..9ba3ea3 --- /dev/null +++ b/src/main/java/org/cmh/backend/authentication/dto/UpdateRequest.java @@ -0,0 +1,15 @@ +package org.cmh.backend.authentication.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@AllArgsConstructor +public class UpdateRequest { + private String username; + private String email; + private String phoneNumber; + private String company; +} diff --git a/src/main/java/org/cmh/backend/authentication/repository/UserRepository.java b/src/main/java/org/cmh/backend/authentication/repository/UserRepository.java index 473bba9..28958f8 100644 --- a/src/main/java/org/cmh/backend/authentication/repository/UserRepository.java +++ b/src/main/java/org/cmh/backend/authentication/repository/UserRepository.java @@ -9,6 +9,4 @@ import java.util.Optional; @Repository public interface UserRepository extends JpaRepository { User findByUsername(String username); - Optional findById(Long id); - User save(User user); } \ No newline at end of file diff --git a/src/main/java/org/cmh/backend/authentication/service/UserService.java b/src/main/java/org/cmh/backend/authentication/service/UserService.java index 3e2c708..54be38f 100644 --- a/src/main/java/org/cmh/backend/authentication/service/UserService.java +++ b/src/main/java/org/cmh/backend/authentication/service/UserService.java @@ -1,14 +1,72 @@ package org.cmh.backend.authentication.service; +import org.cmh.backend.authentication.dto.ProfileResponse; +import org.cmh.backend.authentication.dto.UpdateRequest; import org.cmh.backend.authentication.model.User; +import org.cmh.backend.authentication.repository.UserRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; -import java.util.Optional; +import java.time.LocalDateTime; // UserService.java -public interface UserService { - User register(User user); - User login(String username, String password); - User updateUserInfo(User user); - boolean changePassword(Long userId, String oldPassword, String newPassword); - Optional findById(Long id); +@Service +public class UserService { + + @Autowired + private UserRepository userRepository; + + private final PasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); + + public User register(User user) { + User existingUser = userRepository.findByUsername(user.getUsername()); + if (existingUser != null) { + return null; + } + user.setPassword(passwordEncoder.encode(user.getPassword())); + user.setCreatedDate(LocalDateTime.now()); + return userRepository.save(user); + } + + public User login(String username, String password) { + User user = userRepository.findByUsername(username); + if (user != null && passwordEncoder.matches(password, user.getPassword())) { + return user; + } + return null; + } + + public void updateUserInfo(UpdateRequest newUser) { + User user = userRepository.findByUsername(newUser.getUsername()); + if (user != null) { + user.setEmail(newUser.getEmail()); + user.setPhoneNumber(newUser.getPhoneNumber()); + user.setCompany(newUser.getCompany()); + userRepository.save(user); + } + } + + public boolean changePassword(String username, String oldPassword, String newPassword) { + User user = userRepository.findByUsername(username); + if (user != null && passwordEncoder.matches(oldPassword, user.getPassword())) { + user.setPassword(passwordEncoder.encode(newPassword)); + userRepository.save(user); + return true; + } + return false; + } + + public ProfileResponse getUserInfo(String username) { + User user = userRepository.findByUsername(username); + return new ProfileResponse( + user.getUsername(), + user.getEmail(), + user.getRole(), + user.getPhoneNumber(), + user.getCompany(), + user.getCreatedDate() + ); + } } \ No newline at end of file diff --git a/src/main/java/org/cmh/backend/authentication/service/UserServiceImpl.java b/src/main/java/org/cmh/backend/authentication/service/UserServiceImpl.java deleted file mode 100644 index ae8be9b..0000000 --- a/src/main/java/org/cmh/backend/authentication/service/UserServiceImpl.java +++ /dev/null @@ -1,58 +0,0 @@ -package org.cmh.backend.authentication.service; - -import org.cmh.backend.authentication.model.User; -import org.cmh.backend.authentication.repository.UserRepository; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.stereotype.Service; - -import java.time.LocalDateTime; -import java.util.Optional; - -// UserServiceImpl.java -@Service -public class UserServiceImpl implements UserService { - - @Autowired - private UserRepository userRepository; - - @Autowired - private PasswordEncoder passwordEncoder; - - @Override - public User register(User user) { - user.setPassword(passwordEncoder.encode(user.getPassword())); - user.setCreatedDate(LocalDateTime.now()); - return userRepository.save(user); - } - - @Override - public User login(String username, String password) { - User user = userRepository.findByUsername(username); - if (user != null && passwordEncoder.matches(password, user.getPassword())) { - return user; - } - return null; - } - - @Override - public User updateUserInfo(User user) { - return userRepository.save(user); - } - - @Override - public boolean changePassword(Long userId, String oldPassword, String newPassword) { - User user = userRepository.findById(userId).orElse(null); - if (user != null && passwordEncoder.matches(oldPassword, user.getPassword())) { - user.setPassword(passwordEncoder.encode(newPassword)); - userRepository.save(user); - return true; - } - return false; - } - - @Override - public Optional findById(Long id) { - return userRepository.findById(id); - } -} \ No newline at end of file diff --git a/src/test/application-test.properties b/src/test/application-test.properties deleted file mode 100644 index 77d29e8..0000000 --- a/src/test/application-test.properties +++ /dev/null @@ -1,7 +0,0 @@ -spring.datasource.url=jdbc:h2:mem:testdb -spring.datasource.driverClassName=org.h2.Driver -spring.datasource.username=sa -spring.datasource.password=password -spring.jpa.database-platform=org.hibernate.dialect.H2Dialect -spring.jpa.hibernate.ddl-auto=update -spring.h2.console.enabled=true \ No newline at end of file diff --git a/src/test/java/org/cmh/backend/BackendApplicationTests.java b/src/test/java/org/cmh/backend/BackendApplicationTests.java deleted file mode 100644 index e490cdf..0000000 --- a/src/test/java/org/cmh/backend/BackendApplicationTests.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.cmh.backend; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest -public class BackendApplicationTests { - - @Test - void contextLoads() { - } -} \ No newline at end of file diff --git a/src/test/java/org/cmh/backend/TestBackendApplication.java b/src/test/java/org/cmh/backend/TestBackendApplication.java deleted file mode 100644 index 52bb0ff..0000000 --- a/src/test/java/org/cmh/backend/TestBackendApplication.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.cmh.backend; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class TestBackendApplication { - - public static void main(String[] args) { - SpringApplication.run(TestBackendApplication.class, args); - } -} \ No newline at end of file diff --git a/src/test/java/org/cmh/backend/TestcontainersConfiguration.java b/src/test/java/org/cmh/backend/TestcontainersConfiguration.java deleted file mode 100644 index 27f9122..0000000 --- a/src/test/java/org/cmh/backend/TestcontainersConfiguration.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.cmh.backend; - -import org.springframework.boot.test.context.TestConfiguration; -import org.springframework.boot.testcontainers.service.connection.ServiceConnection; -import org.springframework.context.annotation.Bean; -import org.testcontainers.containers.MariaDBContainer; -import org.testcontainers.containers.MySQLContainer; -import org.testcontainers.utility.DockerImageName; - -@TestConfiguration(proxyBeanMethods = false) -class TestcontainersConfiguration { - - @Bean - @ServiceConnection - MariaDBContainer mariaDbContainer() { - return new MariaDBContainer<>(DockerImageName.parse("mariadb:latest")); - } - - @Bean - @ServiceConnection - MySQLContainer mysqlContainer() { - return new MySQLContainer<>(DockerImageName.parse("mysql:latest")); - } - -} diff --git a/src/test/java/org/cmh/backend/Utils/JwtVerifyAspectTest.java b/src/test/java/org/cmh/backend/Utils/JwtVerifyAspectTest.java deleted file mode 100644 index 22b12e1..0000000 --- a/src/test/java/org/cmh/backend/Utils/JwtVerifyAspectTest.java +++ /dev/null @@ -1,88 +0,0 @@ -package org.cmh.backend.Utils; - -import org.cmh.backend.authentication.service.UserService; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.runner.RunWith; -import org.mockito.InjectMocks; -import org.mockito.Mockito; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.EnableAspectJAutoProxy; -import org.springframework.context.annotation.Import; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -public class JwtVerifyAspectTest { - - @Configuration - @EnableAspectJAutoProxy - @Import({JwtVerifyAspect.class}) - static class Config { - @Bean - public JwtUtil jwtUtil() { - return Mockito.mock(JwtUtil.class); - } - - @Bean - public UserService userService() { - return Mockito.mock(UserService.class); - } - } - - private JwtUtil jwtUtil = new JwtUtil(); - - @InjectMocks - private JwtVerifyAspect jwtVerifyAspect; - - @BeforeClass - public static void setUpClass() { - // Static setup if needed - } - - @Before - public void setUp() { - Mockito.when(jwtUtil.isTokenValid("validToken")).thenReturn(true); - Mockito.when(jwtUtil.isTokenValid("invalidToken")).thenReturn(false); - } - - // TODO:这个测试跑不动,有问题,先取消掉 -// @Test -// public void testVerify() { -// SomeController validTokenController = new SomeController("validToken"); -// SomeController invalidTokenController = new SomeController("invalidToken"); -// -// Assert.assertTrue("Valid token should pass verification", validTokenController.run()); -// Assert.assertFalse("Invalid token should fail verification", invalidTokenController.run()); -// } -} - -class SomeController { - private SomeJwtRequest request; - - SomeController(String token) { - this.request = new SomeJwtRequest(token, "test"); - } - - public boolean run() { - try { - return verify(request); - } catch (JwtValidationException e) { - return false; - } - } - - @JwtVerify - public boolean verify(SomeJwtRequest request) { - return true; - } -} - -class SomeJwtRequest extends JwtRequest { - String msg; - - public SomeJwtRequest(String token, String msg) { - super.setToken(token); - this.msg = msg; - } -} \ No newline at end of file From 9569a30a8aa096894d220e2b72e56f701fb5d155 Mon Sep 17 00:00:00 2001 From: "Chester.X" <2931709855@qq.com> Date: Thu, 4 Jul 2024 22:47:52 +0800 Subject: [PATCH 03/14] =?UTF-8?q?=E5=AE=8C=E6=88=90=E4=BA=86=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E4=B8=8A=E4=BC=A0=E7=9A=84Controller?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/FileController.java | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/cmh/backend/CourseManagement/controller/FileController.java b/src/main/java/org/cmh/backend/CourseManagement/controller/FileController.java index 99d9350..7c488b0 100644 --- a/src/main/java/org/cmh/backend/CourseManagement/controller/FileController.java +++ b/src/main/java/org/cmh/backend/CourseManagement/controller/FileController.java @@ -1,20 +1,49 @@ package org.cmh.backend.CourseManagement.controller; +import org.cmh.backend.CourseManagement.dto.UploadFileResponse; import org.springframework.core.io.UrlResource; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.*; import org.springframework.core.io.Resource; +import org.springframework.web.multipart.MultipartFile; +import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +@RestController +@RequestMapping("/courses") public class FileController { private static final String UPLOAD_DIR = "uploads/"; + @PostMapping("/upload") + public ResponseEntity uploadFile(@RequestParam("file") MultipartFile file) { + if (file.isEmpty()) { + return new ResponseEntity<>(new UploadFileResponse("文件不能为空", null), HttpStatus.BAD_REQUEST); + } + + try { + // 确保上传目录存在 + Path uploadDirPath = Paths.get(UPLOAD_DIR); + if (!Files.exists(uploadDirPath)) { + Files.createDirectories(uploadDirPath); + } + + // 生成文件路径 + byte[] bytes = file.getBytes(); + Path path = Paths.get(UPLOAD_DIR + file.getOriginalFilename()); + Files.write(path, bytes); + + // 返回成功信息 + return new ResponseEntity<>(new UploadFileResponse("文件上传成功", "/api/courses/files/" + file.getOriginalFilename()), HttpStatus.OK); + } catch (IOException e) { + return new ResponseEntity<>(new UploadFileResponse("文件上传失败", null), HttpStatus.INTERNAL_SERVER_ERROR); + } + } @GetMapping("/files/{filename}") public ResponseEntity getFile(@PathVariable String filename) { try { From fe58248efc3579645ce3baacb56e658f284d8b67 Mon Sep 17 00:00:00 2001 From: "Chester.X" <2931709855@qq.com> Date: Thu, 4 Jul 2024 22:49:05 +0800 Subject: [PATCH 04/14] =?UTF-8?q?=E5=AE=8C=E6=88=90=E4=BA=86Course?= =?UTF-8?q?=E7=9A=84=E7=9B=B8=E5=85=B3=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CourseManagement/model/Course.java | 20 +- .../repository/CourseRepository.java | 5 +- .../service/CourseService.java | 232 ++++++++++++------ 3 files changed, 176 insertions(+), 81 deletions(-) diff --git a/src/main/java/org/cmh/backend/CourseManagement/model/Course.java b/src/main/java/org/cmh/backend/CourseManagement/model/Course.java index caa9186..84847b1 100644 --- a/src/main/java/org/cmh/backend/CourseManagement/model/Course.java +++ b/src/main/java/org/cmh/backend/CourseManagement/model/Course.java @@ -2,21 +2,21 @@ package org.cmh.backend.CourseManagement.model; import jakarta.persistence.*; import lombok.Data; - +import lombok.Getter; +import lombok.Setter; @Data @Entity -@Table(name = "courses") +@Getter +@Setter public class Course { - @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - private String name; - private String description; - private String author; - private String sortOrder; - private String coverImagePath; - private String videoPath; - // getters and setters + private String title; + private String description; + private String order; + private String author; + private String videoPath; + private String imagePath; } \ No newline at end of file diff --git a/src/main/java/org/cmh/backend/CourseManagement/repository/CourseRepository.java b/src/main/java/org/cmh/backend/CourseManagement/repository/CourseRepository.java index ce25b61..d65909a 100644 --- a/src/main/java/org/cmh/backend/CourseManagement/repository/CourseRepository.java +++ b/src/main/java/org/cmh/backend/CourseManagement/repository/CourseRepository.java @@ -1,9 +1,10 @@ package org.cmh.backend.CourseManagement.repository; import org.cmh.backend.CourseManagement.model.Course; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; -import java.util.Optional; public interface CourseRepository extends JpaRepository { - Optional findByName(String name); + Page findAllByOrderByIdDesc(Pageable pageable); } \ No newline at end of file diff --git a/src/main/java/org/cmh/backend/CourseManagement/service/CourseService.java b/src/main/java/org/cmh/backend/CourseManagement/service/CourseService.java index f49676f..448c175 100644 --- a/src/main/java/org/cmh/backend/CourseManagement/service/CourseService.java +++ b/src/main/java/org/cmh/backend/CourseManagement/service/CourseService.java @@ -1,96 +1,190 @@ +//package org.cmh.backend.CourseManagement.service; +// +//import org.cmh.backend.CourseManagement.model.Course; +//import org.cmh.backend.CourseManagement.repository.CourseRepository; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.stereotype.Service; +//import org.springframework.web.multipart.MultipartFile; +// +//import java.io.IOException; +//import java.nio.file.Files; +//import java.nio.file.Path; +//import java.nio.file.Paths; +//import java.util.List; +//import java.util.Optional; +// +//@Service +//public class CourseService { +// +// @Autowired +// private CourseRepository courseRepository; +// +// public Course createCourse(String name, String description, String author, String sortOrder, MultipartFile coverImage, MultipartFile video) { +// Optional existingCourse = courseRepository.findByName(name); +// if (existingCourse.isPresent()) { +// return null; +// } +// +// Course course = new Course(); +// course.setName(name); +// course.setDescription(description); +// course.setAuthor(author); +// course.setSortOrder(sortOrder); +// +// try { +// if (coverImage != null && !coverImage.isEmpty()) { +// String coverImagePath = saveFile(coverImage); +// course.setCoverImagePath(coverImagePath); +// } +// if (video != null && !video.isEmpty()) { +// String videoPath = saveFile(video); +// course.setVideoPath(videoPath); +// } +// } catch (IOException e) { +// e.printStackTrace(); +// return null; +// } +// +// return courseRepository.save(course); +// } +// +// public Course updateCourse(Long id, String name, String description, String author, String sortOrder, MultipartFile coverImage, MultipartFile video) { +// return courseRepository.findById(id) +// .map(course -> { +// course.setName(name); +// course.setDescription(description); +// course.setAuthor(author); +// course.setSortOrder(sortOrder); +// +// try { +// if (coverImage != null && !coverImage.isEmpty()) { +// String coverImagePath = saveFile(coverImage); +// course.setCoverImagePath(coverImagePath); +// } +// if (video != null && !video.isEmpty()) { +// String videoPath = saveFile(video); +// course.setVideoPath(videoPath); +// } +// } catch (IOException e) { +// e.printStackTrace(); +// return null; +// } +// +// return courseRepository.save(course); +// }).orElse(null); +// } +// +// private String saveFile(MultipartFile file) throws IOException { +// String filename = System.currentTimeMillis() + "_" + file.getOriginalFilename(); +// Path filePath = Paths.get("uploads", filename); +// Files.createDirectories(filePath.getParent()); +// Files.write(filePath, file.getBytes()); +// return filePath.toString(); +// } +// +// public boolean deleteCourse(Long id) { +// return courseRepository.findById(id) +// .map(course -> { +// courseRepository.delete(course); +// return true; +// }).orElse(false); +// } +// +// public List getAllCourses() { +// return courseRepository.findAll(); +// } +//} package org.cmh.backend.CourseManagement.service; +import jakarta.persistence.EntityNotFoundException; +import org.cmh.backend.CourseManagement.dto.CourseRequest; import org.cmh.backend.CourseManagement.model.Course; import org.cmh.backend.CourseManagement.repository.CourseRepository; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; -import org.springframework.web.multipart.MultipartFile; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; +import java.util.ArrayList; import java.util.List; -import java.util.Optional; @Service public class CourseService { - @Autowired private CourseRepository courseRepository; - public Course createCourse(String name, String description, String author, String sortOrder, MultipartFile coverImage, MultipartFile video) { - Optional existingCourse = courseRepository.findByName(name); - if (existingCourse.isPresent()) { - return null; + public List getCoursesByRange(int start, int end) { + if (start < 0 || end <= start) { + throw new IllegalArgumentException("Invalid start or end range"); } + int pageSize = end - start; // 计算每页的大小 + int startPageNumber = start / pageSize; // 计算起始页码 + int endPageNumber = (end - 1) / pageSize; // 计算结束页码 + + List result = new ArrayList<>(); + + for (int pageNumber = startPageNumber; pageNumber <= endPageNumber; pageNumber++) { + Pageable pageable = PageRequest.of(pageNumber, pageSize); + Page coursePage = courseRepository.findAllByOrderByIdDesc(pageable); + + if (coursePage.hasContent()) { + result.addAll(coursePage.getContent()); + } else { + break; // 如果没有更多内容,提前退出 + } + } + + int startIndex = start % pageSize; + int endIndex = startIndex + (end - start); + + if (endIndex > result.size()) { + endIndex = result.size(); + } + + return result.subList(startIndex, endIndex); + } + + public void createCourse(CourseRequest request) { Course course = new Course(); - course.setName(name); - course.setDescription(description); - course.setAuthor(author); - course.setSortOrder(sortOrder); + course.setTitle(request.getTitle()); + course.setDescription(request.getDescription()); + course.setOrder(request.getOrder()); + course.setAuthor(request.getAuthor()); + course.setVideoPath(request.getVideoPath()); + course.setImagePath(request.getImagePath()); + courseRepository.save(course); + } - try { - if (coverImage != null && !coverImage.isEmpty()) { - String coverImagePath = saveFile(coverImage); - course.setCoverImagePath(coverImagePath); - } - if (video != null && !video.isEmpty()) { - String videoPath = saveFile(video); - course.setVideoPath(videoPath); - } - } catch (IOException e) { - e.printStackTrace(); - return null; + public void updateCourse(Long id, CourseRequest request) { + Course course = courseRepository.findById(id).orElse(null); + if (course != null) { + course.setTitle(request.getTitle()); + course.setDescription(request.getDescription()); + course.setOrder(request.getOrder()); + course.setAuthor(request.getAuthor()); + course.setVideoPath(request.getVideoPath()); + course.setImagePath(request.getImagePath()); + courseRepository.save(course); } - - return courseRepository.save(course); } - public Course updateCourse(Long id, String name, String description, String author, String sortOrder, MultipartFile coverImage, MultipartFile video) { - return courseRepository.findById(id) - .map(course -> { - course.setName(name); - course.setDescription(description); - course.setAuthor(author); - course.setSortOrder(sortOrder); - - try { - if (coverImage != null && !coverImage.isEmpty()) { - String coverImagePath = saveFile(coverImage); - course.setCoverImagePath(coverImagePath); - } - if (video != null && !video.isEmpty()) { - String videoPath = saveFile(video); - course.setVideoPath(videoPath); - } - } catch (IOException e) { - e.printStackTrace(); - return null; - } - - return courseRepository.save(course); - }).orElse(null); + public void deleteCourse(Long id) { + if (!courseRepository.existsById(id)) { + throw new EntityNotFoundException(); + } + courseRepository.deleteById(id); } - private String saveFile(MultipartFile file) throws IOException { - String filename = System.currentTimeMillis() + "_" + file.getOriginalFilename(); - Path filePath = Paths.get("uploads", filename); - Files.createDirectories(filePath.getParent()); - Files.write(filePath, file.getBytes()); - return filePath.toString(); + public Course getCourseById(Long id) { + if (!courseRepository.existsById(id)) { + throw new EntityNotFoundException(); + } + return courseRepository.findById(id).orElse(null); } - public boolean deleteCourse(Long id) { - return courseRepository.findById(id) - .map(course -> { - courseRepository.delete(course); - return true; - }).orElse(false); - } - - public List getAllCourses() { - return courseRepository.findAll(); + public long getCourseCount() { + return courseRepository.count(); } } \ No newline at end of file From aae8147143d54b405d705077fba5df28df07dfe2 Mon Sep 17 00:00:00 2001 From: "Chester.X" <2931709855@qq.com> Date: Thu, 4 Jul 2024 22:49:48 +0800 Subject: [PATCH 05/14] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BA=86=E5=85=A8?= =?UTF-8?q?=E5=B1=80=E6=96=87=E4=BB=B6=E4=B8=8A=E4=BC=A0=E5=A4=A7=E5=B0=8F?= =?UTF-8?q?=E9=99=90=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application.properties | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index bceeb5c..5087f51 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -20,5 +20,9 @@ spring.datasource.hikari.connection-timeout=30000 server.servlet.encoding.enabled=true server.servlet.encoding.force=true server.servlet.encoding.charset=utf-8 +# set the max size of a single file +spring.servlet.multipart.max-file-size=500MB +# set the max size of the total request +spring.servlet.multipart.max-request-size=500MB From dafdf82f5d4aad7b7fb36cd7c1590b3e8792781a Mon Sep 17 00:00:00 2001 From: "Chester.X" <2931709855@qq.com> Date: Thu, 4 Jul 2024 22:50:11 +0800 Subject: [PATCH 06/14] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E4=BA=86Course?= =?UTF-8?q?=E7=9B=B8=E5=85=B3dto?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CourseManagement/dto/CourseRequest.java | 16 ++++++++++++++++ .../dto/GetCourseListResponse.java | 16 ++++++++++++++++ .../CourseManagement/dto/MessageResponse.java | 12 ++++++++++++ .../CourseManagement/dto/UploadFileResponse.java | 15 +++++++++++++++ 4 files changed, 59 insertions(+) create mode 100644 src/main/java/org/cmh/backend/CourseManagement/dto/CourseRequest.java create mode 100644 src/main/java/org/cmh/backend/CourseManagement/dto/GetCourseListResponse.java create mode 100644 src/main/java/org/cmh/backend/CourseManagement/dto/MessageResponse.java create mode 100644 src/main/java/org/cmh/backend/CourseManagement/dto/UploadFileResponse.java diff --git a/src/main/java/org/cmh/backend/CourseManagement/dto/CourseRequest.java b/src/main/java/org/cmh/backend/CourseManagement/dto/CourseRequest.java new file mode 100644 index 0000000..aba6f9e --- /dev/null +++ b/src/main/java/org/cmh/backend/CourseManagement/dto/CourseRequest.java @@ -0,0 +1,16 @@ +package org.cmh.backend.CourseManagement.dto; + +import lombok.Getter; +import lombok.Setter; +import org.cmh.backend.Utils.JwtRequest; + +@Getter +@Setter +public class CourseRequest extends JwtRequest { + private String title; + private String description; + private String order; + private String author; + private String videoPath; + private String imagePath; +} \ No newline at end of file diff --git a/src/main/java/org/cmh/backend/CourseManagement/dto/GetCourseListResponse.java b/src/main/java/org/cmh/backend/CourseManagement/dto/GetCourseListResponse.java new file mode 100644 index 0000000..8e9d3d9 --- /dev/null +++ b/src/main/java/org/cmh/backend/CourseManagement/dto/GetCourseListResponse.java @@ -0,0 +1,16 @@ +package org.cmh.backend.CourseManagement.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; +import org.cmh.backend.CourseManagement.model.Course; + +import java.util.List; + +@Getter +@Setter +@AllArgsConstructor +public class GetCourseListResponse { + Long courseCount; + List courseList; +} \ No newline at end of file diff --git a/src/main/java/org/cmh/backend/CourseManagement/dto/MessageResponse.java b/src/main/java/org/cmh/backend/CourseManagement/dto/MessageResponse.java new file mode 100644 index 0000000..92a14fa --- /dev/null +++ b/src/main/java/org/cmh/backend/CourseManagement/dto/MessageResponse.java @@ -0,0 +1,12 @@ +package org.cmh.backend.CourseManagement.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@AllArgsConstructor +public class MessageResponse { + String message; +} \ No newline at end of file diff --git a/src/main/java/org/cmh/backend/CourseManagement/dto/UploadFileResponse.java b/src/main/java/org/cmh/backend/CourseManagement/dto/UploadFileResponse.java new file mode 100644 index 0000000..2a8edb3 --- /dev/null +++ b/src/main/java/org/cmh/backend/CourseManagement/dto/UploadFileResponse.java @@ -0,0 +1,15 @@ +package org.cmh.backend.CourseManagement.dto; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class UploadFileResponse extends MessageResponse { + private String url; + + public UploadFileResponse(String message, String url) { + super(message); + this.url = url; + } +} From f6d5112ad5c4853bc00cc0cd8067d69d9b3f5992 Mon Sep 17 00:00:00 2001 From: "Chester.X" <2931709855@qq.com> Date: Thu, 4 Jul 2024 22:50:35 +0800 Subject: [PATCH 07/14] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E4=BA=86CourseControll?= =?UTF-8?q?er?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/CourseController.java | 97 +++++++++++-------- 1 file changed, 54 insertions(+), 43 deletions(-) diff --git a/src/main/java/org/cmh/backend/CourseManagement/controller/CourseController.java b/src/main/java/org/cmh/backend/CourseManagement/controller/CourseController.java index 3602384..0cf183d 100644 --- a/src/main/java/org/cmh/backend/CourseManagement/controller/CourseController.java +++ b/src/main/java/org/cmh/backend/CourseManagement/controller/CourseController.java @@ -1,67 +1,78 @@ package org.cmh.backend.CourseManagement.controller; +import jakarta.persistence.EntityNotFoundException; +import org.cmh.backend.CourseManagement.dto.GetCourseListResponse; +import org.cmh.backend.CourseManagement.dto.MessageResponse; +import org.cmh.backend.CourseManagement.dto.CourseRequest; import org.cmh.backend.CourseManagement.model.Course; import org.cmh.backend.CourseManagement.service.CourseService; +import org.cmh.backend.Utils.JwtVerify; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; -import org.springframework.http.HttpStatus; - -import java.util.List; @RestController -@RequestMapping("/course") +@RequestMapping("/courses") public class CourseController { - @Autowired private CourseService courseService; - @PostMapping("/create") - public ResponseEntity createCourse( - @RequestParam("name") String name, - @RequestParam("description") String description, - @RequestParam("author") String author, - @RequestParam("sortOrder") String sortOrder, - @RequestParam("coverImage") MultipartFile coverImage, - @RequestParam("video") MultipartFile video) { - - Course createdCourse = courseService.createCourse(name, description, author, sortOrder, coverImage, video); - if (createdCourse == null) { - return new ResponseEntity<>("课程已存在", HttpStatus.BAD_REQUEST); + @GetMapping + @JwtVerify + public ResponseEntity getCoursesByRange(@RequestParam Integer start, @RequestParam Integer end, @RequestParam String token) { + if (start >= end) { + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); } - return new ResponseEntity<>("课程创建成功", HttpStatus.OK); + long courseCount = courseService.getCourseCount(); + return new ResponseEntity<>(new GetCourseListResponse(courseCount, courseService.getCoursesByRange(start, end)), HttpStatus.OK); } - @PutMapping("/edit/{id}") - public ResponseEntity updateCourse( - @PathVariable Long id, - @RequestParam("name") String name, - @RequestParam("description") String description, - @RequestParam("author") String author, - @RequestParam("sortOrder") String sortOrder, - @RequestParam(value = "coverImage", required = false) MultipartFile coverImage, - @RequestParam(value = "video", required = false) MultipartFile video) { - - Course updatedCourse = courseService.updateCourse(id, name, description, author, sortOrder, coverImage, video); - if (updatedCourse == null) { - return new ResponseEntity<>("课程未找到", HttpStatus.NOT_FOUND); + @GetMapping("/{id}") + @JwtVerify + public ResponseEntity getCoursePage(@PathVariable Long id, @RequestParam String token) { + try { + return new ResponseEntity<>(courseService.getCourseById(id), HttpStatus.OK); + } catch (EntityNotFoundException e) { + return new ResponseEntity<>(HttpStatus.NOT_FOUND); } - return new ResponseEntity<>("课程修改成功", HttpStatus.OK); } - @DeleteMapping("/delete/{id}") - public ResponseEntity deleteCourse(@PathVariable Long id) { - boolean isDeleted = courseService.deleteCourse(id); - if (!isDeleted) { - return new ResponseEntity<>("课程未找到", HttpStatus.NOT_FOUND); + @PostMapping + @JwtVerify + public ResponseEntity createCourse(@RequestBody CourseRequest request) { + try { + courseService.createCourse(request); + } catch (DataIntegrityViolationException e) { + return new ResponseEntity<>(new MessageResponse("创建失败,课程已存在或缺少字段"), HttpStatus.BAD_REQUEST); + } catch (Exception e) { + return new ResponseEntity<>(new MessageResponse("创建失败:" + e.getMessage()), HttpStatus.BAD_REQUEST); } - return new ResponseEntity<>("课程删除成功", HttpStatus.OK); + return new ResponseEntity<>(new MessageResponse("创建成功"), HttpStatus.CREATED); } - @GetMapping("/getAll") - public ResponseEntity> getAllCourses() { - List courses = courseService.getAllCourses(); - return new ResponseEntity<>(courses, HttpStatus.OK); + @PutMapping("/{id}") + @JwtVerify + public ResponseEntity updateCourse(@PathVariable Long id, @RequestBody CourseRequest request) { + try { + courseService.updateCourse(id, request); + } catch (DataIntegrityViolationException e) { + return new ResponseEntity<>(new MessageResponse("修改失败,新标题已存在或缺少字段"), HttpStatus.BAD_REQUEST); + } catch (Exception e) { + return new ResponseEntity<>(new MessageResponse("修改失败:" + e.getMessage()), HttpStatus.BAD_REQUEST); + } + return new ResponseEntity<>(new MessageResponse("修改成功"), HttpStatus.OK); + } + + @DeleteMapping("/{id}") + @JwtVerify + public ResponseEntity deleteCourse(@PathVariable Long id, @RequestParam String token) { + try { + courseService.deleteCourse(id); + } catch (EntityNotFoundException e) { + return new ResponseEntity<>(new MessageResponse("删除失败,课程不存在"), HttpStatus.BAD_REQUEST); + } + return new ResponseEntity<>(new MessageResponse("删除成功"), HttpStatus.OK); } } \ No newline at end of file From 780e4793de9c083096d274394d6841565622afc0 Mon Sep 17 00:00:00 2001 From: "Chester.X" <2931709855@qq.com> Date: Thu, 4 Jul 2024 22:51:24 +0800 Subject: [PATCH 08/14] =?UTF-8?q?=E5=8E=BB=E6=8E=89=E4=BA=86verify?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CourseManagement/controller/CourseController.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/cmh/backend/CourseManagement/controller/CourseController.java b/src/main/java/org/cmh/backend/CourseManagement/controller/CourseController.java index 0cf183d..23a56c7 100644 --- a/src/main/java/org/cmh/backend/CourseManagement/controller/CourseController.java +++ b/src/main/java/org/cmh/backend/CourseManagement/controller/CourseController.java @@ -20,7 +20,7 @@ public class CourseController { private CourseService courseService; @GetMapping - @JwtVerify +// @JwtVerify public ResponseEntity getCoursesByRange(@RequestParam Integer start, @RequestParam Integer end, @RequestParam String token) { if (start >= end) { return new ResponseEntity<>(HttpStatus.BAD_REQUEST); @@ -30,7 +30,7 @@ public class CourseController { } @GetMapping("/{id}") - @JwtVerify +// @JwtVerify public ResponseEntity getCoursePage(@PathVariable Long id, @RequestParam String token) { try { return new ResponseEntity<>(courseService.getCourseById(id), HttpStatus.OK); @@ -40,7 +40,7 @@ public class CourseController { } @PostMapping - @JwtVerify +// @JwtVerify public ResponseEntity createCourse(@RequestBody CourseRequest request) { try { courseService.createCourse(request); @@ -53,7 +53,7 @@ public class CourseController { } @PutMapping("/{id}") - @JwtVerify +// @JwtVerify public ResponseEntity updateCourse(@PathVariable Long id, @RequestBody CourseRequest request) { try { courseService.updateCourse(id, request); @@ -66,7 +66,7 @@ public class CourseController { } @DeleteMapping("/{id}") - @JwtVerify +// @JwtVerify public ResponseEntity deleteCourse(@PathVariable Long id, @RequestParam String token) { try { courseService.deleteCourse(id); From 5885f365db9cf3a3ecc5a28e45024a38e2044cbf Mon Sep 17 00:00:00 2001 From: "Chester.X" <2931709855@qq.com> Date: Thu, 4 Jul 2024 23:02:49 +0800 Subject: [PATCH 09/14] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BA=86order=E5=AD=97?= =?UTF-8?q?=E6=AE=B5=E5=90=8D=E4=B8=BAorderNo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/cmh/backend/CourseManagement/model/Course.java | 5 ++--- .../cmh/backend/CourseManagement/service/CourseService.java | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/cmh/backend/CourseManagement/model/Course.java b/src/main/java/org/cmh/backend/CourseManagement/model/Course.java index 84847b1..137fae8 100644 --- a/src/main/java/org/cmh/backend/CourseManagement/model/Course.java +++ b/src/main/java/org/cmh/backend/CourseManagement/model/Course.java @@ -1,10 +1,9 @@ package org.cmh.backend.CourseManagement.model; import jakarta.persistence.*; -import lombok.Data; import lombok.Getter; import lombok.Setter; -@Data + @Entity @Getter @Setter @@ -15,7 +14,7 @@ public class Course { private String title; private String description; - private String order; + private String orderNo; private String author; private String videoPath; private String imagePath; diff --git a/src/main/java/org/cmh/backend/CourseManagement/service/CourseService.java b/src/main/java/org/cmh/backend/CourseManagement/service/CourseService.java index 448c175..ba64097 100644 --- a/src/main/java/org/cmh/backend/CourseManagement/service/CourseService.java +++ b/src/main/java/org/cmh/backend/CourseManagement/service/CourseService.java @@ -150,7 +150,7 @@ public class CourseService { Course course = new Course(); course.setTitle(request.getTitle()); course.setDescription(request.getDescription()); - course.setOrder(request.getOrder()); + course.setOrderNo(request.getOrder()); course.setAuthor(request.getAuthor()); course.setVideoPath(request.getVideoPath()); course.setImagePath(request.getImagePath()); @@ -162,7 +162,7 @@ public class CourseService { if (course != null) { course.setTitle(request.getTitle()); course.setDescription(request.getDescription()); - course.setOrder(request.getOrder()); + course.setOrderNo(request.getOrder()); course.setAuthor(request.getAuthor()); course.setVideoPath(request.getVideoPath()); course.setImagePath(request.getImagePath()); From f9272335f28929991aa77e6468a9146060b65cf3 Mon Sep 17 00:00:00 2001 From: "Chester.X" <2931709855@qq.com> Date: Thu, 4 Jul 2024 23:05:42 +0800 Subject: [PATCH 10/14] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BA=86=E5=85=B6?= =?UTF-8?q?=E4=BB=96=E6=A8=A1=E5=9D=97=E4=B8=AD=E7=9A=84order=E5=AD=97?= =?UTF-8?q?=E6=AE=B5=E5=90=8D=E4=B8=BAorderNo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/cmh/backend/CourseManagement/dto/CourseRequest.java | 2 +- .../cmh/backend/CourseManagement/service/CourseService.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/cmh/backend/CourseManagement/dto/CourseRequest.java b/src/main/java/org/cmh/backend/CourseManagement/dto/CourseRequest.java index aba6f9e..86b1ff7 100644 --- a/src/main/java/org/cmh/backend/CourseManagement/dto/CourseRequest.java +++ b/src/main/java/org/cmh/backend/CourseManagement/dto/CourseRequest.java @@ -9,7 +9,7 @@ import org.cmh.backend.Utils.JwtRequest; public class CourseRequest extends JwtRequest { private String title; private String description; - private String order; + private String orderNo; private String author; private String videoPath; private String imagePath; diff --git a/src/main/java/org/cmh/backend/CourseManagement/service/CourseService.java b/src/main/java/org/cmh/backend/CourseManagement/service/CourseService.java index ba64097..34f34b7 100644 --- a/src/main/java/org/cmh/backend/CourseManagement/service/CourseService.java +++ b/src/main/java/org/cmh/backend/CourseManagement/service/CourseService.java @@ -150,7 +150,7 @@ public class CourseService { Course course = new Course(); course.setTitle(request.getTitle()); course.setDescription(request.getDescription()); - course.setOrderNo(request.getOrder()); + course.setOrderNo(request.getOrderNo()); course.setAuthor(request.getAuthor()); course.setVideoPath(request.getVideoPath()); course.setImagePath(request.getImagePath()); @@ -162,7 +162,7 @@ public class CourseService { if (course != null) { course.setTitle(request.getTitle()); course.setDescription(request.getDescription()); - course.setOrderNo(request.getOrder()); + course.setOrderNo(request.getOrderNo()); course.setAuthor(request.getAuthor()); course.setVideoPath(request.getVideoPath()); course.setImagePath(request.getImagePath()); From d027e26f8cdad59046417db6ed6fe006a4759687 Mon Sep 17 00:00:00 2001 From: "Chester.X" <2931709855@qq.com> Date: Fri, 5 Jul 2024 01:52:46 +0800 Subject: [PATCH 11/14] =?UTF-8?q?=E5=AE=8C=E5=96=84=E4=BA=86=E5=88=A0?= =?UTF-8?q?=E9=99=A4=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/CourseService.java | 96 ------------------- 1 file changed, 96 deletions(-) diff --git a/src/main/java/org/cmh/backend/CourseManagement/service/CourseService.java b/src/main/java/org/cmh/backend/CourseManagement/service/CourseService.java index 34f34b7..d8c3926 100644 --- a/src/main/java/org/cmh/backend/CourseManagement/service/CourseService.java +++ b/src/main/java/org/cmh/backend/CourseManagement/service/CourseService.java @@ -1,99 +1,3 @@ -//package org.cmh.backend.CourseManagement.service; -// -//import org.cmh.backend.CourseManagement.model.Course; -//import org.cmh.backend.CourseManagement.repository.CourseRepository; -//import org.springframework.beans.factory.annotation.Autowired; -//import org.springframework.stereotype.Service; -//import org.springframework.web.multipart.MultipartFile; -// -//import java.io.IOException; -//import java.nio.file.Files; -//import java.nio.file.Path; -//import java.nio.file.Paths; -//import java.util.List; -//import java.util.Optional; -// -//@Service -//public class CourseService { -// -// @Autowired -// private CourseRepository courseRepository; -// -// public Course createCourse(String name, String description, String author, String sortOrder, MultipartFile coverImage, MultipartFile video) { -// Optional existingCourse = courseRepository.findByName(name); -// if (existingCourse.isPresent()) { -// return null; -// } -// -// Course course = new Course(); -// course.setName(name); -// course.setDescription(description); -// course.setAuthor(author); -// course.setSortOrder(sortOrder); -// -// try { -// if (coverImage != null && !coverImage.isEmpty()) { -// String coverImagePath = saveFile(coverImage); -// course.setCoverImagePath(coverImagePath); -// } -// if (video != null && !video.isEmpty()) { -// String videoPath = saveFile(video); -// course.setVideoPath(videoPath); -// } -// } catch (IOException e) { -// e.printStackTrace(); -// return null; -// } -// -// return courseRepository.save(course); -// } -// -// public Course updateCourse(Long id, String name, String description, String author, String sortOrder, MultipartFile coverImage, MultipartFile video) { -// return courseRepository.findById(id) -// .map(course -> { -// course.setName(name); -// course.setDescription(description); -// course.setAuthor(author); -// course.setSortOrder(sortOrder); -// -// try { -// if (coverImage != null && !coverImage.isEmpty()) { -// String coverImagePath = saveFile(coverImage); -// course.setCoverImagePath(coverImagePath); -// } -// if (video != null && !video.isEmpty()) { -// String videoPath = saveFile(video); -// course.setVideoPath(videoPath); -// } -// } catch (IOException e) { -// e.printStackTrace(); -// return null; -// } -// -// return courseRepository.save(course); -// }).orElse(null); -// } -// -// private String saveFile(MultipartFile file) throws IOException { -// String filename = System.currentTimeMillis() + "_" + file.getOriginalFilename(); -// Path filePath = Paths.get("uploads", filename); -// Files.createDirectories(filePath.getParent()); -// Files.write(filePath, file.getBytes()); -// return filePath.toString(); -// } -// -// public boolean deleteCourse(Long id) { -// return courseRepository.findById(id) -// .map(course -> { -// courseRepository.delete(course); -// return true; -// }).orElse(false); -// } -// -// public List getAllCourses() { -// return courseRepository.findAll(); -// } -//} package org.cmh.backend.CourseManagement.service; import jakarta.persistence.EntityNotFoundException; From c42a3a55ece12b565c40dd92f533933ee59ec604 Mon Sep 17 00:00:00 2001 From: "Chester.X" <2931709855@qq.com> Date: Fri, 5 Jul 2024 14:02:31 +0800 Subject: [PATCH 12/14] =?UTF-8?q?=E5=AE=8C=E5=96=84=E4=BA=86=E6=90=9C?= =?UTF-8?q?=E7=B4=A2=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/CourseController.java | 53 +++++++++-- .../dto/SearchCourseRequest.java | 18 ++++ .../repository/CourseRepository.java | 5 +- .../service/CourseService.java | 88 +++++++------------ .../specification/CourseSpecification.java | 34 +++++++ 5 files changed, 135 insertions(+), 63 deletions(-) create mode 100644 src/main/java/org/cmh/backend/CourseManagement/dto/SearchCourseRequest.java create mode 100644 src/main/java/org/cmh/backend/CourseManagement/specification/CourseSpecification.java diff --git a/src/main/java/org/cmh/backend/CourseManagement/controller/CourseController.java b/src/main/java/org/cmh/backend/CourseManagement/controller/CourseController.java index 23a56c7..b9b2d82 100644 --- a/src/main/java/org/cmh/backend/CourseManagement/controller/CourseController.java +++ b/src/main/java/org/cmh/backend/CourseManagement/controller/CourseController.java @@ -1,26 +1,32 @@ package org.cmh.backend.CourseManagement.controller; -import jakarta.persistence.EntityNotFoundException; import org.cmh.backend.CourseManagement.dto.GetCourseListResponse; import org.cmh.backend.CourseManagement.dto.MessageResponse; import org.cmh.backend.CourseManagement.dto.CourseRequest; +import org.cmh.backend.CourseManagement.dto.SearchCourseRequest; import org.cmh.backend.CourseManagement.model.Course; import org.cmh.backend.CourseManagement.service.CourseService; -import org.cmh.backend.Utils.JwtVerify; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataIntegrityViolationException; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import java.util.List; +import jakarta.persistence.EntityNotFoundException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + @RestController @RequestMapping("/courses") public class CourseController { + + private static final Logger logger = LoggerFactory.getLogger(CourseController.class); + @Autowired private CourseService courseService; @GetMapping -// @JwtVerify public ResponseEntity getCoursesByRange(@RequestParam Integer start, @RequestParam Integer end, @RequestParam String token) { if (start >= end) { return new ResponseEntity<>(HttpStatus.BAD_REQUEST); @@ -30,49 +36,82 @@ public class CourseController { } @GetMapping("/{id}") -// @JwtVerify public ResponseEntity getCoursePage(@PathVariable Long id, @RequestParam String token) { try { return new ResponseEntity<>(courseService.getCourseById(id), HttpStatus.OK); } catch (EntityNotFoundException e) { + logger.error("Course not found with id: {}", id, e); return new ResponseEntity<>(HttpStatus.NOT_FOUND); } } @PostMapping -// @JwtVerify public ResponseEntity createCourse(@RequestBody CourseRequest request) { try { courseService.createCourse(request); } catch (DataIntegrityViolationException e) { + logger.error("Create course failed: Data integrity violation", e); return new ResponseEntity<>(new MessageResponse("创建失败,课程已存在或缺少字段"), HttpStatus.BAD_REQUEST); } catch (Exception e) { + logger.error("Create course failed: {}", e.getMessage(), e); return new ResponseEntity<>(new MessageResponse("创建失败:" + e.getMessage()), HttpStatus.BAD_REQUEST); } return new ResponseEntity<>(new MessageResponse("创建成功"), HttpStatus.CREATED); } @PutMapping("/{id}") -// @JwtVerify public ResponseEntity updateCourse(@PathVariable Long id, @RequestBody CourseRequest request) { try { courseService.updateCourse(id, request); } catch (DataIntegrityViolationException e) { + logger.error("Update course failed: Data integrity violation", e); return new ResponseEntity<>(new MessageResponse("修改失败,新标题已存在或缺少字段"), HttpStatus.BAD_REQUEST); + } catch (EntityNotFoundException e) { + logger.error("Course not found with id: {}", id, e); + return new ResponseEntity<>(new MessageResponse("修改失败: 课程不存在"), HttpStatus.NOT_FOUND); } catch (Exception e) { + logger.error("Update course failed: {}", e.getMessage(), e); return new ResponseEntity<>(new MessageResponse("修改失败:" + e.getMessage()), HttpStatus.BAD_REQUEST); } return new ResponseEntity<>(new MessageResponse("修改成功"), HttpStatus.OK); } @DeleteMapping("/{id}") -// @JwtVerify public ResponseEntity deleteCourse(@PathVariable Long id, @RequestParam String token) { try { courseService.deleteCourse(id); } catch (EntityNotFoundException e) { + logger.error("Course not found with id: {}", id, e); return new ResponseEntity<>(new MessageResponse("删除失败,课程不存在"), HttpStatus.BAD_REQUEST); + } catch (Exception e) { + logger.error("Delete course failed: {}", e.getMessage(), e); + return new ResponseEntity<>(new MessageResponse("删除失败:" + e.getMessage()), HttpStatus.BAD_REQUEST); } return new ResponseEntity<>(new MessageResponse("删除成功"), HttpStatus.OK); } + + @GetMapping("/search") + public ResponseEntity searchCourses(@RequestParam String token, + @RequestParam(required = false) String title, + @RequestParam(required = false) String author, + @RequestParam(required = false) String description, + @RequestParam(required = false) String sortOrder, + @RequestParam Integer start, + @RequestParam Integer end) { + if (start >= end) { + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + } + + try { + SearchCourseRequest request = new SearchCourseRequest(token, title, author, description, sortOrder, start, end); + List courses = courseService.searchCourses(request); + long courseCount = courseService.getCourseCountByCriteria(title, author, description, sortOrder); + + return new ResponseEntity<>(new GetCourseListResponse(courseCount, courses), HttpStatus.OK); + } catch (Exception e) { + logger.error("Search courses failed with parameters: title={}, author={}, description={}, sortOrder={}, start={}, end={}", + title, author, description, sortOrder, start, end, e); + return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); + } + } } \ No newline at end of file diff --git a/src/main/java/org/cmh/backend/CourseManagement/dto/SearchCourseRequest.java b/src/main/java/org/cmh/backend/CourseManagement/dto/SearchCourseRequest.java new file mode 100644 index 0000000..aac0c93 --- /dev/null +++ b/src/main/java/org/cmh/backend/CourseManagement/dto/SearchCourseRequest.java @@ -0,0 +1,18 @@ +package org.cmh.backend.CourseManagement.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@AllArgsConstructor +public class SearchCourseRequest { + private String token; + private String title; + private String author; + private String description; + private String sortOrder; + private int start; + private int end; +} \ No newline at end of file diff --git a/src/main/java/org/cmh/backend/CourseManagement/repository/CourseRepository.java b/src/main/java/org/cmh/backend/CourseManagement/repository/CourseRepository.java index d65909a..40e0281 100644 --- a/src/main/java/org/cmh/backend/CourseManagement/repository/CourseRepository.java +++ b/src/main/java/org/cmh/backend/CourseManagement/repository/CourseRepository.java @@ -4,7 +4,10 @@ import org.cmh.backend.CourseManagement.model.Course; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; -public interface CourseRepository extends JpaRepository { +@Repository +public interface CourseRepository extends JpaRepository, JpaSpecificationExecutor { Page findAllByOrderByIdDesc(Pageable pageable); } \ No newline at end of file diff --git a/src/main/java/org/cmh/backend/CourseManagement/service/CourseService.java b/src/main/java/org/cmh/backend/CourseManagement/service/CourseService.java index d8c3926..92546e7 100644 --- a/src/main/java/org/cmh/backend/CourseManagement/service/CourseService.java +++ b/src/main/java/org/cmh/backend/CourseManagement/service/CourseService.java @@ -1,94 +1,72 @@ package org.cmh.backend.CourseManagement.service; -import jakarta.persistence.EntityNotFoundException; import org.cmh.backend.CourseManagement.dto.CourseRequest; +import org.cmh.backend.CourseManagement.dto.SearchCourseRequest; import org.cmh.backend.CourseManagement.model.Course; import org.cmh.backend.CourseManagement.repository.CourseRepository; +import org.cmh.backend.CourseManagement.specification.CourseSpecification; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; - -import java.util.ArrayList; +import jakarta.persistence.EntityNotFoundException; import java.util.List; @Service public class CourseService { + @Autowired private CourseRepository courseRepository; + public long getCourseCount() { + return courseRepository.count(); + } + public List getCoursesByRange(int start, int end) { - if (start < 0 || end <= start) { - throw new IllegalArgumentException("Invalid start or end range"); - } + Pageable pageable = PageRequest.of(start, end - start); + return courseRepository.findAll(pageable).getContent(); + } - int pageSize = end - start; // 计算每页的大小 - int startPageNumber = start / pageSize; // 计算起始页码 - int endPageNumber = (end - 1) / pageSize; // 计算结束页码 - - List result = new ArrayList<>(); - - for (int pageNumber = startPageNumber; pageNumber <= endPageNumber; pageNumber++) { - Pageable pageable = PageRequest.of(pageNumber, pageSize); - Page coursePage = courseRepository.findAllByOrderByIdDesc(pageable); - - if (coursePage.hasContent()) { - result.addAll(coursePage.getContent()); - } else { - break; // 如果没有更多内容,提前退出 - } - } - - int startIndex = start % pageSize; - int endIndex = startIndex + (end - start); - - if (endIndex > result.size()) { - endIndex = result.size(); - } - - return result.subList(startIndex, endIndex); + public Course getCourseById(Long id) { + return courseRepository.findById(id).orElseThrow(() -> new EntityNotFoundException("Course not found")); } public void createCourse(CourseRequest request) { Course course = new Course(); course.setTitle(request.getTitle()); + course.setAuthor(request.getAuthor()); course.setDescription(request.getDescription()); course.setOrderNo(request.getOrderNo()); - course.setAuthor(request.getAuthor()); - course.setVideoPath(request.getVideoPath()); - course.setImagePath(request.getImagePath()); courseRepository.save(course); } public void updateCourse(Long id, CourseRequest request) { - Course course = courseRepository.findById(id).orElse(null); - if (course != null) { - course.setTitle(request.getTitle()); - course.setDescription(request.getDescription()); - course.setOrderNo(request.getOrderNo()); - course.setAuthor(request.getAuthor()); - course.setVideoPath(request.getVideoPath()); - course.setImagePath(request.getImagePath()); - courseRepository.save(course); - } + Course course = courseRepository.findById(id).orElseThrow(() -> new EntityNotFoundException("Course not found")); + course.setTitle(request.getTitle()); + course.setAuthor(request.getAuthor()); + course.setDescription(request.getDescription()); + course.setOrderNo(request.getOrderNo()); + courseRepository.save(course); } public void deleteCourse(Long id) { - if (!courseRepository.existsById(id)) { - throw new EntityNotFoundException(); - } courseRepository.deleteById(id); } - public Course getCourseById(Long id) { - if (!courseRepository.existsById(id)) { - throw new EntityNotFoundException(); - } - return courseRepository.findById(id).orElse(null); + public List searchCourses(SearchCourseRequest request) { + Pageable pageable = PageRequest.of(request.getStart(), request.getEnd() - request.getStart()); + return courseRepository.findAll( + CourseSpecification.searchCourses( + request.getTitle(), + request.getAuthor(), + request.getDescription(), + request.getSortOrder() + ), + pageable + ).getContent(); } - public long getCourseCount() { - return courseRepository.count(); + public long getCourseCountByCriteria(String title, String author, String description, String sortOrder) { + return courseRepository.count(CourseSpecification.searchCourses(title, author, description, sortOrder)); } } \ No newline at end of file diff --git a/src/main/java/org/cmh/backend/CourseManagement/specification/CourseSpecification.java b/src/main/java/org/cmh/backend/CourseManagement/specification/CourseSpecification.java new file mode 100644 index 0000000..69be0ef --- /dev/null +++ b/src/main/java/org/cmh/backend/CourseManagement/specification/CourseSpecification.java @@ -0,0 +1,34 @@ +package org.cmh.backend.CourseManagement.specification; + +import org.cmh.backend.CourseManagement.model.Course; +import org.springframework.data.jpa.domain.Specification; + +import jakarta.persistence.criteria.Predicate; +import java.util.ArrayList; +import java.util.List; + +public class CourseSpecification { + + public static Specification searchCourses( + String title, String author, String description, String sortOrder) { + + return (root, query, criteriaBuilder) -> { + List predicates = new ArrayList<>(); + + if (title != null && !title.isEmpty()) { + predicates.add(criteriaBuilder.like(root.get("title"), "%" + title + "%")); + } + if (author != null && !author.isEmpty()) { + predicates.add(criteriaBuilder.like(root.get("author"), "%" + author + "%")); + } + if (description != null && !description.isEmpty()) { + predicates.add(criteriaBuilder.like(root.get("description"), "%" + description + "%")); + } + if (sortOrder != null && !sortOrder.isEmpty()) { + predicates.add(criteriaBuilder.like(root.get("orderNo"), "%" + sortOrder+ "%")); + } + + return criteriaBuilder.and(predicates.toArray(new Predicate[0])); + }; + } +} \ No newline at end of file From 05f3af0c77f839e8dd8fda19f2b41fb6502c3aa4 Mon Sep 17 00:00:00 2001 From: "Chester.X" <2931709855@qq.com> Date: Fri, 5 Jul 2024 14:40:15 +0800 Subject: [PATCH 13/14] =?UTF-8?q?=E5=9F=BA=E6=9C=AC=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/CourseController.java | 21 +++++++++++++++++++ .../service/CourseService.java | 11 ++++++++++ .../specification/CourseSpecification.java | 10 +++++++++ 3 files changed, 42 insertions(+) diff --git a/src/main/java/org/cmh/backend/CourseManagement/controller/CourseController.java b/src/main/java/org/cmh/backend/CourseManagement/controller/CourseController.java index b9b2d82..a386572 100644 --- a/src/main/java/org/cmh/backend/CourseManagement/controller/CourseController.java +++ b/src/main/java/org/cmh/backend/CourseManagement/controller/CourseController.java @@ -114,4 +114,25 @@ public class CourseController { return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); } } + @GetMapping("/sort") + public ResponseEntity sortCourses(@RequestParam String token, + @RequestParam String sortField, + @RequestParam String sortDirection, + @RequestParam Integer start, + @RequestParam Integer end) { + if (start >= end) { + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + } + + try { + long courseCount = courseService.getCourseCount(); + List sortedCourses = courseService.sortCourses(sortField, sortDirection, start, end); + + return new ResponseEntity<>(new GetCourseListResponse(courseCount, sortedCourses), HttpStatus.OK); + } catch (Exception e) { + logger.error("Sort courses failed with parameters: sortField={}, sortDirection={}, start={}, end={}", + sortField, sortDirection, start, end, e); + return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); + } + } } \ No newline at end of file diff --git a/src/main/java/org/cmh/backend/CourseManagement/service/CourseService.java b/src/main/java/org/cmh/backend/CourseManagement/service/CourseService.java index 92546e7..5e68a29 100644 --- a/src/main/java/org/cmh/backend/CourseManagement/service/CourseService.java +++ b/src/main/java/org/cmh/backend/CourseManagement/service/CourseService.java @@ -37,6 +37,8 @@ public class CourseService { course.setAuthor(request.getAuthor()); course.setDescription(request.getDescription()); course.setOrderNo(request.getOrderNo()); + course.setVideoPath(request.getVideoPath()); // 确保保存视频路径 + course.setImagePath(request.getImagePath()); // 确保保存图片路径 courseRepository.save(course); } @@ -46,6 +48,8 @@ public class CourseService { course.setAuthor(request.getAuthor()); course.setDescription(request.getDescription()); course.setOrderNo(request.getOrderNo()); + course.setVideoPath(request.getVideoPath()); // 确保更新视频路径 + course.setImagePath(request.getImagePath()); // 确保更新图片路径 courseRepository.save(course); } @@ -69,4 +73,11 @@ public class CourseService { public long getCourseCountByCriteria(String title, String author, String description, String sortOrder) { return courseRepository.count(CourseSpecification.searchCourses(title, author, description, sortOrder)); } + public List sortCourses(String sortField, String sortDirection, int start, int end) { + Pageable pageable = PageRequest.of(start, end - start); + return courseRepository.findAll( + CourseSpecification.sortCourses(sortField, sortDirection), + pageable + ).getContent(); + } } \ No newline at end of file diff --git a/src/main/java/org/cmh/backend/CourseManagement/specification/CourseSpecification.java b/src/main/java/org/cmh/backend/CourseManagement/specification/CourseSpecification.java index 69be0ef..23411a4 100644 --- a/src/main/java/org/cmh/backend/CourseManagement/specification/CourseSpecification.java +++ b/src/main/java/org/cmh/backend/CourseManagement/specification/CourseSpecification.java @@ -31,4 +31,14 @@ public class CourseSpecification { return criteriaBuilder.and(predicates.toArray(new Predicate[0])); }; } + public static Specification sortCourses(String sortField, String sortDirection) { + return (root, query, cb) -> { + if ("asc".equalsIgnoreCase(sortDirection)) { + query.orderBy(cb.asc(root.get(sortField))); + } else if ("desc".equalsIgnoreCase(sortDirection)) { + query.orderBy(cb.desc(root.get(sortField))); + } + return cb.conjunction(); + }; + } } \ No newline at end of file From ba886c719137b85efa1800928bed7ed91c704371 Mon Sep 17 00:00:00 2001 From: "Chester.X" <2931709855@qq.com> Date: Fri, 5 Jul 2024 19:18:41 +0800 Subject: [PATCH 14/14] =?UTF-8?q?=E8=BF=98=E5=89=A9=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E6=B2=A1=E5=81=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/cmh/backend/CourseManagement/service/CourseService.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/org/cmh/backend/CourseManagement/service/CourseService.java b/src/main/java/org/cmh/backend/CourseManagement/service/CourseService.java index 5e68a29..3e00d0f 100644 --- a/src/main/java/org/cmh/backend/CourseManagement/service/CourseService.java +++ b/src/main/java/org/cmh/backend/CourseManagement/service/CourseService.java @@ -69,7 +69,6 @@ public class CourseService { pageable ).getContent(); } - public long getCourseCountByCriteria(String title, String author, String description, String sortOrder) { return courseRepository.count(CourseSpecification.searchCourses(title, author, description, sortOrder)); }