作者:fyupeng
技术专栏:☞ https://github.com/fyupeng
项目地址:☞ https://github.com/fyupeng/distributed-blog-system-api
项目预览地址:☞ 博客第七天


留给读者

前面第六天的开发比较漫长,但你有没有发现,我解耦了数据持久层跟控制层的关联?

还有,mapper配置文件和数据库的配置信息也完全去掉了,也就是完全解耦了与持久层的接触,而专注于控制层业务逻辑。

这是怎么做到的呢?其实归功于RPC的功劳,如果你使用了Spring CloudEureka注册中心,你发现它的优势在于集群,而分布式简单来说是通过间接调用了SpringBoot的接口,也就是真实服务器的接口时可以直接调用的,而我的微服务它虽然真实服务也有接口,但不提供通过get和post请求调用,这也就保证了真实服务器的安全性,而只能通过代理服务去远程代理服务。

远程代理服务怎么感觉听起来很牛掰呢?感觉好难理解呀!

其实不难解释,所谓远程代理,其实是通过Java的反射Reflect + Netty客户端与服务端之间的通信实现。

具体是通过自定义协议,将你要做的事,即调用这个服务(例如UserService接口你已经在控制层规范了),通过该接口去反射调用方法,怎么调用?方法不是抽象方法吗?

Netty通信规范一套字节的编码和解码,比如我要调用这个方法,那么我就将这个类以及方法名和方法所需参数编译成字节码通过客户端传送给服务端,服务端接收到后,按照客户端编译的同方向解码,具体可以看看rpc-netty-framework的底层源码,其实很好理解的。

下面主要开发博客的几块真实服务

1. 通用配置和启动器配置

1.1 文件配置

  • application.properties配置文件
############################################################
#
# Close Port And provide bean definition ioc
#
############################################################
spring.main.web-application-type=none
spring.main.allow-bean-definition-overriding=true############################################################
#
# DataSource Pool - druid
#
############################################################
spring.datasource.url=jdbc:mysql://localhost:3306/fyupeng_blog?useUnicode=true&characterEncoding=utf8&useJDBCComplliantTimezoneShift=true\&useLegacyDatetimeCode=false&serverTimezone=UTC
spring.datasource.username=your_mysql_username
spring.datasource.password=your_mysql_password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.druid.initial-size=1
spring.datasource.druid.min-idle=1
spring.datasource.druid.max-active=20
spring.datasource.druid.test-on-borrow=true
spring.datasource.druid.stat-view-servlet.allow=true
############################################################
#
# mybatis
#
############################################################
# mybatis
mybatis.type-aliases-package=cn.fyupeng.pojo
mybatis.mapper-locations=classpath:mapper/*.xml
# Mapper
mapper.mappers=cn.fyupeng.utils.MyMapper
mapper.not-empty=false
mapper.identity=MYSQL
# page pagination
pagehelper.helperDialect=mysql
pagehelper.supportMethodsArguments=true
pagehelper.params=count=countSql# springboot 1.5
#spring.http.multipart.maxFileSize=150Mb
#spring.http.multipart.maxRequestSize=1000Mb
# springboot 2.0
spring.servlet.multipart.max-file-size=150MB
spring.servlet.multipart.max-request-size=1000MB############################################################
#
# Redis
#
############################################################# Redis default use dataBase
#spring.redis.database=0## Redis Host
spring.redis.host=localhost
## Redis Port
spring.redis.port=6379# Redis password
spring.redis.password=your_redis_password#spring.redis.pool.max-active=300
spring.redis.jedis.pool.max-active=300
#spring.redis.pool.max-wait=10000
spring.redis.jedis.pool.max-wait=10000
#spring.redis.pool.maxIdle=300
spring.redis.jedis.pool.max-idle=300
#spring.redis.pool.minIdle=6
spring.redis.jedis.pool.min-idle=6
spring.redis.timeout=0# mongodb
spring.data.mongodb.host=localhost
spring.data.mongodb.port=27017
spring.data.mongodb.database=database
# 从哪个数据库创建的用户,使用它来验证身份
spring.data.mongodb.authentication-database=database
spring.data.mongodb.username=your_username
spring.data.mongodb.password=your_password
  • resource.properties
# nacos 配置
cn.fyupeng.nacos.register-addr=localhost:8848# 自定义配置
cn.fyupeng.config.serverPort=8082
  • 配置类
package cn.fyupeng.config;import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;/*** @Auther: fyp* @Date: 2022/8/17* @Description: 资源配置* @Package: cn.fyupeng.config* @Version: 1.0*/
@Configuration
@ConfigurationProperties(prefix="cn.fyupeng.config")
//不使用默认配置文件application.properties和application.yml
@PropertySource("classpath:resource.properties")
public class ResourceConfig {private int serverPort;public int getServerPort() {return serverPort;}public void setServerPort(int serverPort) {this.serverPort = serverPort;}
}

1.2 启动器配置

  • 启动器
package cn.fyupeng;import cn.fyupeng.config.ResourceConfig;
import cn.fyupeng.anotion.ServiceScan;
import cn.fyupeng.enums.SerializerCode;
import cn.fyupeng.net.netty.server.NettyServer;
import cn.fyupeng.utils.ResourceLoadUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import tk.mybatis.spring.annotation.MapperScan;import javax.annotation.PostConstruct;
import java.util.Map;/*** @Auther: fyp* @Date: 2022/8/13* @Description:* @Package: cn.fyupeng* @Version: 1.0*/@Slf4j
@ServiceScan
@SpringBootApplication
@MapperScan(basePackages = "cn.fyupeng.mapper")
@ComponentScan(basePackages = {"cn.fyupeng", "org.n3r.idworker"})
public class UserServer implements CommandLineRunner {@Autowiredprivate ResourceConfig resourceConfig;@PostConstructpublic void init() {Map<String, String> resourceLoaders = ResourceLoadUtils.load("resource.properties");if (resourceLoaders != null) {String serverPort = resourceLoaders.get("cn.fyupeng.config.serverPort");resourceConfig.setServerPort(Integer.parseInt(serverPort));}}public static void main(String[] args) throws InterruptedException {SpringApplication.run(UserServer.class, args);}@Overridepublic void run(String... args) throws Exception {//这里也可以添加一些业务处理方法,比如一些初始化参数等while(true){NettyServer nettyServer = new NettyServer("127.0.0.1", resourceConfig.getServerPort(), SerializerCode.KRYO.getCode());log.info("Service bind in port with "+ resourceConfig.getServerPort() +" and start successfully!");nettyServer.start();log.error("RegisterAndLoginService is died,Service is restarting....");}}
}

2. 逻辑服务

1.1 服务接口

与代理服务中的控制层使用的服务接口保持一致

