今天正式开始做一个开发blog的练手项目。

第一天

今天实现项目搭建以及首页内容以及博客作者和标签的显示,前端时使用vue编写的,直接拿过来用,后台创建一个maven的父项目blog-parents,在其中添加子模块blog-api,父子项目依赖如下。
父项目依赖

<?xml version="1.0" encoding="UTF-8"?>
<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><groupId>com.runze</groupId><artifactId>blog-parents</artifactId><version>1.0-SNAPSHOT</version><modules><module>blogapi</module></modules><packaging>pom</packaging><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.5.0</version><relativePath/></parent><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version></properties><dependencyManagement></dependencyManagement><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

子项目依赖

<?xml version="1.0" encoding="UTF-8"?>
<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"><parent><artifactId>blog-parents</artifactId><groupId>com.runze</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>blog-api</artifactId><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><!-- 排除 默认使用的logback  --><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-logging</artifactId></exclusion></exclusions></dependency><!-- log4j2 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-log4j2</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.76</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId></dependency><dependency><groupId>commons-collections</groupId><artifactId>commons-collections</artifactId><version>3.2.2</version></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.3</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><!-- https://mvnrepository.com/artifact/joda-time/joda-time --><dependency><groupId>joda-time</groupId><artifactId>joda-time</artifactId><version>2.10.10</version></dependency></dependencies>
</project>

导入依赖之后创建dao、service、controller、vo、config包,
由于是前后端分离的项目,所以在config包下创建WebMVCConfig进行跨域配置,代码如下:

