springboot实战项目——个人博客系统

1.项目介绍

1.1项目效果

博客首页

登录功能 

 

注册功能

文章分类 

 

文章归档 

文章页面 

  

发布文章 (集成富文本编译器)

 

 1.2项目使用技术

前端:

  • vue
  • element-ui

 后端:

  • Springboot
  • mybatis-plus
  • redis
  • mysql
  • jwt

2.工程搭建

2.1新建springboot项目

2.2在maven中导入相关依赖

<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>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <dependency>
            <groupId>com.qiniu</groupId>
            <artifactId>qiniu-java-sdk</artifactId>
            <version>[7.7.0, 7.7.99]</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</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>

        <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.76</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>

        <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>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.3</version>
        </dependency>

        <dependency>
            <groupId>joda-time</groupId>
            <artifactId>joda-time</artifactId>
            <version>2.10.10</version>
        </dependency>

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>

        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
            <version>1.15</version>
        </dependency>
        <dependency>
            <groupId>commons-collections</groupId>
            <artifactId>commons-collections</artifactId>
            <version>3.2.2</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

        <!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt -->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>

    </dependencies>

 2.3配置文件

mybatis-plus分页插件

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.leggasai.dao.mapper")
public class MybatisPlusConfig {
    //分页插件
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return interceptor;
    }
}

跨域配置文件

import com.leggasai.handler.LoginInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
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 {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        //跨域配置
        registry.addMapping("/**")
                .allowedOrigins("http://localhost:8080")
                .allowedMethods("GET","POST","PUT","OPTIONS","DELETE")
                .allowCredentials(true)
                .maxAge(3600);
    }
}

springboot配置文件 application.yml

server:
  port: 8888


