diff --git a/.gitignore b/.gitignore index 549e00a..4690548 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,5 @@ build/ ### VS Code ### .vscode/ +/src/main/resources/application-dev.yml +/src/main/resources/dev.application.properties diff --git a/pom.xml b/pom.xml index f2222f8..9561c4a 100644 --- a/pom.xml +++ b/pom.xml @@ -61,6 +61,38 @@ 3.0.4 test + + com.baomidou + mybatis-plus-spring-boot3-starter + 3.5.11 + + + io.jsonwebtoken + jjwt-api + 0.11.5 + + + io.jsonwebtoken + jjwt-impl + 0.11.5 + runtime + + + io.jsonwebtoken + jjwt-jackson + 0.11.5 + runtime + + + com.qcloud + cos_api + 5.6.227 + + + com.sun.mail + jakarta.mail + 2.0.1 + diff --git a/src/main/java/top/lichx/webclassbackend/config/MailProperties.java b/src/main/java/top/lichx/webclassbackend/config/MailProperties.java new file mode 100644 index 0000000..5e790c9 --- /dev/null +++ b/src/main/java/top/lichx/webclassbackend/config/MailProperties.java @@ -0,0 +1,64 @@ +package top.lichx.webclassbackend.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +@Component +@ConfigurationProperties(prefix = "mail.smtp") +public class MailProperties { + private String host; + private int port; + private String username; + private String password; + private boolean auth; + private boolean starttls; + + // Getters and Setters + public String getHost() { + return host; + } + + public void setHost(String host) { + this.host = host; + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public boolean isAuth() { + return auth; + } + + public void setAuth(boolean auth) { + this.auth = auth; + } + + public boolean isStarttls() { + return starttls; + } + + public void setStarttls(boolean starttls) { + this.starttls = starttls; + } +} \ No newline at end of file diff --git a/src/main/java/top/lichx/webclassbackend/config/WebConfig.java b/src/main/java/top/lichx/webclassbackend/config/WebConfig.java new file mode 100644 index 0000000..f4afdc0 --- /dev/null +++ b/src/main/java/top/lichx/webclassbackend/config/WebConfig.java @@ -0,0 +1,25 @@ +package top.lichx.webclassbackend.config; + +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import top.lichx.webclassbackend.interceptor.JwtInterceptor; + +@Configuration +@Slf4j +public class WebConfig implements WebMvcConfigurer { + @Resource + private JwtInterceptor jwtInterceptor; + + @Override + public void addInterceptors(InterceptorRegistry registry) { + log.info("addInterceptors"); + registry.addInterceptor(jwtInterceptor) + .addPathPatterns("/**") // 拦截所有路径 + .excludePathPatterns("/login/**") // 放行登录接口 + .excludePathPatterns("/file/uploadAvatar") // 放行头像上传接口 + .excludePathPatterns("/error/**"); // 放行错误处理接口 + } +} \ No newline at end of file diff --git a/src/main/java/top/lichx/webclassbackend/controller/FileController.java b/src/main/java/top/lichx/webclassbackend/controller/FileController.java new file mode 100644 index 0000000..5bfb180 --- /dev/null +++ b/src/main/java/top/lichx/webclassbackend/controller/FileController.java @@ -0,0 +1,68 @@ +package top.lichx.webclassbackend.controller; + +import jakarta.annotation.Resource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import top.lichx.webclassbackend.pojo.vo.AvatarInfo; +import top.lichx.webclassbackend.result.Result; +import top.lichx.webclassbackend.util.COSIO; + +import java.io.File; +import java.io.IOException; +import java.net.URL; + +@RestController +@RequestMapping("/file") +public class FileController { + + @Resource + private COSIO cosio; + + @GetMapping("/test") + public String test() { + // 使用注入的 COSIO 实例 + System.out.println("COSIO: " + cosio); + return "test"; + } + +// @PostMapping("/upload") +// public Result uploadFile(@RequestParam("file") MultipartFile multipartFile) { +// try { +// // 将 MultipartFile 转换为 File +// var file = File.createTempFile("upload-", multipartFile.getOriginalFilename()); +// multipartFile.transferTo(file); +// +// // 调用 COSIO 的上传方法 +// String filename = cosio.UploadFile(file); +// +// // 删除临时文件 +// file.delete(); +// +// return Result.success("文件上传成功,文件路径:", filename); +// } catch (IOException e) { +// e.printStackTrace(); +// // 处理文件上传失败的情况 +// return Result.error("文件上传失败:" + e.getMessage()); +// } +// } + + + @PostMapping("/uploadAvatar") + public Result uploadAvatar(@RequestParam("file") MultipartFile multipartFile) throws IOException { + var file = File.createTempFile("upload-", multipartFile.getOriginalFilename()); + multipartFile.transferTo(file); + var fileName = cosio.UploadFile(file); + file.delete(); + var fileURL = cosio.GetFileLink(fileName); + var avatarInfo = new AvatarInfo(fileName, fileURL); + return Result.success("文件上传成功", avatarInfo); + } + + @GetMapping("/getFileLink") + public Result getFileLink(@RequestParam String fileName) { + URL url = cosio.GetFileLink(fileName); + return Result.success("获取文件链接成功", url.toString()); + } + +} \ No newline at end of file diff --git a/src/main/java/top/lichx/webclassbackend/controller/Login.java b/src/main/java/top/lichx/webclassbackend/controller/Login.java new file mode 100644 index 0000000..98fe108 --- /dev/null +++ b/src/main/java/top/lichx/webclassbackend/controller/Login.java @@ -0,0 +1,287 @@ +package top.lichx.webclassbackend.controller; + +import jakarta.annotation.Resource; +import jakarta.mail.MessagingException; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.web.bind.annotation.*; +import top.lichx.webclassbackend.pojo.dto.LoginDTO; +import top.lichx.webclassbackend.pojo.dto.PasswordResetDTO; +import top.lichx.webclassbackend.pojo.dto.RegisterDTO; +import top.lichx.webclassbackend.pojo.entity.User; +import top.lichx.webclassbackend.result.Result; +import top.lichx.webclassbackend.service.IdentifyingCode; +import top.lichx.webclassbackend.service.UserService; +import top.lichx.webclassbackend.util.JwtUtil; +import top.lichx.webclassbackend.util.MailUtil; +import top.lichx.webclassbackend.util.PasswordUtil; + +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; + +@RestController +@RequestMapping("/login") +public class Login { + + private String mailTemplate = """ + + + + + + + + + +
+ + + + + + +
+ + + + + + +
+ 您好 +
+ + + + + + +
+ {tip},有效时间为 {ExpireTime} 分钟。 +
+ + + + + + +
+ + + + + + +
+ + + + + + + + + + + + +
+ 验证码 +
+ {Captcha} +
+
+
+ +
+ + + + + + +
+ 不是您? +
+ + + + + + +
+ \s + 如果这不是来自您的验证请求,请您忽略本邮件并不要将验证码转发给任何人