package com.runze.blog.config;import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class WebMVCConfig implements WebMvcConfigurer {@Overridepublic void addCorsMappings(CorsRegistry registry) {//跨域控制,前端是8080端口,后端是8888端口registry.addMapping("/**").allowedOrigins("http://localhost:8080");}
}

在config包下创建MyBatisPlusConfig配置分页插件,代码如下

package com.runze.blog.config;import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
@MapperScan("com.runze.blog.dao.mapper")
public class MyBatisPlusConfig {//分页插件@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor(){MybatisPlusInterceptor interceptor=new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new PaginationInnerInterceptor());return interceptor;}
}

在vo包下创建返回对象Result

package com.runze.blog.vo;import lombok.AllArgsConstructor;
import lombok.Data;@Data
@AllArgsConstructor
public class Result {//Controller的返回值private Boolean success;private int code;private String msg;private Object data;//两个静态方法public static Result success(Object data){return new Result(true,200,"success",data);}//两个静态方法public static Result fail(int code,String msg){return new Result(false,code,msg,null);}
}

vo包下创建ArticleVo,TagVo,SysUserVo,代码如下

package com.runze.blog.vo;import lombok.Data;import java.util.List;@Data
public class ArticleVo {private Long id;private String title;private String summary;private int commentCounts;private int viewCounts;private int weight;/*** 创建时间*/private String createDate;private String author;//    private ArticleBodyVo body;private List<TagVo> tags;//    private List<CategoryVo> categorys;}
package com.runze.blog.vo;import lombok.Data;@Data
public class TagVo {private long id;private String tagName;
}

创建Controller.ArticleController

package com.runze.blog.controller;import com.runze.blog.service.ArticleService;
import com.runze.blog.vo.Result;
import com.runze.blog.vo.params.PageParams;
import com.sun.org.apache.regexp.internal.RE;
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("articles")
public class ArticleController {@Autowiredprivate ArticleService articleServiceImpl;/***@ClassName: 首页文章列表*@Param*@Author 李润泽*@Return*@Time*/@PostMappingpublic Result listArticles(@RequestBody PageParams pageParams){return articleServiceImpl.listArticles(pageParams);}

Service层代码

package com.runze.blog.service.impl;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.runze.blog.dao.mapper.ArticleMapper;
import com.runze.blog.dao.pojo.Article;
import com.runze.blog.service.ArticleService;
import com.runze.blog.service.SysUserService;
import com.runze.blog.service.TagService;
import com.runze.blog.vo.ArticleVo;
import com.runze.blog.vo.Result;
import com.runze.blog.vo.TagVo;
import com.runze.blog.vo.params.PageParams;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import java.util.*;@Service
public class ArticleServiceImpl implements ArticleService {@Autowiredprivate ArticleMapper articleMapper;@Autowiredprivate TagService tagService;@Autowiredprivate SysUserService sysUserService;@Overridepublic Result listArticles(PageParams pageParams) {//1.分页查询Article数据库表Page<Article> page = new Page<>(pageParams.getPage(), pageParams.getPageSize());LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();//先进行置顶排序queryWrapper.orderByDesc(Article::getWeight);//再按照时间排序,倒序排列queryWrapper.orderByDesc(Article::getCreateDate);Page<Article> articlePage = articleMapper.selectPage(page, queryWrapper);List<Article> records = articlePage.getRecords();//不能将结果直接返回,需要将其转化成Vo对象List<ArticleVo> articleVoList = copyArticle(records, true, true);return Result.success(articleVoList);}private List<ArticleVo> copyArticle(List<Article> records, boolean isTag, boolean isAuthor) {List<ArticleVo> articleVoList = new ArrayList<ArticleVo>();for (Article record : records) {articleVoList.add(copy(record, isTag, isAuthor));}return articleVoList;}@Overridepublic Result hotArticle(int limit) {LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();//根据浏览量排序queryWrapper.orderByDesc(Article::getViewCounts);//查询id与titlequeryWrapper.select(Article::getId,Article::getTitle);//在sql语句的后来加上查询的数量queryWrapper.last("limit "+limit);List<Article> articles = articleMapper.selectList(queryWrapper);return Result.success(copyArticle(articles,false,false));}private ArticleVo copy(Article article, boolean isTag, boolean isAuthor) {ArticleVo articleVo = new ArticleVo();//Spring自带的属性复制工具,将名称一样类型一样的属性复制BeanUtils.copyProperties(article, articleVo);//creatTime类型不一致,手动进行转换articleVo.setCreateDate(new DateTime(article.getCreateDate()).toString("yyyy-MM-dd HH:mm"));Long articleId = article.getId();//并不是所有的博客都需要标签与作者,在添加之前需要进行一些判断if (isTag) {articleVo.setTags(tagService.findTagsByArticleId(articleId));}Long authorId = article.getAuthorId();if (isAuthor) {articleVo.setAuthor(sysUserService.findSysUserByAuthorId(authorId).getNickname());}return articleVo;}
}

pojo类代码

package com.runze.blog.dao.pojo;import lombok.Data;@Data
public class Article {public static final int Article_TOP = 1;public static final int Article_Common = 0;private Long id;private String title;private String summary;private int commentCounts;private int viewCounts;/*** 作者id*/private Long authorId;/*** 内容id*/private Long bodyId;/***类别id*/private Long categoryId;/*** 置顶*/private int weight = Article_Common;/*** 创建时间*/private Long createDate;}
package com.runze.blog.dao.pojo;
import lombok.Data;@Data
public class SysUser {private Long id;private String account;private Integer admin;private String avatar;private Long createDate;private Integer deleted;private String email;private Long lastLogin;private String mobilePhoneNumber;private String nickname;private String password;private String salt;private String status;
}
package com.runze.blog.dao.pojo;import lombok.Data;@Data
public class Tag {private Long id;private String avatar;private String tagName;}

根据文章id获取作者以及文章标签,多表查询,其mapper文件如下

<?xml version="1.0" encoding="UTF-8" ?>
<!--MyBatis配置文件-->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.runze.blog.dao.mapper.SysUserMapper"><select id="findSysUserByArticleId" parameterType="long" resultType="com.runze.blog.dao.pojo.SysUser">SELECT</select>
</mapper>
<?xml version="1.0" encoding="UTF-8" ?>
<!--MyBatis配置文件-->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.runze.blog.dao.mapper.TagMapper"><select id="findTagsByArticleId" parameterType="long" resultType="com.runze.blog.dao.pojo.Tag">SELECT id,avatar,tag_name as tagNamefrom ms_tagWHERE id IN(SELECT tag_id from ms_article_tag WHERE article_id=#{articleId})</select>

第二天查询最热标签

查询最热标签需要进行多表查询,首先获取article表的最多文章的前几个标签的tag_id,再根据标签id获取tabName即可,
controller层的代码

package com.runze.blog.controller;import com.runze.blog.service.TagService;
import com.runze.blog.vo.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("tags")
public class TagController {@Autowiredprivate TagService tagService;@GetMapping("hot")public Result hot(){//创建最热标签的数量int limit=3;return tagService.hot(limit);}
}

service层代码如下

    @Overridepublic Result hot(int limit) {//标签拥有的文化数量最多称为最热标签List<Long> tagIds=tagMapper.findHotsTags(limit);//得到ids之后查询tag,先进行判断是否为空,如果为空,返回一个空列表if(CollectionUtils.isEmpty(tagIds)){return Result.success(Collections.emptyList());}List<Tag> tagList=tagMapper.findTagByIds(tagIds);return Result.success(tagList);}

mapper.xml如下

<select id="findHotsTags" parameterType="int" resultType="java.lang.Long">SELECT tag_id  FROM ms_article_tag GROUP BY tag_id ORDER BY COUNT(*) DESC LIMIT #{limit}</select><select id="findTagByIds" parameterType="list" resultType="com.runze.blog.dao.pojo.Tag">select id,tag_name as tagName from ms_tagwhere id in<foreach collection="tagIds" item="tagId" separator="," open="(" close=")">#{tagId}</foreach></select></mapper>

第三天

  • 查询最热文章
@PostMapping("hot")public Result hot(){int limit=5;return articleServiceImpl.hotArticle(limit);}
@PostMapping("hot")public Result hot(){int limit=5;return articleServiceImpl.hotArticle(limit);}
    @Overridepublic Result hotArticle(int limit) {LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();//根据浏览量排序queryWrapper.orderByDesc(Article::getViewCounts);//查询id与titlequeryWrapper.select(Article::getId,Article::getTitle);//在sql语句的后来加上查询的数量queryWrapper.last("limit "+limit);List<Article> articles = articleMapper.selectList(queryWrapper);return Result.success(copyArticle(articles,false,false));}
  • 最新文章与最热文章类似,不做赘述
  • 文章归档
    @PostMapping("listArchives")public Result listArchives(){return articleServiceImpl.listArchives();}
    @Overridepublic Result listArchives() {List<Archives> archives=articleMapper.listArchives();return Result.success(archives);}
<mapper namespace="com.runze.blog.dao.mapper.ArticleMapper"><select id="listArchives" resultType="com.runze.blog.dao.dos.Archives">SELECT year(FROM_UNIXTIME(create_date/1000)) as year,month(FROM_UNIXTIME(create_date/1000)) as month,COUNT(*) as account from ms_articlegroup by year,month</select>
</mapper>

RunZeBlog项目开发流程相关推荐

  1. 对 VR 项目开发流程的调研

    0. 参考资料 学习参考自以下资料: 一个 VR 游戏 DEMO 的开发历程是怎样的 http://tech.163.com/16/0726/08/BSSSPPT600097U7U.html 虚拟现实 ...

  2. 软件项目开发流程及配置人员

    项目需求汇总分析 架构设计 产品设计 代码编写 项目测试 上线 项目需求汇总分析(调研) 项目经理 在这个阶段,上项目经理应该先要求客户(项目发起人)提供一个项目需求及要求明细的清单. 清楚需求及项目 ...

  3. 小型软件项目开发流程探讨

    一.导言   国内很多项目都是小型项目, 参与人员少(两到五个人), 要快速交付(一两个月) . 要成功完成这种项目, 除了使用成熟且被团队成员熟练使用的技术之外, 有一个良好的开发流程, 也是很必要 ...

  4. Java-GUI编程实战之管理系统 Day1【项目开发流程、软件三层架构、项目需求、项目结构分析】

    视频.课件.源码[链接:https://pan.baidu.com/s/13ffqGDzH-DZib6-MFViW3Q 提取码:zjxs] Java-GUI编程实战之管理系统 Day1[项目开发流程. ...

  5. 项目开发流程_绿维文旅:旅游项目开发模式与流程

    一.旅游项目开发模式 旅游综合开发是立足旅游项目自有资源基础,以旅游产业为主导,以市场为导向,以资本为驱动,以资源整合为核心,通过集中土地.资本.技术.交通.劳动力等生产要素,推进土地开发.交通建设. ...

  6. 软件项目开发流程以及人员职责

    软件项目开发流程以及人员职责 实行软件工程项目管理: ▲ 项目经理(负责人):项目经理(负责人)对整个项目负完全责任,是指导.控制.管理和规范某个软件和软/硬件系统建设的人,项目经理(负责人)是最终对 ...

  7. 移动端电商项目开发流程

    目录 项目介绍 项目页面介绍 项目开发流程 首页介绍: 搜索页: 搜索页: 项目打包优化上线: 这是我自己写的一个电商开发流程,欢迎大家来补充! 项目介绍 我的项目叫✖✖✖✖,是B2C模式,也就是商家 ...

  8. SpringMVC+Mybatis框架集成开发基础——项目开发流程——01

    项目开发一般流程: 1.描述项目的主要功能及各个模块的功能 2.系统采用的技术方案 3.创建E-R模型图(实体关系模型图,数据库)​​​​​​ 4.搭建数据库环境.创建数据库表及表间约束 5.搭建项目 ...

  9. 技术总监之路——App项目开发流程

    App项目开发流程 一. 需求阶段 1. 初期由leader或者项目责任人和PM沟通下阶段开发计划,确认需求的可行性和优先级等初步达成共识 2. 接下来PM提供详细UE文档(需求颗粒感尽可能小)发起三 ...

最新文章

  1. hive mysql 远程_ubuntu中为hive配置远程MYSQL database
  2. 那些顶级的AI机器人“大脑”
  3. 预加载系列一:DNS Prefetching 的正确使用姿势
  4. OssImport系列之四——最佳实践
  5. 构建Flex数据服务程序
  6. Win32汇编基本编程框架
  7. mysql删除端口配置文件,linux中的Mysql的安装、重置安装密码、修改权限详解
  8. U3D的飞船太空射击例子中,使用coroutine
  9. php实战搭建博客,yii2项目实战-博客管理平台的搭建
  10. mysql 即学a又学b_MySQL学习第一天
  11. 嵌入式OS入门笔记-以RTX为案例:一.简介
  12. 开启Hive的本地模式
  13. vptr初始化语义学
  14. layui表格工具条
  15. 基于uniapp的个人课程表
  16. 【上海落户-个人感受】想到一个城市落户,需要提前打算。
  17. 探索 ES8 Object.entries()
  18. JavaWeb - 软件开发的流程,综合案例
  19. 使用css3 filter属性实现图片毛玻璃效果
  20. DB2的HADR的搭建

热门文章

  1. 苹果手机量体温_用手机可以量体温?反派不能用 iPhone?奇怪的知识又增加了.........
  2. 要么读书,要么健身,要么恋爱(一)偷影子的人
  3. 编程自救指南--0x01 第一章 你真的了解你的专业吗 ?
  4. 手机信息不小心删了怎么恢复?2个简单的方法
  5. linux media player
  6. 零基础学Python应该学习哪些入门知识
  7. MATLAB程序采用非支配排序遗传算法(NSGA2)求解分布式电源选址定容问题,可作为一个有用的参考,程序注释明确,算法原理可以自己搜。
  8. 开发婚庆APP需要的功能
  9. Servlet的体系结构(一张图清晰明了)
  10. redis操作map