  • UserService接口
package cn.fyupeng.service;import cn.fyupeng.pojo.User;
import cn.fyupeng.pojo.UserInfo;/*** @Auther: fyp* @Date: 2022/8/17* @Description: 用户业务服务接口* @Package: cn.fyupeng.service* @Version: 1.0*/
public interface UserService {/*** @Description: 判断用户名是否存在* @param username* @return*/public boolean queryUsernameIsExist(String username);/*** @Description: 用户登录,根据用户名和密码查询用户* @param username* @param password* @return*/public User queryUserForLogin(String username, String password);/*** 查询用户信息* @param userId* @return*/User queryUser(String userId);/*** 查询用户详细信息* @param userId* @return*/public UserInfo queryUserInfo(String userId);/*** 查询用户是否存在* @param userId* @return*/boolean queryUserIdIsExist(String userId);/*** @Description: 用户修改信息* @param user*/public boolean updateUser(User user);/*** @Description: 用户修改详细信息* @param user*//*** @Description: 保存用户(注册用户)* @param user*/public void saveUser(User user);public void updateUserInfo(UserInfo user);}
  • ArticleService接口
package cn.fyupeng.service;import cn.fyupeng.utils.PagedResult;
import cn.fyupeng.pojo.Article;
import cn.fyupeng.pojo.vo.ArticleVO;import java.util.List;
import java.util.Map;/*** @Auther: fyp* @Date: 2022/4/2* @Description:* @Package: com.crop.service* @Version: 1.0*/
public interface ArticleService {boolean queryArticleIsExist(String articleId);boolean queryArticleIsUser(Article article);boolean save(Article article);PagedResult queryArticleSelective(Article article, Integer page, Integer pageSize);ArticleVO queryArticleDetail(String articleId);boolean saveWithIdAndUserId(Article article);void multiUpdateArticleReadCounts(List<String> articleIdKeys, Map<String, String> articleMap);void removeArticle(String articleId);PagedResult queryArticleByTime(Long timeDifference, Integer page, Integer pageSize);List<ArticleVO> queryArticleWithNoneTagByUser(String userId);
}
  • ClassficationService接口
package cn.fyupeng.service;import cn.fyupeng.pojo.Classfication;import java.util.List;/*** @Auther: fyp* @Date: 2022/4/3* @Description:* @Package: com.crop.service* @Version: 1.0*/
public interface ClassficationService {boolean queryClassficationIdIsExist(String classId);boolean saveClassfication(Classfication classfication);Classfication queryClassfication(Classfication classfication);List<Classfication> queryAllClassfications();boolean deleteClassfication(String classficationId);boolean updateClassfication(Classfication clssfication);
}
  • TagService接口
package cn.fyupeng.service;import cn.fyupeng.pojo.Articles2tags;
import cn.fyupeng.pojo.Tag;
import cn.fyupeng.pojo.vo.Articles2tagsVO;
import cn.fyupeng.pojo.vo.TagVO;import java.util.List;/*** @Auther: fyp* @Date: 2022/4/8* @Description:* @Package: com.crop.service* @Version: 1.0*/
public interface TagService {boolean queryTagIsExist(Tag tag);boolean queryArticleTagIsExist(String id);boolean queryArticleTagIsExist(Articles2tags articles2tags);List<TagVO> queryAllTags(Tag tag);boolean saveTag(Tag tag);boolean updateTag(Tag tag);boolean deleteTag(String tagId);void delArticleTag(String tagId);boolean deleteTagAndArticleTagWithTagId(String tagId);Tag queryTag(String tagId);List<Articles2tagsVO> queryArticleTag(Articles2tags articles2tags);boolean saveArticleTag(Articles2tags articles2tags);boolean updateArticleTag(Articles2tags articles2tags);boolean deleteTagAndArticleTagWithArticleId(String articleId);
}
  • CommentService接口
package cn.fyupeng.service;import cn.fyupeng.pojo.Comment;
import cn.fyupeng.pojo.vo.CommentVO;
import cn.fyupeng.enums.CommentStatus;
import cn.fyupeng.utils.PagedResult;import java.util.Date;
import java.util.List;/*** @Auther: fyp* @Date: 2022/4/3* @Description:* @Package: com.crop.service* @Version: 1.0*/
public interface CommentService {boolean saveComment(Comment comment);void removeCommentById(String commentId);Comment queryComment(String commentId);boolean queryCommentIsExist(String commentId);boolean updateComment(Comment comment);PagedResult queryAllComments(String articleId, Integer page, Integer pageSize, Integer sort);boolean queryCommentWithFatherCommentIsExist(String commentId);void removeCommentWithFatherCommentId(String fatherCommentId);List<CommentVO> queryAllComments(String aPattern, String cPattern, String userId, Date startTime, Date endTime);void setCommentStatusWithFatherId(Comment comment, CommentStatus commentStatus);
}

2.2 服务实现

