SpringBoot+vue练手项目---博客系统

本文档详细介绍了使用SpringBoot、Vue构建博客系统的全过程,涵盖工程搭建、前后端交互、分页、跨域配置、登录注册、权限管理、AOP日志、缓存处理、七牛云图片上传等多个方面,旨在提供一个完整的练手项目。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SpringBoot+vue练手项目---博客系统


项目使用技术 :

springboot + mybatisplus+redis+mysql+jwt

项目讲解:https://www.bilibili.com/video/BV1Gb4y1d7zb?p=1

1. 工程搭建


前端的工程地址:

链接:https://pan.baidu.com/s/1cg_11ctsbbq_WM9BnpcOaQ 提取码:nrun

npm install

npm run build

npm run dev

1.1 新建maven工程

pom.xml(blog-parent)

<?xmlversion="1.0" encoding="UTF-8"?>

<projectxmlns="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 " target="_blank">http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<groupId>com.jihu</groupId>

<artifactId>blog-parent</artifactId>

<version>1.0-SNAPSHOT</version>

<modules>

<module>blog-api</module>

</modules>

<!--声明pom代表他是一个父工程-->

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

<dependencies>

<dependency>

<groupId>com.alibaba</groupId>

<artifactId>fastjson</artifactId>

<version>1.2.76</version>

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

<!-- https://mvnrepository.com/artifact/joda-time/joda-time -->

<dependency>

<groupId>joda-time</groupId>

<artifactId>joda-time</artifactId>

<version>2.10.10</version>

</dependency>

</dependencies>

</dependencyManagement>

<build>

<plugins>

<plugin>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-maven-plugin</artifactId>

</plugin>

</plugins>

</build>

</project>

