From 58060b51694c0c8dd465d50399d1dcd982d86da9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=83=91=E5=AE=B6=E9=AA=9C=5B=C3=A0o=5D?= Date: Fri, 27 Sep 2024 09:09:20 +0800 Subject: [PATCH] =?UTF-8?q?feat(data-mongodb)=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E9=9D=9E=E7=BB=93=E6=9E=84=E5=8C=96json=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- starter-data/starter-data-mongodb/pom.xml | 9 ++ .../NonStructuredJsonController.java | 69 ++++++++ .../java/com/zja/model/BasePageRequest.java | 36 +++++ .../src/main/java/com/zja/model/PageData.java | 72 +++++++++ .../zja/service/NonStructuredJsonService.java | 26 +++ .../service/NonStructuredJsonServiceImpl.java | 149 ++++++++++++++++++ 6 files changed, 361 insertions(+) create mode 100644 starter-data/starter-data-mongodb/src/main/java/com/zja/controller/NonStructuredJsonController.java create mode 100644 starter-data/starter-data-mongodb/src/main/java/com/zja/model/BasePageRequest.java create mode 100644 starter-data/starter-data-mongodb/src/main/java/com/zja/model/PageData.java create mode 100644 starter-data/starter-data-mongodb/src/main/java/com/zja/service/NonStructuredJsonService.java create mode 100644 starter-data/starter-data-mongodb/src/main/java/com/zja/service/NonStructuredJsonServiceImpl.java diff --git a/starter-data/starter-data-mongodb/pom.xml b/starter-data/starter-data-mongodb/pom.xml index 36be34f..b2399e4 100644 --- a/starter-data/starter-data-mongodb/pom.xml +++ b/starter-data/starter-data-mongodb/pom.xml @@ -22,6 +22,10 @@ org.springframework.boot spring-boot-starter-web + + org.springframework.boot + spring-boot-starter-validation + org.springframework.boot spring-boot-starter-test @@ -43,5 +47,10 @@ springfox-boot-starter 3.0.0 + + com.alibaba + fastjson + 1.2.83 + diff --git a/starter-data/starter-data-mongodb/src/main/java/com/zja/controller/NonStructuredJsonController.java b/starter-data/starter-data-mongodb/src/main/java/com/zja/controller/NonStructuredJsonController.java new file mode 100644 index 0000000..048a5ab --- /dev/null +++ b/starter-data/starter-data-mongodb/src/main/java/com/zja/controller/NonStructuredJsonController.java @@ -0,0 +1,69 @@ +package com.zja.controller; + +import com.alibaba.fastjson.JSONObject; +import com.zja.model.BasePageRequest; +import com.zja.model.PageData; +import com.zja.service.NonStructuredJsonService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; + +/** + * 非结构化数据 接口层(一般与页面、功能对应) + * + * @author: zhengja + * @since: 2024/09/26 9:15 + */ +@Validated +@RestController +@RequestMapping("/rest/non/structured/json") +@Api(tags = {"BASE-非结构化JSON数据管理页面"}) +public class NonStructuredJsonController { + + @Autowired + NonStructuredJsonService service; + + @GetMapping("/query/{id}") + @ApiOperation("查询单个非结构化数据详情") + public JSONObject queryById(@NotBlank @PathVariable("id") String id) { + return service.queryById(id); + } + + @GetMapping("/page/list") + @ApiOperation("分页查询非结构化数据列表") + public PageData pageList(@Valid BasePageRequest pageRequest) { + return service.pageList(pageRequest); + } + + @PostMapping("/add") + @ApiOperation("添加非结构化数据") + public String add(@Valid @NotEmpty @RequestBody JSONObject jsonData) { + return service.add(jsonData); + } + + @PutMapping("/update/{id}") + @ApiOperation("更新非结构化数据") + public JSONObject update(@NotBlank @PathVariable("id") String id, + @Valid @NotEmpty @RequestBody JSONObject jsonData) { + return service.update(id, jsonData); + } + + @GetMapping("/exists/{id}") + @ApiOperation("存在非结构化数据") + public boolean exists(@NotBlank @PathVariable("id") String id) { + return service.exists(id); + } + + @DeleteMapping("/delete/{id}") + @ApiOperation("删除非结构化数据") + public boolean deleteById(@NotBlank @PathVariable("id") String id) { + return service.deleteById(id); + } + +} \ No newline at end of file diff --git a/starter-data/starter-data-mongodb/src/main/java/com/zja/model/BasePageRequest.java b/starter-data/starter-data-mongodb/src/main/java/com/zja/model/BasePageRequest.java new file mode 100644 index 0000000..14ec186 --- /dev/null +++ b/starter-data/starter-data-mongodb/src/main/java/com/zja/model/BasePageRequest.java @@ -0,0 +1,36 @@ +package com.zja.model; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +import java.io.Serializable; + +/** + * 分页请求(通用的) + * + * @author: zhengja + * @since: 2024/09/27 9:05 + */ +@ApiModel("BasePageRequest") +public class BasePageRequest implements Serializable { + @ApiModelProperty("页码 从第1页开始") + private Integer page = 1; + @ApiModelProperty("每页数量 默认 10") + private Integer size = 10; + + public Integer getPage() { + return page - 1; // 注:jpa page 从 0 开始 + } + + public void setPage(Integer page) { + this.page = page; + } + + public Integer getSize() { + return size; + } + + public void setSize(Integer size) { + this.size = size; + } +} \ No newline at end of file diff --git a/starter-data/starter-data-mongodb/src/main/java/com/zja/model/PageData.java b/starter-data/starter-data-mongodb/src/main/java/com/zja/model/PageData.java new file mode 100644 index 0000000..3b13b67 --- /dev/null +++ b/starter-data/starter-data-mongodb/src/main/java/com/zja/model/PageData.java @@ -0,0 +1,72 @@ +package com.zja.model; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.data.domain.Page; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * a 数据传输 + * + * @author: zhengja + * @since: 2024/09/27 9:05 + */ +@Data +@ApiModel("PageData") +public final class PageData implements Serializable { + + @ApiModelProperty("数据") + private List data; + @ApiModelProperty("当前页号") + private int index; + @ApiModelProperty("页大小") + private int size; + @ApiModelProperty("查询到的数据量") + private int length; + @ApiModelProperty("总数据量") + private long count; + @ApiModelProperty("总页数") + private int pages; + @ApiModelProperty("是否第一页") + private boolean first; + @ApiModelProperty("是否最后一页") + private boolean last; + @ApiModelProperty("是否有下一页") + private boolean hasNext; + @ApiModelProperty("是否有上一页") + private boolean hasPrev; + + public static PageData of(Page page) { + return of(page.getContent(), page.getNumber(), page.getSize(), page.getTotalElements()); + } + + public static PageData of(List data, int pageIndex, int pageSize, long totalSize) { + PageData dp = new PageData<>(); + dp.data = data; + dp.index = pageIndex; + dp.size = pageSize; + dp.length = data.size(); + dp.count = totalSize; + dp.pages = BigDecimal.valueOf(totalSize).divide(BigDecimal.valueOf(pageSize), RoundingMode.UP).intValue(); + dp.first = pageIndex == 0; + dp.hasPrev = !dp.first; + dp.hasNext = (dp.pages - dp.index) > 1; + dp.last = !dp.hasNext; + return dp; + } + + public void convert(Function mapper) { + this.data = data.stream().map(mapper).collect(Collectors.toList()); + } + + public PageData map(Function, List> mapper) { + return of(mapper.apply(this.getData()), this.getIndex(), this.getSize(), this.getCount()); + } +} \ No newline at end of file diff --git a/starter-data/starter-data-mongodb/src/main/java/com/zja/service/NonStructuredJsonService.java b/starter-data/starter-data-mongodb/src/main/java/com/zja/service/NonStructuredJsonService.java new file mode 100644 index 0000000..c918077 --- /dev/null +++ b/starter-data/starter-data-mongodb/src/main/java/com/zja/service/NonStructuredJsonService.java @@ -0,0 +1,26 @@ +package com.zja.service; + +import com.alibaba.fastjson.JSONObject; +import com.zja.model.BasePageRequest; +import com.zja.model.PageData; + +/** + * mongo非结构化json数据管理 + * + * @Author: zhengja + * @Date: 2024-09-25 15:39 + */ +public interface NonStructuredJsonService { + + String add(JSONObject jsonData); + + JSONObject update(String id, JSONObject jsonData); + + JSONObject queryById(String id); + + PageData pageList(BasePageRequest pageRequest); + + boolean exists(String id); + + boolean deleteById(String id); +} diff --git a/starter-data/starter-data-mongodb/src/main/java/com/zja/service/NonStructuredJsonServiceImpl.java b/starter-data/starter-data-mongodb/src/main/java/com/zja/service/NonStructuredJsonServiceImpl.java new file mode 100644 index 0000000..65e443f --- /dev/null +++ b/starter-data/starter-data-mongodb/src/main/java/com/zja/service/NonStructuredJsonServiceImpl.java @@ -0,0 +1,149 @@ +package com.zja.service; + +import com.alibaba.fastjson.JSONObject; +import com.mongodb.MongoException; +import com.mongodb.client.result.DeleteResult; +import com.zja.model.BasePageRequest; +import com.zja.model.PageData; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.query.Criteria; +import org.springframework.data.mongodb.core.query.Query; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; + +/** + * mongo非结构化json数据管理实现类 + * + * @Author: zhengja + * @Date: 2024-09-25 15:44 + */ +@Slf4j +@Component +public class NonStructuredJsonServiceImpl implements NonStructuredJsonService { + + @Autowired + private MongoTemplate mongoTemplate; + + // 集合名称 + private static final String COLLECTION_NAME = "non_structured_json"; + + private void checkJsonData(JSONObject jsonData) { + if (jsonData == null) { + throw new IllegalArgumentException("jsonData cannot be null"); + } + } + + @Override + public String add(JSONObject jsonData) { + checkJsonData(jsonData); + + // 添加数据 + JSONObject addData = new JSONObject(); + addData.put("data", jsonData); + addData.put("createdAt", LocalDateTime.now()); + addData.put("sort", System.currentTimeMillis()); + // 保存添加的数据 + JSONObject entity = mongoTemplate.save(addData, COLLECTION_NAME); + + return entity.getString("_id"); + } + + @Override + public JSONObject update(String id, JSONObject jsonData) { + checkJsonData(jsonData); + + if (!exists(id)) { + throw new RuntimeException("不存在的记录,更新失败."); + } + + // 查询原有数据 + Query query = new Query(Criteria.where("_id").is(id)); + JSONObject updatedData = mongoTemplate.findOne(query, JSONObject.class, COLLECTION_NAME); + if (updatedData == null) { + throw new RuntimeException("找不到对应的记录,更新失败."); + } + + // 更新数据 + updatedData.put("data", jsonData); + updatedData.put("updatedAt", LocalDateTime.now()); + // 保存更新后的数据 + JSONObject entity = mongoTemplate.save(updatedData, COLLECTION_NAME); + + return entity.getJSONObject("data"); + } + + @Override + public JSONObject queryById(String id) { + Query query = new Query(Criteria.where("_id").is(id)); + List jsonDocuments = mongoTemplate.find(query, JSONObject.class, COLLECTION_NAME); + if (!jsonDocuments.isEmpty()) { + return jsonDocuments.get(0).getJSONObject("data"); + } else { + return null; + } + } + + @Override + public PageData pageList(BasePageRequest pageRequest) { + Pageable pageable = PageRequest.of(pageRequest.getPage(), pageRequest.getSize(), Sort.by(Sort.Direction.DESC, "sort")); + Query query = new Query().with(pageable); + + List result = mongoTemplate.find(query, JSONObject.class, COLLECTION_NAME); + long totalSize = mongoTemplate.count(new Query(), COLLECTION_NAME); + + List resultData = result.stream() + .map(this::convertId) + .collect(Collectors.toList()); + + return PageData.of(resultData, pageRequest.getPage(), pageRequest.getSize(), totalSize); + } + + private JSONObject convertId(JSONObject jsonObject) { + JSONObject convertedJson = new JSONObject(); + convertedJson.putAll(jsonObject); + String id = convertedJson.getString("_id"); + convertedJson.put("id", id); + convertedJson.remove("_id"); + return convertedJson; + } + + @Override + public boolean exists(String id) { + Query query = new Query(Criteria.where("_id").is(id)); + return mongoTemplate.exists(query, JSONObject.class, COLLECTION_NAME); + } + + @Override + public boolean deleteById(String id) { + if (!exists(id)) { + return true; + } + + try { + Query query = new Query(Criteria.where("_id").is(id)); + DeleteResult deleteResult = mongoTemplate.remove(query, COLLECTION_NAME); + + if (deleteResult.wasAcknowledged() && deleteResult.getDeletedCount() > 0) { + log.debug("删除成功,id={}", id); + return true; + } else { + log.warn("删除失败,可能是由于数据不存在或数据库问题,id={}", id); + return false; + } + } catch (MongoException me) { + log.error("MongoDB异常:删除失败,请排查id={},异常信息:{}", id, me.getMessage(), me); + return false; + } catch (Exception e) { + log.error("未知异常:删除失败,请排查id={},异常信息:{}", id, e.getMessage(), e); + return false; + } + } +}