  • UserService实现类
package cn.fyupeng.service.impl;import cn.fyupeng.mapper.UserInfoMapper;
import cn.fyupeng.mapper.UserMapper;
import cn.fyupeng.pojo.User;
import cn.fyupeng.pojo.UserInfo;
import cn.fyupeng.service.UserService;
import cn.fyupeng.anotion.Service;
import org.n3r.idworker.Sid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.entity.Example.Criteria;import javax.annotation.PostConstruct;@SuppressWarnings("all")
@Service
@Component
public class UserServiceImpl implements UserService {private static UserServiceImpl basicService;@Autowiredprivate UserMapper userMapper;@Autowiredprivate UserInfoMapper userInfoMapper;@Autowiredprivate Sid sid;@PostConstructpublic void init() {basicService = this;}public UserServiceImpl() {}@Override@Transactional(propagation = Propagation.SUPPORTS)public boolean queryUserIdIsExist(String userId) {User user = new User();user.setId(userId);User result = basicService.userMapper.selectOne(user);return result == null ? false : true;}@Override@Transactional(propagation = Propagation.SUPPORTS)public boolean queryUsernameIsExist(String username) {User user = new User();user.setUsername(username);User result = basicService.userMapper.selectOne(user);return result == null ? false : true;}@Override@Transactional(propagation = Propagation.SUPPORTS)public User queryUser(String userId) {Example userExample = new Example(User.class);Criteria criteria = userExample.createCriteria();criteria.andEqualTo("id", userId);User user = basicService.userMapper.selectOneByExample(userExample);return user;}@Override@Transactional(propagation = Propagation.SUPPORTS)public UserInfo queryUserInfo(String userId) {Example userInfoExample = new Example(UserInfo.class);Criteria criteria = userInfoExample.createCriteria();criteria.andEqualTo("userId", userId);UserInfo userInfo = basicService.userInfoMapper.selectOneByExample(userInfoExample);return userInfo;}@Override@Transactional(propagation = Propagation.SUPPORTS)public User queryUserForLogin(String username, String password){Example userExample = new Example(User.class);Criteria criteria = userExample.createCriteria();criteria.andEqualTo("username", username);criteria.andEqualTo("password", password);User result = basicService.userMapper.selectOneByExample(userExample);return result;}@Override@Transactional(propagation = Propagation.REQUIRED)public void saveUser(User user) {String userId = basicService.sid.nextShort();String userInfoId = basicService.sid.nextShort();UserInfo userInfo = new UserInfo();user.setId(userId);userInfo.setId(userInfoId);userInfo.setUserId(userId);basicService.userMapper.insert(user);basicService.userInfoMapper.insert(userInfo);}@Override@Transactional(propagation = Propagation.REQUIRED)public boolean updateUser(User user){int i = basicService.userMapper.updateByPrimaryKey(user);return i > 0 ? true : false;/*** 防止 在 controller 忘记 传进 id 值,将会导致 所有用户 被更改*  fix : 弃用if (StringUtils.isBlank(user.getId())) {return;}Example userExample = new Example(User.class);// id 值为空时, 会 匹配所有用户,危险 !!!Criteria criteria = userExample.createCriteria();criteria.andEqualTo("id", user.getId());userMapper.updateByExampleSelective(user, userExample);*/}@Override@Transactional(propagation = Propagation.REQUIRED)public void updateUserInfo(UserInfo userInfo){Example userInfoExample = new Example(UserInfo.class);Criteria criteria = userInfoExample.createCriteria();criteria.andEqualTo("id", userInfo.getId());criteria.andEqualTo("userId", userInfo.getUserId());basicService.userInfoMapper.updateByExampleSelective(userInfo, userInfoExample);}}
  • ArticleServiceImpl实现
package cn.fyupeng.service.impl;import cn.fyupeng.mapper.*;
import cn.fyupeng.pojo.*;
import cn.fyupeng.pojo.vo.Articles2tagsVO;
import cn.fyupeng.utils.PagedResult;
import cn.fyupeng.utils.TimeAgoUtils;
import cn.fyupeng.pojo.vo.ArticleVO;
import cn.fyupeng.service.ArticleService;
import cn.fyupeng.anotion.Service;
import org.apache.commons.lang3.StringUtils;
import org.n3r.idworker.Sid;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
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 org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;import javax.annotation.PostConstruct;
import java.text.SimpleDateFormat;
import java.util.*;/*** @Auther: fyp* @Date: 2022/4/2* @Description:* @Package: com.crop.service.impl* @Version: 1.0*/
@SuppressWarnings("all")
@Component
@Service
public class ArticleServiceImpl implements ArticleService {private static ArticleServiceImpl basicService;@Autowiredprivate ArticleRepository articleRepository;@Autowiredprivate MongoTemplate mongoTemplate;@Autowiredprivate UserInfoMapper userinfoMapper;@Autowiredprivate ClassficationMapper classficationMapper;@Autowiredprivate TagMapper tagMapper;@Autowiredprivate Articles2tagsMapper articles2tagsMapper;@Autowiredprivate Sid sid;@PostConstructpublic void init() {this.basicService = this;}@Override@Transactional(propagation = Propagation.SUPPORTS)public boolean queryArticleIsExist(String articleId) {Article article = new Article();article.setId(articleId);Example<Article> articleExample = Example.of(article);Optional<Article> one = basicService.articleRepository.findOne(articleExample);Article result = one.isPresent() ? one.get() : null;return article == null ? false : true;}@Override@Transactional(propagation = Propagation.SUPPORTS)public boolean queryArticleIsUser(Article article) {ExampleMatcher matching = ExampleMatcher.matching();ExampleMatcher exampleMatcher = matching.withMatcher("id", ExampleMatcher.GenericPropertyMatchers.exact()).withMatcher("userId", ExampleMatcher.GenericPropertyMatchers.exact());Example<Article> articleExample = Example.of(article, exampleMatcher);Optional<Article> one = basicService.articleRepository.findOne(articleExample);Article result = one.isPresent() ? one.get() : null;return result == null ? false : true;}/*** 查询 所有文章 时, 不做 流量统计,查询单篇文章,统计 阅读量* @param article* @param page* @param pageSize* @return*/@Override@Transactional(propagation = Propagation.SUPPORTS)public PagedResult queryArticleSelective(Article article, Integer page, Integer pageSize) {//分页查询对象if(page <= 0){page = 1;}// page 分页 在 mongodb 中是 从 0 开始的,转换为物理位置page = page - 1;if(pageSize <= 0){pageSize = 6;}ExampleMatcher matching = ExampleMatcher.matching();Page<Article> all = null;Article a = new Article();// 存在 分类名 为 keyif (!StringUtils.isBlank(article.getClassId())) {all = readAndExcute("classId", matching, article, page, pageSize);} else {Article titleArticle = new Article();titleArticle.setTitle(article.getTitle());all = readAndExcute("title", matching, titleArticle, page, pageSize);if (all.getTotalElements() == 0) {Article summaryArticle = new Article();summaryArticle.setSummary(article.getSummary());all = readAndExcute("summary", matching, summaryArticle, page, pageSize);if (all.getTotalElements() == 0) {Article contentArticle = new Article();contentArticle.setContent(article.getSummary());all = readAndExcute("content", matching, contentArticle, page, pageSize);if (all.getTotalElements() == 0)return null;}}}// 总 记录数long total = all.getTotalElements();List<Article> content = all.getContent();List<ArticleVO> artileVOList = new ArrayList<>();// 时间处理for (Article ac : content) {String createTimeAgo = TimeAgoUtils.format(ac.getCreateTime());String updateTimeAgo = TimeAgoUtils.format(ac.getUpdateTime());ArticleVO articleVO = new ArticleVO();BeanUtils.copyProperties(ac, articleVO);SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");String normalCreateTime = sdf.format(ac.getCreateTime());String normalUpdateTime = sdf.format(ac.getUpdateTime());articleVO.setNormalCreateTime(normalCreateTime);articleVO.setNormalUpdateTime(normalUpdateTime);articleVO.setCreateTimeAgoStr(createTimeAgo);articleVO.setUpdateTimeAgoStr(updateTimeAgo);/*** 查询量 太大,流量大,而且 用户 只是在 查询而已,不需要评论 和 内容*/articleVO.setContent(null);artileVOList.add(articleVO);}// 降序排序,最近发表的文章 放到了 最前面Collections.sort(artileVOList);// 总 页数int pages = all.getTotalPages();PagedResult pagedResult = new PagedResult();// 设置 总记录数pagedResult.setRecords(total);// 设置 内容列表//pagedResult.setRows(content); 原始数据pagedResult.setRows(artileVOList);// 设置 当前页,转换为逻辑位置pagedResult.setPage(page+1);// 设置 总页数pagedResult.setTotal(pages);return pagedResult;}@Override@Transactional(propagation = Propagation.SUPPORTS)public ArticleVO queryArticleDetail(String articleId) {/*** 每次获取 文章,该 文章的 阅读数要 自增 1*/Article article = new Article();article.setId(articleId);Example<Article> articleExample = Example.of(article);Optional<Article> one = basicService.articleRepository.findOne(articleExample);Article result = one.isPresent() ? one.get() : null;ArticleVO articleVO = new ArticleVO();if (result != null) {BeanUtils.copyProperties(result, articleVO);String createTimeAgo = TimeAgoUtils.format(result.getCreateTime());String updateTimeAgo = TimeAgoUtils.format(result.getUpdateTime());tk.mybatis.mapper.entity.Example userInfoExample = new tk.mybatis.mapper.entity.Example(UserInfo.class);tk.mybatis.mapper.entity.Example.Criteria criteria = userInfoExample.createCriteria();criteria.andEqualTo("userId", result.getUserId());UserInfo userInfo = basicService.userinfoMapper.selectOneByExample(userInfoExample);Classfication classfication = basicService.classficationMapper.selectByPrimaryKey(result.getClassId());articleVO.setAvatar(userInfo.getAvatar());articleVO.setNickName(userInfo.getNickname());articleVO.setClassficationName(classfication.getName());// 标签String aid = result.getId();Articles2tags articles2tags = new Articles2tags();articles2tags.setArticleId(aid);List<Articles2tagsVO> select = queryArticleTag(articles2tags);if (select.size() != 0) {Tag tag = basicService.tagMapper.selectByPrimaryKey(select.get(0).getTagId());articleVO.setTagId(tag.getId());articleVO.setTagName(tag.getName());}SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");String normalCreateTime = sdf.format(result.getCreateTime());String normalUpdateTime = sdf.format(result.getUpdateTime());articleVO.setNormalCreateTime(normalCreateTime);articleVO.setNormalUpdateTime(normalUpdateTime);articleVO.setCreateTimeAgoStr(createTimeAgo);articleVO.setUpdateTimeAgoStr(updateTimeAgo);return articleVO;}return null;}private List<Articles2tagsVO> queryArticleTag(Articles2tags articles2tags) {List<Articles2tags> articles2tagsList = basicService.articles2tagsMapper.select(articles2tags);for (Articles2tags tags : articles2tagsList) {System.out.println(tags);}List<Articles2tagsVO> articles2tagsVOList = new ArrayList<>();for (Articles2tags articleTags : articles2tagsList) {String articleId = articleTags.getArticleId();String tagId = articleTags.getTagId();Tag tag = basicService.tagMapper.selectByPrimaryKey(tagId);Article article = new Article();article.setId(articleId);org.springframework.data.domain.Example<Article> articleExample = org.springframework.data.domain.Example.of(article);Optional<Article> articleOptional = basicService.articleRepository.findOne(articleExample);Article one = articleOptional.isPresent() ? articleOptional.get() : null;if (one != null) {Classfication classfication = basicService.classficationMapper.selectByPrimaryKey(one.getClassId());Articles2tagsVO articles2tagsVO = new Articles2tagsVO();BeanUtils.copyProperties(articleTags, articles2tagsVO);articles2tagsVO.setTagName(tag.getName());articles2tagsVO.setTitle(one.getTitle());articles2tagsVO.setClassficationName(classfication.getName());articles2tagsVO.setCommentCounts(one.getCommentCounts());articles2tagsVO.setReadCounts(one.getReadCounts());articles2tagsVO.setReceiveLikeCounts(one.getReceiveLikeCounts());String createTimeAgo = TimeAgoUtils.format(one.getCreateTime());String updateTimaAgo = TimeAgoUtils.format(one.getUpdateTime());articles2tagsVO.setCreateTimeAgoStr(createTimeAgo);articles2tagsVO.setUpdateTimeAgoStr(updateTimaAgo);articles2tagsVOList.add(articles2tagsVO);}}return articles2tagsVOList;}@Override@Transactional(propagation = Propagation.REQUIRED)public void multiUpdateArticleReadCounts(List<String> articleIdKeys, Map<String, String> articleMap) {for (String articleId : articleIdKeys) {Article article = new Article();article.setId(articleId);Example<Article> articleExample = Example.of(article);Optional<Article> one = basicService.articleRepository.findOne(articleExample);Article oldArticle = one.isPresent() ? one.get() : null;// 获取 articleId 对应的 readCountsString readCounts = articleMap.get(articleId);// 更新 readCountsif (oldArticle != null) {oldArticle.setReadCounts(Integer.parseInt(readCounts));basicService.articleRepository.save(oldArticle);}}}@Override@Transactional(propagation = Propagation.REQUIRED)public void removeArticle(String articleId) {/*** 必须根据 id 删除Article article = new Article();article.setId(articleId);articleRepository.delete(article);*/Query queryArticle = new Query();queryArticle.addCriteria(Criteria.where("id").is(articleId));basicService.mongoTemplate.remove(queryArticle, Article.class);// 删除评论Query queryComment = new Query();queryComment.addCriteria(Criteria.where("articleId").is(articleId));basicService.mongoTemplate.remove(queryComment, Comment.class);// 删除关联标签navdeleteTagAndArticleTagWithArticleId(articleId);}private boolean deleteTag(String tagId) {int i = basicService.tagMapper.deleteByPrimaryKey(tagId);return i > 0 ? true : false;}private void delArticleTag(String tagId) {tk.mybatis.mapper.entity.Example articles2tagsExample = new tk.mybatis.mapper.entity.Example(Articles2tags.class);tk.mybatis.mapper.entity.Example.Criteria criteria = articles2tagsExample.createCriteria();criteria.andEqualTo("tagId", tagId);int i = basicService.articles2tagsMapper.deleteByExample(articles2tagsExample);}private boolean deleteTagAndArticleTagWithArticleId(String articleId) {tk.mybatis.mapper.entity.Example example = new tk.mybatis.mapper.entity.Example(Articles2tags.class);tk.mybatis.mapper.entity.Example.Criteria criteria = example.createCriteria();criteria.andEqualTo("articleId", articleId);int i = basicService.articles2tagsMapper.deleteByExample(example);return i > 0 ? true : false;}@Override@Transactional(propagation = Propagation.SUPPORTS)public PagedResult queryArticleByTime(Long timeDifference, Integer page, Integer pageSize) {//分页查询对象if(page <= 0){page = 1;}// page 分页 在 mongodb 中是 从 0 开始的,转换为 物理位置page = page - 1;if(pageSize <= 0){pageSize = 10;}// 当前时间Long now = System.currentTimeMillis();Long time = now - timeDifference;// 一周前的 日期Date oneWekkAgodate = new Date(time);Query queryAll = new Query();Query queryCurrentPage = new Query();queryAll.addCriteria(Criteria.where("createTime").gt(oneWekkAgodate));queryCurrentPage.addCriteria(Criteria.where("createTime").gt(oneWekkAgodate));// 倒序 时间Sort sort = new Sort(Sort.Direction.DESC, "createTime");queryAll.with(sort);queryCurrentPage.with(sort);PageRequest pageRequest = new PageRequest(page, pageSize);queryCurrentPage.with(pageRequest);// 分页/*** PageHelper 不支持 mongodb 查询*///PageHelper.startPage(page, pageSize);List<Article> allArticleList = basicService.mongoTemplate.find(queryAll, Article.class);List<Article> currentPageArticleList = basicService.mongoTemplate.find(queryCurrentPage, Article.class);List<ArticleVO> artileVOList = new ArrayList<>();// 时间处理for (Article ac : currentPageArticleList) {String createTimeAgo = TimeAgoUtils.format(ac.getCreateTime());String updateTimeAgo = TimeAgoUtils.format(ac.getUpdateTime());ArticleVO articleVO = new ArticleVO();BeanUtils.copyProperties(ac, articleVO);articleVO.setCreateTimeAgoStr(createTimeAgo);articleVO.setUpdateTimeAgoStr(updateTimeAgo);/*** 查询量 太大,流量大,而且 用户 只是在 查询而已,不需要评论 和 内容*/articleVO.setContent(null);artileVOList.add(articleVO);}long records = allArticleList.size();int total = 1;// 每页 大小 小于 总记录数 时才需要分页if (pageSize < records) {// 最后一页 还有 数据if (records % pageSize != 0) {total += records / pageSize;} else {total = (int) (records / pageSize);}}PagedResult pagedResult = new PagedResult();pagedResult.setTotal(total);pagedResult.setRecords(records);pagedResult.setRows(artileVOList);// page 最后转换为 逻辑位置pagedResult.setPage(page+1);return pagedResult;}@Override@Transactional(propagation = Propagation.SUPPORTS)public List<ArticleVO> queryArticleWithNoneTagByUser(String userId) {ExampleMatcher matching = ExampleMatcher.matching();ExampleMatcher articleExampleMatcher = matching.withMatcher("userId", ExampleMatcher.GenericPropertyMatchers.exact());Article article = new Article();article.setUserId(userId);Example<Article> articleExample = Example.of(article, articleExampleMatcher);List<Article> all = basicService.articleRepository.findAll(articleExample);List<ArticleVO> artileVOList = new ArrayList<>();for (Article ac : all) {String articleId = ac.getId();Articles2tags articles2tags = new Articles2tags();articles2tags.setArticleId(articleId);// 过滤掉 有标签 标记的 用户文章boolean articleTagIsExist = queryArticleTagIsExist(articles2tags);if (articleTagIsExist) {continue;}String createTimeAgo = TimeAgoUtils.format(ac.getCreateTime());String updateTimeAgo = TimeAgoUtils.format(ac.getUpdateTime());ArticleVO articleVO = new ArticleVO();BeanUtils.copyProperties(ac, articleVO);SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");String normalCreateTime = sdf.format(ac.getCreateTime());String normalUpdateTime = sdf.format(ac.getUpdateTime());articleVO.setNormalCreateTime(normalCreateTime);articleVO.setNormalUpdateTime(normalUpdateTime);articleVO.setCreateTimeAgoStr(createTimeAgo);articleVO.setUpdateTimeAgoStr(updateTimeAgo);/*** 查询量 太大,流量大,而且 用户 只是在 查询而已,不需要评论 和 内容*/articleVO.setContent(null);artileVOList.add(articleVO);}return artileVOList;}public boolean queryArticleTagIsExist(Articles2tags articles2tags) {List<Articles2tags> result = basicService.articles2tagsMapper.select(articles2tags);return result.size() == 0 ? false : true;}@Override@Transactional(propagation = Propagation.REQUIRED)public boolean save(Article article) {String articleId = basicService.sid.nextShort();article.setId(articleId);article.setCreateTime(new Date());article.setUpdateTime(new Date());article.setReadCounts(0);article.setCommentCounts(0);article.setReceiveLikeCounts(0);Article result = basicService.articleRepository.save(article);return result == null ? false : true;}@Override@Transactional(propagation = Propagation.REQUIRED)public boolean saveWithIdAndUserId(Article article) {Article article1 = new Article();article1.setId(article.getId());Example<Article> articleExample = Example.of(article1);Optional<Article> one = basicService.articleRepository.findOne(articleExample);Article oldArticle = one.isPresent() ? one.get() : null;article.setCreateTime(oldArticle.getCreateTime());article.setReadCounts(oldArticle.getReadCounts());article.setReceiveLikeCounts(oldArticle.getReceiveLikeCounts());article.setCommentCounts(oldArticle.getCommentCounts());article.setUpdateTime(new Date());Article result = basicService.articleRepository.save(article);return result == null ? false : true;}private Page<Article> readAndExcute(String metcherProperty, ExampleMatcher matching, Article article, Integer page, Integer pageSize) {ExampleMatcher exampleMatcher = matching.withMatcher(metcherProperty, ExampleMatcher.GenericPropertyMatchers.contains());Example<Article> articleExample = Example.of(article, exampleMatcher);Pageable pageable = new PageRequest(page, pageSize);return basicService.articleRepository.findAll(articleExample, pageable);}}
  • TagServiceImpl实现
package cn.fyupeng.service.impl;import cn.fyupeng.pojo.Article;
import cn.fyupeng.pojo.Articles2tags;
import cn.fyupeng.pojo.Classfication;
import cn.fyupeng.pojo.Tag;
import cn.fyupeng.utils.TimeAgoUtils;
import cn.fyupeng.mapper.ArticleRepository;
import cn.fyupeng.mapper.Articles2tagsMapper;
import cn.fyupeng.mapper.ClassficationMapper;
import cn.fyupeng.mapper.TagMapper;
import cn.fyupeng.pojo.vo.Articles2tagsVO;
import cn.fyupeng.pojo.vo.TagVO;
import cn.fyupeng.service.TagService;
import cn.fyupeng.anotion.Service;
import org.n3r.idworker.Sid;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;/*** @Auther: fyp* @Date: 2022/4/8* @Description:* @Package: com.crop.service.impl* @Version: 1.0*/
@SuppressWarnings("all")
@Component
@Service
public class TagServiceImpl implements TagService {private static TagServiceImpl basicService;@Autowiredprivate TagMapper tagMapper;@Autowiredprivate Articles2tagsMapper articles2tagsMapper;@Autowiredprivate ArticleRepository articleRepository;@Autowiredprivate ClassficationMapper classficationMapper;@Autowiredprivate Sid sid;@PostConstructpublic void init() {this.basicService = this;}@Override@Transactional(propagation = Propagation.SUPPORTS)public boolean queryTagIsExist(Tag tag) {Tag result = basicService.tagMapper.selectOne(tag);return result == null ? false : true;}@Override@Transactional(propagation = Propagation.SUPPORTS)public boolean queryArticleTagIsExist(String id) {Articles2tags result = basicService.articles2tagsMapper.selectByPrimaryKey(id);return result == null ? false : true;}@Overridepublic boolean queryArticleTagIsExist(Articles2tags articles2tags) {List<Articles2tags> result = basicService.articles2tagsMapper.select(articles2tags);return result.size() == 0 ? false : true;}@Override@Transactional(propagation = Propagation.SUPPORTS)public Tag queryTag(String tagId) {Tag tag = basicService.tagMapper.selectByPrimaryKey(tagId);return tag;}@Override@Transactional(propagation = Propagation.SUPPORTS)public List<Articles2tagsVO> queryArticleTag(Articles2tags articles2tags) {List<Articles2tags> articles2tagsList = basicService.articles2tagsMapper.select(articles2tags);for (Articles2tags tags : articles2tagsList) {System.out.println(tags);}List<Articles2tagsVO> articles2tagsVOList = new ArrayList<>();for (Articles2tags articleTags : articles2tagsList) {String articleId = articleTags.getArticleId();String tagId = articleTags.getTagId();Tag tag = basicService.tagMapper.selectByPrimaryKey(tagId);Article article = new Article();article.setId(articleId);org.springframework.data.domain.Example<Article> articleExample = org.springframework.data.domain.Example.of(article);Optional<Article> articleOptional = basicService.articleRepository.findOne(articleExample);Article one = articleOptional.isPresent() ? articleOptional.get() : null;if (one != null) {Classfication classfication = basicService.classficationMapper.selectByPrimaryKey(one.getClassId());Articles2tagsVO articles2tagsVO = new Articles2tagsVO();BeanUtils.copyProperties(articleTags, articles2tagsVO);articles2tagsVO.setTagName(tag.getName());articles2tagsVO.setTitle(one.getTitle());articles2tagsVO.setClassficationName(classfication.getName());articles2tagsVO.setCommentCounts(one.getCommentCounts());articles2tagsVO.setReadCounts(one.getReadCounts());articles2tagsVO.setReceiveLikeCounts(one.getReceiveLikeCounts());String createTimeAgo = TimeAgoUtils.format(one.getCreateTime());String updateTimaAgo = TimeAgoUtils.format(one.getUpdateTime());articles2tagsVO.setCreateTimeAgoStr(createTimeAgo);articles2tagsVO.setUpdateTimeAgoStr(updateTimaAgo);articles2tagsVOList.add(articles2tagsVO);}}return articles2tagsVOList;}@Override@Transactional(propagation = Propagation.SUPPORTS)public List<TagVO> queryAllTags(Tag tag) {List<Tag> select = basicService.tagMapper.select(tag);List<TagVO> tagVOList = new ArrayList<>();for (Tag one : select) {String tagId = one.getId();Articles2tags articles2tags = new Articles2tags();articles2tags.setTagId(tagId);List<Articles2tags> articles2tagsList = basicService.articles2tagsMapper.select(articles2tags);TagVO tagVO = new TagVO();BeanUtils.copyProperties(one, tagVO);tagVO.setArticleNum(articles2tagsList.size());tagVOList.add(tagVO);}return tagVOList;}@Override@Transactional(propagation = Propagation.REQUIRED)public boolean saveTag(Tag tag) {String tagId = basicService.sid.nextShort();tag.setId(tagId);int i = basicService.tagMapper.insert(tag);return i > 0 ? true : false;}@Override@Transactional(propagation = Propagation.REQUIRED)public boolean saveArticleTag(Articles2tags articles2tags) {String articles2tagsId = basicService.sid.nextShort();articles2tags.setId(articles2tagsId);int i = basicService.articles2tagsMapper.insert(articles2tags);return i > 0 ? true : false;}@Override@Transactional(propagation = Propagation.REQUIRED)public boolean updateArticleTag(Articles2tags articles2tags) {int i = basicService.articles2tagsMapper.updateByPrimaryKey(articles2tags);return i > 0 ? true : false;}@Override@Transactional(propagation = Propagation.REQUIRED)public boolean deleteTagAndArticleTagWithArticleId(String articleId) {Example example = new Example(Articles2tags.class);Example.Criteria criteria = example.createCriteria();criteria.andEqualTo("articleId", articleId);int i = basicService.articles2tagsMapper.deleteByExample(example);return i > 0 ? true : false;}@Override@Transactional(propagation = Propagation.REQUIRED)public boolean updateTag(Tag tag) {int i = basicService.tagMapper.updateByPrimaryKeySelective(tag);return i > 0 ? true : false;}@Override@Transactional(propagation = Propagation.REQUIRED)public boolean deleteTag(String tagId) {int i = basicService.tagMapper.deleteByPrimaryKey(tagId);return i > 0 ? true : false;}@Override@Transactional(propagation = Propagation.REQUIRED)public void delArticleTag(String tagId) {Example articles2tagsExample = new Example(Articles2tags.class);Example.Criteria criteria = articles2tagsExample.createCriteria();criteria.andEqualTo("tagId", tagId);int i = basicService.articles2tagsMapper.deleteByExample(articles2tagsExample);}@Override@Transactional(propagation = Propagation.REQUIRED)public boolean deleteTagAndArticleTagWithTagId(String tagId) {boolean result = deleteTag(tagId);if (result)delArticleTag(tagId);return result;}}
  • CommentServiceImpl实现
package cn.fyupeng.service.impl;import cn.fyupeng.anotion.Service;
import cn.fyupeng.mapper.CommentRepository;
import cn.fyupeng.mapper.UserInfoMapper;
import cn.fyupeng.pojo.Article;
import cn.fyupeng.pojo.Comment;
import cn.fyupeng.pojo.UserInfo;
import cn.fyupeng.service.CommentService;
import cn.fyupeng.pojo.vo.CommentVO;
import cn.fyupeng.enums.CommentStatus;
import cn.fyupeng.utils.PagedResult;
import cn.fyupeng.utils.TimeAgoUtils;
import org.apache.commons.lang3.StringUtils;
import org.n3r.idworker.Sid;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
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 org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;import javax.annotation.PostConstruct;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;/*** @Auther: fyp* @Date: 2022/4/3* @Description:* @Package: com.crop.service.impl* @Version: 1.0*/
@SuppressWarnings("all")
@Component
@Service
public class CommentServiceImpl implements CommentService {private static CommentServiceImpl basicService;@Autowiredprivate CommentRepository commentRepository;@Autowiredprivate UserInfoMapper userInfoMapper;@Autowiredprivate MongoTemplate mongoTemplate;@Autowiredprivate Sid sid;@PostConstructpublic void init() {this.basicService = this;}@Override@Transactional(propagation = Propagation.SUPPORTS)public boolean queryCommentIsExist(String commentId) {Comment comment = new Comment();comment.setId(commentId);Example<Comment> commentExample = Example.of(comment);Optional<Comment> one = basicService.commentRepository.findOne(commentExample);return one.isPresent() ? true : false;}@Override@Transactional(propagation = Propagation.SUPPORTS)public Comment queryComment(String commentId) {Comment comment = new Comment();comment.setId(commentId);Example<Comment> commentExample = Example.of(comment);Optional<Comment> one = basicService.commentRepository.findOne(commentExample);return one.isPresent() ? one.get() : null;}@Override@Transactional(propagation = Propagation.SUPPORTS)public PagedResult queryAllComments(String articleId, Integer page, Integer pageSize, Integer sortNum) {//分页查询对象if(page <= 0){page = 1;}// page 分页 在 mongodb 中是 从 0 开始的page = page - 1;if(pageSize <= 0){pageSize = 10;}ExampleMatcher matching = ExampleMatcher.matching();ExampleMatcher articleExampleMatcher = matching.withMatcher("articleId", ExampleMatcher.GenericPropertyMatchers.exact()).withMatcher("status", ExampleMatcher.GenericPropertyMatchers.exact());Comment comment = new Comment();comment.setArticleId(articleId);comment.setStatus(CommentStatus.NORMAL.getStatus());Example<Comment> articleExample = Example.of(comment, articleExampleMatcher);//mongodb数据中默认是 按时间正序排序(顺着时间走向排序、升序)Pageable pageable = new PageRequest(page, pageSize);if (sortNum == 2) {Sort sort = new Sort(Sort.Direction.DESC, "createTime");pageable = new PageRequest(page, pageSize, sort);}Page<Comment> all = basicService.commentRepository.findAll(articleExample, pageable);int pages = all.getTotalPages();long total = all.getTotalElements();List<Comment> content = all.getContent();List<CommentVO> commentVOList = new ArrayList<>();// po -> vo 永久层对象 - 视图层对象forCopyComment(content, commentVOList);PagedResult pagedResult = new PagedResult();// 页数pagedResult.setTotal(pages);// 当前页pagedResult.setPage(page);// 总记录数pagedResult.setRecords(total);// 内容列表pagedResult.setRows(commentVOList);return pagedResult;}@Override@Transactional(propagation = Propagation.SUPPORTS)public boolean queryCommentWithFatherCommentIsExist(String commentId) {ExampleMatcher matching = ExampleMatcher.matching();ExampleMatcher exampleMatcher = matching.withMatcher("fatherCommentId", ExampleMatcher.GenericPropertyMatchers.exact());Comment comment = new Comment();comment.setFatherCommentId(commentId);Example<Comment> commentExample = Example.of(comment, exampleMatcher);Optional<Comment> one = basicService.commentRepository.findOne(commentExample);return one.isPresent() ? true : false;}@Override@Transactional(propagation = Propagation.REQUIRED)public boolean saveComment(Comment comment) {String commentId = basicService.sid.nextShort();comment.setId(commentId);comment.setCreateTime(new Date());comment.setStatus(CommentStatus.NORMAL.getStatus());Comment result = basicService.commentRepository.save(comment);return result == null ? false : true;}@Override@Transactional(propagation = Propagation.REQUIRED)public boolean updateComment(Comment comment) {comment.setStatus(CommentStatus.NORMAL.getStatus());Comment result = basicService.commentRepository.save(comment);return result == null ? false : true;}@Override@Transactional(propagation = Propagation.REQUIRED)public void removeCommentById(String commentId) {Comment comment = new Comment();comment.setId(commentId);basicService.commentRepository.delete(comment);}@Override@Transactional(propagation = Propagation.REQUIRED)public void removeCommentWithFatherCommentId(String fatherCommentId) {Comment comment = new Comment();comment.setFatherCommentId(fatherCommentId);basicService.commentRepository.delete(comment);}@Override@Transactional(propagation = Propagation.SUPPORTS)public List<CommentVO> queryAllComments(String aPattern, String cPattern, String userId, Date startDate, Date endDate) {if (StringUtils.isBlank(aPattern)) {aPattern = "";}Article article = new Article();article.setTitle(aPattern);article.setSummary(aPattern);ExampleMatcher articleMatcher = ExampleMatcher.matching().withMatcher("title", ExampleMatcher.GenericPropertyMatchers.contains()).withMatcher("summary", ExampleMatcher.GenericPropertyMatchers.contains());Example<Article> articleExample = Example.of(article, articleMatcher);if (StringUtils.isBlank(cPattern)) {cPattern = "";}Comment comment = new Comment();comment.setComment(cPattern);ExampleMatcher commentMatcher = ExampleMatcher.matching().withMatcher("comment", ExampleMatcher.GenericPropertyMatchers.contains());Example<Comment> commentExample = Example.of(comment, commentMatcher);// 不去匹配cPattern, 做时间 跨度 过滤Query queryAllArticle = new Query();// 不去 查询文章 时间//queryAllArticle.addCriteria(Criteria.where("createTime").gt(startDate).lt(endDate));List<Comment> resultCommentList = new ArrayList<>();if (StringUtils.isNotBlank(aPattern) && StringUtils.isNotBlank(cPattern)) {queryAllArticle.addCriteria(new Criteria().alike(articleExample));List<Article> articleAllList = basicService.mongoTemplate.find(queryAllArticle, Article.class);for (Article ac : articleAllList) {Query queryAllComment = new Query();prepareQuery(queryAllComment, startDate, endDate);queryAllComment.addCriteria(Criteria.where("articleId").is(ac.getId()));if (userId != null)queryAllComment.addCriteria(Criteria.where("fromUserId").is(userId));queryAllComment.addCriteria(new Criteria().alike(commentExample));List<Comment> comments = basicService.mongoTemplate.find(queryAllComment, Comment.class);resultCommentList.addAll(comments);}} else {if (StringUtils.isBlank(cPattern)) {queryAllArticle.addCriteria(new Criteria().alike(articleExample));List<Article> articleAllList = basicService.mongoTemplate.find(queryAllArticle, Article.class);for (Article ac : articleAllList) {Query queryAllComment = new Query();prepareQuery(queryAllComment, startDate, endDate);queryAllComment.addCriteria(Criteria.where("articleId").is(ac.getId()));if (userId != null)queryAllComment.addCriteria(Criteria.where("fromUserId").is(userId));List<Comment> comments = basicService.mongoTemplate.find(queryAllComment, Comment.class);resultCommentList.addAll(comments);}}if (StringUtils.isBlank(aPattern)) {Query queryAllComment = new Query();prepareQuery(queryAllComment, startDate, endDate);queryAllComment.addCriteria(new Criteria().alike(commentExample));if (userId != null)queryAllComment.addCriteria(Criteria.where("fromUserId").is(userId));List<Comment> comments = basicService.mongoTemplate.find(queryAllComment, Comment.class);resultCommentList.addAll(comments);}}List<CommentVO> commentVOList = new ArrayList<>();forCopyComment(resultCommentList, commentVOList);return commentVOList;}@Override@Transactional(propagation = Propagation.REQUIRED)public void setCommentStatusWithFatherId(Comment comment, CommentStatus commentStatus) {// 本评论comment.setStatus(commentStatus.getStatus());basicService.commentRepository.save(comment);String fatherCommentId = comment.getId();Comment childComment = new Comment();childComment.setFatherCommentId(fatherCommentId);ExampleMatcher commentMatcher = ExampleMatcher.matching();ExampleMatcher commentExampleMatcher = commentMatcher.withMatcher("fatherCommentId", ExampleMatcher.GenericPropertyMatchers.exact());Example<Comment> commentExample = Example.of(childComment, commentExampleMatcher);// 子评论List<Comment> childCommentList = basicService.commentRepository.findAll(commentExample);for (Comment ct : childCommentList) {ct.setStatus(commentStatus.getStatus());basicService.commentRepository.save(ct);}}private void forCopyComment(List<Comment> commentList, List<CommentVO> commentVOList) {for (Comment ct : commentList) {CommentVO commentVO = new CommentVO();BeanUtils.copyProperties(ct, commentVO);// fromUserString fromUserId = ct.getFromUserId();UserInfo userInfoWithFromUserId = new UserInfo();userInfoWithFromUserId.setUserId(fromUserId);UserInfo fromUserInfo = basicService.userInfoMapper.selectOne(userInfoWithFromUserId);commentVO.setFromUserNickName(fromUserInfo.getNickname());commentVO.setFromUserAvatar(fromUserInfo.getAvatar());// fatherCommentContentString fatherCommentId = ct.getFatherCommentId();if (fatherCommentId != null) {Comment comment = new Comment();comment.setId(fatherCommentId);Example<Comment> commentExample = Example.of(comment);Optional<Comment> one = basicService.commentRepository.findOne(commentExample);if (one.isPresent()) {commentVO.setFatherCommentContent(one.get().getComment());}}// toUserString toUserId = ct.getToUserId();if (toUserId != null) {UserInfo userInfoWithToUserId = new UserInfo();userInfoWithToUserId.setUserId(toUserId);UserInfo toUserInfo = basicService.userInfoMapper.selectOne(userInfoWithToUserId);commentVO.setToUserNickName(toUserInfo == null ? null : toUserInfo.getNickname());}//timeString createTimeAgo = TimeAgoUtils.format(ct.getCreateTime());commentVO.setCreateTimeAgo(createTimeAgo);SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");String normalCreateTime = sdf.format(ct.getCreateTime());commentVO.setNormalCreateTime(normalCreateTime);// 防止 被恶意使用commentVO.setToUserId(null);commentVOList.add(commentVO);}}private void prepareQuery(Query query, Date startDate, Date endDate) {query.addCriteria(Criteria.where("createTime").gt(startDate).lt(endDate));/*** 管理员应该 获取所有状态的 评论*///query.addCriteria(Criteria.where("status").is(CommentStatus.NORMAL.getStatus()));Sort sort = new Sort(Sort.Direction.DESC, "createTime");query.with(sort);}}
  • ClassficationServiceImpl实现
package cn.fyupeng.service.impl;import cn.fyupeng.mapper.ClassficationMapper;
import cn.fyupeng.pojo.Classfication;
import cn.fyupeng.service.ClassficationService;
import cn.fyupeng.anotion.Service;
import org.n3r.idworker.Sid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.entity.Example.Criteria;import javax.annotation.PostConstruct;
import java.util.List;/*** @Auther: fyp* @Date: 2022/4/3* @Description:* @Package: com.crop.service.impl* @Version: 1.0*/
@SuppressWarnings("all")
@Component
@Service
public class ClassficationServiceImpl implements ClassficationService {private static ClassficationServiceImpl basicService;@Autowiredprivate ClassficationMapper classficationMapper;@Autowiredprivate Sid sid;@PostConstructpublic void init() {this.basicService = this;}@Override@Transactional(propagation = Propagation.SUPPORTS)public boolean queryClassficationIdIsExist(String classId) {Classfication classfication = basicService.classficationMapper.selectByPrimaryKey(classId);return classfication == null ? false : true;}/*** 当前没有事务,以 无事务方式 执行,有 事务,多个查询线程 使用同一个 事务* @param classfication* @return*/@Override@Transactional(propagation = Propagation.SUPPORTS)public Classfication queryClassfication(Classfication classfication) {List<Classfication> result = basicService.classficationMapper.select(classfication);return (result == null || result.size() == 0) ? null : result.get(0);}@Override@Transactional(propagation = Propagation.SUPPORTS)public List<Classfication> queryAllClassfications() {Example classficationExample = new Example(Classfication.class);Criteria criteria = classficationExample.createCriteria();List<Classfication> result = basicService.classficationMapper.selectAll();return result;}/*** 当前没有其他事务,新建事务,这样该方法 调用多次 实际上是 多个事务,体现原子性* @param classfication*/@Override@Transactional(propagation = Propagation.REQUIRED)public boolean saveClassfication(Classfication classfication) {String classficationId = basicService.sid.nextShort();classfication.setId(classficationId);int i = basicService.classficationMapper.insert(classfication);return i > 0 ? true : false;}@Override@Transactional(propagation = Propagation.REQUIRED)public boolean updateClassfication(Classfication clssfication) {int i = basicService.classficationMapper.updateByPrimaryKeySelective(clssfication);return i > 0 ? true : false;}@Override@Transactional(propagation = Propagation.REQUIRED)public boolean deleteClassfication(String classficationId) {int i = basicService.classficationMapper.deleteByPrimaryKey(classficationId);return i > 0 ? true : false;}}

这样真实服务的五个具体服务实现了,接下来就是要将它们部署到服务器,怎么部署呢?

在第一天的时候就给了大家的脚本文件,可以用它来快速启动和关闭。

首先必装JDK

