目录
- 一、分页配置代码解读(使用MP自带分页)
- 二、Controller层代码解读
- 三、service层代码解读
- 四、Mapper层代码解读
- 五、结果展示
一、分页配置代码解读(使用MP自带分页)
package com.minster.yanapi.Config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
-
package com.minster.yanapi.Config;
: 声明该Java类所属的包。 -
import com.baomidou.mybatisplus.annotation.DbType;
: 导入DbType
类,该类是 MyBatis-Plus 中用于表示数据库类型的枚举类。 -
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
: 导入MybatisPlusInterceptor
类,这是 MyBatis-Plus 提供的拦截器类,用于配置各种插件。 -
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
: 导入PaginationInnerInterceptor
类,这是 MyBatis-Plus 提供的分页插件。 -
import org.springframework.context.annotation.Bean;
: 导入 Spring 框架的@Bean
注解,用于将方法返回的对象注册为 Spring 容器中的 Bean。 -
import org.springframework.context.annotation.Configuration;
: 导入 Spring 框架的@Configuration
注解,表明这是一个配置类。 -
@Configuration
: 声明这是一个配置类,用于定义配置信息。 -
public class MybatisPlusConfig {
: 定义名为MybatisPlusConfig
的类。 -
@Bean
: 注解在方法上,表示该方法返回的对象将被注册为一个 Bean。 -
public MybatisPlusInterceptor mybatisPlusInterceptor() {
: 定义一个名为mybatisPlusInterceptor
的方法,返回一个MybatisPlusInterceptor
对象。 -
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
: 创建一个MybatisPlusInterceptor
对象。 -
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
: 向拦截器中添加一个内部拦截器,这里添加了一个用于支持MySQL数据库的分页插件。 -
return interceptor;
: 返回配置好的拦截器对象。
二、Controller层代码解读
@GetMapping()
public ApiResponse<Page<ArticleResp>> getArticleList(@RequestParam("current") Integer current,
@RequestParam("pageSize") Integer pageSize) {
Page<Map<String, Object>> page = new Page<>(current, pageSize);
return yanArticleService.getArticleList(page);
}
-
@GetMapping()
注解表示这个方法处理 HTTP GET 请求,并且没有指定具体的路径,即映射到当前路径。这说明该方法应该处理类似于http://example.com/your-controller-path
这样的请求。 -
public ApiResponse<Page<ArticleResp>>
是方法的返回类型。这个方法返回一个包含ApiResponse
对象的泛型,而ApiResponse
的泛型参数是Page<ArticleResp>
,表示返回的数据是分页的文章列表。 -
@RequestParam("current") Integer current
和@RequestParam("pageSize") Integer pageSize
是用来接收请求中的参数的。current
参数用于指定当前页码,pageSize
参数用于指定每页的条目数量。这两个参数会被Spring自动从请求中获取并传递给方法。 -
Page<Map<String, Object>> page = new Page<>(current, pageSize);
创建了一个Page
对象,该对象用于表示分页信息,其中current
是当前页码,pageSize
是每页的条目数量。这里使用了一个泛型为Map<String, Object>
的Page
类型。 -
yanArticleService.getArticleList(page);
调用了一个名为yanArticleService
的服务(Service)的getArticleList
方法,并传递了前面创建的Page
对象作为参数。这个方法似乎返回一个ApiResponse
对象,其中包含了一个分页的文章列表。
三、service层代码解读
public ApiResponse<Page<ArticleResp>> getArticleList(Page<Map<String, Object>> page) {
Page<Map<String, Object>> result = yanArticleMapper.getArticleList(page);
// 将查询结果转换为 Page<YanArticle>
List<ArticleResp> yanArticles = result.getRecords().stream()
.map(record -> {
ArticleResp articleResp = new ArticleResp();
articleResp.setId((Long) record.get("id"));
articleResp.setTitle((String) record.get("title"));
articleResp.setSummary((String) record.get("summary"));
articleResp.setCreateTime((Date) record.get("createTime"));
articleResp.setUsername((String) record.get("username"));
articleResp.setAvatar((String) record.get("avatar"));
articleResp.setLikeCount((Long) record.get("likeCount"));
articleResp.setCommentCount((Long) record.get("commentCount"));
return articleResp;
})
.collect(Collectors.toList());
Page<ArticleResp> yanArticlePage = new Page<>();
yanArticlePage.setRecords(yanArticles);
yanArticlePage.setCurrent(result.getCurrent());
yanArticlePage.setSize(result.getSize());
yanArticlePage.setTotal(result.getTotal());
yanArticlePage.setPages(result.getPages());
return ApiResponse.success(yanArticlePage);
}
-
方法声明了一个返回类型为
ApiResponse<Page<ArticleResp>>
的公共方法,方法名为getArticleList
。方法接收一个Page<Map<String, Object>>
类型的参数page
,该参数用于表示分页信息。 -
调用了
yanArticleMapper
的getArticleList
方法,传递了上面接收的page
对象作为参数。getArticleList
方法返回一个Page<Map<String, Object>>
类型的分页结果,其中包含了从数据库中查询到的原始数据。 -
使用Java 8+的流式处理,对从数据库中查询到的原始数据进行转换。通过
stream()
对结果集进行流式处理,使用map
将每个原始记录转换为一个ArticleResp
对象,最后通过collect(Collectors.toList())
将转换后的对象集合收集成一个列表。 -
创建一个新的
Page<ArticleResp>
对象yanArticlePage
,并将上面转换后的文章列表设置为新对象的记录(setRecords
),同时将原始分页结果中的页码、每页条目数、总条目数、总页数等信息也设置到新对象中。 -
最后,使用
ApiResponse.success()
方法将新创建的分页结果对象yanArticlePage
包装为成功的ApiResponse
对象,并将其返回。这个方法的最终返回结果是一个带有文章分页信息的成功响应对象。
四、Mapper层代码解读
@Select("SELECT\n" +
" a.id,\n" +
" a.title ,\n" +
" a.summary ,\n" +
" a.create_time AS createTime,\n" +
" u.username ,\n" +
" d.avatar, \n" +
" COUNT(DISTINCT c.id) AS likeCount ,\n" +
" COUNT(DISTINCT l.id) AS commentCount\n" +
"FROM\n" +
" yan_article a\n" +
"JOIN\n" +
" yan_user u ON a.author_id = u.id\n" +
"LEFT JOIN\n" +
" yan_details d ON u.detail_id = d.id\n" +
"LEFT JOIN\n" +
" yan_comment c ON a.id = c.article_id\n" +
"LEFT JOIN\n" +
" yan_like l ON a.id = l.article_id\n" +
"GROUP BY\n" +
" a.id, a.title, a.summary, a.create_time, u.username, d.avatar")
Page<Map<String, Object>> getArticleList(Page<Map<String, Object>> page);
SQL语句
SELECT
a.id,
a.title ,
a.summary ,
a.create_time AS createTime,
u.username ,
d.avatar, -- 不使用前缀
COUNT(DISTINCT c.id) AS likeCount ,
COUNT(DISTINCT l.id) AS commentCount
FROM
yan_article a
JOIN
yan_user u ON a.author_id = u.id
LEFT JOIN
yan_details d ON u.detail_id = d.id
LEFT JOIN
yan_comment c ON a.id = c.article_id
LEFT JOIN
yan_like l ON a.id = l.article_id
GROUP BY
a.id, a.title, a.summary, a.create_time, u.username, d.avatar
-
@Select
注解表示这是一个查询语句。该语句使用了类似 SQL 的语法,用于从数据库中获取文章列表的相关信息。 -
查询语句中使用了表别名(如
a
、u
、d
、c
、l
)来简化表的引用。 -
查询语句主要涉及以下表:
yan_article a
: 文章表,用别名a
引用。yan_user u
: 用户表,用别名u
引用。yan_details d
: 用户详情表,用别名d
引用。yan_comment c
: 评论表,用别名c
引用。yan_like l
: 点赞表,用别名l
引用。
-
在查询语句中,使用了左连接 (
LEFT JOIN
) 将文章表与用户表、用户详情表、评论表、点赞表进行关联。 -
使用
COUNT(DISTINCT c.id)
计算每篇文章的点赞数量,使用COUNT(DISTINCT l.id)
计算每篇文章的评论数量。 -
最后,使用
GROUP BY
对文章的相关字段进行分组,包括文章的id
、title
、summary
、create_time
、作者的username
以及作者的头像avatar
。 -
查询结果的字段包括文章的基本信息(
id
、title
、summary
、createTime
)、作者的用户名 (username
)、作者的头像 (avatar
)、点赞数量 (likeCount
) 以及评论数量 (commentCount
)。 -
查询结果以
Page<Map<String, Object>>
的形式返回,其中Map<String, Object>
表示每一行数据,Page
则表示分页信息。