feat: tag模块首次提交

main
itao 1 year ago
parent 21d10a00a6
commit 4394ccc43e

@ -0,0 +1,57 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.luoo</groupId>
<artifactId>luoo_parent</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>luoo_tag</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.luoo</groupId>
<artifactId>luoo_common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,26 @@
package com.luoo.tag;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import util.IdWorker;
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
@EnableFeignClients
@EnableCaching
public class TagApplication {
public static void main(String[] args) {
SpringApplication.run(TagApplication.class, args);
}
@Bean
public IdWorker idWorkker(){
return new IdWorker(1, 1);
}
}

@ -0,0 +1,13 @@
package com.luoo.tag.client;
import entity.Result;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@FeignClient("luoo-user")
public interface UserClient {
@RequestMapping(value = "/admin",method= RequestMethod.GET)
public Result findAll();
}

@ -0,0 +1,22 @@
package com.luoo.tag.controller;
import entity.Result;
import entity.StatusCode;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
*
*/
@ControllerAdvice
public class BaseExceptionHandler {
@ExceptionHandler(value = Exception.class)
@ResponseBody
public Result error(Exception e){
e.printStackTrace();
return new Result(false, StatusCode.ERROR, "执行出错");
}
}

@ -0,0 +1,59 @@
package com.luoo.tag.controller;
import com.luoo.tag.pojo.TagCreateReq;
import com.luoo.tag.pojo.TagQueryReq;
import com.luoo.tag.pojo.TagUpdateReq;
import com.luoo.tag.service.TagService;
import entity.Result;
import entity.StatusCode;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
/**
* Web
*/
@RestController
@CrossOrigin
@RequestMapping("/tag")
@RequiredArgsConstructor
public class TagController {
private final TagService tagService;
@GetMapping("/list")
public Result getById(@Validated @RequestBody TagQueryReq queryReq, @RequestParam int pageNum, @RequestParam int pageSize){
return new Result(true, StatusCode.OK, "查询成功", tagService.queryPage(queryReq, pageNum, pageSize));
}
@GetMapping("/{id}")
public Result getById(@PathVariable String id){
return new Result(true, StatusCode.OK, "查询成功", tagService.queryById(id));
}
@PostMapping
public Result create(@Validated @RequestBody TagCreateReq createReq){
tagService.create(createReq);
return new Result(true, StatusCode.OK, "创建成功");
}
@PutMapping("/{id}")
public Result update(@Validated @RequestBody TagUpdateReq updateReq, @PathVariable String id){
updateReq.setId(id);
tagService.update(updateReq);
return new Result(true, StatusCode.OK, "更新成功");
}
@PutMapping("/status/{id}")
public Result updateStatus(@PathVariable String id, @RequestParam Integer state){
tagService.updateState(id, state);
return new Result(true, StatusCode.OK,"状态更新成功");
}
@DeleteMapping("/{id}")
public Result delete(@PathVariable String id){
tagService.delete(id);
return new Result(true, StatusCode.OK,"删除成功");
}
}

@ -0,0 +1,16 @@
package com.luoo.tag.controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* Web
*/
@RestController
@CrossOrigin
@RequestMapping("/tag/creator")
public class TagCreatorController {
}

@ -0,0 +1,37 @@
package com.luoo.tag.dao;
import com.luoo.tag.pojo.Tag;
import com.luoo.tag.pojo.TagStatistic;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import java.util.List;
import java.util.Map;
/**
* 访
* @author Administrator
*
*/
public interface TagDao extends JpaRepository<Tag, String>, JpaSpecificationExecutor<Tag>{
@Query(value = "select distinct id from tb_tag where name_ch = ? or name_en = ?", nativeQuery = true)
List<Tag> findByName(String nameCh, String nameEn);
@Modifying
@Query(value = "update tb_tag set state = ? where id = ?", nativeQuery = true)
void updateStateById(Integer state, String id);
@Modifying
@Query(value = "update tb_tag set state = ? where parent_id = ?", nativeQuery = true)
void updateStateByParentId(Integer state, String parentId);
@Query(value = "select count(*) from tb_tag where parent_id = ?", nativeQuery = true)
long countByParentId(String parentId);
@Query(value = "select new com.luoo.tag.pojo.TagStatistic(parent_id, count(*)) from tb_tag where parent_id in ? group by parent_id", nativeQuery = true)
List<TagStatistic> countByParentIds(List<String> parentIds);
}