  • 第一种,Oracle官方下载,需要先登录,再获取下载链接

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FqN3dIiD-1663662505781)(C:\Users\fyp01\AppData\Roaming\Typora\typora-user-images\image-20220905213433073.png)]

由于Oracle这里设置了得验证登录,所以没法使用wget方式直接拉取下载,得先下载到本地再使用xftp拉取到服务器中

  • 第二种,Open JDK下载

先到OpenJDK官网:https://jdk.java.net/18/,选择不是Arch版本的tar.gz软件包,右键复制链接

直接在linux上存放软件压缩包的地方,我存在/opt/software/上,通过以下命名拉取

wget https://download.java.net/java/GA/jdk18.0.2.1/db379da656dc47308e138f21b33976fa/1/GPL/openjdk-18.0.2.1_linux-x64_bin.tar.gz

拉取完成后,通过以下命令完成解压

tar -xf openjdk-18.0.2.1_linux-x64_bin.tar.gz

在移动到合适位置,我一般移动到/usr/local/目录中

mv jdk18.0.2.1 /usr/local/

接着配置环境变量,我一般不改动系统原有变量,而是将环境变量生效的目录/etc/profile.d中添加一个my_env.sh文件,在里面添加变量再去生效

# JAVA_HOME
export JAVA_HOME=/usr/local/jdk1.8.0_341
export PATH=$PATH:$JAVA_HOME/bin

生效使用"touch"命令或“.”命令

touch my_env.sh

使用以下命令校验是否生效

java -version

其次是Nacos的下载和启动

Nacos被注册的是哪一台服务器,即五个真实服务的机器上,因为这样注册服务在同一台机器比在其他服务上注册性能要高,服务器性能允许情况下可以这么使用。

Nacos官网在国内访问很慢,下载Linux版本也很慢,推荐下载的时候可以在凌晨5点到9点之间,会快些。

wget https://github.com/alibaba/nacos/releases/download/2.1.1/nacos-server-2.1.1.tar.gz

拉取完毕后,解压后移动步骤跟上面一样,不再赘述

启动是在主目录下的bin下通过以下命令

./start.sh -m standalone

再使用jps命令查看是否已经启动,jps是对java进程的查询

[root@localhost bin]# jps
1840896 Jps
1840881 nacos-server.jar

启动项目的话,我是将项目放到了下面目录中

[root@localhost jarList]# ls
blog-article-server        blog-comment-server  blog-user-server  status.sh
blog-classfication-server  blog-tag-server      start.sh          stop.sh
[root@localhost jarList]# pwd
/usr/local/jarList
[root@localhost jarList]# cd blog-user-server/
[root@localhost blog-user-server]# ls
config  fyupeng-blog-user-server.jar  logs
[root@localhost blog-user-server]# ls config/
application.properties  resource.properties

记住每个服务启动前,配置的端口号不能相同,并且如果是在云服务器上,要保证端口开放而且防火墙没有限制该端口(或者关闭防火墙)。

centos6.5及之前:

[root@localhost]# service iptable status

centos7.0及以上:

[root@localhost]# systemctl status firewalld.service

服务启动完毕后,当然就是部署完毕了,可以试着上线,如果不配置域名直接访问也是可以的,配置域名需要到云服务器所在服务提供商按照官方配置域名流程,一般为1个礼拜即可下来。

各位伙伴也陪伴了我一个礼拜了,相信你们这个项目不仅可以拿下,而且在任何时候都能拿得出手,因为涉及到分布式,如果面试介绍项目时,大概率会面临一致性的问题,该项目没有涉及到分布式事务的设计,所以大家加油吧,剩下的交给各位了!

分布式事务可以考虑消息队列去同步事务,可以考虑轻量级的RabbitMQ,它以易上手易使用而闻名。

手写一个博客平台 ~ 第七天相关推荐