spring:
  datasource:
    username: "mysql用户名"
    password: "mysql密码"
    url: jdbc:mysql://localhost:3306/blog?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
    driver-class-name: com.mysql.cj.jdbc.Driver
  redis:
    host: localhost
    port: 6379
  servlet:
    multipart:
      max-file-size: 2MB
      max-request-size: 20MB

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
#mysql中表前缀为ms_
  global-config:
    db-config:
      table-prefix: ms_
  type-aliases-package: com.leggasai.dao.pojo
  mapper-locations: classpath*:mapper/*.xml

2.4特殊类

异常类:用于统一处理异常

package com.leggasai.handler;


import com.leggasai.vo.Result;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

//对加了@controller注解的方法进行拦截处理 Aop的实现
@ControllerAdvice
public class AllExceptionHandler {
    @ExceptionHandler(Exception.class)
    @ResponseBody//返回json数据
    public Result doException(Exception ex){
        ex.printStackTrace();
        return Result.fail(-999, "系统异常");
    }
}

返回结果类:用于给前端返回数据 

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
//返回结果类
public class Result {
    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);
    }
}

异常码类:枚举类,用于显示不同的出错提示 

package com.leggasai.vo;

public enum  ErrorCode {

    PARAMS_ERROR(10001,"参数有误"),
    ACCOUNT_PWD_NOT_EXIST(10002,"用户名或密码不存在"),
    TOKEN_ERROR(10003,"token不合法"),
    ACCOUNT_EXISTED(10004,"账号已存在"),

    NO_PERMISSION(70001,"无访问权限"),
    SESSION_TIME_OUT(90001,"会话超时"),
    NO_LOGIN(90002,"未登录"),
    UPLOAD_ERROR(20001,"上传失败"),;
    private int code;
    private String msg;

    ErrorCode(int code, String msg){
        this.code = code;
        this.msg = msg;
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }
}

3.数据库搭建 

在sqlyog(或navicat)中新建名为blog的数据库

3.1表一:ms_article文章表

CREATE TABLE `blog`.`ms_article`  (
  `id` bigint(0) NOT NULL AUTO_INCREMENT,
  `comment_counts` int(0) NULL DEFAULT NULL COMMENT '评论数量',
  `create_date` bigint(0) NULL DEFAULT NULL COMMENT '创建时间',
  `summary` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '简介',
  `title` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '标题',
  `view_counts` int(0) NULL DEFAULT NULL COMMENT '浏览数量',
  `weight` int(0) NOT NULL COMMENT '是否置顶',
  `author_id` bigint(0) NULL DEFAULT NULL COMMENT '作者id',
  `body_id` bigint(0) NULL DEFAULT NULL COMMENT '内容id',
  `category_id` int(0) NULL DEFAULT NULL COMMENT '类别id',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 25 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

 3.2表二:ms_article_body文章内容表

drop table if exists `ms_article_body`;
create table `ms_article_body`  (
  `id` bigint(0) not null auto_increment,
  `content` longtext character set utf8 collate utf8_general_ci null,
  `content_html` longtext character set utf8 collate utf8_general_ci null,
  `article_id` bigint(0) not null,
  primary key (`id`) using btree,
  index `article_id`(`article_id`) using btree
) engine = innodb auto_increment = 1405916999854342147 character set = utf8 collate = utf8_general_ci row_format = dynamic;

 3.3表三:ms_article_tag关联表

 这个表是用于关联article表和tag表(文章标签表)

drop table if exists `ms_article_tag`;
create table `ms_article_tag`  (
  `id` bigint(0) not null auto_increment,
  `article_id` bigint(0) not null,
  `tag_id` bigint(0) not null,
  primary key (`id`) using btree,
  index `article_id`(`article_id`) using btree,
  index `tag_id`(`tag_id`) using btree
) engine = innodb auto_increment = 1405916999787233282 character set = utf8 collate = utf8_general_ci row_format = dynamic;

3.4表四:ms_sys_user用户表

drop table if exists `ms_sys_user`;
create table `ms_sys_user`  (
  `id` bigint(0) not null auto_increment,
  `account` varchar(64) character set utf8 collate utf8_general_ci null default null comment '账号',
  `admin` bit(1) null default null comment '是否管理员',
  `avatar` varchar(255) character set utf8 collate utf8_general_ci null default null comment '头像',
  `create_date` bigint(0) null default null comment '注册时间',
  `deleted` bit(1) null default null comment '是否删除',
  `email` varchar(128) character set utf8 collate utf8_general_ci null default null comment '邮箱',
  `last_login` bigint(0) null default null comment '最后登录时间',
  `mobile_phone_number` varchar(20) character set utf8 collate utf8_general_ci null default null comment '手机号',
  `nickname` varchar(255) character set utf8 collate utf8_general_ci null default null comment '昵称',
  `password` varchar(64) character set utf8 collate utf8_general_ci null default null comment '密码',
  `salt` varchar(255) character set utf8 collate utf8_general_ci null default null comment '加密盐',
  `status` varchar(255) character set utf8 collate utf8_general_ci null default null comment '状态',
  primary key (`id`) using btree
) engine = innodb auto_increment = 1404448588146192387 character set = utf8 collate = utf8_general_ci row_format = dynamic;

3.5表五: ms_tag文章标签表

drop table if exists `ms_tag`;
create table `ms_tag`  (
  `id` bigint(0) not null auto_increment,
  `avatar` varchar(255) character set utf8mb4 collate utf8mb4_unicode_ci null default null,
  `tag_name` varchar(255) character set utf8mb4 collate utf8mb4_unicode_ci null default null,
  primary key (`id`) using btree
) engine = innodb auto_increment = 11 character set = utf8 collate = utf8_general_ci row_format = dynamic;

3.6表六:ms_comment评论表 

drop table if exists `ms_comment`;
create table `ms_comment`  (
  `id` bigint(0) not null auto_increment,
  `content` varchar(255) character set utf8mb4 collate utf8mb4_unicode_ci not null,
  `create_date` bigint(0) not null,
  `article_id` int(0) not null,
  `author_id` bigint(0) not null,
  `parent_id` bigint(0) not null,
  `to_uid` bigint(0) not null,
  `level` varchar(1) character set utf8 collate utf8_general_ci not null,
  primary key (`id`) using btree,
  index `article_id`(`article_id`) using btree
) engine = innodb auto_increment = 1405209691876790275 character set = utf8 collate = utf8_general_ci row_format = dynamic;

3.7表七: ms_category类别表

drop table if exists `ms_category`;
create table `ms_category`  (
  `id` bigint(0) not null auto_increment,
  `avatar` varchar(255) character set utf8mb4 collate utf8mb4_unicode_ci null default null,
  `category_name` varchar(255) character set utf8mb4 collate utf8mb4_unicode_ci null default null,
  `description` varchar(255) character set utf8mb4 collate utf8mb4_unicode_ci null default null,
  primary key (`id`) using btree
) engine = innodb auto_increment = 6 character set = utf8 collate = utf8_general_ci row_format = dynamic;

4.首页功能

4.1文章列表实现

效果图

 

4.1.1pojo类 

 1.建立pojo类——article

package com.leggasai.dao.pojo;


import lombok.Data;

@Data
public class Article {
    public static final int Article_TOP=1;//是否指定,默认是
    public static final int Article_Common=0;//默认评论数0
    private Long id;//文章id
    private String title;//文章标题
    private String summary;//文章简介
    private Integer commentCounts;//文章评论数
    private Integer viewCounts;//文章阅读数
    private Long authorId;//作者id
    private Long bodyId;//文章内容id
    private Long categoryId;//文章类别id
    private Integer weight=Article_Common;//文章权重
    private Long createDate;//文章创建时间
}

 2.建立pojo类——sysUser用户类

package com.leggasai.dao.pojo;


import lombok.Data;

@Data
public class SysUser {
    private Long id;//用户id
    private String account;//用户账号
    private String password;//用户密码
    private Integer admin;//是否管理员
    private String avatar;//用户头像地址
    private Long createDate;//用户创建时间
    private Integer deleted;//是否被删除
    private String email;//用户邮箱
    private Long lastLogin;//用户最后一次登录时间
    private String nickname;//用户昵称
    private String mobilePhoneNumber;//用户手机号
    private String salt;//加密盐
    private String status;//用户状态

}

3.建立pojo类——tag标签类 

package com.leggasai.dao.pojo;
import lombok.Data;
@Data
public class Tag {
    private Long id;//标签id
    private String avatar;//标签图片地址
    private String tagName;//标签名
}

4.建立vo类——articleVo:前端显示类往往和数据库中的类有差别 


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;

}

4.1.2controller类

ArticleController类:用于处理和article相关业务

import java.util.List;

@RestController
@RequestMapping("articles")
public class ArticleController {

    @Autowired
    private ArticleService articleService;
	//Result是统一结果返回
    @PostMapping
    public Result articles(@RequestBody PageParams pageParams) {
        //ArticleVo 页面接收的数据
        List<ArticleVo> articles = articleService.listArticlesPage(pageParams);

        return Result.success(articles);
    }


}

 4.1.3service类

ArticleService接口与ArticleServiceImpl实现类

import java.util.List;

public interface ArticleService {

    List<ArticleVo> listArticlesPage(PageParams pageParams);

}
package com.leggasai.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.leggasai.common.aop.LogAnnotation;
import com.leggasai.dao.dos.Archives;
import com.leggasai.dao.mapper.ArticleBodyMapper;
import com.leggasai.dao.mapper.ArticleMapper;
import com.leggasai.dao.mapper.ArticleTagMapper;
import com.leggasai.dao.pojo.Article;
import com.leggasai.dao.pojo.ArticleBody;
import com.leggasai.dao.pojo.ArticleTag;
import com.leggasai.dao.pojo.SysUser;
import com.leggasai.service.*;
import com.leggasai.utils.UserThreadLocal;
import com.leggasai.vo.ArticleBodyVo;
import com.leggasai.vo.ArticleVo;
import com.leggasai.vo.Result;
import com.leggasai.vo.TagVo;
import com.leggasai.vo.params.ArticleParam;
import com.leggasai.vo.params.PageParams;
import net.sf.jsqlparser.expression.DateTimeLiteralExpression;
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.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class ArticleServiceImpl implements ArticleService {
    @Autowired
    private ArticleMapper articleMapper;
   @Autowired
   private SysUserService sysUserService;
    @Autowired
    private TagsService tagsService;

    public ArticleVo copy(Article article,boolean isAuthor,boolean isBody,boolean isTags){
        ArticleVo articleVo = new ArticleVo();
        BeanUtils.copyProperties(article, articleVo);
        if (isAuthor) {
            SysUser sysUser = sysUserService.findSysUserById(article.getAuthorId());
            articleVo.setAuthor(sysUser.getNickname());
        }
        articleVo.setCreateDate(new DateTime(article.getCreateDate()).toString("yyyy-MM-dd HH:mm"));
        if (isTags){
           List<TagVo> tags = tagsService.findTagsByArticleId(article.getId());
           articleVo.setTags(tags);
        }
        return articleVo;
    }

    private List<ArticleVo> copyList(List<Article> records,boolean isAuthor,boolean isBody,boolean isTags) {
        List<ArticleVo> articleVoList = new ArrayList<>();
        for (Article article : records) {
            ArticleVo articleVo = copy(article,isAuthor,isBody,isTags);
            articleVoList.add(articleVo);
        }
        return articleVoList;
    }


    @Override
    public List<ArticleVo> listArticlesPage(PageParams pageParams) {
        QueryWrapper<Article> queryWrapper = new QueryWrapper<>();
        Page<Article> page = new Page<>(pageParams.getPage(),pageParams.getPageSize());
        Page<Article> articlePage = articleMapper.selectPage(page, queryWrapper);
        List<ArticleVo> articleVoList = copyList(articlePage.getRecords(),true,false,true);
        return articleVoList;
    }


}

sysUserService和sysUserServiceImpl 

public interface UserService {

    SysUser findUserById(Long userId);
}
package com.leggasai.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.leggasai.dao.mapper.SysUserMapper;
import com.leggasai.dao.pojo.SysUser;
import com.leggasai.service.LoginService;
import com.leggasai.service.SysUserService;
import com.leggasai.vo.ErrorCode;
import com.leggasai.vo.LoginUserVo;
import com.leggasai.vo.Result;
import com.leggasai.vo.UserVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private SysUserMapper sysUserMapper;

    @Override
    public SysUser findUserById(Long userId) {
        SysUser sysUser = sysUserMapper.selectById(userId);
        if (sysUser == null) {
            sysUser = new SysUser();
            sysUser.setNickname("码神之路");
        }
        return sysUser;
    }
}

tagService和tagServiceImpl 

package com.leggasai.service;

import com.leggasai.vo.Result;
import com.leggasai.vo.TagVo;

import java.util.List;

public interface TagService {
    List<TagVo> findTagsByArticleId(Long articleId);
}
package com.leggasai.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.leggasai.dao.mapper.TagMapper;
import com.leggasai.dao.pojo.Tag;
import com.leggasai.service.TagService;
import com.leggasai.vo.Result;
import com.leggasai.vo.TagVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;


@Service
public class TagServiceImpl implements TagService {
    @Autowired
    private TagMapper tagMapper;
    @Override
    public List<TagVo> findTagsByArticleId(Long articleId) {
        //mybatis-plus无法进行多表查询
        List<Tag> tags=tagMapper.findTagsByArticleId(articleId);
        return copyList(tags);
    }


    public TagVo copy(Tag tag){
        TagVo tagVo=new TagVo();
        BeanUtils.copyProperties(tag,tagVo);
        tagVo.setId(String.valueOf(tag.getId()));
        return tagVo;
    }
    public List<TagVo> copyList(List<Tag> tagList){
        List<TagVo> tagVoList = new ArrayList<>();
        for (Tag tag : tagList) {
            tagVoList.add(copy(tag));
        }
        return tagVoList;
    }



}

4.1.4dao层

ArticleMapper接口

package com.leggasai.dao.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.leggasai.dao.dos.Archives;
import com.leggasai.dao.pojo.Article;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;

import java.util.List;
@Mapper
public interface ArticleMapper extends BaseMapper<Article> {
    List<Archives> listArchives();

    IPage<Article> listArticle(Page<Article> page,
                               Long categoryId,
                               Long tagId,
                               String year,
                               String month);
}

SysUserMapper接口 

package com.leggasai.dao.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.leggasai.dao.pojo.SysUser;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;

@Mapper
public interface SysUserMapper extends BaseMapper<SysUser> {
}

TagMapper接口 

package com.leggasai.dao.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.leggasai.dao.pojo.Tag;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;


import java.util.List;
@Mapper
public interface TagMapper extends BaseMapper<Tag> {
    /*
    根据文章id查询标签列表
     */
    List<Tag> findTagsByArticleId(Long articleId);

   
}

 TagMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!--中文错误改成UTF8即可-->
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.leggasai.dao.mapper.TagMapper">
<!--    List<Tag> findTagsByArticleId(Long articleId);-->
    <select id="findTagsByArticleId" parameterType="long" resultType="com.leggasai.dao.pojo.Tag">
        select id,avatar,tag_name as tagName from ms_tag
        where id in (select tag_id from ms_article_tag where article_id=#{articleId})
    </select>

</mapper>

4.2首页最热标签功能

 4.2.1前端接口

接口url:/tags/hot

请求方式:GET

请求参数:无

返回数据:

{
    "success": true,
    "code": 200,
    "msg": "success",
    "data": [
        {
            "id":1,
            "tagName":"4444"
        }
    ]
}

4.2.2controller类

    @GetMapping("/hot")
    public Result hot(){
        int limit =6;
        Result hots = tagService.hots(limit);
        return hots;
    }

4.2.3service层

    Result hots(int limit);
    @Override
    public Result hots(int limit) {
        /*
        标签所拥有的文章数量做多,就是最热标签
         */
        List<Long> tagIds=tagMapper.findHotsTagIds(limit);
        if(CollectionUtils.isEmpty(tagIds)){
            return Result.success(Collections.emptyList());
        }
        //需要的是tagId和tagName
        List<Tag> tagList=tagMapper.findTagesByTagIds(tagIds);
        //System.out.println("最热标签");
        //System.out.println(tagList);
        return Result.success(tagList);
    }

4.2.4mapper层

    <select id="findHotsTagIds" 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="findTagesByTagIds" parameterType="list" resultType="com.leggasai.dao.pojo.Tag">
        select id,tag_name as tagName from ms_tag
        where id in
        <foreach collection="tagIds" item="tagId" separator="," open="(" close=")">
            #{tagId}
        </foreach>
    </select>

4.3首页最热文章功能

 

后续可以用cache优化

4.3.1前端接口

接口url:/articles/hot

请求方式:POST

请求参数:

返回数据:

{
    "success": true,
    "code": 200,
    "msg": "success",
    "data": [
        {
            "id": 1,
            "title": "springboot介绍以及入门案例",
        },
        {
            "id": 9,
            "title": "Vue.js 是什么",
        },
        {
            "id": 10,
            "title": "Element相关",
            
        }
    ]
}

4.3.2controller层

    @PostMapping("/hot")
    public Result hotArticle(){
        int limit =5;
        return articleService.hotArticle(limit);
    }

4.3.3service层

    @Override
    public Result hotArticle(int limit) {
        LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.orderByDesc(Article::getViewCounts);
        queryWrapper.select(Article::getId,Article::getTitle);
        queryWrapper.last("limit "+limit);
        //select id,title from article order by view_counts desc limit 5
        List<Article> articles = articleMapper.selectList(queryWrapper);
        return Result.success(copyList(articles,false,false));
    }

4.4首页最新文章功能

 

后续可以用cache优化 

4.4.1前端接口

接口url:/articles/new

请求方式:POST

请求参数:

返回数据:

{
    "success": true,
    "code": 200,
    "msg": "success",
    "data": [
        {
            "id": 1,
            "title": "springboot介绍以及入门案例",
        },
        {
            "id": 9,
            "title": "Vue.js 是什么",
        },
        {
            "id": 10,
            "title": "Element相关",
            
        }
    ]
}

4.4.2controller层

    @PostMapping("/new")
    public Result newArticles(){
        int limit =5;
        return articleService.newArticles(limit);
    }

4.4.3service层

    @Override
    public Result newArticles(int limit) {
        LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.orderByDesc(Article::getCreateDate);
        queryWrapper.select(Article::getId,Article::getTitle);
        queryWrapper.last("limit "+limit);
        //select id,title from article order by create_date desc limit 5
        List<Article> articles = articleMapper.selectList(queryWrapper);
        return Result.success(copyList(articles,false,false));
    }

4.5首页文章归档功能

 

4.5.1前端接口

接口url:/articles/listArchives

请求方式:POST

请求参数:

返回数据:

{
    "success": true,
    "code": 200,
    "msg": "success",
    "data": [
        {
            "year": "2021",
            "month": "6",
            "count": 2
        }
            
    ]

}

4.5.2controller层

    @PostMapping("listArchives")
    public Result listArchives(){
        return articleService.listArchives();
    }

4.5.3service层

    @Override
    public Result listArchives() {
        List<Archives> archivesList=articleMapper.listArchives();
        return Result.success(archivesList);
    }

4.5.4mapper层 

    List<Archives> listArchives();

注意数据库中create_date是时间戳,需要使用FROM_UNIXTIME转化为xxxx年xx月的格式!

    <select id="listArchives" resultType="com.leggasai.dao.dos.Archives">
        select FROM_UNIXTIME(create_date/1000,'%Y') as year,FROM_UNIXTIME(create_date/1000,'%m') as month,COUNT(*) as COUNT
        from ms_article group by year,month
    </select>

 Archives类

package com.leggasai.dao.dos;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Archives {

    private Integer year;
    private Integer month;
    private Long count;

}

5.登录功能

5.1jwt技术

5.2退出功能

5.3注册功能

5.4登录拦截器

5.5ThreadLocal使用

未完待续~

核心功能 文章/图片/视频发布、喜欢、统计阅读次数。 文章标签tag功能、支持按tag分类 文章支持ueditor/markdown编辑器切换(后台配置) 评论功能,支持回复,支持表情。 第三方(微博、QQ)登录。 lucene实现的站内搜索。 响应式布局 支持用户订阅 先看效果图 SpringBoot开发非常美观的java博客系统(包含后台管理功能) SpringBoot开发非常美观的java博客系统(包含后台管理功能) SpringBoot开发非常美观的java博客系统(包含后台管理功能) http://localhost:8080/admin/group/list SpringBoot开发非常美观的java博客系统(包含后台管理功能) SpringBoot开发非常美观的java博客系统(包含后台管理功能)SpringBoot开发非常美观的java博客系统(包含后台管理功能) 技术选型: JDK8 数据库MySQL 主框架 (Spring-bootSpring-data-jpa) 安全权限 Shiro 搜索工具 Lucene 缓存 Ehcache 视图模板 Freemarker 其它 Jsoup、fastjson jQuery、Seajs Bootstrap 前端框架 UEditor/Markdown编辑器 font-Awesome 字体/图标 准备工作(sql文件在项目里面) 安装 Jdk8 安装 Maven 准备 IDE (如果你不看源码,可以忽略下面的步骤,直接通过Maven编译war包:mvn clean package -DskipTests) IDE 需要配置的东西 编码方式设为UTF-8 配置Maven 设置Jdk8 关于这些配置,网上有一大把的资料,所以此处不再重复。 获取代码导入到IDE 下载代码 导入到IDE的时候请选择以Maven的方式导入 项目配置参考 系统配置手册 配置完毕 启动项目,在控制台看到Mblog加载完毕的信息后,表示启动成功 打开浏览器输入:http//localhost/mblog/ (此处仅是示例,具体具体端口因人而异),访问成功即部署完毕 后台管理的地址是 /admin, 如果你是管理员账号点导航栏的头像会看到"后台管理" 启动成功后,你应该去后台的系统配置里配置你的网站信息等。 常见问题总结 进入系统后, 菜单加载不出来, 那应该是你没有导 db_init.sql 点标签显示乱码, 请设置Tomcat的 URIEncoding 为 UTF-8 项目截图 SpringBoot开发非常美观的java博客系统(包含后台管理功能) 转自:https://gitee.com/mtons/mblog SpringBoot开发非常美观的java博客系统(包含后台管理功能) 注意: 一、java main方式运行mblog-web下的BootApplication.java时抛出异常的解决方案 Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean. SpringBoot开发非常美观的java博客系统(包含后台管理功能) 注释掉后下面图片的这段后,记得maven要重新reimport SpringBoot开发非常美观的java博客系统(包含后台管理功能) SpringBoot开发非常美观的java博客系统(包含后台管理功能) 否则maven依赖不生效还是会抛出以上的异常 二、第三方登录点击后无响应,那是因为第三方开放平台回调的url失效导致,需要你去对应的第三方开放平台注册app后获取对应的oauth帐号 SpringBoot开发非常美观的java博客系统(包含后台管理功能) 三、idea以maven项目导入该项目后,发现没有maven的依赖包时,需要对每个maven module进行clear和install,并且注意maven的依赖顺序 SpringBoot开发非常美观的java博客系统(包含后台管理功能) SpringBoot开发非常美观的java博客系统(包含后台管理功能) 四、访问地址是http://localhost:8080 登录时,帐号,密码只要自己找个密码,然后md5下在更新到db中即可登录成功。 比如:zuidaima 111111,md5后密码是 3931MUEQD1939MQMLM4AISPVNE,md5的javaSpringBoot开发非常美观的java博客系统(包含后台管理功能) SpringBoot开发非常美观的java博客系统(包含后台管理功能)
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Leg丶Gasai

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值