@ -0,0 +1,55 @@
package com.luoo.tag.pojo;
import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.io.Serializable;
import java.time.LocalDateTime;
@Data
@Entity
@Table(name = "tb_tag")
public class Tag implements Serializable {
private static final long serialVersionUID = -5593148272164146667L;
@Id
private String id;
/**
* ID
*/
private String parentId;
/**
*
*/
private String nameCh;
/**
*
*/
private String nameEn;
/**
* : 0., 1.
*/
private Integer state;
/**
* ID
*/
private Long creatorId;
/**
*
*/
private LocalDateTime createTime;
/**
*
*/
private LocalDateTime updateTime;
}

@ -0,0 +1,25 @@
package com.luoo.tag.pojo;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import java.io.Serializable;
/**
*
*/
@Data
public class TagCreateReq implements Serializable {
private static final long serialVersionUID = -3431829126574541980L;
/**
* ID
*/
private String parentId = "";
@NotBlank(message = "标签中文名称必填")
private String nameCh;
@NotBlank(message = "标签英文名称必填")
private String nameEn;
}

@ -0,0 +1,35 @@
package com.luoo.tag.pojo;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
@Data
public class TagDTO implements Serializable {
private static final long serialVersionUID = -1198060864891902188L;
private String id;
private String parentId;
private String parentNameCh;
private String nameCh;
private String nameEn;
private Integer state;
private Long childTagCount = 0L;
private Long articleRefCount = 0L;
private Long songRefCount = 0L;
private String creatorName;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;
}

@ -0,0 +1,36 @@
package com.luoo.tag.pojo;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
*
*/
@Data
public class TagQueryReq implements Serializable {
private static final long serialVersionUID = -1198060864891902188L;
@NotNull(message = "标签层级不能为空1=一级2=二级")
private Integer level;
private String id;
private String parentId;
/**
*
*/
private String name;
private Integer state;
private String creatorId;
private LocalDateTime createTimeStart;
private LocalDateTime createTimeEnd;
}

@ -0,0 +1,52 @@
package com.luoo.tag.pojo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
*
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class TagStatistic implements Serializable {
private static final long serialVersionUID = 7243999657362371575L;
/**
* ID
*/
private String tagId;
/**
*
*/
@Builder.Default
private Long childTagCount = 0L;
/**
*
*/
@Builder.Default
private Long articleRefCount = 0L;
/**
*
*/
@Builder.Default
private Long songRefCount = 0L;
public TagStatistic(String tagId){
this.tagId = tagId;
}
public TagStatistic(String tagId, Long childTagCount){
this.tagId = tagId;
this.childTagCount = childTagCount;
}
}

@ -0,0 +1,24 @@
package com.luoo.tag.pojo;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
/**
*
*/
@Data
public class TagUpdateReq implements Serializable {
private static final long serialVersionUID = -8810544476079524714L;
private String id;
@NotBlank(message = "标签中文名称必填")
private String nameCh;
@NotBlank(message = "标签英文名称必填")
private String nameEn;
}