  1. 手写一个博客平台~第一天

    作者:fyupeng 技术专栏:☞ https://github.com/fyupeng 项目地址:☞ https://github.com/fyupeng/distributed-blog-syst ...

  2. PHP+JS写一个博客系统

    文章目录 注册和登录界面的完成 注册界面 登录界面 数据库的创建 导入 连接 使用 数据库的连接 验证码的生成 DOACTION 即登录和注册的验证 发表博客 PHP学习完成,随之的实验是结合数据库, ...

  3. 前端开发 使用html写一个博客 基本标签的体验 0226

    新建一个html文件 写一段文本作为博客的标题 在body中写内容 *号的出现代表,文件有改变 保存文件后消失 快捷键: ctrl + s 效果 当前这个页面已经在一个模拟的服务器上运行了 当代码内容 ...

  4. 基于Bmob从零开始写一个博客小程序

    2019独角兽企业重金招聘Python工程师标准>>> 实现以下技能点 1.集成Bmob小程序SDK作为数据存储 2.wemark解析markdown文本 3.列表页布局与上拉无限加 ...

  5. 程序员可以选择哪些平台写技术博客?

    前言 只有光头才能变强. 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y 很多时候,别人问我怎么学习Java,怎么可以提升自己 ...

  6. 搭建一个属于自己的博客平台