pom.xml(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 " target="_blank">http://maven.apache.org/xsd/maven-4.0.0.xsd">

<parent>

<artifactId>blog-parent</artifactId>

<groupId>com.jihu</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>

1.2 application.yml

server:

port: 8888

spring:

application:

name: jihu

#数据库的配置

datasource:

url: jdbc:mysql://localhost:3306/blog?useUnicode=true&characterEncoding=UTF-8&serverTimeZone=UTC

username: root

password: 123456

driver-class-name: com.mysql.cj.jdbc.Driver

#mybatis-plus

mybatis-plus:

configuration:

log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #打印日志 如sql语句

global-config:

db-config:

table-prefix: ms_ #标识表的前缀为ms_

#指定mapper文件的位置

mybatis-plus:

config-location: classpath:mapper/*.xml

1.3 配置 分页 和跨域

分页

package com.jihu.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

//扫包,将此包下的接口生成代理实现类,并且注册到spring容器中

@MapperScan("com.jihu.blog.mapper")

public class MybatisPlusConfig {

//分页插件

@Bean

public MybatisPlusInterceptor mybatisPlusInterceptor(){

MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();

interceptor.addInnerInterceptor(new PaginationInnerInterceptor());

return interceptor;

}

}

跨域

package com.jihu.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 {

//实现跨域请求

@Override

public void addCorsMappings(CorsRegistry registry) {

registry.addMapping("/**")

.allowedOriginPatterns("*")

.allowedMethods("GET","HEAD","POST","PUT","DELETE","OPTIONS")

.allowCredentials(true)

.maxAge(3600)

.allowedHeaders("*");

}

}

1.4启动类

package com.jihu.blog;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication

public class BlogApp {

public static void main(String[] args) {

SpringApplication.run(BlogApp.class,args);

}

}

2.首页-文章列表


2.1 接口说明

接口url:/articles

请求方式:POST

请求参数:

参数名称

参数类型

说明

page

int

当前页数

pageSize

int

每页显示的数量

返回数据:

{

"success": true,

"code": 200,

"msg": "success",

"data": [

{

"id": 1,

"title": "springboot介绍以及入门案例",

"summary": "通过Spring Boot实现的服务,只需要依靠一个Java类,把它打包成jar,并通过`java -jar`命令就可以运行起来。\r\n\r\n这一切相较于传统Spring应用来说,已经变得非常的轻便、简单。",

"commentCounts": 2,

"viewCounts": 54,

"weight": 1,

"createDate": "2609-06-26 15:58",

"author": "12",

"body": null,

"tags": [

{

"id": 5,

"avatar": null,

"tagName": "444"

},

{

"id": 7,

"avatar": null,

"tagName": "22"

},

{

"id": 8,

"avatar": null,

"tagName": "11"

}

],

"categorys": null

}

]

}

2.2 编码

Spring基于注解的开发每个注解的作用

2.2.1 表结构

文章表

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;

标签表

id,文章id,标签id,通过文章id可以间接查到标签id

CREATE TABLE `blog`.`ms_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 = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

用户表

CREATE TABLE `blog`.`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 = 16 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

2.2.2 entity层
Article 文章实体类

package com.jihu.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;

}

SysUser 用户实体类

package com.jihu.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;

}

Tag 标签实体类

package com.jihu.blog.dao.pojo;

import lombok.Data;

@Data

public class Tag {

private Long id;

private String avatar;

private String tagName;

}

2.2.3 Controller层
ArticleController

package com.jihu.blog.controller;

import com.jihu.blog.service.ArticleService;

import com.jihu.blog.vo.Result;

import com.jihu.blog.vo.params.PageParams;

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 {

@Autowired

private ArticleService articleService;

//首页 文章列表

@PostMapping

public Result listArticle(@RequestBody PageParams pageParams){

//ArticleVo 页面接收的数据

return articleService.listArticle(pageParams);

}

}

2.2.4 Service层
ArticleService

package com.jihu.blog.service;

import com.jihu.blog.vo.Result;

import com.jihu.blog.vo.params.PageParams;

public interface ArticleService {

Result listArticle(PageParams pageParams);

}

ArticleServiceImpl

package com.jihu.blog.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.jihu.blog.dao.mapper.ArticleMapper;

import com.jihu.blog.dao.mapper.TagMapper;

import com.jihu.blog.dao.pojo.Article;

import com.jihu.blog.service.ArticleService;

import com.jihu.blog.service.SysUserService;

import com.jihu.blog.service.TagService;

import com.jihu.blog.vo.ArticleVo;

import com.jihu.blog.vo.Result;

import com.jihu.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.ArrayList;

import java.util.List;

@Service

public class ArticleServiceImpl implements ArticleService {

@Autowired

private ArticleMapper articleMapper;

@Autowired

private TagService tagService;

@Autowired

private SysUserService sysUserService;

@Override

public Result listArticle(PageParams pageParams) {

Page<Article> page = new Page<>(pageParams.getPage(), pageParams.getPageSize());

LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();

//是否置顶进行排序

queryWrapper.orderByDesc(Article::getWeight,Article::getCreateDate);

Page<Article> articlePage = articleMapper.selectPage(page, queryWrapper);

List<Article> records = articlePage.getRecords();

//能直接返回吗 肯定不行 所以需要进行如下转换

List<ArticleVo> articleVoList = copyList(records,true,true);

return Result.success(articleVoList);

}

private List<ArticleVo> copyList(List<Article> records,boolean isTag,boolean isAuthor) {

List<ArticleVo> articleVoList = new ArrayList<>();

for (Article record : records) {

articleVoList.add(copy(record,isTag,isAuthor));

}

return articleVoList;

}

private ArticleVo copy(Article article,boolean isTag,boolean isAuthor){

ArticleVo articleVo = new ArticleVo();

BeanUtils.copyProperties(article,articleVo);

articleVo.setCreateDate(new DateTime(article.getCreateDate()).toString("yyyy-MM-dd HH:mm"));

//并不是所有的接口,都需要标签,作者信息

if (isTag){

Long articleId = article.getId();

articleVo.setTags(tagService.findTagsByrticleId(articleId));

}

if (isAuthor){

Long authorId = article.getAuthorId();

articleVo.setAuthor(sysUserService.findUserById(authorId).getNickname());

}

return articleVo;

}

}

SysUserService

package com.jihu.blog.service;

import com.jihu.blog.dao.pojo.SysUser;

public interface SysUserService {

SysUser findUserById(Long id);

}

SysUserServiceImpl

package com.jihu.blog.service.impl;

import com.jihu.blog.dao.mapper.SysUserMapper;

import com.jihu.blog.dao.pojo.SysUser;

import com.jihu.blog.service.SysUserService;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

@Service

public class SysUserServiceImpl implements SysUserService {

@Autowired

private SysUserMapper sysUserMapper;

@Override

public SysUser findUserById(Long id) {

SysUser sysUser = sysUserMapper.selectById(id);

//防止空指针出现 加一个判断

if (sysUser == null){

sysUser = new SysUser();

sysUser.setNickname("马神之路");

}

return sysUser;

}

}

TagService

package com.jihu.blog.service;

import com.jihu.blog.vo.TagVo;

import java.util.List;

public interface TagService {

List<TagVo> findTagsByrticleId(Long articleId);

}

TagServiceImpl

package com.jihu.blog.service.impl;

import com.jihu.blog.dao.mapper.TagMapper;

import com.jihu.blog.dao.pojo.Tag;

import com.jihu.blog.service.TagService;

import com.jihu.blog.vo.TagVo;

import org.springframework.beans.BeanUtils;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import java.util.ArrayList;

import java.util.List;

@Service

public class TagServiceImpl implements TagService {

@Autowired

private TagMapper tagMapper;

@Override

public List<TagVo> findTagsByrticleId(Long articleId) {

//mybatisplus 无法进行多表查询

List<Tag> tags = tagMapper.findTagsByrticleId(articleId);

return copyList(tags);

}

private List<TagVo> copyList(List<Tag> tags) {

List<TagVo> tagVoList = new ArrayList<>();

for (Tag tag : tags) {

tagVoList.add(copy(tag));

}

return tagVoList;

}

private TagVo copy(Tag tag) {

TagVo tagVo = new TagVo();

BeanUtils.copyProperties(tag,tagVo);

return tagVo;

}

}

2.2.5 Mapper层
ArticleMapper

package com.jihu.blog.dao.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;

import com.jihu.blog.dao.pojo.Article;

//BaseMapper mybatisplus中提供的可以让我们很方便的查询这张表

public interface ArticleMapper extends BaseMapper<Article> {

}

SysUserMapper

package com.jihu.blog.dao.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;

import com.jihu.blog.dao.pojo.SysUser;

public interface SysUserMapper extends BaseMapper<SysUser> {

}

TagMapper

package com.jihu.blog.dao.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;

import com.jihu.blog.dao.pojo.Tag;

import java.util.List;

public interface TagMapper extends BaseMapper<Tag> {

/**

* 根据文章id 查询标签列表

* @param articleId

* @return

*/

List<Tag> findTagsByrticleId(Long articleId);

}

TagMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>

<!--MyBatis配置文件-->

<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "" target="_blank">http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.jihu.blog.dao.mapper.TagMapper">

<sql id="all">

id,avatar,tag_name as tagName

</sql>

<!-- List<Tag> findTagsByArticleId(Long articleId);

在这个文件中,id代表方法名,parameterType表示输入变量的名字,resultType表示泛型的类型-->

<select id="findTagsByrticleId" parameterType="long" resultType="com.jihu.blog.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>

2.2.6 Vo层
Result(统一最后的结果)

package com.jihu.blog.vo;

import lombok.AllArgsConstructor;

import lombok.Data;

@Data

@AllArgsConstructor

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

}

}

ArticleVo 建立与前端交互的Vo文件

package com.jihu.blog.vo;

import lombok.Data;

import java.util.List;

//建立与前端交互的Vo文件

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

}

新建TagVo

package com.jihu.blog.vo;

import lombok.Data;

@Data

public class TagVo {

private Long id;

private String tagName;

}

新建PageParams

package com.jihu.blog.vo.params;

import lombok.Data;

@Data

public class PageParams {

private int Page =1; //当前页数

private int PageSize =10; //每页显示的数量

}

2.2.7 测试:

3.首页- 最热标签


3.1接口说明

接口url:/tags/hot