@ -0,0 +1,211 @@
package com.luoo.tag.service;
import com.google.common.collect.Lists;
import com.luoo.common.util.AssertUtil;
import com.luoo.tag.dao.TagDao;
import com.luoo.tag.pojo.*;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import util.IdWorker;
import javax.persistence.criteria.Predicate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;
/**
*
*/
@Service
@RequiredArgsConstructor
public class TagService {
private final TagDao tagDao;
private final IdWorker idWorker;
/**
*
* @return
*/
public Page<TagDTO> queryPage(TagQueryReq queryReq, int pageNum, int pageSize){
Specification<Tag> specification = createSpecification(queryReq);
PageRequest pageRequest = PageRequest.of(pageNum-1, pageSize);
Page<Tag> tagPage = tagDao.findAll(specification, pageRequest);
List<String> tagIdList = tagPage.stream().map(Tag::getId).collect(toList());
Map<String, TagStatistic> tagStatisticMap = queryTagStatistic(tagIdList);
return tagPage.map(tag -> {
TagDTO tagDTO = new TagDTO();
BeanUtils.copyProperties(tag, tagDTO);
TagStatistic tagStatistic = tagStatisticMap.get(tag.getId());
tagDTO.setChildTagCount(tagStatistic.getChildTagCount());
tagDTO.setArticleRefCount(tagStatistic.getArticleRefCount());
tagDTO.setSongRefCount(tagStatistic.getSongRefCount());
//todo parentTagName
return tagDTO;
});
}
/**
*
* @param createReq
*/
public void create(TagCreateReq createReq){
List<Tag> tagListByName = tagDao.findByName(createReq.getNameCh(), createReq.getNameEn());
AssertUtil.mustEmpty(tagListByName, "标签中英文名称不允许重复");
String parentId = createReq.getParentId();
Optional<Tag> tagOptional = tagDao.findById(parentId);
AssertUtil.mustTrue(tagOptional.isPresent(), "父标签记录不存在");
Tag tag = new Tag();
BeanUtils.copyProperties(createReq, tag);
tag.setId(idWorker.nextId()+"");
LocalDateTime now = LocalDateTime.now();
tag.setCreateTime(now);
tag.setCreateTime(now);
tagDao.save(tag);
}
/**
*
* @param updateReq
*/
public void update(TagUpdateReq updateReq){
String id = updateReq.getId();
Optional<Tag> tagOptional = tagDao.findById(id);
AssertUtil.mustTrue(tagOptional.isPresent(), "标签记录不存在");
List<Tag> tagListByName = tagDao.findByName(updateReq.getNameCh(), updateReq.getNameEn());
boolean nameDuplicateCheck = tagListByName.stream().map(Tag::getId).allMatch(id::equals);
AssertUtil.mustTrue(nameDuplicateCheck, "标签中英文名称不允许重复");
Tag tag = new Tag();
BeanUtils.copyProperties(updateReq, tag);
tagDao.save(tag);
}
/**
*
* @param id ID
* @return
*/
public TagDTO queryById(String id){
Optional<Tag> tagOptional = tagDao.findById(id);
AssertUtil.mustTrue(tagOptional.isPresent(), "标签记录不存在");
Tag tag = tagOptional.get();
TagDTO tagDTO = new TagDTO();
BeanUtils.copyProperties(tag, tagDTO);
TagStatistic tagStatistic = queryTagStatistic(id);
tagDTO.setChildTagCount(tagStatistic.getChildTagCount());
tagDTO.setArticleRefCount(tagStatistic.getArticleRefCount());
tagDTO.setSongRefCount(tagStatistic.getSongRefCount());
return tagDTO;
}
/**
*
* @param id ID
* @param state
*/
public void updateState(String id, Integer state){
tagDao.updateStateById(state, id);
// 级联更新子标签状态
tagDao.updateStateByParentId(state, id);
}
/**
*
* @param id ID
*/
public void delete(String id){
Optional<Tag> tagOptional = tagDao.findById(id);
if(!tagOptional.isPresent()){
return;
}
TagStatistic referenceStatistic = queryTagStatistic(id);
AssertUtil.mustEq(referenceStatistic.getArticleRefCount(), 0L,"无法执行删除, 该标签还存在关联的期刊");
AssertUtil.mustEq(referenceStatistic.getSongRefCount(), 0L,"无法执行删除, 该标签还存在关联的音乐");
AssertUtil.mustEq(referenceStatistic.getChildTagCount(), 0L,"无法执行删除, 该标签还存在关联的子标签");
tagDao.deleteById(id);
}
/**
*
* @param tagId ID
* @return
*/
private TagStatistic queryTagStatistic(String tagId){
Map<String, TagStatistic> tagStatisticMap = queryTagStatistic(Lists.newArrayList(tagId));
return tagStatisticMap.get(tagId);
}
/**
*
* @param tagIdList
* @return
*/
private Map<String, TagStatistic> queryTagStatistic(List<String> tagIdList){
Map<String, TagStatistic> tagStatisticMap = tagIdList.stream()
.collect(toMap(Function.identity(), TagStatistic::new));
List<TagStatistic> childTagStatisticList = tagDao.countByParentIds(tagIdList);
childTagStatisticList.forEach(childTagStatistic -> {
tagStatisticMap.get(childTagStatistic.getTagId()).setChildTagCount(childTagStatistic.getChildTagCount());
});
// todo 关联音乐或期刊
return tagStatisticMap;
}
/**
*
* @param queryReq
* @return
*/
private Specification<Tag> createSpecification(TagQueryReq queryReq) {
return (root, criteriaQuery, criteriaBuilder) -> {
List<Predicate> predicateList = new ArrayList<>();
String tagName = queryReq.getName();
if(StringUtils.isNotBlank(tagName)){
Predicate tagNameChPredicate = criteriaBuilder.like(root.get("name_ch"), '%'+tagName+'%');
Predicate tagNameEnPredicate = criteriaBuilder.like(root.get("name_en"), '%'+tagName+'%');
predicateList.add(criteriaBuilder.or(tagNameChPredicate, tagNameEnPredicate));
}
if(Objects.nonNull(queryReq.getState())){
predicateList.add(criteriaBuilder.equal(root.get("state").as(Integer.class), queryReq.getState()));
}
if(Objects.nonNull(queryReq.getCreatorId())){
predicateList.add(criteriaBuilder.equal(root.get("creator_id"), queryReq.getCreatorId()));
}
if(Objects.nonNull(queryReq.getId())){
predicateList.add(criteriaBuilder.equal(root.get("id"), queryReq.getId()));
}
Integer level = queryReq.getLevel();
if (level.compareTo(1) == 0){
predicateList.add(criteriaBuilder.equal(root.get("parent_id"), ""));
}
if(level.compareTo(2) == 0 && StringUtils.isNotBlank(queryReq.getParentId())){
predicateList.add(criteriaBuilder.equal(root.get("parent_id"), queryReq.getParentId()));
}
if(Objects.nonNull(queryReq.getCreateTimeStart())){
predicateList.add(criteriaBuilder.greaterThanOrEqualTo(root.get("create_time").as(LocalDateTime.class),
queryReq.getCreateTimeStart()));
}
if(Objects.nonNull(queryReq.getCreateTimeEnd())){
predicateList.add(criteriaBuilder.lessThanOrEqualTo(root.get("create_time").as(LocalDateTime.class),
queryReq.getCreateTimeEnd()));
}
Predicate[] predicates = new Predicate[predicateList.size()];
return criteriaBuilder.and(predicateList.toArray(predicates));
};
}
}

@ -0,0 +1,22 @@
server:
port: 9013
spring:
application:
name: luoo-tag #指定服务名
datasource:
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://8.134.98.47:3307/indie_music?characterEncoding=UTF8&useSSL=false
username: root
password: 47084735abc
jpa:
database: MySQL
show-sql: true
redis:
host: 8.134.98.47
port: 36379
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:6868/eureka/
instance:
prefer-ip-address: true

@ -18,6 +18,7 @@
<module>luoo_manage</module>
<module>luoo_web</module>
<module>luoo_sms</module>
<module>luoo_tag</module>
</modules>
<packaging>pom</packaging>
<name>luoo_parent</name>

Loading…
Cancel
Save