    本文摘要:文章先讲解了如何从零开始搭建属于自己的博客或者网站平台,接着文章列举了搭建过程中遇到的问题及解决方案.文章步骤详细,适合没有任何基础但想要搭建自己的网站的朋友参考. 正文 最近花了几天时间, ...

  7. 3. 你也要写技术博客?这篇博客告诉你平台怎么选

    橡皮擦,一个逗趣的互联网高级网虫,为你带来新职场故事,搬来程序员敲门砖. 已完成文章 国内,首套,成体系,技术博客写作专栏发布啦 技术博客只能写技术文章吗?当然是由我们自己来定义. 为"她& ...

  8. 程序员为什么要写技术博客?都在哪些平台呢?

    目录 一.程序员为什么要写技术博客? 1.真正掌握技术 2.没有人会那么在意你 3.珍惜时间 4.懒于思考,疏于总结 5.碎片化学习 6.优秀大神 7.更好的求职机会 8.努力的人一直都有 二.程序员 ...

  9. 写技术博客,如何选择博客平台

    序言 很多技术开发在工作2-3年的时候,都会选择去写一些技术博客.一方面可以总结用到的一些技术,另一方面可以帮助到别人. 开始写技术博客,首要面临的问题是如何选择一个合适的博客平台? 选择标准 选择技 ...

最新文章

