diff --git a/pom.xml b/pom.xml index 2c80c70..7d5bce9 100644 --- a/pom.xml +++ b/pom.xml @@ -19,6 +19,11 @@ spring-boot-starter + + org.springframework.boot + spring-boot-starter-web + + com.mysql mysql-connector-j @@ -44,6 +49,25 @@ spring-boot-starter-test test + + + com.aliyun.oss + aliyun-sdk-oss + 3.17.4 + + + + com.aliyun + green20220302 + 3.0.1 + + + + com.alibaba + fastjson + 1.2.83 + + @@ -89,4 +113,4 @@ - + \ No newline at end of file diff --git a/src/main/java/com/bao/dating/DatingApplication.java b/src/main/java/com/bao/dating/DatingApplication.java index 72eb307..c1e229b 100644 --- a/src/main/java/com/bao/dating/DatingApplication.java +++ b/src/main/java/com/bao/dating/DatingApplication.java @@ -3,9 +3,9 @@ package com.bao.dating; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; + @SpringBootApplication public class DatingApplication { - public static void main(String[] args) { SpringApplication.run(DatingApplication.class, args); } diff --git a/src/main/java/com/bao/dating/common/Result.java b/src/main/java/com/bao/dating/common/Result.java new file mode 100644 index 0000000..337e7ac --- /dev/null +++ b/src/main/java/com/bao/dating/common/Result.java @@ -0,0 +1,60 @@ +package com.bao.dating.common; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 通用返回结果类 + * @author lenovo + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +public class Result { + private int code; + private String msg; + private T data; + + /** + * 返回成功结果 + * @param data 返回的数据 + * @param 数据类型 + * @return Result对象 + */ + public static Result success(ResultCode code, T data) { + return new Result<>(code.code(), code.msg(), data); + } + + /** + * 返回成功结果 + * @param data 返回的数据 + * @param msg 提示信息 + * @param 数据类型 + * @return Result对象 + */ + public static Result success(ResultCode code, String msg, T data) { + return new Result<>(code.code(), msg, data); + } + + /** + * 返回失败结果 + * @param code 错误码 + * @param 数据类型 + * @return Result对象 + */ + public static Result error(ResultCode code) { + return new Result<>(code.code(), code.msg(), null); + } + + /** + * 返回失败结果 + * @param code 错误码 + * @param msg 错误信息 + * @param 数据类型 + * @return Result对象 + */ + public static Result error(ResultCode code, String msg) { + return new Result<>(code.code(), msg, null); + } +} \ No newline at end of file diff --git a/src/main/java/com/bao/dating/common/ResultCode.java b/src/main/java/com/bao/dating/common/ResultCode.java new file mode 100644 index 0000000..bb6eafd --- /dev/null +++ b/src/main/java/com/bao/dating/common/ResultCode.java @@ -0,0 +1,27 @@ +package com.bao.dating.common; + +public enum ResultCode { + SUCCESS(200, "成功"), + SUCCESS_REVIEW(201, "请求已成功处理"), + PARAM_ERROR(400, "参数错误"), + UNAUTHORIZED(401, "未登录或 Token 失效"), + FORBIDDEN(403, "无权限"), + NOT_FOUND(404, "数据不存在"), + SYSTEM_ERROR(500, "系统异常"); + + private final int code; + private final String msg; + + ResultCode(int code, String msg) { + this.code = code; + this.msg = msg; + } + + public int code() { + return code; + } + + public String msg() { + return msg; + } +} diff --git a/src/main/java/com/bao/dating/config/OssConfiguration.java b/src/main/java/com/bao/dating/config/OssConfiguration.java new file mode 100644 index 0000000..01189d1 --- /dev/null +++ b/src/main/java/com/bao/dating/config/OssConfiguration.java @@ -0,0 +1,26 @@ +package com.bao.dating.config; + + +import com.bao.dating.properties.AliOssProperties; +import com.bao.dating.util.AliOssUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * 配置类,用于创建AliOssUtil对象 + */ +@Configuration +@Slf4j +public class OssConfiguration { + @Bean + @ConditionalOnMissingBean + public AliOssUtil aliOssUtil(AliOssProperties aliOssProperties){ + log.info("开始创建阿里云文件上传工具类对象:{}",aliOssProperties); + return new AliOssUtil(aliOssProperties.getEndpoint(), + aliOssProperties.getAccessKeyId(), + aliOssProperties.getAccessKeySecret(), + aliOssProperties.getBucketName()); + } +} diff --git a/src/main/java/com/bao/dating/controller/PostController.java b/src/main/java/com/bao/dating/controller/PostController.java new file mode 100644 index 0000000..a752ea7 --- /dev/null +++ b/src/main/java/com/bao/dating/controller/PostController.java @@ -0,0 +1,31 @@ +package com.bao.dating.controller; + + +import com.bao.dating.common.Result; +import com.bao.dating.common.ResultCode; +import com.bao.dating.pojo.entity.Post; +import com.bao.dating.service.PostService; +import com.bao.dating.util.AliOssUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/posts") +public class PostController { + + @Autowired + private AliOssUtil ossUtil; + + @Autowired + private PostService postService; + + @PostMapping + public Result createPost(@RequestBody Post post) { + // 调用 Service 层处理发布动态业务逻辑 + Post result = postService.createPost(post); + return Result.success(ResultCode.SUCCESS_REVIEW,"动态发布成功,等待审核。",result); + } +} diff --git a/src/main/java/com/bao/dating/mapper/PostMapper.java b/src/main/java/com/bao/dating/mapper/PostMapper.java new file mode 100644 index 0000000..2a2d08d --- /dev/null +++ b/src/main/java/com/bao/dating/mapper/PostMapper.java @@ -0,0 +1,9 @@ +package com.bao.dating.mapper; + +import com.bao.dating.pojo.entity.Post; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface PostMapper { + int insert(Post post); +} diff --git a/src/main/java/com/bao/dating/pojo/entity/Post.java b/src/main/java/com/bao/dating/pojo/entity/Post.java index 478456d..59fa507 100644 --- a/src/main/java/com/bao/dating/pojo/entity/Post.java +++ b/src/main/java/com/bao/dating/pojo/entity/Post.java @@ -3,6 +3,7 @@ package com.bao.dating.pojo.entity; import lombok.Data; import java.time.LocalDateTime; +import java.util.List; /** * 动态表 @@ -17,7 +18,9 @@ public class Post { private String content; - private String mediaOssKeys; + private List mediaOssKeys; + + private List tags; private String location; diff --git a/src/main/java/com/bao/dating/properties/AliOssProperties.java b/src/main/java/com/bao/dating/properties/AliOssProperties.java new file mode 100644 index 0000000..7756754 --- /dev/null +++ b/src/main/java/com/bao/dating/properties/AliOssProperties.java @@ -0,0 +1,15 @@ +package com.bao.dating.properties; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +@Component +@ConfigurationProperties(prefix = "aliyun.oss") +@Data +public class AliOssProperties { + private String endpoint; + private String accessKeyId; + private String accessKeySecret; + private String bucketName; +} diff --git a/src/main/java/com/bao/dating/service/PostService.java b/src/main/java/com/bao/dating/service/PostService.java new file mode 100644 index 0000000..7ab86ae --- /dev/null +++ b/src/main/java/com/bao/dating/service/PostService.java @@ -0,0 +1,7 @@ +package com.bao.dating.service; + +import com.bao.dating.pojo.entity.Post; + +public interface PostService { + Post createPost(Post post); +} diff --git a/src/main/java/com/bao/dating/service/impl/PostServiceImpl.java b/src/main/java/com/bao/dating/service/impl/PostServiceImpl.java new file mode 100644 index 0000000..67de1f0 --- /dev/null +++ b/src/main/java/com/bao/dating/service/impl/PostServiceImpl.java @@ -0,0 +1,65 @@ +package com.bao.dating.service.impl; + +import com.bao.dating.mapper.PostMapper; +import com.bao.dating.pojo.entity.Post; +import com.bao.dating.service.PostService; +import com.bao.dating.util.AliOssUtil; +import com.bao.dating.util.FileUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +@Service +public class PostServiceImpl implements PostService { + + @Autowired + private AliOssUtil ossUtil; + + @Autowired + private PostMapper postMapper; + + @Override + public Post createPost(Post post) { + // 处理图片和视频上传到 OSS + List mediaOssKeys = new ArrayList<>(); + + // 判断媒体文件是否为空 + if (post.getMediaOssKeys() != null && !post.getMediaOssKeys().isEmpty()) { + + // 上传媒体文件并判断文件类型 + for (String mediaUrl : post.getMediaOssKeys()) { + // 根据文件扩展名判断文件类型 + String fileType = FileUtil.getFileType(mediaUrl); + + // 生成唯一文件名 + String fileName = UUID.randomUUID().toString() + "." + FileUtil.getFileExtension(mediaUrl); + + // 获取文件字节数据 + byte[] fileBytes = mediaUrl.getBytes(); + + // 根据文件类型处理 + String ossUrl = ""; + if ("image".equals(fileType)) { + // 上传图片 + ossUrl = ossUtil.upload(fileBytes, fileName); + } else if ("video".equals(fileType)) { + // 上传视频 + ossUrl = ossUtil.upload(fileBytes, fileName); + } + // 添加上传后的 URL + mediaOssKeys.add(ossUrl); + } + } + post.setMediaOssKeys(mediaOssKeys); + post.setIsPublic(0); + post.setUpdatedAt(LocalDateTime.now()); + post.setCreatedAt(LocalDateTime.now()); + // 保存动态到数据库 + postMapper.insert(post); + return post; + } +} diff --git a/src/main/java/com/bao/dating/util/AliOssUtil.java b/src/main/java/com/bao/dating/util/AliOssUtil.java new file mode 100644 index 0000000..44b344b --- /dev/null +++ b/src/main/java/com/bao/dating/util/AliOssUtil.java @@ -0,0 +1,59 @@ +package com.bao.dating.util; + +import com.aliyun.oss.ClientException; +import com.aliyun.oss.OSS; +import com.aliyun.oss.OSSClientBuilder; +import com.aliyun.oss.OSSException; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.io.ByteArrayInputStream; + +@Data +@AllArgsConstructor +@Slf4j +public class AliOssUtil { + + private String endpoint; + private String accessKeyId; + private String accessKeySecret; + private String bucketName; + + /** + * 文件上传 + * @param bytes + * @param objectName + * @return + */ + public String upload(byte[] bytes, String objectName) { + + // 创建OSSClient实例。 + OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); + + try { + // 创建PutObject请求。 + ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(bytes)); + } catch (OSSException oe) { + log.error("OSS Exception: {}", oe.getMessage()); + } catch (ClientException ce) { + log.error("Client Exception: {}", ce.getMessage()); + } finally { + if (ossClient != null) { + ossClient.shutdown(); + } + } + + //文件访问路径规则 https://BucketName.Endpoint/ObjectName + StringBuilder stringBuilder = new StringBuilder("https://"); + stringBuilder + .append(bucketName) + .append(".") + .append(endpoint) + .append("/") + .append(objectName); + log.info("文件上传到:{}", stringBuilder.toString()); + + return stringBuilder.toString(); + } +} diff --git a/src/main/java/com/bao/dating/util/FileUtil.java b/src/main/java/com/bao/dating/util/FileUtil.java new file mode 100644 index 0000000..5543dcd --- /dev/null +++ b/src/main/java/com/bao/dating/util/FileUtil.java @@ -0,0 +1,36 @@ +package com.bao.dating.util; + +/** + * 文件工具类 + * @author KilLze + */ +public class FileUtil { + /** + * 根据文件 URL 扩展名获取文件类型 + * @param fileUrl 文件的 URL + * @return 文件类型(image、video、unknown) + */ + public static String getFileType(String fileUrl) { + String extension = getFileExtension(fileUrl); + + if (extension.equals("jpg") || extension.equals("jpeg") || extension.equals("png") || extension.equals("gif")) { + return "image"; + } else if (extension.equals("mp4") || extension.equals("avi") || extension.equals("mov")) { + return "video"; + } + return "unknown"; + } + + /** + * 获取文件的扩展名 + * @param fileUrl 文件的 URL + * @return 文件扩展名(小写) + */ + public static String getFileExtension(String fileUrl) { + int dotIndex = fileUrl.lastIndexOf("."); + if (dotIndex != -1) { + return fileUrl.substring(dotIndex + 1).toLowerCase(); + } + return ""; + } +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 50520e9..9064b7c 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -8,9 +8,18 @@ spring: password: root driver-class-name: com.mysql.cj.jdbc.Driver +# MyBatis 配置 mybatis: mapper-locations: classpath:mapper/*.xml type-aliases-package: com.bao.dating.pojo configuration: map-underscore-to-camel-case: true - log-impl: org.apache.ibatis.logging.stdout.StdOutImpl \ No newline at end of file + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl + +# 阿里云 OSS 配置 +aliyun: + oss: + endpoint: oss-cn-hangzhou.aliyuncs.com + access-key-id: LTAI5tKo9TpWH1aW6JxWm1Gp + access-key-secret: LHk9DdHECKCwIdaIM9fkGgEuowt18W + bucket-name: heimato \ No newline at end of file diff --git a/src/main/resources/com/bao/dating/mapper/PostMapper.xml b/src/main/resources/com/bao/dating/mapper/PostMapper.xml new file mode 100644 index 0000000..138c06e --- /dev/null +++ b/src/main/resources/com/bao/dating/mapper/PostMapper.xml @@ -0,0 +1,22 @@ + + + + + + + INSERT INTO post + (user_id, content, + + media_oss_keys, + + tags, + + location, + + is_public, like_count, favorite_count, created_at, updated_at) + VALUES + (#{userId}, #{content}, #{mediaOssKeys}, #{tags}, #{location}, #{isPublic}, 0, 0, #{created_at}, #{updated_at}) + + + \ No newline at end of file