请求方式:GET

请求参数:无

id: 标签名称 ,我们期望点击标签关于文章的所有列表都显示出来

返回数据:

{

"success": true,

"code": 200,

"msg": "success",

"data": [

{

"id":1,

"tagName":"4444"

}

]

}

3.2编码

3.2.1Controller层

package com.jihu.blog.controller;

import com.jihu.blog.service.TagService;

import com.jihu.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 TagsController {

@Autowired

private TagService tagService;

@GetMapping("hot")

public Result hot(){

int limit = 6;

return tagService.hots(limit);

}

}

3.2.2 Service层

建立service接口

TagService

package com.jihu.blog.service;

import com.jihu.blog.vo.Result;

import com.jihu.blog.vo.TagVo;

import java.util.List;

public interface TagService {

Result hots(int limit);

}

建立serviceimpl实现类

TagServiceImpl

@Service

public class TagServiceImpl implements TagService {

@Autowired

private TagMapper tagMapper;

@Override

public Result hots(int limit) {

/*

1.标签所拥有的文章数量最多 即为最热标签

2. 查询 根据tag_id 分组 计数,从大到小 排列 取前 limit个

*/

List<Long> tagIds = tagMapper.findHotsIds(limit);

//判断一下是否为空

if (tagIds == null){

return Result.success(Collections.emptyList());

}

//需求的是 tagId 和 tagName tag对象

//需要的是这样的一个sql语句 select * from tag where id in (1,2,3...)

List<Tag> tagList = tagMapper.findTagdByTagIds(tagIds);

return Result.success(tagList);

}

}

3.2.3 Mapper层
TagMapper

package com.jihu.blog.dao.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;

import com.jihu.blog.dao.pojo.Tag;

import java.util.List;

public interface TagMapper extends BaseMapper<Tag> {

/**

* 查询最热的标签 前limit条

* @param limit

* @return

*/

List<Long> findHotsIds(int limit);

/*

根据最热标签查询 最热文章名字

*/

List<Tag> findTagdByTagIds(List<Long> tagIds);

}

TagMapper

<?xml version="1.0" encoding="UTF-8" ?>

<!--MyBatis配置文件-->

<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "" target="_blank">http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.jihu.blog.dao.mapper.TagMapper">

<sql id="all">

id,avatar,tag_name as tagName

</sql>

<select id="findHotsIds" 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="findTagdByTagIds" parameterType="list" resultType="com.jihu.blog.dao.pojo.Tag">

select id,tag_name as tagName from ms_tag

where id in

<foreach collection="collection" item="tagId" separator="," open="(" close=")">

#{tagId}

</foreach>

</select>

</mapper>

3.2.4 测试

4.统一异常处理


不管是controller层还是service,dao层,都有可能报异常,如果是预料中的异常,可以直接捕获处理,如果是意料之外的异常,需要统一进行处理,进行记录,并给用户提示相对比较友好的信息。

AllExceptionHandler

package com.jihu.blog.handler;

import com.jihu.blog.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 {

//进行异常处理, 处理Exception.class的异常

@ExceptionHandler(Exception.class)

@ResponseBody //返回json数据

public Result doException(Exception ex){

ex.printStackTrace();

return Result.fail(-999,"系统异常");

}

}

5.首页-最热文章


5.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相关",

}

]

}

5.2 Controller层

ArticleController

@RestController

@RequestMapping("articles")

public class ArticleController {

@Autowired

private ArticleService articleService;

//首页 最热文章

@PostMapping("hot")</

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值