  1. C++拓展笔记2-3:C++中this指针用法简介
  2. 注册界面翻译_B站UP主自制的开源OCR翻译器走红Github,用一次就粉了
  3. Python 的6个日期时间库
  4. angularjs与PHP,我应该混合AngularJS与PHP框架吗?
  5. mysql 查看有没有drop权限的命令
  6. c++读取json文件_[SpringMVC]-SpringMVC架构-07-SpringMVC文件上传
  7. HashSet和LinkedHashSet使用
  8. unknown error mysql_mysql执行sql文件报错Error: Unknown storage engine‘InnoDB’的解决方法...
  9. linux使用教程_iTOP-4412-QtE系统源码以及Linux系统-wfi设置以及使用文档 - 心底狂像...
  10. find linux 目录深度_把 Linux 上的文件列表和排序玩出花来
  11. [译]10-Spring BeanPostProcessor
  12. node.js 实现udp传输_nodejs实现UDP组播示例方法
  13. opsForValue() 的 set 用法
  14. 什么是U盘量产工具?量产基本知识
  15. 大数据算法-重复率计算 ICardinality
  16. 怎么用Python爬取抖音小视频? 资深程序员都这样爬取的(附源码)
  17. Postman中文教程
  18. 邮箱登录名身份证号码等验证
  19. 百度网盘,到底限了谁的速?
  20. 获取城市a-z jso列表

热门文章

  1. 难忘赤名莉香的一些话
  2. 游戏服务器停服维护公告,《黑潮之上》2020年12月22日全服务器停服维护公告
  3. 基于springboot的校园医疗保险管理系统
  4. python rgb转hsv_Python colors.hsv_to_rgb方法代码示例
  5. php中的stripos,php字符串函数stripos()的定义与用法
  6. 给自己的html5加上背景音乐,网页加背景音乐用JS控制播放 HTML5 - audio
  7. java.sql.SQLException: ORA-01008: 并非所有变量都已绑定的解决方法
  8. 服务器网站打开速度慢怎么办
  9. 第一篇:C++11关键字
  10. 股票交易的眼和心的一些看法