├── .mvn └── wrapper │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── src ├── main │ ├── java │ │ └── com │ │ │ └── zouht │ │ │ └── todolist │ │ │ ├── mapper │ │ │ ├── NoteMapper.java │ │ │ ├── TodoMapper.java │ │ │ └── UserMapper.java │ │ │ ├── TodoListBackendApplication.java │ │ │ ├── controller │ │ │ ├── RootController.java │ │ │ ├── user │ │ │ │ ├── CheckController.java │ │ │ │ ├── UploadAvatarController.java │ │ │ │ ├── LoginController.java │ │ │ │ ├── RegisterController.java │ │ │ │ └── UserUpdateController.java │ │ │ ├── note │ │ │ │ ├── NoteListController.java │ │ │ │ ├── NoteDeleteController.java │ │ │ │ ├── NoteGetController.java │ │ │ │ ├── NoteToggleStarController.java │ │ │ │ ├── NoteCreateController.java │ │ │ │ └── NoteUpdateController.java │ │ │ └── todo │ │ │ │ ├── TodoListController.java │ │ │ │ ├── TodoGetController.java │ │ │ │ ├── TodoDeleteController.java │ │ │ │ ├── TodoToggleFinishController.java │ │ │ │ ├── TodoGetTodayController.java │ │ │ │ ├── TodoCreateController.java │ │ │ │ └── TodoUpdateController.java │ │ │ ├── pojo │ │ │ ├── User.java │ │ │ ├── Note.java │ │ │ └── Todo.java │ │ │ ├── service │ │ │ ├── note │ │ │ │ ├── NoteDeleteService.java │ │ │ │ ├── NoteGetService.java │ │ │ │ ├── NoteToggleStarService.java │ │ │ │ ├── NoteUpdateService.java │ │ │ │ ├── NoteCreateService.java │ │ │ │ └── NoteListService.java │ │ │ ├── todo │ │ │ │ ├── TodoDeleteService.java │ │ │ │ ├── TodoGetService.java │ │ │ │ ├── TodoToggleFinishService.java │ │ │ │ ├── TodoUpdateService.java │ │ │ │ ├── TodoCreateService.java │ │ │ │ ├── TodoListService.java │ │ │ │ └── TodoGetTodayService.java │ │ │ └── user │ │ │ │ ├── CheckService.java │ │ │ │ ├── RegisterService.java │ │ │ │ ├── UploadAvatarService.java │ │ │ │ ├── UserDetailsServiceImpl.java │ │ │ │ ├── UserUpdateService.java │ │ │ │ ├── LoginService.java │ │ │ │ └── UserDetailImpl.java │ │ │ ├── config │ │ │ ├── WebConfig.java │ │ │ ├── CorsConfig.java │ │ │ ├── SecurityConfig.java │ │ │ └── JwtAuthenticationTokenFilter.java │ │ │ └── util │ │ │ └── JwtUtil.java │ └── resources │ │ ├── application.properties │ │ └── schema.sql └── test │ └── java │ └── com │ └── zouht │ └── todolist │ └── TodoListBackendApplicationTests.java ├── .gitignore ├── README.md ├── LICENSE ├── pom.xml ├── mvnw.cmd ├── mvnw └── API.md /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChrisKimZHT/web-exp-backend/master/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.5/apache-maven-3.9.5-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar 3 | -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/mapper/NoteMapper.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.zouht.todolist.pojo.Note; 5 | import org.apache.ibatis.annotations.Mapper; 6 | 7 | @Mapper 8 | public interface NoteMapper extends BaseMapper { 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/mapper/TodoMapper.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.zouht.todolist.pojo.Todo; 5 | import org.apache.ibatis.annotations.Mapper; 6 | 7 | @Mapper 8 | public interface TodoMapper extends BaseMapper { 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/mapper/UserMapper.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.zouht.todolist.pojo.User; 5 | import org.apache.ibatis.annotations.Mapper; 6 | 7 | @Mapper 8 | public interface UserMapper extends BaseMapper { 9 | } 10 | -------------------------------------------------------------------------------- /src/test/java/com/zouht/todolist/TodoListBackendApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class TodoListBackendApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.port=5000 2 | spring.datasource.username=root 3 | spring.datasource.password=password 4 | spring.datasource.url=jdbc:mysql://192.168.6.3:3306/web_exp_backend?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8 5 | spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver 6 | upload.path=E:\\Pictures\\spring-upld\\ -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/TodoListBackendApplication.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class TodoListBackendApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(TodoListBackendApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/controller/RootController.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.controller; 2 | 3 | import org.springframework.web.bind.annotation.GetMapping; 4 | import org.springframework.web.bind.annotation.RestController; 5 | 6 | import java.util.Map; 7 | 8 | @RestController 9 | public class RootController { 10 | @GetMapping("/") 11 | public Map root() { 12 | return Map.of("status", 0, "message", "OK", "project", "Todo List Backend"); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/pojo/User.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.pojo; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableId; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | @Data 10 | @NoArgsConstructor 11 | @AllArgsConstructor 12 | public class User { 13 | @TableId(type = IdType.AUTO) 14 | private Integer userId; 15 | private String email; 16 | private String hashedPassword; 17 | private String avatarFileName; 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/service/note/NoteDeleteService.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.service.note; 2 | 3 | import com.zouht.todolist.mapper.NoteMapper; 4 | import org.springframework.stereotype.Service; 5 | 6 | import javax.annotation.Resource; 7 | import java.util.Map; 8 | 9 | @Service 10 | public class NoteDeleteService { 11 | @Resource 12 | NoteMapper noteMapper; 13 | 14 | public Map delete(Integer noteId) { 15 | // TODO: 没判平行越权 16 | noteMapper.deleteById(noteId); 17 | return Map.of("status", 0, "message", "OK"); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/service/todo/TodoDeleteService.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.service.todo; 2 | 3 | import com.zouht.todolist.mapper.TodoMapper; 4 | import org.springframework.stereotype.Service; 5 | 6 | import javax.annotation.Resource; 7 | import java.util.Map; 8 | 9 | @Service 10 | public class TodoDeleteService { 11 | @Resource 12 | TodoMapper todoMapper; 13 | 14 | public Map delete(Integer todoId) { 15 | // TODO: 没判平行越权 16 | todoMapper.deleteById(todoId); 17 | return Map.of("status", 0, "message", "OK"); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/pojo/Note.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.pojo; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableId; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | @Data 10 | @NoArgsConstructor 11 | @AllArgsConstructor 12 | public class Note { 13 | @TableId(type = IdType.AUTO) 14 | private Integer noteId; 15 | private Integer userId; 16 | private String title; 17 | private String content; 18 | private Integer date; 19 | private Boolean isStared; 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/pojo/Todo.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.pojo; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableId; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | @Data 10 | @NoArgsConstructor 11 | @AllArgsConstructor 12 | public class Todo { 13 | @TableId(type = IdType.AUTO) 14 | private Integer todoId; 15 | private Integer userId; 16 | private String title; 17 | private String detail; 18 | private Integer begin; 19 | private Integer end; 20 | private Boolean isFinished; 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/service/note/NoteGetService.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.service.note; 2 | 3 | import com.zouht.todolist.mapper.NoteMapper; 4 | import com.zouht.todolist.pojo.Note; 5 | import org.springframework.stereotype.Service; 6 | 7 | import javax.annotation.Resource; 8 | import java.util.Map; 9 | 10 | @Service 11 | public class NoteGetService { 12 | @Resource 13 | NoteMapper noteMapper; 14 | 15 | public Map get(Integer noteId) { 16 | // TODO: 没判平行越权 17 | Note note = noteMapper.selectById(noteId); 18 | return Map.of("status", 0, "message", "OK", "data", note); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/service/todo/TodoGetService.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.service.todo; 2 | 3 | import com.zouht.todolist.mapper.TodoMapper; 4 | import com.zouht.todolist.pojo.Todo; 5 | import org.springframework.stereotype.Service; 6 | 7 | import javax.annotation.Resource; 8 | import java.util.Map; 9 | 10 | @Service 11 | public class TodoGetService { 12 | @Resource 13 | TodoMapper todoMapper; 14 | 15 | public Map get(Integer todoId) { 16 | // TODO: 没判平行越权 17 | Todo todo = todoMapper.selectById(todoId); 18 | return Map.of("status", 0, "message", "OK", "data", todo); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/service/note/NoteToggleStarService.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.service.note; 2 | 3 | import com.zouht.todolist.mapper.NoteMapper; 4 | import com.zouht.todolist.pojo.Note; 5 | import org.springframework.stereotype.Service; 6 | 7 | import javax.annotation.Resource; 8 | import java.util.Map; 9 | 10 | @Service 11 | public class NoteToggleStarService { 12 | @Resource 13 | NoteMapper noteMapper; 14 | 15 | public Map toggleStar(Integer noteId) { 16 | // TODO: 没判平行越权 17 | Note note = noteMapper.selectById(noteId); 18 | note.setIsStared(!note.getIsStared()); 19 | noteMapper.updateById(note); 20 | return Map.of("status", 0, "message", "OK"); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/service/todo/TodoToggleFinishService.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.service.todo; 2 | 3 | import com.zouht.todolist.mapper.TodoMapper; 4 | import com.zouht.todolist.pojo.Todo; 5 | import org.springframework.stereotype.Service; 6 | 7 | import javax.annotation.Resource; 8 | import java.util.Map; 9 | 10 | @Service 11 | public class TodoToggleFinishService { 12 | @Resource 13 | TodoMapper todoMapper; 14 | 15 | public Map toggleFinish(Integer todoId) { 16 | // TODO: 没判平行越权 17 | Todo todo = todoMapper.selectById(todoId); 18 | todo.setIsFinished(!todo.getIsFinished()); 19 | todoMapper.updateById(todo); 20 | return Map.of("status", 0, "message", "OK"); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/resources/schema.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE user 2 | ( 3 | user_id INT PRIMARY KEY AUTO_INCREMENT, 4 | email VARCHAR(255) NOT NULL UNIQUE, 5 | hashed_password VARCHAR(255) NOT NULL, 6 | avatar_file_name VARCHAR(255) 7 | ); 8 | 9 | CREATE TABLE note 10 | ( 11 | note_id INT PRIMARY KEY AUTO_INCREMENT, 12 | user_id INT NOT NULL, 13 | title VARCHAR(255) NOT NULL, 14 | content TEXT, 15 | date INT, 16 | is_stared BOOLEAN 17 | ); 18 | 19 | CREATE TABLE todo 20 | ( 21 | todo_id INT PRIMARY KEY AUTO_INCREMENT, 22 | user_id INT NOT NULL, 23 | title VARCHAR(255) NOT NULL, 24 | detail TEXT, 25 | begin INT, 26 | end INT, 27 | is_finished BOOLEAN 28 | ); 29 | -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/service/user/CheckService.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.service.user; 2 | 3 | import com.zouht.todolist.pojo.User; 4 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 5 | import org.springframework.security.core.context.SecurityContextHolder; 6 | import org.springframework.stereotype.Service; 7 | 8 | import java.util.Map; 9 | 10 | @Service 11 | public class CheckService { 12 | public Map check() { 13 | UsernamePasswordAuthenticationToken authenticationToken = (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication(); 14 | UserDetailImpl loginUser = (UserDetailImpl) authenticationToken.getPrincipal(); 15 | User user = loginUser.getUser(); 16 | return Map.of("status", 0, "message", "OK", "userId", user.getUserId()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/controller/user/CheckController.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.controller.user; 2 | 3 | import com.zouht.todolist.service.user.CheckService; 4 | import org.springframework.web.bind.annotation.PostMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | import javax.annotation.Resource; 8 | import javax.servlet.http.HttpServletResponse; 9 | import java.util.Map; 10 | 11 | @RestController 12 | public class CheckController { 13 | @Resource 14 | CheckService checkService; 15 | 16 | @PostMapping("/user/check") 17 | public Map check(HttpServletResponse response) { 18 | try { 19 | return checkService.check(); 20 | } catch (Exception e) { 21 | response.setStatus(500); 22 | return Map.of("status", 1, "message", e.getMessage()); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/service/note/NoteUpdateService.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.service.note; 2 | 3 | import com.zouht.todolist.mapper.NoteMapper; 4 | import com.zouht.todolist.pojo.Note; 5 | import org.springframework.stereotype.Service; 6 | 7 | import javax.annotation.Resource; 8 | import java.util.Map; 9 | 10 | @Service 11 | public class NoteUpdateService { 12 | @Resource 13 | NoteMapper noteMapper; 14 | 15 | public Map update(Integer noteId, String title, String content, Integer date, Boolean isStared) { 16 | // TODO: 没判平行越权 17 | Note note = noteMapper.selectById(noteId); 18 | note.setTitle(title); 19 | note.setContent(content); 20 | note.setDate(date); 21 | note.setIsStared(isStared); 22 | noteMapper.updateById(note); 23 | return Map.of("status", 0, "message", "OK"); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/controller/note/NoteListController.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.controller.note; 2 | 3 | import com.zouht.todolist.service.note.NoteListService; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | import javax.annotation.Resource; 8 | import javax.servlet.http.HttpServletResponse; 9 | import java.util.Map; 10 | 11 | @RestController 12 | public class NoteListController { 13 | @Resource 14 | NoteListService noteListService; 15 | 16 | @GetMapping("/note/list") 17 | public Map list(HttpServletResponse response) { 18 | try { 19 | return noteListService.list(); 20 | } catch (Exception e) { 21 | response.setStatus(500); 22 | return Map.of("status", 1, "message", e.getMessage()); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/controller/todo/TodoListController.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.controller.todo; 2 | 3 | import com.zouht.todolist.service.todo.TodoListService; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | import javax.annotation.Resource; 8 | import javax.servlet.http.HttpServletResponse; 9 | import java.util.Map; 10 | 11 | @RestController 12 | public class TodoListController { 13 | @Resource 14 | TodoListService todoListService; 15 | 16 | @GetMapping("/todo/list") 17 | public Map list(HttpServletResponse response) { 18 | try { 19 | return todoListService.list(); 20 | } catch (Exception e) { 21 | response.setStatus(500); 22 | return Map.of("status", 1, "message", e.getMessage()); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/service/todo/TodoUpdateService.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.service.todo; 2 | 3 | import com.zouht.todolist.mapper.TodoMapper; 4 | import com.zouht.todolist.pojo.Todo; 5 | import org.springframework.stereotype.Service; 6 | 7 | import javax.annotation.Resource; 8 | import java.util.Map; 9 | 10 | @Service 11 | public class TodoUpdateService { 12 | @Resource 13 | TodoMapper todoMapper; 14 | 15 | public Map update(Integer todoId, String title, String detail, Integer begin, Integer end, Boolean isFinished) { 16 | // TODO: 没判平行越权 17 | Todo todo = todoMapper.selectById(todoId); 18 | todo.setTitle(title); 19 | todo.setDetail(detail); 20 | todo.setBegin(begin); 21 | todo.setEnd(end); 22 | todo.setIsFinished(isFinished); 23 | todoMapper.updateById(todo); 24 | return Map.of("status", 0, "message", "OK"); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/service/user/RegisterService.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.service.user; 2 | 3 | import com.zouht.todolist.mapper.UserMapper; 4 | import com.zouht.todolist.pojo.User; 5 | import org.springframework.security.crypto.password.PasswordEncoder; 6 | import org.springframework.stereotype.Service; 7 | 8 | import javax.annotation.Resource; 9 | import java.util.Map; 10 | 11 | @Service 12 | public class RegisterService { 13 | @Resource 14 | private PasswordEncoder passwordEncoder; 15 | 16 | @Resource 17 | UserMapper userMapper; 18 | 19 | public Map register(String email, String password, String avatarFileName) { 20 | String encodedPassword = passwordEncoder.encode(password); 21 | 22 | User user = new User(null, email, encodedPassword, avatarFileName); 23 | userMapper.insert(user); 24 | 25 | return Map.of("status", 0, "message", "OK", "userId", user.getUserId()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/service/user/UploadAvatarService.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.service.user; 2 | 3 | import org.springframework.beans.factory.annotation.Value; 4 | import org.springframework.stereotype.Service; 5 | import org.springframework.web.multipart.MultipartFile; 6 | 7 | import java.io.File; 8 | import java.io.IOException; 9 | import java.util.Map; 10 | import java.util.UUID; 11 | 12 | @Service 13 | public class UploadAvatarService { 14 | @Value("${upload.path}") 15 | private String uploadPath; 16 | 17 | public Map uploadAvatar(MultipartFile avatar) throws IOException { 18 | String originalFilename = avatar.getOriginalFilename(); 19 | String suffix = originalFilename.substring(originalFilename.lastIndexOf(".")); 20 | String fileName = UUID.randomUUID() + suffix; 21 | 22 | String savePath = uploadPath + fileName; 23 | File dest = new File(savePath); 24 | avatar.transferTo(dest); 25 | 26 | return Map.of("status", 0, "message", "OK", "avatar", fileName); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Web Exp Backend 2 | 3 | Web 应用开发 - 实验 & 大作业后端【[前端仓库](https://github.com/ChrisKimZHT/web-exp-frontend)】【[API 文档](./API.md)】 4 | 5 | ### 功能设计 6 | 7 | 拟设计一个多用户的 B/S 架构待办事项系统,用户可添加代办(Todo)和便签(Note),数据均具有增删改查功能。 8 | 9 | ### 后端技术栈 10 | 11 | 基于 Java 17 开发,使用 Spring Web 框架,使用 MyBatis Plus 数据库框架,使用 MySQL 8.0 数据库。 12 | 13 | 登录基于 Json Web Token,头像功能由后端直接分发静态资源。 14 | 15 | ### 配置与部署 16 | 17 | **修改配置文件** 18 | 19 | 配置文件: `src\main\resourcessrc\main\resources\application.properties` 20 | 21 | 配置示例如下: 22 | 23 | ```properties 24 | server.port=5000 25 | spring.datasource.username=root 26 | spring.datasource.password=password 27 | spring.datasource.url=jdbc:mysql://192.168.6.3:3306/web_exp_backend?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8 28 | spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver 29 | upload.path=E:\\Pictures\\spring-upld\\ 30 | ``` 31 | 32 | 需要注意的是,`upload.path` 必须以斜杠结尾,否则会导致路径拼接错误。 33 | 34 | **初始化数据库** 35 | 36 | 运行建库脚本: `src\main\resourcessrc\main\resources\schema.sql` 37 | 38 | **运行项目** 39 | 40 | 经过以上配置后,即可运行该项目。项目默认将会运行在 5000 端口。 -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/controller/note/NoteDeleteController.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.controller.note; 2 | 3 | import com.zouht.todolist.service.note.NoteDeleteService; 4 | import org.springframework.web.bind.annotation.DeleteMapping; 5 | import org.springframework.web.bind.annotation.RequestBody; 6 | import org.springframework.web.bind.annotation.RequestParam; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | import javax.annotation.Resource; 10 | import java.util.Map; 11 | 12 | @RestController 13 | public class NoteDeleteController { 14 | @Resource 15 | NoteDeleteService noteDeleteService; 16 | 17 | @DeleteMapping("/note/delete") 18 | public Map delete(@RequestParam Integer noteId) { 19 | if (noteId == null) { 20 | return Map.of("status", 1, "message", "id is null"); 21 | } 22 | 23 | try { 24 | return noteDeleteService.delete(noteId); 25 | } catch (Exception e) { 26 | return Map.of("status", 1, "message", e.getMessage()); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Haotian Zou 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/controller/note/NoteGetController.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.controller.note; 2 | 3 | import com.zouht.todolist.service.note.NoteGetService; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.RequestParam; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | import javax.annotation.Resource; 9 | import javax.servlet.http.HttpServletResponse; 10 | import java.util.Map; 11 | 12 | @RestController 13 | public class NoteGetController { 14 | @Resource 15 | NoteGetService noteGetService; 16 | 17 | @GetMapping("/note/get") 18 | public Map get(@RequestParam Integer noteId, HttpServletResponse response) { 19 | if (noteId == null) { 20 | response.setStatus(400); 21 | return Map.of("status", 1, "message", "noteId is null"); 22 | } 23 | 24 | try { 25 | return noteGetService.get(noteId); 26 | } catch (Exception e) { 27 | response.setStatus(500); 28 | return Map.of("status", 1, "message", e.getMessage()); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/controller/todo/TodoGetController.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.controller.todo; 2 | 3 | import com.zouht.todolist.service.todo.TodoGetService; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.RequestParam; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | import javax.annotation.Resource; 9 | import javax.servlet.http.HttpServletResponse; 10 | import java.util.Map; 11 | 12 | @RestController 13 | public class TodoGetController { 14 | @Resource 15 | private TodoGetService todoGetService; 16 | 17 | @GetMapping("/todo/get") 18 | public Map get(@RequestParam Integer todoId, HttpServletResponse response) { 19 | if (todoId == null) { 20 | response.setStatus(400); 21 | return Map.of("status", 1, "message", "todoId is null"); 22 | } 23 | 24 | try { 25 | return todoGetService.get(todoId); 26 | } catch (Exception e) { 27 | response.setStatus(500); 28 | return Map.of("status", 1, "message", e.getMessage()); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/config/WebConfig.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.config; 2 | 3 | import org.springframework.beans.factory.annotation.Value; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.web.servlet.config.annotation.PathMatchConfigurer; 6 | import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; 7 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 8 | import org.springframework.web.util.pattern.PathPatternParser; 9 | 10 | @Configuration 11 | public class WebConfig implements WebMvcConfigurer { 12 | @Value("${upload.path}") 13 | private String uploadPath; 14 | 15 | @Override 16 | public void configurePathMatch(PathMatchConfigurer configurer) { 17 | PathPatternParser pathPatternParser = new PathPatternParser(); 18 | pathPatternParser.setMatchOptionalTrailingSeparator(true); 19 | configurer.setPatternParser(pathPatternParser); 20 | } 21 | 22 | @Override 23 | public void addResourceHandlers(ResourceHandlerRegistry registry) { 24 | registry.addResourceHandler("/upload/**").addResourceLocations("file:" + uploadPath); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/controller/todo/TodoDeleteController.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.controller.todo; 2 | 3 | import com.zouht.todolist.service.todo.TodoDeleteService; 4 | import org.springframework.web.bind.annotation.DeleteMapping; 5 | import org.springframework.web.bind.annotation.RequestParam; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | import javax.annotation.Resource; 9 | import javax.servlet.http.HttpServletResponse; 10 | import java.util.Map; 11 | 12 | @RestController 13 | public class TodoDeleteController { 14 | @Resource 15 | private TodoDeleteService todoDeleteService; 16 | 17 | @DeleteMapping("/todo/delete") 18 | public Map delete(@RequestParam Integer todoId, HttpServletResponse response) { 19 | if (todoId == null) { 20 | response.setStatus(400); 21 | return Map.of("status", 1, "message", "todoId is null"); 22 | } 23 | 24 | try { 25 | return todoDeleteService.delete(todoId); 26 | } catch (Exception e) { 27 | response.setStatus(500); 28 | return Map.of("status", 1, "message", e.getMessage()); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/controller/note/NoteToggleStarController.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.controller.note; 2 | 3 | import com.zouht.todolist.service.note.NoteToggleStarService; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.RequestParam; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | import javax.annotation.Resource; 9 | import javax.servlet.http.HttpServletResponse; 10 | import java.util.Map; 11 | 12 | @RestController 13 | public class NoteToggleStarController { 14 | @Resource 15 | NoteToggleStarService noteToggleStarService; 16 | 17 | @GetMapping("/note/toggleStar") 18 | public Map toggleStar(@RequestParam Integer noteId, HttpServletResponse response) { 19 | if (noteId == null) { 20 | response.setStatus(400); 21 | return Map.of("status", 1, "message", "noteId is null"); 22 | } 23 | 24 | try { 25 | return noteToggleStarService.toggleStar(noteId); 26 | } catch (Exception e) { 27 | response.setStatus(500); 28 | return Map.of("status", 1, "message", e.getMessage()); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/service/user/UserDetailsServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.service.user; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 4 | import com.zouht.todolist.mapper.UserMapper; 5 | import com.zouht.todolist.pojo.User; 6 | import org.springframework.security.core.userdetails.UserDetails; 7 | import org.springframework.security.core.userdetails.UserDetailsService; 8 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 9 | import org.springframework.stereotype.Service; 10 | 11 | import javax.annotation.Resource; 12 | 13 | @Service 14 | public class UserDetailsServiceImpl implements UserDetailsService { 15 | 16 | @Resource 17 | private UserMapper userMapper; 18 | 19 | @Override 20 | public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException { 21 | QueryWrapper queryWrapper = new QueryWrapper<>(); 22 | queryWrapper.eq("email", email); 23 | 24 | User user = userMapper.selectOne(queryWrapper); 25 | 26 | if (user == null) { 27 | throw new RuntimeException("UserNotFound"); 28 | } 29 | return new UserDetailImpl(user); 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/controller/todo/TodoToggleFinishController.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.controller.todo; 2 | 3 | import com.zouht.todolist.service.todo.TodoToggleFinishService; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.RequestParam; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | import javax.annotation.Resource; 9 | import javax.servlet.http.HttpServletResponse; 10 | import java.util.Map; 11 | 12 | @RestController 13 | public class TodoToggleFinishController { 14 | @Resource 15 | TodoToggleFinishService todoToggleFinishService; 16 | 17 | @GetMapping("/todo/toggleFinish") 18 | public Map toggleFinish(@RequestParam Integer todoId, HttpServletResponse response) { 19 | if (todoId == null) { 20 | response.setStatus(400); 21 | return Map.of("status", 1, "message", "id is null"); 22 | } 23 | 24 | try { 25 | return todoToggleFinishService.toggleFinish(todoId); 26 | } catch (Exception e) { 27 | response.setStatus(500); 28 | return Map.of("status", 1, "message", e.getMessage()); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/service/user/UserUpdateService.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.service.user; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 4 | import com.zouht.todolist.mapper.UserMapper; 5 | import com.zouht.todolist.pojo.User; 6 | import org.springframework.security.crypto.password.PasswordEncoder; 7 | import org.springframework.stereotype.Service; 8 | 9 | import javax.annotation.Resource; 10 | import java.util.Map; 11 | 12 | @Service 13 | public class UserUpdateService { 14 | @Resource 15 | private PasswordEncoder passwordEncoder; 16 | 17 | @Resource 18 | UserMapper userMapper; 19 | 20 | public Map update(String email, String password, String avatarFileName) { 21 | // TODO: 没判平行越权 22 | QueryWrapper queryWrapper = new QueryWrapper<>(); 23 | queryWrapper.eq("email", email); 24 | User user = userMapper.selectOne(queryWrapper); 25 | 26 | user.setEmail(email); 27 | if (!password.isEmpty()) { 28 | user.setHashedPassword(passwordEncoder.encode(password)); 29 | } 30 | user.setAvatarFileName(avatarFileName); 31 | userMapper.updateById(user); 32 | 33 | return Map.of("status", 0, "message", "OK"); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/controller/user/UploadAvatarController.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.controller.user; 2 | 3 | import com.zouht.todolist.service.user.UploadAvatarService; 4 | import org.springframework.web.bind.annotation.PostMapping; 5 | import org.springframework.web.bind.annotation.RequestParam; 6 | import org.springframework.web.bind.annotation.RestController; 7 | import org.springframework.web.multipart.MultipartFile; 8 | 9 | import javax.annotation.Resource; 10 | import javax.servlet.http.HttpServletResponse; 11 | import java.util.Map; 12 | 13 | @RestController 14 | public class UploadAvatarController { 15 | @Resource 16 | UploadAvatarService uploadAvatarService; 17 | 18 | @PostMapping("/user/uploadAvatar") 19 | public Map uploadAvatar(@RequestParam("avatar") MultipartFile avatar, HttpServletResponse response) { 20 | if (avatar.isEmpty()) { 21 | response.setStatus(400); 22 | return Map.of("status", 1, "message", "avatar is empty"); 23 | } 24 | 25 | try { 26 | return uploadAvatarService.uploadAvatar(avatar); 27 | } catch (Exception e) { 28 | response.setStatus(500); 29 | return Map.of("status", 1, "message", e.getMessage()); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/controller/todo/TodoGetTodayController.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.controller.todo; 2 | 3 | import com.zouht.todolist.service.todo.TodoGetTodayService; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.RequestParam; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | import javax.annotation.Resource; 9 | import javax.servlet.http.HttpServletResponse; 10 | import java.util.Map; 11 | 12 | @RestController 13 | public class TodoGetTodayController { 14 | @Resource 15 | private TodoGetTodayService todoGetTodayService; 16 | 17 | @GetMapping("/todo/getToday") 18 | public Map getToday(@RequestParam Integer year, @RequestParam Integer month, @RequestParam Integer day, HttpServletResponse response) { 19 | if (year == null || month == null) { 20 | response.setStatus(400); 21 | return Map.of("status", 1, "message", "year, month are required"); 22 | } 23 | 24 | try { 25 | return todoGetTodayService.getToday(year, month, day); 26 | } catch (Exception e) { 27 | response.setStatus(500); 28 | return Map.of("status", 1, "message", e.getMessage()); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/service/note/NoteCreateService.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.service.note; 2 | 3 | import com.zouht.todolist.mapper.NoteMapper; 4 | import com.zouht.todolist.pojo.Note; 5 | import com.zouht.todolist.service.user.UserDetailImpl; 6 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 7 | import org.springframework.security.core.context.SecurityContextHolder; 8 | import org.springframework.stereotype.Service; 9 | 10 | import javax.annotation.Resource; 11 | import java.util.Map; 12 | 13 | @Service 14 | public class NoteCreateService { 15 | @Resource 16 | private NoteMapper noteMapper; 17 | 18 | public Map create(String title, String content) { 19 | UsernamePasswordAuthenticationToken authenticationToken = (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication(); 20 | UserDetailImpl loginUser = (UserDetailImpl) authenticationToken.getPrincipal(); 21 | Integer userId = loginUser.getUser().getUserId(); 22 | Integer date = (int) (System.currentTimeMillis() / 1000); 23 | Note note = new Note(null, userId, title, content, date, false); 24 | noteMapper.insert(note); 25 | return Map.of("status", 0, "message", "OK", "noteId", note.getNoteId()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/controller/user/LoginController.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.controller.user; 2 | 3 | import com.zouht.todolist.service.user.LoginService; 4 | import org.springframework.web.bind.annotation.PostMapping; 5 | import org.springframework.web.bind.annotation.RequestBody; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | import javax.annotation.Resource; 9 | import javax.servlet.http.HttpServletResponse; 10 | import java.util.Map; 11 | 12 | @RestController 13 | public class LoginController { 14 | @Resource 15 | private LoginService loginService; 16 | 17 | @PostMapping("/user/login") 18 | public Map login(@RequestBody Map map, HttpServletResponse response) { 19 | String email = (String) map.get("email"); 20 | String password = (String) map.get("password"); 21 | 22 | if (email == null || password == null) { 23 | response.setStatus(400); 24 | return Map.of("status", 1, "message", "email and password are required"); 25 | } 26 | 27 | try { 28 | return loginService.login(email, password); 29 | } catch (Exception e) { 30 | response.setStatus(500); 31 | return Map.of("status", 1, "message", e.getMessage()); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/service/user/LoginService.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.service.user; 2 | 3 | import com.zouht.todolist.pojo.User; 4 | import com.zouht.todolist.util.JwtUtil; 5 | import org.springframework.security.authentication.AuthenticationManager; 6 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 7 | import org.springframework.security.core.Authentication; 8 | import org.springframework.stereotype.Service; 9 | 10 | import javax.annotation.Resource; 11 | import java.util.Map; 12 | 13 | @Service 14 | public class LoginService { 15 | @Resource 16 | private AuthenticationManager authenticationManager; 17 | 18 | public Map login(String username, String password) { 19 | UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password); 20 | Authentication authenticate = authenticationManager.authenticate(authenticationToken); 21 | UserDetailImpl loginUser = (UserDetailImpl) authenticate.getPrincipal(); 22 | 23 | User user = loginUser.getUser(); 24 | String jwt = JwtUtil.createJWT(user.getUserId().toString()); 25 | 26 | return Map.of("status", 0, "message", "OK", "token", jwt, "userId", user.getUserId(), "avatar", user.getAvatarFileName()); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/service/user/UserDetailImpl.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.service.user; 2 | 3 | import com.zouht.todolist.pojo.User; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | import org.springframework.security.core.GrantedAuthority; 8 | import org.springframework.security.core.userdetails.UserDetails; 9 | 10 | import java.util.Collection; 11 | 12 | @Data 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | public class UserDetailImpl implements UserDetails { 16 | private User user; 17 | 18 | @Override 19 | public Collection getAuthorities() { 20 | return null; 21 | } 22 | 23 | @Override 24 | public String getPassword() { 25 | return user.getHashedPassword(); 26 | } 27 | 28 | @Override 29 | public String getUsername() { return user.getEmail(); } 30 | 31 | @Override 32 | public boolean isAccountNonExpired() { 33 | return true; 34 | } 35 | 36 | @Override 37 | public boolean isAccountNonLocked() { 38 | return true; 39 | } 40 | 41 | @Override 42 | public boolean isCredentialsNonExpired() { 43 | return true; 44 | } 45 | 46 | @Override 47 | public boolean isEnabled() { 48 | return true; 49 | } 50 | } 51 | 52 | -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/controller/note/NoteCreateController.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.controller.note; 2 | 3 | import com.zouht.todolist.service.note.NoteCreateService; 4 | import org.springframework.web.bind.annotation.PostMapping; 5 | import org.springframework.web.bind.annotation.RequestBody; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | import javax.annotation.Resource; 9 | import javax.servlet.http.HttpServletResponse; 10 | import java.util.Map; 11 | 12 | @RestController 13 | public class NoteCreateController { 14 | @Resource 15 | NoteCreateService noteCreateService; 16 | 17 | @PostMapping("/note/create") 18 | public Map create(@RequestBody Map map, HttpServletResponse response) { 19 | String title = (String) map.get("title"); 20 | String content = (String) map.get("content"); 21 | 22 | if (title == null || content == null) { 23 | response.setStatus(400); 24 | return Map.of("status", 1, "message", "title or content is null"); 25 | } 26 | 27 | try { 28 | return noteCreateService.create(title, content); 29 | } catch (Exception e) { 30 | response.setStatus(500); 31 | return Map.of("status", 1, "message", e.getMessage()); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/controller/todo/TodoCreateController.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.controller.todo; 2 | 3 | import com.zouht.todolist.service.todo.TodoCreateService; 4 | import org.springframework.web.bind.annotation.PostMapping; 5 | import org.springframework.web.bind.annotation.RequestBody; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | import javax.annotation.Resource; 9 | import javax.servlet.http.HttpServletResponse; 10 | import java.util.Map; 11 | 12 | @RestController 13 | public class TodoCreateController { 14 | @Resource 15 | private TodoCreateService todoCreateService; 16 | 17 | @PostMapping("/todo/create") 18 | public Map create(@RequestBody Map map, HttpServletResponse response) { 19 | String title = (String) map.get("title"); 20 | String detail = (String) map.get("detail"); 21 | Integer begin = (Integer) map.get("begin"); 22 | Integer end = (Integer) map.get("end"); 23 | Boolean isFinished = (Boolean) map.get("isFinished"); 24 | 25 | try { 26 | return todoCreateService.create(title, detail, begin, end, isFinished); 27 | } catch (Exception e) { 28 | response.setStatus(500); 29 | return Map.of("status", 1, "message", e.getMessage()); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/service/todo/TodoCreateService.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.service.todo; 2 | 3 | import com.zouht.todolist.mapper.TodoMapper; 4 | import com.zouht.todolist.pojo.Todo; 5 | import com.zouht.todolist.pojo.User; 6 | import com.zouht.todolist.service.user.UserDetailImpl; 7 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 8 | import org.springframework.security.core.context.SecurityContextHolder; 9 | import org.springframework.stereotype.Service; 10 | 11 | import javax.annotation.Resource; 12 | import java.util.Map; 13 | 14 | @Service 15 | public class TodoCreateService { 16 | @Resource 17 | TodoMapper todoMapper; 18 | 19 | public Map create(String title, String detail, Integer begin, Integer end, Boolean isFinished) { 20 | UsernamePasswordAuthenticationToken authenticationToken = (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication(); 21 | UserDetailImpl loginUSer = (UserDetailImpl) authenticationToken.getPrincipal(); 22 | User user = loginUSer.getUser(); 23 | 24 | Todo todo = new Todo(null, user.getUserId(), title, detail, begin, end, isFinished); 25 | todoMapper.insert(todo); 26 | 27 | return Map.of("status", 0, "message", "OK", "todoId", todo.getTodoId()); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/service/note/NoteListService.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.service.note; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 4 | import com.zouht.todolist.mapper.NoteMapper; 5 | import com.zouht.todolist.pojo.Note; 6 | import com.zouht.todolist.service.user.UserDetailImpl; 7 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 8 | import org.springframework.security.core.context.SecurityContextHolder; 9 | import org.springframework.stereotype.Service; 10 | 11 | import javax.annotation.Resource; 12 | import java.util.List; 13 | import java.util.Map; 14 | 15 | @Service 16 | public class NoteListService { 17 | @Resource 18 | NoteMapper noteMapper; 19 | 20 | public Map list() { 21 | UsernamePasswordAuthenticationToken authenticationToken = (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication(); 22 | UserDetailImpl loginUSer = (UserDetailImpl) authenticationToken.getPrincipal(); 23 | Integer user = loginUSer.getUser().getUserId(); 24 | 25 | QueryWrapper queryWrapper = new QueryWrapper<>(); 26 | queryWrapper.eq("user_id", user); 27 | List noteList = noteMapper.selectList(queryWrapper); 28 | 29 | return Map.of("status", 0, "message", "OK", "data", noteList); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/service/todo/TodoListService.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.service.todo; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 4 | import com.zouht.todolist.mapper.TodoMapper; 5 | import com.zouht.todolist.pojo.Todo; 6 | import com.zouht.todolist.service.user.UserDetailImpl; 7 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 8 | import org.springframework.security.core.context.SecurityContextHolder; 9 | import org.springframework.stereotype.Service; 10 | 11 | import javax.annotation.Resource; 12 | import java.util.List; 13 | import java.util.Map; 14 | 15 | @Service 16 | public class TodoListService { 17 | @Resource 18 | TodoMapper todoMapper; 19 | 20 | public Map list() { 21 | UsernamePasswordAuthenticationToken authenticationToken = (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication(); 22 | UserDetailImpl loginUSer = (UserDetailImpl) authenticationToken.getPrincipal(); 23 | Integer user = loginUSer.getUser().getUserId(); 24 | 25 | QueryWrapper queryWrapper = new QueryWrapper<>(); 26 | queryWrapper.eq("user_id", user); 27 | List todoList = todoMapper.selectList(queryWrapper); 28 | 29 | return Map.of("status", 0, "message", "OK", "data", todoList); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/controller/user/RegisterController.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.controller.user; 2 | 3 | import com.zouht.todolist.service.user.RegisterService; 4 | import org.springframework.web.bind.annotation.PostMapping; 5 | import org.springframework.web.bind.annotation.RequestBody; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | import javax.annotation.Resource; 9 | import javax.servlet.http.HttpServletResponse; 10 | import java.util.Map; 11 | 12 | @RestController 13 | public class RegisterController { 14 | @Resource 15 | private RegisterService registerService; 16 | 17 | @PostMapping("/user/register") 18 | public Map register(@RequestBody Map map, HttpServletResponse response) { 19 | String email = (String) map.get("email"); 20 | String password = (String) map.get("password"); 21 | String avatar = (String) map.get("avatar"); 22 | 23 | if (email == null || password == null) { 24 | response.setStatus(400); 25 | return Map.of("status", 1, "message", "email and password are required"); 26 | } 27 | 28 | try { 29 | return registerService.register(email, password, avatar); 30 | } catch (Exception e) { 31 | response.setStatus(500); 32 | return Map.of("status", 1, "message", e.getMessage()); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/controller/user/UserUpdateController.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.controller.user; 2 | 3 | import com.zouht.todolist.service.user.UserUpdateService; 4 | import org.springframework.web.bind.annotation.PostMapping; 5 | import org.springframework.web.bind.annotation.RequestBody; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | import javax.annotation.Resource; 9 | import javax.servlet.http.HttpServletResponse; 10 | import java.util.Map; 11 | 12 | @RestController 13 | public class UserUpdateController { 14 | @Resource 15 | private UserUpdateService userUpdateService; 16 | 17 | @PostMapping("/user/update") 18 | public Map update(@RequestBody Map map, HttpServletResponse response) { 19 | String email = (String) map.get("email"); 20 | String password = (String) map.get("password"); 21 | String avatar = (String) map.get("avatar"); 22 | 23 | if (email == null || password == null) { 24 | response.setStatus(400); 25 | return Map.of("status", 1, "message", "email and password are required"); 26 | } 27 | 28 | try { 29 | return userUpdateService.update(email, password, avatar); 30 | } catch (Exception e) { 31 | response.setStatus(500); 32 | return Map.of("status", 1, "message", e.getMessage()); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/controller/todo/TodoUpdateController.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.controller.todo; 2 | 3 | import com.zouht.todolist.service.todo.TodoUpdateService; 4 | import org.springframework.web.bind.annotation.PostMapping; 5 | import org.springframework.web.bind.annotation.RequestBody; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | import javax.annotation.Resource; 9 | import javax.servlet.http.HttpServletResponse; 10 | import java.util.Map; 11 | 12 | @RestController 13 | public class TodoUpdateController { 14 | @Resource 15 | TodoUpdateService todoUpdateService; 16 | 17 | @PostMapping("/todo/update") 18 | public Map update(@RequestBody Map map, HttpServletResponse response) { 19 | Integer todoId = (Integer) map.get("todoId"); 20 | String title = (String) map.get("title"); 21 | String detail = (String) map.get("detail"); 22 | Integer begin = (Integer) map.get("begin"); 23 | Integer end = (Integer) map.get("end"); 24 | Boolean isFinished = (Boolean) map.get("isFinished"); 25 | 26 | if (todoId == null) { 27 | response.setStatus(400); 28 | return Map.of("status", 1, "message", "todoId is null"); 29 | } 30 | 31 | try { 32 | return todoUpdateService.update(todoId, title, detail, begin, end, isFinished); 33 | } catch (Exception e) { 34 | response.setStatus(500); 35 | return Map.of("status", 1, "message", e.getMessage()); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/config/CorsConfig.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.config; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | 5 | import javax.servlet.*; 6 | import javax.servlet.http.HttpServletRequest; 7 | import javax.servlet.http.HttpServletResponse; 8 | import java.io.IOException; 9 | 10 | @Configuration 11 | public class CorsConfig implements Filter { 12 | @Override 13 | public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { 14 | HttpServletResponse response = (HttpServletResponse) res; 15 | HttpServletRequest request = (HttpServletRequest) req; 16 | 17 | String origin = request.getHeader("Origin"); 18 | if (origin != null) { 19 | response.setHeader("Access-Control-Allow-Origin", origin); 20 | } 21 | 22 | String headers = request.getHeader("Access-Control-Request-Headers"); 23 | if (headers != null) { 24 | response.setHeader("Access-Control-Allow-Headers", headers); 25 | response.setHeader("Access-Control-Expose-Headers", headers); 26 | } 27 | 28 | response.setHeader("Access-Control-Allow-Methods", "*"); 29 | response.setHeader("Access-Control-Max-Age", "3600"); 30 | response.setHeader("Access-Control-Allow-Credentials", "true"); 31 | 32 | chain.doFilter(request, response); 33 | } 34 | 35 | @Override 36 | public void init(FilterConfig filterConfig) { 37 | 38 | } 39 | 40 | @Override 41 | public void destroy() { 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/controller/note/NoteUpdateController.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.controller.note; 2 | 3 | import com.zouht.todolist.service.note.NoteUpdateService; 4 | import org.springframework.web.bind.annotation.PostMapping; 5 | import org.springframework.web.bind.annotation.RequestBody; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | import javax.annotation.Resource; 9 | import javax.servlet.http.HttpServletResponse; 10 | import java.util.Map; 11 | 12 | @RestController 13 | public class NoteUpdateController { 14 | @Resource 15 | NoteUpdateService noteUpdateService; 16 | 17 | @PostMapping("/note/update") 18 | public Map update(@RequestBody Map map, HttpServletResponse response) { 19 | Integer noteId = (Integer) map.get("noteId"); 20 | String title = (String) map.get("title"); 21 | String content = (String) map.get("content"); 22 | Integer date = (Integer) map.get("date"); 23 | Boolean isStared = (Boolean) map.get("isStared"); 24 | 25 | if (noteId == null || title == null || content == null || date == null || isStared == null) { 26 | response.setStatus(400); 27 | return Map.of("status", 1, "message", "Invalid parameters"); 28 | } 29 | 30 | try { 31 | return noteUpdateService.update(noteId, title, content, date, isStared); 32 | } catch (Exception e) { 33 | response.setStatus(500); 34 | return Map.of("status", 1, "message", e.getMessage()); 35 | } 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/service/todo/TodoGetTodayService.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.service.todo; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 4 | import com.zouht.todolist.mapper.TodoMapper; 5 | import com.zouht.todolist.pojo.Todo; 6 | import org.springframework.stereotype.Service; 7 | 8 | import javax.annotation.Resource; 9 | import java.time.LocalDate; 10 | import java.util.List; 11 | import java.util.Map; 12 | 13 | @Service 14 | public class TodoGetTodayService { 15 | @Resource 16 | TodoMapper todoMapper; 17 | 18 | public Map getToday(Integer year, Integer month, Integer day) { 19 | // TODO: 没判平行越权 20 | LocalDate dateLowerBound, dateUpperBound; 21 | if (day != null) { 22 | dateLowerBound = LocalDate.of(year, month, day); 23 | dateUpperBound = dateLowerBound.plusDays(1); 24 | } else { 25 | dateLowerBound = LocalDate.of(year, month, 1); 26 | dateUpperBound = dateLowerBound.plusMonths(1); 27 | } 28 | Integer timestampLowerBound = (int) dateLowerBound.toEpochDay() * 24 * 60 * 60; 29 | Integer timestampUpperBound = (int) dateUpperBound.toEpochDay() * 24 * 60 * 60; 30 | QueryWrapper queryWrapper = new QueryWrapper<>(); 31 | queryWrapper.between("begin", timestampLowerBound, timestampUpperBound); 32 | queryWrapper.or(); 33 | queryWrapper.between("end", timestampLowerBound, timestampUpperBound); 34 | List todoList = todoMapper.selectList(queryWrapper); 35 | return Map.of("status", 0, "message", "OK", "data", todoList); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/config/SecurityConfig.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.config; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.http.HttpMethod; 7 | import org.springframework.security.authentication.AuthenticationManager; 8 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 9 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 10 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 11 | import org.springframework.security.config.http.SessionCreationPolicy; 12 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 13 | import org.springframework.security.crypto.password.PasswordEncoder; 14 | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; 15 | 16 | @Configuration 17 | @EnableWebSecurity 18 | public class SecurityConfig extends WebSecurityConfigurerAdapter { 19 | @Autowired 20 | private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter; 21 | 22 | @Bean 23 | public PasswordEncoder passwordEncoder() { 24 | return new BCryptPasswordEncoder(); 25 | } 26 | 27 | @Bean 28 | @Override 29 | public AuthenticationManager authenticationManagerBean() throws Exception { 30 | return super.authenticationManagerBean(); 31 | } 32 | 33 | @Override 34 | protected void configure(HttpSecurity http) throws Exception { 35 | http.csrf().disable() 36 | .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) 37 | .and() 38 | .authorizeRequests() 39 | .antMatchers("/", "/user/login", "/user/register", "/user/uploadAvatar", "/upload/*").permitAll() 40 | .antMatchers(HttpMethod.OPTIONS).permitAll() 41 | .anyRequest().authenticated(); 42 | 43 | http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); 44 | } 45 | } -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/util/JwtUtil.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.util; 2 | 3 | import io.jsonwebtoken.Claims; 4 | import io.jsonwebtoken.JwtBuilder; 5 | import io.jsonwebtoken.Jwts; 6 | import io.jsonwebtoken.SignatureAlgorithm; 7 | import org.springframework.stereotype.Component; 8 | 9 | import javax.crypto.SecretKey; 10 | import javax.crypto.spec.SecretKeySpec; 11 | import java.util.Base64; 12 | import java.util.Date; 13 | import java.util.UUID; 14 | 15 | @Component 16 | public class JwtUtil { 17 | public static final long JWT_TTL = 60 * 60 * 1000L * 24 * 14; // 有效期14天 18 | public static final String JWT_KEY = "SDFGjhdsfalshdfHFdsjkdsfds121232131afasdfac"; 19 | 20 | public static String getUUID() { 21 | return UUID.randomUUID().toString().replaceAll("-", ""); 22 | } 23 | 24 | public static String createJWT(String subject) { 25 | JwtBuilder builder = getJwtBuilder(subject, null, getUUID()); 26 | return builder.compact(); 27 | } 28 | 29 | private static JwtBuilder getJwtBuilder(String subject, Long ttlMillis, String uuid) { 30 | SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256; 31 | SecretKey secretKey = generalKey(); 32 | long nowMillis = System.currentTimeMillis(); 33 | Date now = new Date(nowMillis); 34 | if (ttlMillis == null) { 35 | ttlMillis = JwtUtil.JWT_TTL; 36 | } 37 | 38 | long expMillis = nowMillis + ttlMillis; 39 | Date expDate = new Date(expMillis); 40 | return Jwts.builder() 41 | .setId(uuid) 42 | .setSubject(subject) 43 | .setIssuer("sg") 44 | .setIssuedAt(now) 45 | .signWith(signatureAlgorithm, secretKey) 46 | .setExpiration(expDate); 47 | } 48 | 49 | public static SecretKey generalKey() { 50 | byte[] encodeKey = Base64.getDecoder().decode(JwtUtil.JWT_KEY); 51 | return new SecretKeySpec(encodeKey, 0, encodeKey.length, "HmacSHA256"); 52 | } 53 | 54 | public static Claims parseJWT(String jwt) throws Exception { 55 | SecretKey secretKey = generalKey(); 56 | return Jwts.parser() 57 | .setSigningKey(secretKey) 58 | .build() 59 | .parseClaimsJws(jwt) 60 | .getBody(); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/com/zouht/todolist/config/JwtAuthenticationTokenFilter.java: -------------------------------------------------------------------------------- 1 | package com.zouht.todolist.config; 2 | 3 | import com.zouht.todolist.mapper.UserMapper; 4 | import com.zouht.todolist.pojo.User; 5 | import com.zouht.todolist.service.user.UserDetailImpl; 6 | import com.zouht.todolist.util.JwtUtil; 7 | import io.jsonwebtoken.Claims; 8 | import org.jetbrains.annotations.NotNull; 9 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 10 | import org.springframework.security.core.context.SecurityContextHolder; 11 | import org.springframework.stereotype.Component; 12 | import org.springframework.util.StringUtils; 13 | import org.springframework.web.filter.OncePerRequestFilter; 14 | 15 | import javax.annotation.Resource; 16 | import javax.servlet.FilterChain; 17 | import javax.servlet.ServletException; 18 | import javax.servlet.http.HttpServletRequest; 19 | import javax.servlet.http.HttpServletResponse; 20 | import java.io.IOException; 21 | 22 | @Component 23 | public class JwtAuthenticationTokenFilter extends OncePerRequestFilter { 24 | @Resource 25 | private UserMapper userMapper; 26 | 27 | @Override 28 | protected void doFilterInternal(HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull FilterChain filterChain) throws ServletException, IOException { 29 | String token = request.getHeader("Authorization"); 30 | 31 | if (!StringUtils.hasText(token) || !token.startsWith("Bearer ")) { 32 | filterChain.doFilter(request, response); 33 | return; 34 | } 35 | 36 | token = token.substring(7); 37 | 38 | String userId; 39 | try { 40 | Claims claims = JwtUtil.parseJWT(token); 41 | userId = claims.getSubject(); 42 | } catch (Exception e) { 43 | throw new RuntimeException(e); 44 | } 45 | 46 | User user = userMapper.selectById(Integer.parseInt(userId)); 47 | 48 | if (user == null) { 49 | throw new RuntimeException("用户不存在"); 50 | } 51 | 52 | UserDetailImpl loginUser = new UserDetailImpl(user); 53 | UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, null); 54 | 55 | SecurityContextHolder.getContext().setAuthentication(authenticationToken); 56 | 57 | filterChain.doFilter(request, response); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 2.6.0 9 | 10 | 11 | com.zouht 12 | todolist 13 | 0.0.1-SNAPSHOT 14 | Todo List Backend 15 | Todo List Backend 16 | 17 | 17 18 | 19 | 20 | 21 | org.springframework.boot 22 | spring-boot-starter-web 23 | 24 | 25 | org.springframework.boot 26 | spring-boot-starter-test 27 | test 28 | 29 | 30 | 31 | org.springframework.boot 32 | spring-boot-starter-jdbc 33 | 3.2.0 34 | 35 | 36 | 37 | org.projectlombok 38 | lombok 39 | 1.18.30 40 | provided 41 | 42 | 43 | 44 | com.mysql 45 | mysql-connector-j 46 | 8.2.0 47 | 48 | 49 | 50 | com.baomidou 51 | mybatis-plus-boot-starter 52 | 3.5.4.1 53 | 54 | 55 | 56 | com.baomidou 57 | mybatis-plus-generator 58 | 3.5.4.1 59 | 60 | 61 | 62 | org.springframework.boot 63 | spring-boot-starter-security 64 | 3.2.0 65 | 66 | 67 | 68 | io.jsonwebtoken 69 | jjwt-api 70 | 0.12.3 71 | 72 | 73 | 74 | io.jsonwebtoken 75 | jjwt-impl 76 | 0.12.3 77 | runtime 78 | 79 | 80 | 81 | io.jsonwebtoken 82 | jjwt-jackson 83 | 0.12.3 84 | runtime 85 | 86 | 87 | org.jetbrains 88 | annotations 89 | RELEASE 90 | compile 91 | 92 | 93 | 94 | 95 | 96 | 97 | org.springframework.boot 98 | spring-boot-maven-plugin 99 | 100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM https://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Apache Maven Wrapper startup batch script, version 3.2.0 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 28 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending 29 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 30 | @REM e.g. to debug Maven itself, use 31 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 32 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 33 | @REM ---------------------------------------------------------------------------- 34 | 35 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 36 | @echo off 37 | @REM set title of command window 38 | title %0 39 | @REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' 40 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 41 | 42 | @REM set %HOME% to equivalent of $HOME 43 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 44 | 45 | @REM Execute a user defined script before this one 46 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 47 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 48 | if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* 49 | if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* 50 | :skipRcPre 51 | 52 | @setlocal 53 | 54 | set ERROR_CODE=0 55 | 56 | @REM To isolate internal variables from possible post scripts, we use another setlocal 57 | @setlocal 58 | 59 | @REM ==== START VALIDATION ==== 60 | if not "%JAVA_HOME%" == "" goto OkJHome 61 | 62 | echo. 63 | echo Error: JAVA_HOME not found in your environment. >&2 64 | echo Please set the JAVA_HOME variable in your environment to match the >&2 65 | echo location of your Java installation. >&2 66 | echo. 67 | goto error 68 | 69 | :OkJHome 70 | if exist "%JAVA_HOME%\bin\java.exe" goto init 71 | 72 | echo. 73 | echo Error: JAVA_HOME is set to an invalid directory. >&2 74 | echo JAVA_HOME = "%JAVA_HOME%" >&2 75 | echo Please set the JAVA_HOME variable in your environment to match the >&2 76 | echo location of your Java installation. >&2 77 | echo. 78 | goto error 79 | 80 | @REM ==== END VALIDATION ==== 81 | 82 | :init 83 | 84 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 85 | @REM Fallback to current working directory if not found. 86 | 87 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 88 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 89 | 90 | set EXEC_DIR=%CD% 91 | set WDIR=%EXEC_DIR% 92 | :findBaseDir 93 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 94 | cd .. 95 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 96 | set WDIR=%CD% 97 | goto findBaseDir 98 | 99 | :baseDirFound 100 | set MAVEN_PROJECTBASEDIR=%WDIR% 101 | cd "%EXEC_DIR%" 102 | goto endDetectBaseDir 103 | 104 | :baseDirNotFound 105 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 106 | cd "%EXEC_DIR%" 107 | 108 | :endDetectBaseDir 109 | 110 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 111 | 112 | @setlocal EnableExtensions EnableDelayedExpansion 113 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 114 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 115 | 116 | :endReadAdditionalConfig 117 | 118 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 119 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 120 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 121 | 122 | set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" 123 | 124 | FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( 125 | IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B 126 | ) 127 | 128 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 129 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data. 130 | if exist %WRAPPER_JAR% ( 131 | if "%MVNW_VERBOSE%" == "true" ( 132 | echo Found %WRAPPER_JAR% 133 | ) 134 | ) else ( 135 | if not "%MVNW_REPOURL%" == "" ( 136 | SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" 137 | ) 138 | if "%MVNW_VERBOSE%" == "true" ( 139 | echo Couldn't find %WRAPPER_JAR%, downloading it ... 140 | echo Downloading from: %WRAPPER_URL% 141 | ) 142 | 143 | powershell -Command "&{"^ 144 | "$webclient = new-object System.Net.WebClient;"^ 145 | "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ 146 | "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ 147 | "}"^ 148 | "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^ 149 | "}" 150 | if "%MVNW_VERBOSE%" == "true" ( 151 | echo Finished downloading %WRAPPER_JAR% 152 | ) 153 | ) 154 | @REM End of extension 155 | 156 | @REM If specified, validate the SHA-256 sum of the Maven wrapper jar file 157 | SET WRAPPER_SHA_256_SUM="" 158 | FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( 159 | IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B 160 | ) 161 | IF NOT %WRAPPER_SHA_256_SUM%=="" ( 162 | powershell -Command "&{"^ 163 | "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^ 164 | "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^ 165 | " Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^ 166 | " Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^ 167 | " Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^ 168 | " exit 1;"^ 169 | "}"^ 170 | "}" 171 | if ERRORLEVEL 1 goto error 172 | ) 173 | 174 | @REM Provide a "standardized" way to retrieve the CLI args that will 175 | @REM work with both Windows and non-Windows executions. 176 | set MAVEN_CMD_LINE_ARGS=%* 177 | 178 | %MAVEN_JAVA_EXE% ^ 179 | %JVM_CONFIG_MAVEN_PROPS% ^ 180 | %MAVEN_OPTS% ^ 181 | %MAVEN_DEBUG_OPTS% ^ 182 | -classpath %WRAPPER_JAR% ^ 183 | "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ 184 | %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 185 | if ERRORLEVEL 1 goto error 186 | goto end 187 | 188 | :error 189 | set ERROR_CODE=1 190 | 191 | :end 192 | @endlocal & set ERROR_CODE=%ERROR_CODE% 193 | 194 | if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost 195 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 196 | if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" 197 | if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" 198 | :skipRcPost 199 | 200 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 201 | if "%MAVEN_BATCH_PAUSE%"=="on" pause 202 | 203 | if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% 204 | 205 | cmd /C exit /B %ERROR_CODE% 206 | -------------------------------------------------------------------------------- /mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # https://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Apache Maven Wrapper startup batch script, version 3.2.0 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | # e.g. to debug Maven itself, use 32 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | # ---------------------------------------------------------------------------- 35 | 36 | if [ -z "$MAVEN_SKIP_RC" ] ; then 37 | 38 | if [ -f /usr/local/etc/mavenrc ] ; then 39 | . /usr/local/etc/mavenrc 40 | fi 41 | 42 | if [ -f /etc/mavenrc ] ; then 43 | . /etc/mavenrc 44 | fi 45 | 46 | if [ -f "$HOME/.mavenrc" ] ; then 47 | . "$HOME/.mavenrc" 48 | fi 49 | 50 | fi 51 | 52 | # OS specific support. $var _must_ be set to either true or false. 53 | cygwin=false; 54 | darwin=false; 55 | mingw=false 56 | case "$(uname)" in 57 | CYGWIN*) cygwin=true ;; 58 | MINGW*) mingw=true;; 59 | Darwin*) darwin=true 60 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 61 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 62 | if [ -z "$JAVA_HOME" ]; then 63 | if [ -x "/usr/libexec/java_home" ]; then 64 | JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME 65 | else 66 | JAVA_HOME="/Library/Java/Home"; export JAVA_HOME 67 | fi 68 | fi 69 | ;; 70 | esac 71 | 72 | if [ -z "$JAVA_HOME" ] ; then 73 | if [ -r /etc/gentoo-release ] ; then 74 | JAVA_HOME=$(java-config --jre-home) 75 | fi 76 | fi 77 | 78 | # For Cygwin, ensure paths are in UNIX format before anything is touched 79 | if $cygwin ; then 80 | [ -n "$JAVA_HOME" ] && 81 | JAVA_HOME=$(cygpath --unix "$JAVA_HOME") 82 | [ -n "$CLASSPATH" ] && 83 | CLASSPATH=$(cygpath --path --unix "$CLASSPATH") 84 | fi 85 | 86 | # For Mingw, ensure paths are in UNIX format before anything is touched 87 | if $mingw ; then 88 | [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] && 89 | JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)" 90 | fi 91 | 92 | if [ -z "$JAVA_HOME" ]; then 93 | javaExecutable="$(which javac)" 94 | if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then 95 | # readlink(1) is not available as standard on Solaris 10. 96 | readLink=$(which readlink) 97 | if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then 98 | if $darwin ; then 99 | javaHome="$(dirname "\"$javaExecutable\"")" 100 | javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac" 101 | else 102 | javaExecutable="$(readlink -f "\"$javaExecutable\"")" 103 | fi 104 | javaHome="$(dirname "\"$javaExecutable\"")" 105 | javaHome=$(expr "$javaHome" : '\(.*\)/bin') 106 | JAVA_HOME="$javaHome" 107 | export JAVA_HOME 108 | fi 109 | fi 110 | fi 111 | 112 | if [ -z "$JAVACMD" ] ; then 113 | if [ -n "$JAVA_HOME" ] ; then 114 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 115 | # IBM's JDK on AIX uses strange locations for the executables 116 | JAVACMD="$JAVA_HOME/jre/sh/java" 117 | else 118 | JAVACMD="$JAVA_HOME/bin/java" 119 | fi 120 | else 121 | JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)" 122 | fi 123 | fi 124 | 125 | if [ ! -x "$JAVACMD" ] ; then 126 | echo "Error: JAVA_HOME is not defined correctly." >&2 127 | echo " We cannot execute $JAVACMD" >&2 128 | exit 1 129 | fi 130 | 131 | if [ -z "$JAVA_HOME" ] ; then 132 | echo "Warning: JAVA_HOME environment variable is not set." 133 | fi 134 | 135 | # traverses directory structure from process work directory to filesystem root 136 | # first directory with .mvn subdirectory is considered project base directory 137 | find_maven_basedir() { 138 | if [ -z "$1" ] 139 | then 140 | echo "Path not specified to find_maven_basedir" 141 | return 1 142 | fi 143 | 144 | basedir="$1" 145 | wdir="$1" 146 | while [ "$wdir" != '/' ] ; do 147 | if [ -d "$wdir"/.mvn ] ; then 148 | basedir=$wdir 149 | break 150 | fi 151 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 152 | if [ -d "${wdir}" ]; then 153 | wdir=$(cd "$wdir/.." || exit 1; pwd) 154 | fi 155 | # end of workaround 156 | done 157 | printf '%s' "$(cd "$basedir" || exit 1; pwd)" 158 | } 159 | 160 | # concatenates all lines of a file 161 | concat_lines() { 162 | if [ -f "$1" ]; then 163 | # Remove \r in case we run on Windows within Git Bash 164 | # and check out the repository with auto CRLF management 165 | # enabled. Otherwise, we may read lines that are delimited with 166 | # \r\n and produce $'-Xarg\r' rather than -Xarg due to word 167 | # splitting rules. 168 | tr -s '\r\n' ' ' < "$1" 169 | fi 170 | } 171 | 172 | log() { 173 | if [ "$MVNW_VERBOSE" = true ]; then 174 | printf '%s\n' "$1" 175 | fi 176 | } 177 | 178 | BASE_DIR=$(find_maven_basedir "$(dirname "$0")") 179 | if [ -z "$BASE_DIR" ]; then 180 | exit 1; 181 | fi 182 | 183 | MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR 184 | log "$MAVEN_PROJECTBASEDIR" 185 | 186 | ########################################################################################## 187 | # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 188 | # This allows using the maven wrapper in projects that prohibit checking in binary data. 189 | ########################################################################################## 190 | wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" 191 | if [ -r "$wrapperJarPath" ]; then 192 | log "Found $wrapperJarPath" 193 | else 194 | log "Couldn't find $wrapperJarPath, downloading it ..." 195 | 196 | if [ -n "$MVNW_REPOURL" ]; then 197 | wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" 198 | else 199 | wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" 200 | fi 201 | while IFS="=" read -r key value; do 202 | # Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' ) 203 | safeValue=$(echo "$value" | tr -d '\r') 204 | case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;; 205 | esac 206 | done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" 207 | log "Downloading from: $wrapperUrl" 208 | 209 | if $cygwin; then 210 | wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath") 211 | fi 212 | 213 | if command -v wget > /dev/null; then 214 | log "Found wget ... using wget" 215 | [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet" 216 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then 217 | wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" 218 | else 219 | wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" 220 | fi 221 | elif command -v curl > /dev/null; then 222 | log "Found curl ... using curl" 223 | [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent" 224 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then 225 | curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" 226 | else 227 | curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" 228 | fi 229 | else 230 | log "Falling back to using Java to download" 231 | javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java" 232 | javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class" 233 | # For Cygwin, switch paths to Windows format before running javac 234 | if $cygwin; then 235 | javaSource=$(cygpath --path --windows "$javaSource") 236 | javaClass=$(cygpath --path --windows "$javaClass") 237 | fi 238 | if [ -e "$javaSource" ]; then 239 | if [ ! -e "$javaClass" ]; then 240 | log " - Compiling MavenWrapperDownloader.java ..." 241 | ("$JAVA_HOME/bin/javac" "$javaSource") 242 | fi 243 | if [ -e "$javaClass" ]; then 244 | log " - Running MavenWrapperDownloader.java ..." 245 | ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath" 246 | fi 247 | fi 248 | fi 249 | fi 250 | ########################################################################################## 251 | # End of extension 252 | ########################################################################################## 253 | 254 | # If specified, validate the SHA-256 sum of the Maven wrapper jar file 255 | wrapperSha256Sum="" 256 | while IFS="=" read -r key value; do 257 | case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;; 258 | esac 259 | done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" 260 | if [ -n "$wrapperSha256Sum" ]; then 261 | wrapperSha256Result=false 262 | if command -v sha256sum > /dev/null; then 263 | if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then 264 | wrapperSha256Result=true 265 | fi 266 | elif command -v shasum > /dev/null; then 267 | if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then 268 | wrapperSha256Result=true 269 | fi 270 | else 271 | echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." 272 | echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties." 273 | exit 1 274 | fi 275 | if [ $wrapperSha256Result = false ]; then 276 | echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2 277 | echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2 278 | echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2 279 | exit 1 280 | fi 281 | fi 282 | 283 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 284 | 285 | # For Cygwin, switch paths to Windows format before running java 286 | if $cygwin; then 287 | [ -n "$JAVA_HOME" ] && 288 | JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME") 289 | [ -n "$CLASSPATH" ] && 290 | CLASSPATH=$(cygpath --path --windows "$CLASSPATH") 291 | [ -n "$MAVEN_PROJECTBASEDIR" ] && 292 | MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR") 293 | fi 294 | 295 | # Provide a "standardized" way to retrieve the CLI args that will 296 | # work with both Windows and non-Windows executions. 297 | MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*" 298 | export MAVEN_CMD_LINE_ARGS 299 | 300 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 301 | 302 | # shellcheck disable=SC2086 # safe args 303 | exec "$JAVACMD" \ 304 | $MAVEN_OPTS \ 305 | $MAVEN_DEBUG_OPTS \ 306 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 307 | "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 308 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 309 | -------------------------------------------------------------------------------- /API.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Web-Course-Exp 3 | language_tabs: 4 | - shell: Shell 5 | - http: HTTP 6 | - javascript: JavaScript 7 | - ruby: Ruby 8 | - python: Python 9 | - php: PHP 10 | - java: Java 11 | - go: Go 12 | toc_footers: [] 13 | includes: [] 14 | search: true 15 | code_clipboard: true 16 | highlight_theme: darkula 17 | headingLevel: 2 18 | generator: "@tarslib/widdershins v4.0.23" 19 | 20 | --- 21 | 22 | # Web-Course-Exp 23 | 24 | Base URLs: 25 | 26 | # Authentication 27 | 28 | - HTTP Authentication, scheme: bearer 29 | 30 | # 待办 todo 31 | 32 | ## POST 新建待办 create 33 | 34 | POST /todo/create 35 | 36 | > Body 请求参数 37 | 38 | ```json 39 | { 40 | "title": "string", 41 | "detail": "string", 42 | "begin": 0, 43 | "end": 0, 44 | "isFinished": true 45 | } 46 | ``` 47 | 48 | ### 请求参数 49 | 50 | |名称|位置|类型|必选|中文名|说明| 51 | |---|---|---|---|---|---| 52 | |body|body|object| 否 ||none| 53 | |» title|body|string| 是 | 标题|none| 54 | |» detail|body|string| 是 | 详情|none| 55 | |» begin|body|integer¦null| 是 | 开始时间戳|none| 56 | |» end|body|integer| 是 | 结束时间戳|none| 57 | |» isFinished|body|boolean| 是 | 是否完成|none| 58 | 59 | > 返回示例 60 | 61 | > 200 Response 62 | 63 | ```json 64 | { 65 | "status": 0, 66 | "message": "string", 67 | "todoId": 0 68 | } 69 | ``` 70 | 71 | ### 返回结果 72 | 73 | |状态码|状态码含义|说明|数据模型| 74 | |---|---|---|---| 75 | |200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|成功|Inline| 76 | 77 | ### 返回数据结构 78 | 79 | 状态码 **200** 80 | 81 | |名称|类型|必选|约束|中文名|说明| 82 | |---|---|---|---|---|---| 83 | |» status|integer|true|none|状态|none| 84 | |» message|string|true|none|信息|none| 85 | |» todoId|integer|true|none||none| 86 | 87 | ## DELETE 删除待办 delete 88 | 89 | DELETE /todo/delete 90 | 91 | ### 请求参数 92 | 93 | |名称|位置|类型|必选|中文名|说明| 94 | |---|---|---|---|---|---| 95 | |todoId|query|integer| 否 ||none| 96 | 97 | > 返回示例 98 | 99 | > 200 Response 100 | 101 | ```json 102 | { 103 | "status": 0, 104 | "message": "string" 105 | } 106 | ``` 107 | 108 | ### 返回结果 109 | 110 | |状态码|状态码含义|说明|数据模型| 111 | |---|---|---|---| 112 | |200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|成功|Inline| 113 | 114 | ### 返回数据结构 115 | 116 | 状态码 **200** 117 | 118 | |名称|类型|必选|约束|中文名|说明| 119 | |---|---|---|---|---|---| 120 | |» status|integer|true|none|状态|none| 121 | |» message|string|true|none|信息|none| 122 | 123 | ## POST 修改待办 update 124 | 125 | POST /todo/update 126 | 127 | > Body 请求参数 128 | 129 | ```json 130 | { 131 | "todoId": 0, 132 | "title": "string", 133 | "detail": "string", 134 | "begin": 0, 135 | "end": 0, 136 | "isFinished": true 137 | } 138 | ``` 139 | 140 | ### 请求参数 141 | 142 | |名称|位置|类型|必选|中文名|说明| 143 | |---|---|---|---|---|---| 144 | |body|body|[Todo](#schematodo)| 否 | 待办 Todo|none| 145 | 146 | > 返回示例 147 | 148 | > 200 Response 149 | 150 | ```json 151 | { 152 | "status": 0, 153 | "message": "string" 154 | } 155 | ``` 156 | 157 | ### 返回结果 158 | 159 | |状态码|状态码含义|说明|数据模型| 160 | |---|---|---|---| 161 | |200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|成功|Inline| 162 | 163 | ### 返回数据结构 164 | 165 | 状态码 **200** 166 | 167 | |名称|类型|必选|约束|中文名|说明| 168 | |---|---|---|---|---|---| 169 | |» status|integer|true|none|状态|none| 170 | |» message|string|true|none|信息|none| 171 | 172 | ## GET 获取待办列表 list 173 | 174 | GET /todo/list 175 | 176 | > 返回示例 177 | 178 | > 200 Response 179 | 180 | ```json 181 | { 182 | "status": 0, 183 | "message": "string", 184 | "data": [ 185 | { 186 | "todoId": 0, 187 | "title": "string", 188 | "detail": "string", 189 | "begin": 0, 190 | "end": 0, 191 | "isFinished": true 192 | } 193 | ] 194 | } 195 | ``` 196 | 197 | ### 返回结果 198 | 199 | |状态码|状态码含义|说明|数据模型| 200 | |---|---|---|---| 201 | |200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|成功|Inline| 202 | 203 | ### 返回数据结构 204 | 205 | 状态码 **200** 206 | 207 | |名称|类型|必选|约束|中文名|说明| 208 | |---|---|---|---|---|---| 209 | |» status|integer|true|none|状态|none| 210 | |» message|string|true|none|信息|none| 211 | |» data|[[Todo](#schematodo)]|true|none||none| 212 | |»» 待办 Todo|[Todo](#schematodo)|false|none|待办 Todo|none| 213 | |»»» todoId|integer|true|none|ID|none| 214 | |»»» title|string|true|none|标题|none| 215 | |»»» detail|string|true|none|详情|none| 216 | |»»» begin|integer¦null|true|none|开始时间戳|none| 217 | |»»» end|integer|true|none|结束时间戳|none| 218 | |»»» isFinished|boolean|true|none|是否完成|none| 219 | 220 | ## GET 获取指定待办 get 221 | 222 | GET /todo/get 223 | 224 | ### 请求参数 225 | 226 | |名称|位置|类型|必选|中文名|说明| 227 | |---|---|---|---|---|---| 228 | |todoId|query|integer| 否 ||none| 229 | 230 | > 返回示例 231 | 232 | > 200 Response 233 | 234 | ```json 235 | { 236 | "status": 0, 237 | "message": "string", 238 | "data": { 239 | "todoId": 0, 240 | "title": "string", 241 | "detail": "string", 242 | "begin": 0, 243 | "end": 0, 244 | "isFinished": true 245 | } 246 | } 247 | ``` 248 | 249 | ### 返回结果 250 | 251 | |状态码|状态码含义|说明|数据模型| 252 | |---|---|---|---| 253 | |200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|成功|Inline| 254 | 255 | ### 返回数据结构 256 | 257 | 状态码 **200** 258 | 259 | |名称|类型|必选|约束|中文名|说明| 260 | |---|---|---|---|---|---| 261 | |» status|integer|true|none|状态|none| 262 | |» message|string|true|none|信息|none| 263 | |» data|[Todo](#schematodo)|true|none|待办 Todo|none| 264 | |»» todoId|integer|true|none|ID|none| 265 | |»» title|string|true|none|标题|none| 266 | |»» detail|string|true|none|详情|none| 267 | |»» begin|integer¦null|true|none|开始时间戳|none| 268 | |»» end|integer|true|none|结束时间戳|none| 269 | |»» isFinished|boolean|true|none|是否完成|none| 270 | 271 | ## GET 获取今日待办 getToday 272 | 273 | GET /todo/getToday 274 | 275 | ### 请求参数 276 | 277 | |名称|位置|类型|必选|中文名|说明| 278 | |---|---|---|---|---|---| 279 | |year|query|integer| 否 ||none| 280 | |month|query|integer| 否 ||none| 281 | |day|query|integer| 否 ||none| 282 | 283 | > 返回示例 284 | 285 | > 200 Response 286 | 287 | ```json 288 | { 289 | "status": 0, 290 | "message": "string", 291 | "data": [ 292 | { 293 | "todoId": 0, 294 | "title": "string", 295 | "detail": "string", 296 | "begin": 0, 297 | "end": 0, 298 | "isFinished": true 299 | } 300 | ] 301 | } 302 | ``` 303 | 304 | ### 返回结果 305 | 306 | |状态码|状态码含义|说明|数据模型| 307 | |---|---|---|---| 308 | |200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|成功|Inline| 309 | 310 | ### 返回数据结构 311 | 312 | 状态码 **200** 313 | 314 | |名称|类型|必选|约束|中文名|说明| 315 | |---|---|---|---|---|---| 316 | |» status|integer|true|none|状态|none| 317 | |» message|string|true|none|信息|none| 318 | |» data|[[Todo](#schematodo)]|true|none||none| 319 | |»» 待办 Todo|[Todo](#schematodo)|false|none|待办 Todo|none| 320 | |»»» todoId|integer|true|none|ID|none| 321 | |»»» title|string|true|none|标题|none| 322 | |»»» detail|string|true|none|详情|none| 323 | |»»» begin|integer¦null|true|none|开始时间戳|none| 324 | |»»» end|integer|true|none|结束时间戳|none| 325 | |»»» isFinished|boolean|true|none|是否完成|none| 326 | 327 | ## GET 切换完成状态 toggleFinish 328 | 329 | GET /todo/toggleFinish 330 | 331 | ### 请求参数 332 | 333 | |名称|位置|类型|必选|中文名|说明| 334 | |---|---|---|---|---|---| 335 | |todoId|query|integer| 否 ||none| 336 | 337 | > 返回示例 338 | 339 | > 200 Response 340 | 341 | ```json 342 | { 343 | "status": 0, 344 | "message": "string" 345 | } 346 | ``` 347 | 348 | ### 返回结果 349 | 350 | |状态码|状态码含义|说明|数据模型| 351 | |---|---|---|---| 352 | |200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|成功|Inline| 353 | 354 | ### 返回数据结构 355 | 356 | 状态码 **200** 357 | 358 | |名称|类型|必选|约束|中文名|说明| 359 | |---|---|---|---|---|---| 360 | |» status|integer|true|none|状态|none| 361 | |» message|string|true|none|信息|none| 362 | 363 | # 便签 note 364 | 365 | ## POST 新建便签 create 366 | 367 | POST /note/create 368 | 369 | > Body 请求参数 370 | 371 | ```json 372 | { 373 | "noteId": 0, 374 | "title": "string", 375 | "content": "string" 376 | } 377 | ``` 378 | 379 | ### 请求参数 380 | 381 | |名称|位置|类型|必选|中文名|说明| 382 | |---|---|---|---|---|---| 383 | |body|body|object| 否 ||none| 384 | |» noteId|body|integer| 是 | ID|none| 385 | |» title|body|string| 是 | 标题|none| 386 | |» content|body|string| 是 | 内容|none| 387 | 388 | > 返回示例 389 | 390 | > 200 Response 391 | 392 | ```json 393 | { 394 | "status": 0, 395 | "message": "string", 396 | "noteId": 0 397 | } 398 | ``` 399 | 400 | ### 返回结果 401 | 402 | |状态码|状态码含义|说明|数据模型| 403 | |---|---|---|---| 404 | |200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|成功|Inline| 405 | 406 | ### 返回数据结构 407 | 408 | 状态码 **200** 409 | 410 | |名称|类型|必选|约束|中文名|说明| 411 | |---|---|---|---|---|---| 412 | |» status|integer|true|none|状态|none| 413 | |» message|string|true|none|信息|none| 414 | |» noteId|integer|true|none||none| 415 | 416 | ## DELETE 删除便签 delete 417 | 418 | DELETE /note/delete 419 | 420 | ### 请求参数 421 | 422 | |名称|位置|类型|必选|中文名|说明| 423 | |---|---|---|---|---|---| 424 | |noteId|query|integer| 否 ||none| 425 | 426 | > 返回示例 427 | 428 | > 200 Response 429 | 430 | ```json 431 | { 432 | "status": 0, 433 | "message": "string" 434 | } 435 | ``` 436 | 437 | ### 返回结果 438 | 439 | |状态码|状态码含义|说明|数据模型| 440 | |---|---|---|---| 441 | |200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|成功|Inline| 442 | 443 | ### 返回数据结构 444 | 445 | 状态码 **200** 446 | 447 | |名称|类型|必选|约束|中文名|说明| 448 | |---|---|---|---|---|---| 449 | |» status|integer|true|none|状态|none| 450 | |» message|string|true|none|信息|none| 451 | 452 | ## POST 修改便签 update 453 | 454 | POST /note/update 455 | 456 | > Body 请求参数 457 | 458 | ```json 459 | { 460 | "noteId": 0, 461 | "title": "string", 462 | "content": "string", 463 | "date": 0, 464 | "isStared": true 465 | } 466 | ``` 467 | 468 | ### 请求参数 469 | 470 | |名称|位置|类型|必选|中文名|说明| 471 | |---|---|---|---|---|---| 472 | |body|body|[Note](#schemanote)| 否 | 便签 Note|none| 473 | 474 | > 返回示例 475 | 476 | > 200 Response 477 | 478 | ```json 479 | { 480 | "status": 0, 481 | "message": "string" 482 | } 483 | ``` 484 | 485 | ### 返回结果 486 | 487 | |状态码|状态码含义|说明|数据模型| 488 | |---|---|---|---| 489 | |200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|成功|Inline| 490 | 491 | ### 返回数据结构 492 | 493 | 状态码 **200** 494 | 495 | |名称|类型|必选|约束|中文名|说明| 496 | |---|---|---|---|---|---| 497 | |» status|integer|true|none|状态|none| 498 | |» message|string|true|none|信息|none| 499 | 500 | ## GET 获取便签列表 list 501 | 502 | GET /note/list 503 | 504 | > 返回示例 505 | 506 | > 200 Response 507 | 508 | ```json 509 | { 510 | "status": 0, 511 | "message": "string", 512 | "data": [ 513 | { 514 | "noteId": 0, 515 | "title": "string", 516 | "content": "string", 517 | "date": 0, 518 | "isStared": true 519 | } 520 | ] 521 | } 522 | ``` 523 | 524 | ### 返回结果 525 | 526 | |状态码|状态码含义|说明|数据模型| 527 | |---|---|---|---| 528 | |200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|成功|Inline| 529 | 530 | ### 返回数据结构 531 | 532 | 状态码 **200** 533 | 534 | |名称|类型|必选|约束|中文名|说明| 535 | |---|---|---|---|---|---| 536 | |» status|integer|true|none|状态|none| 537 | |» message|string|true|none|信息|none| 538 | |» data|[[Note](#schemanote)]|true|none||none| 539 | |»» 便签 Note|[Note](#schemanote)|false|none|便签 Note|none| 540 | |»»» noteId|integer|true|none|ID|none| 541 | |»»» title|string|true|none|标题|none| 542 | |»»» content|string|true|none|内容|none| 543 | |»»» date|integer|true|none|时间戳|none| 544 | |»»» isStared|boolean|true|none|是否收藏|none| 545 | 546 | ## GET 获取指定便签 get 547 | 548 | GET /note/get 549 | 550 | ### 请求参数 551 | 552 | |名称|位置|类型|必选|中文名|说明| 553 | |---|---|---|---|---|---| 554 | |noteId|query|integer| 否 ||none| 555 | 556 | > 返回示例 557 | 558 | > 200 Response 559 | 560 | ```json 561 | { 562 | "status": 0, 563 | "message": "string", 564 | "data": { 565 | "noteId": 0, 566 | "title": "string", 567 | "content": "string", 568 | "date": 0, 569 | "isStared": true 570 | } 571 | } 572 | ``` 573 | 574 | ### 返回结果 575 | 576 | |状态码|状态码含义|说明|数据模型| 577 | |---|---|---|---| 578 | |200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|成功|Inline| 579 | 580 | ### 返回数据结构 581 | 582 | 状态码 **200** 583 | 584 | |名称|类型|必选|约束|中文名|说明| 585 | |---|---|---|---|---|---| 586 | |» status|integer|true|none|状态|none| 587 | |» message|string|true|none|信息|none| 588 | |» data|[Note](#schemanote)|true|none|便签 Note|none| 589 | |»» noteId|integer|true|none|ID|none| 590 | |»» title|string|true|none|标题|none| 591 | |»» content|string|true|none|内容|none| 592 | |»» date|integer|true|none|时间戳|none| 593 | |»» isStared|boolean|true|none|是否收藏|none| 594 | 595 | ## GET 切换收藏状态 toggleStar 596 | 597 | GET /note/toggleStar 598 | 599 | ### 请求参数 600 | 601 | |名称|位置|类型|必选|中文名|说明| 602 | |---|---|---|---|---|---| 603 | |noteId|query|integer| 否 ||none| 604 | 605 | > 返回示例 606 | 607 | > 200 Response 608 | 609 | ```json 610 | { 611 | "status": 0, 612 | "message": "string" 613 | } 614 | ``` 615 | 616 | ### 返回结果 617 | 618 | |状态码|状态码含义|说明|数据模型| 619 | |---|---|---|---| 620 | |200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|成功|Inline| 621 | 622 | ### 返回数据结构 623 | 624 | 状态码 **200** 625 | 626 | |名称|类型|必选|约束|中文名|说明| 627 | |---|---|---|---|---|---| 628 | |» status|integer|true|none|状态|none| 629 | |» message|string|true|none|信息|none| 630 | 631 | # 用户 user 632 | 633 | ## POST 测试登录 check 634 | 635 | POST /user/check 636 | 637 | > 返回示例 638 | 639 | > 200 Response 640 | 641 | ```json 642 | { 643 | "status": 0, 644 | "message": "string", 645 | "userId": 0 646 | } 647 | ``` 648 | 649 | ### 返回结果 650 | 651 | |状态码|状态码含义|说明|数据模型| 652 | |---|---|---|---| 653 | |200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|成功|Inline| 654 | 655 | ### 返回数据结构 656 | 657 | 状态码 **200** 658 | 659 | |名称|类型|必选|约束|中文名|说明| 660 | |---|---|---|---|---|---| 661 | |» status|integer|true|none|状态|none| 662 | |» message|string|true|none|信息|none| 663 | |» userId|integer|true|none||none| 664 | 665 | ## POST 用户注册 register 666 | 667 | POST /user/register 668 | 669 | > Body 请求参数 670 | 671 | ```json 672 | { 673 | "email": "string", 674 | "password": "string", 675 | "avatar": "string" 676 | } 677 | ``` 678 | 679 | ### 请求参数 680 | 681 | |名称|位置|类型|必选|中文名|说明| 682 | |---|---|---|---|---|---| 683 | |body|body|object| 否 ||none| 684 | |» email|body|string| 是 ||none| 685 | |» password|body|string| 是 ||none| 686 | |» avatar|body|string| 是 ||none| 687 | 688 | > 返回示例 689 | 690 | > 200 Response 691 | 692 | ```json 693 | { 694 | "status": 0, 695 | "message": "string", 696 | "userId": 0 697 | } 698 | ``` 699 | 700 | ### 返回结果 701 | 702 | |状态码|状态码含义|说明|数据模型| 703 | |---|---|---|---| 704 | |200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|成功|Inline| 705 | 706 | ### 返回数据结构 707 | 708 | 状态码 **200** 709 | 710 | |名称|类型|必选|约束|中文名|说明| 711 | |---|---|---|---|---|---| 712 | |» status|integer|true|none|状态|none| 713 | |» message|string|true|none|信息|none| 714 | |» userId|integer|true|none||none| 715 | 716 | ## POST 用户登录 login 717 | 718 | POST /user/login 719 | 720 | > Body 请求参数 721 | 722 | ```json 723 | { 724 | "email": "string", 725 | "password": "string" 726 | } 727 | ``` 728 | 729 | ### 请求参数 730 | 731 | |名称|位置|类型|必选|中文名|说明| 732 | |---|---|---|---|---|---| 733 | |body|body|object| 否 ||none| 734 | |» email|body|string| 是 ||none| 735 | |» password|body|string| 是 ||none| 736 | 737 | > 返回示例 738 | 739 | > 200 Response 740 | 741 | ```json 742 | { 743 | "status": 0, 744 | "message": "string", 745 | "token": "string", 746 | "userId": 0, 747 | "avatar": "string" 748 | } 749 | ``` 750 | 751 | ### 返回结果 752 | 753 | |状态码|状态码含义|说明|数据模型| 754 | |---|---|---|---| 755 | |200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|成功|Inline| 756 | 757 | ### 返回数据结构 758 | 759 | 状态码 **200** 760 | 761 | |名称|类型|必选|约束|中文名|说明| 762 | |---|---|---|---|---|---| 763 | |» status|integer|true|none|状态|none| 764 | |» message|string|true|none|信息|none| 765 | |» token|string|true|none||none| 766 | |» userId|integer|true|none||none| 767 | |» avatar|string|true|none||none| 768 | 769 | ## POST 上传头像 uploadAvatar 770 | 771 | POST /user/uploadAvatar 772 | 773 | > Body 请求参数 774 | 775 | ```yaml 776 | avatar: string 777 | 778 | ``` 779 | 780 | ### 请求参数 781 | 782 | |名称|位置|类型|必选|中文名|说明| 783 | |---|---|---|---|---|---| 784 | |body|body|object| 否 ||none| 785 | |» avatar|body|string(binary)| 否 ||none| 786 | 787 | > 返回示例 788 | 789 | > 200 Response 790 | 791 | ```json 792 | { 793 | "status": 0, 794 | "message": "string", 795 | "avatar": "string" 796 | } 797 | ``` 798 | 799 | ### 返回结果 800 | 801 | |状态码|状态码含义|说明|数据模型| 802 | |---|---|---|---| 803 | |200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|成功|Inline| 804 | 805 | ### 返回数据结构 806 | 807 | 状态码 **200** 808 | 809 | |名称|类型|必选|约束|中文名|说明| 810 | |---|---|---|---|---|---| 811 | |» status|integer|true|none|状态|none| 812 | |» message|string|true|none|信息|none| 813 | |» avatar|string|true|none||none| 814 | 815 | ## POST 更新用户 update 816 | 817 | POST /user/update 818 | 819 | > Body 请求参数 820 | 821 | ```json 822 | { 823 | "userId": "string", 824 | "email": "string", 825 | "password": "string", 826 | "avatar": "string" 827 | } 828 | ``` 829 | 830 | ### 请求参数 831 | 832 | |名称|位置|类型|必选|中文名|说明| 833 | |---|---|---|---|---|---| 834 | |body|body|[User](#schemauser)| 否 | 用户 User|none| 835 | 836 | > 返回示例 837 | 838 | > 200 Response 839 | 840 | ```json 841 | { 842 | "status": 0, 843 | "message": "string" 844 | } 845 | ``` 846 | 847 | ### 返回结果 848 | 849 | |状态码|状态码含义|说明|数据模型| 850 | |---|---|---|---| 851 | |200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|成功|Inline| 852 | 853 | ### 返回数据结构 854 | 855 | 状态码 **200** 856 | 857 | |名称|类型|必选|约束|中文名|说明| 858 | |---|---|---|---|---|---| 859 | |» status|integer|true|none|状态|none| 860 | |» message|string|true|none|信息|none| 861 | 862 | # 数据模型 863 | 864 |

User

865 | 866 | 867 | 868 | 869 | 870 | 871 | ```json 872 | { 873 | "userId": "string", 874 | "email": "string", 875 | "password": "string", 876 | "avatar": "string" 877 | } 878 | 879 | ``` 880 | 881 | 用户 User 882 | 883 | ### 属性 884 | 885 | |名称|类型|必选|约束|中文名|说明| 886 | |---|---|---|---|---|---| 887 | |userId|string|true|none||none| 888 | |email|string|true|none||none| 889 | |password|string|true|none||none| 890 | |avatar|string|true|none||none| 891 | 892 |

Note

893 | 894 | 895 | 896 | 897 | 898 | 899 | ```json 900 | { 901 | "noteId": 0, 902 | "title": "string", 903 | "content": "string", 904 | "date": 0, 905 | "isStared": true 906 | } 907 | 908 | ``` 909 | 910 | 便签 Note 911 | 912 | ### 属性 913 | 914 | |名称|类型|必选|约束|中文名|说明| 915 | |---|---|---|---|---|---| 916 | |noteId|integer|true|none|ID|none| 917 | |title|string|true|none|标题|none| 918 | |content|string|true|none|内容|none| 919 | |date|integer|true|none|时间戳|none| 920 | |isStared|boolean|true|none|是否收藏|none| 921 | 922 |

响应 Resp

923 | 924 | 925 | 926 | 927 | 928 | 929 | ```json 930 | { 931 | "status": 0, 932 | "message": "string" 933 | } 934 | 935 | ``` 936 | 937 | ### 属性 938 | 939 | |名称|类型|必选|约束|中文名|说明| 940 | |---|---|---|---|---|---| 941 | |status|integer|true|none|状态|none| 942 | |message|string|true|none|信息|none| 943 | 944 |

Todo

945 | 946 | 947 | 948 | 949 | 950 | 951 | ```json 952 | { 953 | "todoId": 0, 954 | "title": "string", 955 | "detail": "string", 956 | "begin": 0, 957 | "end": 0, 958 | "isFinished": true 959 | } 960 | 961 | ``` 962 | 963 | 待办 Todo 964 | 965 | ### 属性 966 | 967 | |名称|类型|必选|约束|中文名|说明| 968 | |---|---|---|---|---|---| 969 | |todoId|integer|true|none|ID|none| 970 | |title|string|true|none|标题|none| 971 | |detail|string|true|none|详情|none| 972 | |begin|integer¦null|true|none|开始时间戳|none| 973 | |end|integer|true|none|结束时间戳|none| 974 | |isFinished|boolean|true|none|是否完成|none| 975 | 976 | --------------------------------------------------------------------------------