+ 此电子邮件包含一个代码,您需要用它验证您的帐户。切勿与任何人分享此代码。 +
+ + + + + + +
+ + + + + + + + +
+ + + + + + + + +
+ 祝您愉快,
+ Lichx +
+
+
+
+
+ + """; +// @Resource +// private Test test; + + @Resource + private MailUtil mailUtil; + + @Resource + private IdentifyingCode identifyingCode; + + @Resource + private UserService userService; + + @Resource + private PasswordUtil passwordUtil; + +// @GetMapping("/test") +// public String test() { +// test.test(); +// return "test"; +// } +// +// @PostMapping("/test/{id}") +// public String testPost(@PathVariable Integer id) { +// test.test(); +// return "testPost"; +// } + + @PostMapping("/") + public Result login(@RequestBody LoginDTO loginInfo, HttpServletResponse response) { + // 验证用户名和密码(此处省略具体逻辑) + String usernameOrEmail = loginInfo.getUsernameOrEmail(); + String password = loginInfo.getPassword(); + var user = usernameOrEmail.contains("@")?userService.getUserByEmail(usernameOrEmail) : userService.getUserByUserName(usernameOrEmail); + if (user != null && passwordUtil.matches(password,user.getPassword())) { + String token = JwtUtil.generateToken(user.getName()); + // 设置HttpOnly和Secure属性的Cookie + response.setHeader("Set-Cookie", "Authorization=Bearer " + token + "; HttpOnly; Max-Age=86400; Path=/; SameSite=Strict"); +// response.setHeader("Set-Cookie", "token=Bearer " + token + "; HttpOnly; Secure; Path=/; SameSite=Strict"); + return Result.success("登录成功"); + } + return Result.error("用户名或密码错误"); + } + + @GetMapping("/logout") + public Result logout(HttpServletResponse response) { + // 清除Cookie + response.setHeader("Set-Cookie", "Authorization=; HttpOnly; Max-Age=0; Path=/; SameSite=Strict"); + return Result.success("注销成功"); + } + + @GetMapping("/register/identifyingCode") + public Result registerIdentifyingCode(String email) throws MessagingException { + var captcha = identifyingCode.getIdentifyingCode(email, IdentifyingCode.IdentifyingCodeType.REGISTER, 15 * 60); + if (captcha == null) { + return Result.error("验证码请求过于频繁,请稍后再试"); + } + String mailTemplate = this.mailTemplate; + String tip = "您正在进行注册操作,这是您验证帐户所需的令牌验证码"; + String expireTime = "15"; + mailTemplate = mailTemplate.replace("{tip}", tip); + mailTemplate = mailTemplate.replace("{Captcha}", captcha); + mailTemplate = mailTemplate.replace("{ExpireTime}", expireTime); + mailUtil.sendHtmlEmail( + email, + "Lichx's WebClass", + mailTemplate); + return Result.success("验证码已发送到您的邮箱,请注意查收"); + } + + @PostMapping("/register") + public Result register(@RequestBody RegisterDTO registerDTO) { + var user = new User(); + user.setId(userService.getUserLastId()); + user.setName(registerDTO.getUsername()); + user.setPassword(passwordUtil.encrypt(registerDTO.getPassword())); + user.setEmail(registerDTO.getEmail()); + user.setBirth(LocalDate.parse(registerDTO.getBirth(), DateTimeFormatter.ISO_LOCAL_DATE).atStartOfDay()); + user.setAvatarURL(registerDTO.getAvatarFile()); + + if (!identifyingCode.testIdentifyingCode(registerDTO.getEmail(), + IdentifyingCode.IdentifyingCodeType.REGISTER, + registerDTO.getIdentifyingCode())) { + return Result.error("验证码错误或已过期"); + } + if (userService.getUserByUserName(user.getName()) != null) { + return Result.error("用户名已存在"); + } + userService.insertUser(user); + return Result.success("用户已注册"); + } + + @GetMapping("/passwordReset/identifyingCode") + public Result resetIdentifyingCode(String usernameOrEmail) throws MessagingException { + var email = usernameOrEmail.contains("@") ? usernameOrEmail : userService.getUserByUserName(usernameOrEmail).getEmail(); + var captcha = identifyingCode.getIdentifyingCode(email, IdentifyingCode.IdentifyingCodeType.PASSWORD_RESET, 15 * 60); + if (captcha == null) { + return Result.error("验证码请求过于频繁,请稍后再试"); + } + String mailTemplate = this.mailTemplate; + String tip = "您正在进行密码重置操作,这是您验证帐户所需的令牌验证码"; + String expireTime = "15"; + mailTemplate = mailTemplate.replace("{tip}", tip); + mailTemplate = mailTemplate.replace("{Captcha}", captcha); + mailTemplate = mailTemplate.replace("{ExpireTime}", expireTime); + mailUtil.sendHtmlEmail( + email, + "Lichx's WebClass", + mailTemplate); + return Result.success("验证码已发送到您的邮箱,请注意查收"); + } + + @PostMapping("/passwordReset") + public Result passwordReset(@RequestBody PasswordResetDTO passwordResetDTO) { + System.out.println(); + String usernameOrEmail = passwordResetDTO.getUsernameOrEmail(); + String password = passwordResetDTO.getPassword(); + var user = usernameOrEmail.contains("@")?userService.getUserByEmail(usernameOrEmail) : userService.getUserByUserName(usernameOrEmail); + if (!identifyingCode.testIdentifyingCode(user.getEmail(), + IdentifyingCode.IdentifyingCodeType.PASSWORD_RESET, + passwordResetDTO.getIdentifyingCode())) { + return Result.error("验证码错误或已过期"); + } + userService.changeUserPasswordByUserName(user.getName(), passwordUtil.encrypt(password)); + return Result.success("密码已重置"); + } +} diff --git a/src/main/java/top/lichx/webclassbackend/controller/User.java b/src/main/java/top/lichx/webclassbackend/controller/User.java new file mode 100644 index 0000000..c392dc8 --- /dev/null +++ b/src/main/java/top/lichx/webclassbackend/controller/User.java @@ -0,0 +1,71 @@ +package top.lichx.webclassbackend.controller; + +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import top.lichx.webclassbackend.pojo.vo.VisibleUserInfoVO; +import top.lichx.webclassbackend.result.Result; +import top.lichx.webclassbackend.service.UserService; +import top.lichx.webclassbackend.util.COSIO; +import top.lichx.webclassbackend.util.JwtUtil; + +@RestController +@RequestMapping("/user") +public class User { + @Resource + private UserService userService; + + @Resource + private COSIO cosio; + + @GetMapping("/info") + public Result getUserInfo(HttpServletRequest request) { + + String cookieHeader = request.getHeader("Cookie"); + String token = null; + if (cookieHeader != null) { + String[] cookies = cookieHeader.split("; "); + for (String cookie : cookies) { + if (cookie.startsWith("Authorization=")) { + token = cookie.substring("Authorization=".length()); + break; + } + } + } + token = token.substring(7); // 去掉 "Bearer " 前缀 + String username = JwtUtil.parseToken(token); + + var user = userService.getUserByUserName(username); + if (user == null) + return Result.error("用户不存在"); + var returnVO = new VisibleUserInfoVO(); + returnVO.setUserId("" + user.getId()); + returnVO.setUserName(user.getName()); + returnVO.setUserEmail(user.getEmail()); + returnVO.setUserAvatar(cosio.GetFileLink(user.getAvatarURL())); + return Result.success("", returnVO); + } + + @GetMapping("/avatar") + public Result getUserAvatar(HttpServletRequest request) { + String cookieHeader = request.getHeader("Cookie"); + String token = null; + if (cookieHeader != null) { + String[] cookies = cookieHeader.split("; "); + for (String cookie : cookies) { + if (cookie.startsWith("Authorization=")) { + token = cookie.substring("Authorization=".length()); + break; + } + } + } + token = token.substring(7); // 去掉 "Bearer " 前缀 + String username = JwtUtil.parseToken(token); + var user = userService.getUserByUserName(username); + if (user == null) + return Result.error("用户不存在"); + return Result.success("", cosio.GetFileLink(user.getAvatarURL())); + } +} diff --git a/src/main/java/top/lichx/webclassbackend/controller/UserManager.java b/src/main/java/top/lichx/webclassbackend/controller/UserManager.java new file mode 100644 index 0000000..b043d38 --- /dev/null +++ b/src/main/java/top/lichx/webclassbackend/controller/UserManager.java @@ -0,0 +1,67 @@ +package top.lichx.webclassbackend.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import jakarta.annotation.Resource; +import org.springframework.web.bind.annotation.*; +import top.lichx.webclassbackend.pojo.dto.UserManagerDTO; +import top.lichx.webclassbackend.pojo.entity.UserManagerInfo; +import top.lichx.webclassbackend.result.Result; +import top.lichx.webclassbackend.service.UserManagerService; + +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; + +@RestController +@RequestMapping("/userManager") +public class UserManager { + @Resource + private UserManagerService userManagerService; + + @PostMapping("/addUser") + public Result addUser(@RequestBody UserManagerDTO userManagerDTO) + { + var info = new UserManagerInfo(); + info.setId(userManagerService.getUserManagerInfoLastId()); + info.setName(userManagerDTO.getName()); + info.setDate(LocalDate.parse(userManagerDTO.getDate(), DateTimeFormatter.ISO_LOCAL_DATE)); + info.setProvince(userManagerDTO.getProvince()); + info.setCity(userManagerDTO.getCity()); + info.setAddress(userManagerDTO.getAddress()); + info.setZip(userManagerDTO.getZip()); + userManagerService.insertUserManagerInfo(info); + return Result.success("添加用户成功"); + } + + @GetMapping("/page") + public Result> getUserManagerInfoPage(@RequestParam int page, @RequestParam int size, @RequestParam String situation) { + return Result.success("",userManagerService.getUserManagerInfoPage(page, size, situation)); + } + + @PostMapping("/updateUser") + public ResultupdateUser(@RequestBody UserManagerDTO userManagerDTO) + { + var info = new UserManagerInfo(); + info.setId(userManagerDTO.getId()); + info.setName(userManagerDTO.getName()); + info.setDate(LocalDate.parse(userManagerDTO.getDate(), DateTimeFormatter.ISO_LOCAL_DATE)); + info.setProvince(userManagerDTO.getProvince()); + info.setCity(userManagerDTO.getCity()); + info.setAddress(userManagerDTO.getAddress()); + info.setZip(userManagerDTO.getZip()); + userManagerService.updateUserManagerInfo(info); + return Result.success("更新用户成功"); + } + + @GetMapping("deleteUser") + public Result deleteUser(@RequestParam Integer id) + { + userManagerService.deleteUserManagerInfo(id); + return Result.success("删除用户成功"); + } + + @GetMapping("total") + public Result total(@RequestParam String situation) + { + return Result.success("", userManagerService.getTotal(situation)); + } +} diff --git a/src/main/java/top/lichx/webclassbackend/exception/GlobalExceptionHandler.java b/src/main/java/top/lichx/webclassbackend/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..9f38152 --- /dev/null +++ b/src/main/java/top/lichx/webclassbackend/exception/GlobalExceptionHandler.java @@ -0,0 +1,24 @@ +package top.lichx.webclassbackend.exception; + +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import top.lichx.webclassbackend.result.Result; + +@RestControllerAdvice +public class GlobalExceptionHandler { + +// // 处理空指针异常 +// @ExceptionHandler(NullPointerException.class) +// public Result handleNullPointerException(NullPointerException ex) { +// ex.printStackTrace(); +// return Result.error("空指针异常,请检查代码!"); +// } + + // 处理其他异常 + @ExceptionHandler(Exception.class) + public Result handleException(Exception ex) { + ex.printStackTrace(); + return Result.error("服务器内部错误:" + ex.getMessage()); + } +} \ No newline at end of file diff --git a/src/main/java/top/lichx/webclassbackend/interceptor/JwtInterceptor.java b/src/main/java/top/lichx/webclassbackend/interceptor/JwtInterceptor.java new file mode 100644 index 0000000..f5d0981 --- /dev/null +++ b/src/main/java/top/lichx/webclassbackend/interceptor/JwtInterceptor.java @@ -0,0 +1,43 @@ +package top.lichx.webclassbackend.interceptor; + +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.HandlerInterceptor; +import top.lichx.webclassbackend.util.JwtUtil; + +@Component +@Slf4j +public class JwtInterceptor implements HandlerInterceptor { + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + String cookieHeader = request.getHeader("Cookie"); + String token = null; + if (cookieHeader != null) { + String[] cookies = cookieHeader.split("; "); + for (String cookie : cookies) { + if (cookie.startsWith("Authorization=")) { + token = cookie.substring("Authorization=".length()); + break; + } + } + } + log.info("token:{}, URI:{}", token, request.getRequestURI()); + if (token == null || !token.startsWith("Bearer ")) { + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + return false; + } + token = token.substring(7); // 去掉 "Bearer " 前缀 + String username = JwtUtil.parseToken(token); + if (username == null) { + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + log.error("Token解析失败"); + return false; + } + request.setAttribute("username", username); + log.info("用户 {} 访问了 {}", username, request.getRequestURI()); + return true; + } +} \ No newline at end of file diff --git a/src/main/java/top/lichx/webclassbackend/mapper/userManagerInfoMapper.java b/src/main/java/top/lichx/webclassbackend/mapper/userManagerInfoMapper.java new file mode 100644 index 0000000..5e40fa5 --- /dev/null +++ b/src/main/java/top/lichx/webclassbackend/mapper/userManagerInfoMapper.java @@ -0,0 +1,7 @@ +package top.lichx.webclassbackend.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; +import top.lichx.webclassbackend.pojo.entity.UserManagerInfo; +@Mapper +public interface userManagerInfoMapper extends BaseMapper { } diff --git a/src/main/java/top/lichx/webclassbackend/mapper/userMapper.java b/src/main/java/top/lichx/webclassbackend/mapper/userMapper.java new file mode 100644 index 0000000..bf4e390 --- /dev/null +++ b/src/main/java/top/lichx/webclassbackend/mapper/userMapper.java @@ -0,0 +1,9 @@ +package top.lichx.webclassbackend.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; +import top.lichx.webclassbackend.pojo.entity.User; + +@Mapper +public interface userMapper extends BaseMapper { } + diff --git a/src/main/java/top/lichx/webclassbackend/pojo/dto/In.java b/src/main/java/top/lichx/webclassbackend/pojo/dto/In.java new file mode 100644 index 0000000..b09bf3d --- /dev/null +++ b/src/main/java/top/lichx/webclassbackend/pojo/dto/In.java @@ -0,0 +1,9 @@ +package top.lichx.webclassbackend.pojo.dto; + +import lombok.Data; + +@Data +public class In { + Long id; + String test; +} diff --git a/src/main/java/top/lichx/webclassbackend/pojo/dto/LoginDTO.java b/src/main/java/top/lichx/webclassbackend/pojo/dto/LoginDTO.java new file mode 100644 index 0000000..a67ec8e --- /dev/null +++ b/src/main/java/top/lichx/webclassbackend/pojo/dto/LoginDTO.java @@ -0,0 +1,10 @@ +package top.lichx.webclassbackend.pojo.dto; + +import lombok.Data; + +@Data +public class LoginDTO { + + private String usernameOrEmail; + private String password; +} diff --git a/src/main/java/top/lichx/webclassbackend/pojo/dto/PasswordResetDTO.java b/src/main/java/top/lichx/webclassbackend/pojo/dto/PasswordResetDTO.java new file mode 100644 index 0000000..7ffb0b6 --- /dev/null +++ b/src/main/java/top/lichx/webclassbackend/pojo/dto/PasswordResetDTO.java @@ -0,0 +1,10 @@ +package top.lichx.webclassbackend.pojo.dto; + +import lombok.Data; + +@Data +public class PasswordResetDTO { + private String usernameOrEmail; + private String identifyingCode; + private String password; +} diff --git a/src/main/java/top/lichx/webclassbackend/pojo/dto/RegisterCodeDTO.java b/src/main/java/top/lichx/webclassbackend/pojo/dto/RegisterCodeDTO.java new file mode 100644 index 0000000..dcba8c2 --- /dev/null +++ b/src/main/java/top/lichx/webclassbackend/pojo/dto/RegisterCodeDTO.java @@ -0,0 +1,8 @@ +package top.lichx.webclassbackend.pojo.dto; + +import lombok.Data; + +@Data +public class RegisterCodeDTO { + private String email; +} diff --git a/src/main/java/top/lichx/webclassbackend/pojo/dto/RegisterDTO.java b/src/main/java/top/lichx/webclassbackend/pojo/dto/RegisterDTO.java new file mode 100644 index 0000000..8cdce98 --- /dev/null +++ b/src/main/java/top/lichx/webclassbackend/pojo/dto/RegisterDTO.java @@ -0,0 +1,13 @@ +package top.lichx.webclassbackend.pojo.dto; + +import lombok.Data; + +@Data +public class RegisterDTO { + private String username; + private String password; + private String email; + private String identifyingCode; + private String birth; + private String avatarFile; +} diff --git a/src/main/java/top/lichx/webclassbackend/pojo/dto/UserManagerDTO.java b/src/main/java/top/lichx/webclassbackend/pojo/dto/UserManagerDTO.java new file mode 100644 index 0000000..112460a --- /dev/null +++ b/src/main/java/top/lichx/webclassbackend/pojo/dto/UserManagerDTO.java @@ -0,0 +1,16 @@ +package top.lichx.webclassbackend.pojo.dto; + +import lombok.Data; + +import java.time.LocalDate; + +@Data +public class UserManagerDTO { + private Integer id; + private String name; + private String date; + private String province; + private String city; + private String address; + private String zip; +} diff --git a/src/main/java/top/lichx/webclassbackend/pojo/entity/User.java b/src/main/java/top/lichx/webclassbackend/pojo/entity/User.java new file mode 100644 index 0000000..44ab0a0 --- /dev/null +++ b/src/main/java/top/lichx/webclassbackend/pojo/entity/User.java @@ -0,0 +1,23 @@ +package top.lichx.webclassbackend.pojo.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@TableName("userT") +public class User { + Integer id; + String name; + String password; + String email; + LocalDateTime birth; + @TableField("avatarURL") + String avatarURL; +} diff --git a/src/main/java/top/lichx/webclassbackend/pojo/entity/UserManagerInfo.java b/src/main/java/top/lichx/webclassbackend/pojo/entity/UserManagerInfo.java new file mode 100644 index 0000000..9c975a6 --- /dev/null +++ b/src/main/java/top/lichx/webclassbackend/pojo/entity/UserManagerInfo.java @@ -0,0 +1,22 @@ +package top.lichx.webclassbackend.pojo.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDate; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@TableName("User") +public class UserManagerInfo { + Integer id; + String name; + LocalDate date; + String province; + String city; + String address; + String zip; +} diff --git a/src/main/java/top/lichx/webclassbackend/pojo/vo/AvatarInfo.java b/src/main/java/top/lichx/webclassbackend/pojo/vo/AvatarInfo.java new file mode 100644 index 0000000..52a3c6d --- /dev/null +++ b/src/main/java/top/lichx/webclassbackend/pojo/vo/AvatarInfo.java @@ -0,0 +1,14 @@ +package top.lichx.webclassbackend.pojo.vo; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import java.net.URL; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class AvatarInfo { + private String avatarFilePath; + private URL avatarFileURL; +} diff --git a/src/main/java/top/lichx/webclassbackend/pojo/vo/VisibleUserInfoVO.java b/src/main/java/top/lichx/webclassbackend/pojo/vo/VisibleUserInfoVO.java new file mode 100644 index 0000000..b92a2ef --- /dev/null +++ b/src/main/java/top/lichx/webclassbackend/pojo/vo/VisibleUserInfoVO.java @@ -0,0 +1,17 @@ +package top.lichx.webclassbackend.pojo.vo; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.net.URL; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class VisibleUserInfoVO { + private String userId; + private String userName; + private String userEmail; + private URL userAvatar; +} diff --git a/src/main/java/top/lichx/webclassbackend/result/Result.java b/src/main/java/top/lichx/webclassbackend/result/Result.java new file mode 100644 index 0000000..b7d26bb --- /dev/null +++ b/src/main/java/top/lichx/webclassbackend/result/Result.java @@ -0,0 +1,50 @@ +package top.lichx.webclassbackend.result; + +import lombok.Data; + +import java.io.Serializable; + +@Data +public class Result implements Serializable { + private Integer code; + private String message; + private T data; + + public static Result success() { + Result result = new Result<>(); + result.setCode(200); + result.setMessage("success"); + result.data = null; + return result; + } + + public static Result success(String msg) { + Result result = new Result<>(); + result.setCode(200); + result.setMessage(msg); + result.data = null; + return result; + } + + public static Result success(String msg, T data) { + Result result = new Result<>(); + result.setCode(200); + result.setMessage(msg); + result.setData(data); + return result; + } + + public static Result error() { + Result result = new Result<>(); + result.setCode(500); + result.setMessage("error"); + return result; + } + + public static Result error(String msg) { + Result result = new Result<>(); + result.setCode(500); + result.setMessage(msg); + return result; + } +} diff --git a/src/main/java/top/lichx/webclassbackend/service/IdentifyingCode.java b/src/main/java/top/lichx/webclassbackend/service/IdentifyingCode.java new file mode 100644 index 0000000..e14261a --- /dev/null +++ b/src/main/java/top/lichx/webclassbackend/service/IdentifyingCode.java @@ -0,0 +1,13 @@ +package top.lichx.webclassbackend.service; + +import jakarta.mail.MessagingException; + +public interface IdentifyingCode { + String getIdentifyingCode(String email, IdentifyingCodeType type, long expireTimeInSeconds); + boolean testIdentifyingCode(String email, IdentifyingCodeType type, String code ); + enum IdentifyingCodeType { + REGISTER, + PASSWORD_RESET + } + +} diff --git a/src/main/java/top/lichx/webclassbackend/service/Test.java b/src/main/java/top/lichx/webclassbackend/service/Test.java new file mode 100644 index 0000000..8126029 --- /dev/null +++ b/src/main/java/top/lichx/webclassbackend/service/Test.java @@ -0,0 +1,5 @@ +package top.lichx.webclassbackend.service; + +public interface Test { + void test(); +} diff --git a/src/main/java/top/lichx/webclassbackend/service/UserManagerService.java b/src/main/java/top/lichx/webclassbackend/service/UserManagerService.java new file mode 100644 index 0000000..dbadeb0 --- /dev/null +++ b/src/main/java/top/lichx/webclassbackend/service/UserManagerService.java @@ -0,0 +1,14 @@ +package top.lichx.webclassbackend.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import top.lichx.webclassbackend.pojo.entity.UserManagerInfo; + +public interface UserManagerService { + public void insertUserManagerInfo(UserManagerInfo userManagerInfo); + public void updateUserManagerInfo(UserManagerInfo userManagerInfo); + public void deleteUserManagerInfo(Integer id); + public IPage getUserManagerInfoPage(int page, int size, String situation); + public Integer getUserManagerInfoLastId(); + public Integer getTotal(String situation); + +} diff --git a/src/main/java/top/lichx/webclassbackend/service/UserService.java b/src/main/java/top/lichx/webclassbackend/service/UserService.java new file mode 100644 index 0000000..b6ac82b --- /dev/null +++ b/src/main/java/top/lichx/webclassbackend/service/UserService.java @@ -0,0 +1,13 @@ +package top.lichx.webclassbackend.service; + +import top.lichx.webclassbackend.pojo.entity.User; + +public interface UserService { + public void insertUser(User user); + public User getUserByUserName(String userName); + public void changeUserPasswordByUserName(String userName, String password); + + public User getUserByEmail(String email); + public Integer getUserLastId(); + public Integer getTotal(); +} diff --git a/src/main/java/top/lichx/webclassbackend/service/impl/IdentifyingCodeImpl.java b/src/main/java/top/lichx/webclassbackend/service/impl/IdentifyingCodeImpl.java new file mode 100644 index 0000000..e48496a --- /dev/null +++ b/src/main/java/top/lichx/webclassbackend/service/impl/IdentifyingCodeImpl.java @@ -0,0 +1,88 @@ +package top.lichx.webclassbackend.service.impl; + +import jakarta.mail.MessagingException; +import lombok.NoArgsConstructor; +import org.springframework.stereotype.Service; +import top.lichx.webclassbackend.service.IdentifyingCode; + +import java.util.Dictionary; +import java.util.Hashtable; +import java.util.Random; + +@Service +public class IdentifyingCodeImpl implements IdentifyingCode { + + Dictionary data = new Hashtable<>(); + + @Override + public String getIdentifyingCode(String email, IdentifyingCodeType type, long expireTimeInSeconds) { + dataClear(); + var structure = data.get(IdentifyingCodeStructure.getId(email, type)); + if (structure != null && System.currentTimeMillis() / 1000 < structure.startTimeInSeconds + 60) + return null; + structure = IdentifyingCodeStructure.createIdentifyingCodeStructure(email, type, expireTimeInSeconds); + data.put(structure.id, structure); + return structure.code; + } + + @Override + public boolean testIdentifyingCode(String email, IdentifyingCodeType type, String code) { + dataClear(); + var structure = data.get(IdentifyingCodeStructure.getId(email, type)); + if (structure == null) { + return false; + } + if (structure.isExpired()) { + data.remove(structure.id); + return false; + } + if (structure.code.equals(code)) { + data.remove(structure.id); + return true; + } + return false; + } + + private void dataClear() { + var keys = data.keys(); + while (keys.hasMoreElements()) { + var key = keys.nextElement(); + var structure = data.get(key); + if (structure.isExpired()) { + data.remove(key); + } + } + } +} + +@NoArgsConstructor +class IdentifyingCodeStructure { + public String id; + public String username; + public IdentifyingCode.IdentifyingCodeType type; + public String code; + public long startTimeInSeconds; + public long expireTimeInSeconds; + + boolean isExpired() { + long currentTimeInSeconds = System.currentTimeMillis() / 1000; + return currentTimeInSeconds > startTimeInSeconds + expireTimeInSeconds; + } + + static String getId(String username, IdentifyingCode.IdentifyingCodeType type) { + return username + type; + } + + static IdentifyingCodeStructure createIdentifyingCodeStructure(String email, IdentifyingCode.IdentifyingCodeType type, long expireTimeInSeconds) { + IdentifyingCodeStructure identifyingCodeStructure = new IdentifyingCodeStructure(); + identifyingCodeStructure.id = email + type; + identifyingCodeStructure.username = email; + identifyingCodeStructure.type = type; + Random random = new Random(); + int randomNumber = 100000 + random.nextInt(900000); // 范围是 100000 到 999999 + identifyingCodeStructure.code = "" + randomNumber; + identifyingCodeStructure.startTimeInSeconds = System.currentTimeMillis() / 1000; + identifyingCodeStructure.expireTimeInSeconds = expireTimeInSeconds; + return identifyingCodeStructure; + } +} \ No newline at end of file diff --git a/src/main/java/top/lichx/webclassbackend/service/impl/TestImpl.java b/src/main/java/top/lichx/webclassbackend/service/impl/TestImpl.java new file mode 100644 index 0000000..10385f2 --- /dev/null +++ b/src/main/java/top/lichx/webclassbackend/service/impl/TestImpl.java @@ -0,0 +1,13 @@ +package top.lichx.webclassbackend.service.impl; + +import org.springframework.stereotype.Service; +import top.lichx.webclassbackend.service.Test; + +@Service +public class TestImpl implements Test { + + @Override + public void test() { + + } +} diff --git a/src/main/java/top/lichx/webclassbackend/service/impl/UserManagerServiceImpl.java b/src/main/java/top/lichx/webclassbackend/service/impl/UserManagerServiceImpl.java new file mode 100644 index 0000000..1768ed0 --- /dev/null +++ b/src/main/java/top/lichx/webclassbackend/service/impl/UserManagerServiceImpl.java @@ -0,0 +1,60 @@ +package top.lichx.webclassbackend.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import top.lichx.webclassbackend.mapper.userManagerInfoMapper; +import top.lichx.webclassbackend.pojo.entity.UserManagerInfo; +import top.lichx.webclassbackend.service.UserManagerService; +@Service +public class UserManagerServiceImpl implements UserManagerService { + @Resource + private userManagerInfoMapper userManagerInfoMapper; + public void insertUserManagerInfo(UserManagerInfo userManagerInfo) { + // 插入用户信息 + userManagerInfoMapper.insert(userManagerInfo); + } + + public void updateUserManagerInfo(UserManagerInfo userManagerInfo) { + // 更新用户信息 + userManagerInfoMapper.updateById(userManagerInfo); + } + + public void deleteUserManagerInfo(Integer id) { + // 删除用户信息 + userManagerInfoMapper.deleteById(id); + } + + public IPage getUserManagerInfoPage(int page, int size, String situation) { + // 使用 MyBatis-Plus 提供的分页功能 + Page pageRequest = new Page<>(page, size); + QueryWrapper queryWrapper = new QueryWrapper<>(); + + // 如果 situation 不为空,则添加模糊查询条件 + if (situation != null && !situation.trim().isEmpty()) { + queryWrapper.like("name", situation); + } + + return userManagerInfoMapper.selectPage(pageRequest, queryWrapper); + } + + public Integer getUserManagerInfoLastId() { + UserManagerInfo lastRecord = userManagerInfoMapper.selectOne( + new QueryWrapper().orderByDesc("id").last("LIMIT 1") + ); + // 如果记录为空,返回 0,否则返回最后一条记录的 ID + return lastRecord == null ? 0 : lastRecord.getId() + 1; + } + + @Override + public Integer getTotal(String situation) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + if (situation != null && !situation.trim().isEmpty()) { + queryWrapper.like("name", situation); + } + return userManagerInfoMapper.selectCount(queryWrapper).intValue(); + } + +} diff --git a/src/main/java/top/lichx/webclassbackend/service/impl/UserServiceImpl.java b/src/main/java/top/lichx/webclassbackend/service/impl/UserServiceImpl.java new file mode 100644 index 0000000..27eb6a7 --- /dev/null +++ b/src/main/java/top/lichx/webclassbackend/service/impl/UserServiceImpl.java @@ -0,0 +1,55 @@ +package top.lichx.webclassbackend.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import top.lichx.webclassbackend.mapper.userMapper; +import top.lichx.webclassbackend.pojo.entity.User; +import top.lichx.webclassbackend.pojo.entity.UserManagerInfo; +import top.lichx.webclassbackend.service.UserService; + +@Service +public class UserServiceImpl implements UserService { + @Resource + private userMapper webclassMapper; + + public void insertUser(User user) { + webclassMapper.insert(user); + } + + public User getUserByUserName(String userName) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("name", userName); + return webclassMapper.selectOne(queryWrapper); + } + + public void changeUserPasswordByUserName(String userName, String password) { + User user = getUserByUserName(userName); + if (user != null) { + user.setPassword(password); + webclassMapper.updateById(user); + } + } + + @Override + public User getUserByEmail(String email) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("email", email); + return webclassMapper.selectOne(queryWrapper); + } + + @Override + public Integer getUserLastId() { + User lastRecord = webclassMapper.selectOne( + new QueryWrapper().orderByDesc("id").last("LIMIT 1") + ); + // 如果记录为空,返回 0,否则返回最后一条记录的 ID + return lastRecord == null ? 0 : lastRecord.getId() + 1; + + } + + @Override + public Integer getTotal() { + return webclassMapper.selectCount(null).intValue(); + } +} diff --git a/src/main/java/top/lichx/webclassbackend/util/COSIO.java b/src/main/java/top/lichx/webclassbackend/util/COSIO.java new file mode 100644 index 0000000..792b324 --- /dev/null +++ b/src/main/java/top/lichx/webclassbackend/util/COSIO.java @@ -0,0 +1,70 @@ +package top.lichx.webclassbackend.util; + +import com.qcloud.cos.COSClient; +import com.qcloud.cos.ClientConfig; +import com.qcloud.cos.Headers; +import com.qcloud.cos.auth.BasicCOSCredentials; +import com.qcloud.cos.http.HttpMethodName; +import com.qcloud.cos.model.GeneratePresignedUrlRequest; +import com.qcloud.cos.model.PutObjectRequest; +import com.qcloud.cos.model.PutObjectResult; +import com.qcloud.cos.model.ResponseHeaderOverrides; +import com.qcloud.cos.region.Region; +import com.qcloud.cos.utils.DateUtils; +import jakarta.annotation.PostConstruct; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.io.File; +import java.net.URL; +import java.util.Date; +import java.util.UUID; + +@Component +public class COSIO { + private COSClient cosClient; + + @Value("${tencent.secretId}") + private String secretId; + + @Value("${tencent.secretKey}") + private String secretKey; + + @Value("${tencent.bucketName}") + private String bucketName; + + @Value("${tencent.baseDIR}") + private String baseDir; + + @PostConstruct + public void Init() { + var cred = new BasicCOSCredentials(secretId, secretKey); + var region = new Region("ap-shanghai"); + var clientConfig = new ClientConfig(region); + cosClient = new COSClient(cred, clientConfig); + } + + + public String UploadFile(File file) { + String fileName = UUID.randomUUID().toString(); + String key = baseDir + fileName; + PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, key, file); + cosClient.putObject(putObjectRequest); + return fileName; + } + + public URL GetFileLink(String fileName) { + GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, baseDir + fileName, HttpMethodName.GET); + ResponseHeaderOverrides responseHeaderOverrides = new ResponseHeaderOverrides(); + String responseCacheControl = "no-cache"; + String cacheExpireStr = + DateUtils.formatRFC822Date(new Date(System.currentTimeMillis() + 10L * 60L * 1000L)); + responseHeaderOverrides.setCacheControl(responseCacheControl); + responseHeaderOverrides.setExpires(cacheExpireStr); + request.setResponseHeaders(responseHeaderOverrides); + Date expirationDate = new Date(System.currentTimeMillis() + 10L * 60L * 1000L); + request.setExpiration(expirationDate); + request.putCustomRequestHeader(Headers.HOST, cosClient.getClientConfig().getEndpointBuilder().buildGeneralApiEndpoint(bucketName)); + return cosClient.generatePresignedUrl(request); + } +} \ No newline at end of file diff --git a/src/main/java/top/lichx/webclassbackend/util/JwtUtil.java b/src/main/java/top/lichx/webclassbackend/util/JwtUtil.java new file mode 100644 index 0000000..1824d26 --- /dev/null +++ b/src/main/java/top/lichx/webclassbackend/util/JwtUtil.java @@ -0,0 +1,34 @@ +package top.lichx.webclassbackend.util; + +import io.jsonwebtoken.*; +import io.jsonwebtoken.security.Keys; + +import java.security.Key; +import java.util.Date; + +public class JwtUtil { + private static final Key key = Keys.secretKeyFor(SignatureAlgorithm.HS256); // 生成密钥 + private static final long EXPIRATION_TIME = 86400000; // 1 天 + + public static String generateToken(String username) { + return Jwts.builder() + .setSubject(username) + .setIssuedAt(new Date()) + .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME)) + .signWith(key) + .compact(); + } + + public static String parseToken(String token) { + try { + Claims claims = Jwts.parserBuilder() + .setSigningKey(key) + .build() + .parseClaimsJws(token) + .getBody(); + return claims.getSubject(); + } catch (JwtException e) { + return null; // Token 无效或过期 + } + } +} \ No newline at end of file diff --git a/src/main/java/top/lichx/webclassbackend/util/MailUtil.java b/src/main/java/top/lichx/webclassbackend/util/MailUtil.java new file mode 100644 index 0000000..bb1bf6b --- /dev/null +++ b/src/main/java/top/lichx/webclassbackend/util/MailUtil.java @@ -0,0 +1,49 @@ +package top.lichx.webclassbackend.util; + +import jakarta.annotation.Resource; +import jakarta.mail.*; +import jakarta.mail.internet.InternetAddress; +import jakarta.mail.internet.MimeMessage; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import top.lichx.webclassbackend.config.MailProperties; + +import java.util.Properties; + +@Component +public class MailUtil { + + @Resource + private MailProperties mailProperties; + + public void sendHtmlEmail(String to, String subject, String htmlContent) throws MessagingException { + // 配置 SMTP 服务器 + Properties props = new Properties(); + props.put("mail.smtp.host", mailProperties.getHost()); + props.put("mail.smtp.port", String.valueOf(mailProperties.getPort())); + props.put("mail.smtp.auth", String.valueOf(mailProperties.isAuth())); + props.put("mail.smtp.starttls.enable", String.valueOf(mailProperties.isStarttls())); + + // 认证信息 + String username = mailProperties.getUsername(); + String password = mailProperties.getPassword(); + + // 创建会话 + Session session = Session.getInstance(props, new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(username, password); + } + }); + + // 创建邮件 + Message message = new MimeMessage(session); + message.setFrom(new InternetAddress(username)); + message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to)); + message.setSubject(subject); + message.setContent(htmlContent, "text/html; charset=utf-8"); // 设置内容为 HTML 格式 + + // 发送邮件 + Transport.send(message); + } +} \ No newline at end of file diff --git a/src/main/java/top/lichx/webclassbackend/util/PasswordUtil.java b/src/main/java/top/lichx/webclassbackend/util/PasswordUtil.java new file mode 100644 index 0000000..3443b7f --- /dev/null +++ b/src/main/java/top/lichx/webclassbackend/util/PasswordUtil.java @@ -0,0 +1,18 @@ +package top.lichx.webclassbackend.util; + +import org.apache.commons.codec.digest.DigestUtils; +import org.springframework.stereotype.Component; + +@Component +public class PasswordUtil { + + // 加密密码(使用 SHA-256) + public String encrypt(String rawPassword) { + return DigestUtils.sha256Hex(rawPassword); + } + + // 验证密码 + public boolean matches(String rawPassword, String encryptedPassword) { + return encrypt(rawPassword).equals(encryptedPassword); + } +} \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index be7598f..ef5ec82 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1 +1,11 @@ spring.application.name=WebClassBackend + +# ??????? +spring.datasource.url=jdbc:mariadb://localhost:3306/webclass +spring.datasource.username=webclass +spring.datasource.password=123456 + +spring.servlet.multipart.enabled=true +spring.servlet.multipart.max-file-size=50MB +spring.servlet.multipart.max-request-size=50MB +p \ No newline at end of file diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..caf4dfc --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,3 @@ +spring: + profiles: + active: dev \ No newline at end of file