412 lines
9.7 KiB
Markdown
412 lines
9.7 KiB
Markdown
![]() |
# 开发社区首页
|
|||
|
|
|||
|
---
|
|||
|
|
|||
|

|
|||
|
|
|||
|
## DiscussPost 讨论帖
|
|||
|
|
|||
|
### Entity
|
|||
|
|
|||
|
### DAO
|
|||
|
|
|||
|
- Mapper 接口 `DiscussPostMapper`
|
|||
|
- 对应的 xml 配置文件 `discusspost-mapper.xml`
|
|||
|
|
|||
|
`@Param` 注解用于给参数起别名,**如果只有一个参数**,并且需要在 `<if>` 里使用,则必须加别名
|
|||
|
|
|||
|
```java
|
|||
|
@Mapper
|
|||
|
public interface DiscussPostMapper {
|
|||
|
|
|||
|
/**
|
|||
|
* 分页查询讨论贴信息
|
|||
|
*
|
|||
|
* @param userId 当传入的 userId = 0 时查找所有用户的帖子
|
|||
|
* 当传入的 userId != 0 时,查找该指定用户的帖子
|
|||
|
* @param offset 每页的起始索引
|
|||
|
* @param limit 每页显示多少条数据
|
|||
|
* @return
|
|||
|
*/
|
|||
|
List<DiscussPost> selectDiscussPosts(int userId, int offset, int limit);
|
|||
|
|
|||
|
/**
|
|||
|
* 查询讨论贴的个数
|
|||
|
* @param userId 当传入的 userId = 0 时计算所有用户的帖子总数
|
|||
|
* 当传入的 userId != 0 时计算该指定用户的帖子总数
|
|||
|
* @return
|
|||
|
*/
|
|||
|
int selectDiscussPostRows(@Param("userId") int userId);
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
对应的 Mapper:
|
|||
|
|
|||
|
```xml
|
|||
|
<?xml version="1.0" encoding="UTF-8"?>
|
|||
|
<!DOCTYPE mapper
|
|||
|
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
|||
|
<mapper namespace="com.greate.community.dao.DiscussPostMapper">
|
|||
|
|
|||
|
<sql id = "selectFields">
|
|||
|
id, user_id, title, content, type, status, create_time, comment_count, score
|
|||
|
</sql>
|
|||
|
|
|||
|
<!--分页查询讨论贴信息-->
|
|||
|
<!--不显示拉黑的帖子, 按照是否置顶和创建时间排序-->
|
|||
|
<select id = "selectDiscussPosts" resultType="DiscussPost">
|
|||
|
select <include refid="selectFields"></include>
|
|||
|
from discuss_post
|
|||
|
where status != 2
|
|||
|
<if test = "userId!=0">
|
|||
|
and user_id = #{userId}
|
|||
|
</if>
|
|||
|
order by type desc, create_time desc
|
|||
|
limit #{offset}, #{limit}
|
|||
|
</select>
|
|||
|
|
|||
|
<!--查询讨论贴的个数-->
|
|||
|
<select id = "selectDiscussPostRows" resultType="int">
|
|||
|
select count(id)
|
|||
|
from discuss_post
|
|||
|
where status != 2
|
|||
|
<if test = "userId != 0">
|
|||
|
and user_id = #{userId}
|
|||
|
</if>
|
|||
|
</select>
|
|||
|
|
|||
|
</mapper>
|
|||
|
```
|
|||
|
|
|||
|
### Service
|
|||
|
|
|||
|
关于自动注入 Mapper 报错问题:可参考 [关于IDEA中@Autowired 注解报错~图文](https://www.cnblogs.com/taopanfeng/p/10994075.html)
|
|||
|
|
|||
|
```java
|
|||
|
@Service
|
|||
|
public class DiscussPostSerivce {
|
|||
|
|
|||
|
@Autowired
|
|||
|
private DiscussPostMapper discussPostMapper;
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* 分页查询讨论帖信息
|
|||
|
*
|
|||
|
* @param userId 当传入的 userId = 0 时查找所有用户的帖子
|
|||
|
* 当传入的 userId != 0 时,查找该指定用户的帖子
|
|||
|
* @param offset 每页的起始索引
|
|||
|
* @param limit 每页显示多少条数据
|
|||
|
* @return
|
|||
|
*/
|
|||
|
public List<DiscussPost> findDiscussPosts (int userId, int offset, int limit) {
|
|||
|
return discussPostMapper.selectDiscussPosts(userId, offset, limit);
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 查询讨论贴的个数
|
|||
|
* @param userId 当传入的 userId = 0 时计算所有用户的帖子总数
|
|||
|
* 当传入的 userId != 0 时计算该指定用户的帖子总数
|
|||
|
* @return
|
|||
|
*/
|
|||
|
public int findDiscussPostRows (int userId) {
|
|||
|
return discussPostMapper.selectDiscussPostRows(userId);
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
## User
|
|||
|
|
|||
|
### Entity
|
|||
|
|
|||
|
### DAO
|
|||
|
|
|||
|
```java
|
|||
|
@Mapper
|
|||
|
public interface UserMapper {
|
|||
|
|
|||
|
/**
|
|||
|
* 根据 id 查询用户
|
|||
|
* @param id
|
|||
|
* @return
|
|||
|
*/
|
|||
|
User selectById (int id);
|
|||
|
|
|||
|
/**
|
|||
|
* 根据 username 查询用户
|
|||
|
* @param username
|
|||
|
* @return
|
|||
|
*/
|
|||
|
User selectByName(String username);
|
|||
|
|
|||
|
/**
|
|||
|
* 根据 email 查询用户
|
|||
|
* @param email
|
|||
|
* @return
|
|||
|
*/
|
|||
|
User selectByEmail(String email);
|
|||
|
|
|||
|
/**
|
|||
|
* 插入用户(注册)
|
|||
|
* @param user
|
|||
|
* @return
|
|||
|
*/
|
|||
|
int insertUser(User user);
|
|||
|
|
|||
|
/**
|
|||
|
* 修改用户状态
|
|||
|
* @param id
|
|||
|
* @param status 0:未激活,1:已激活
|
|||
|
* @return
|
|||
|
*/
|
|||
|
int updateStatus(int id, int status);
|
|||
|
|
|||
|
/**
|
|||
|
* 修改头像
|
|||
|
* @param id
|
|||
|
* @param headerUrl
|
|||
|
* @return
|
|||
|
*/
|
|||
|
int updateHeader(int id, String headerUrl);
|
|||
|
|
|||
|
/**
|
|||
|
* 修改密码
|
|||
|
* @param id
|
|||
|
* @param password
|
|||
|
* @return
|
|||
|
*/
|
|||
|
int updatePassword(int id, String password);
|
|||
|
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
对应的 mapper.xml:
|
|||
|
|
|||
|
```xml
|
|||
|
<?xml version="1.0" encoding="UTF-8"?>
|
|||
|
<!DOCTYPE mapper
|
|||
|
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
|||
|
<mapper namespace="com.greate.community.dao.UserMapper">
|
|||
|
|
|||
|
<sql id = "insertFields">
|
|||
|
username, password, salt, email, type, status, activation_code, header_url, create_time
|
|||
|
</sql>
|
|||
|
|
|||
|
<sql id = "selectFields">
|
|||
|
id, username, password, salt, email, type, status, activation_code, header_url, create_time
|
|||
|
</sql>
|
|||
|
|
|||
|
<!--根据 Id 查询用户信息-->
|
|||
|
<select id = "selectById" resultType = "User">
|
|||
|
select <include refid="selectFields"></include>
|
|||
|
from user
|
|||
|
where id = #{id}
|
|||
|
</select>
|
|||
|
|
|||
|
<!--根据 Username 查询用户信息-->
|
|||
|
<select id="selectByName" resultType="User">
|
|||
|
select <include refid="selectFields"></include>
|
|||
|
from user
|
|||
|
where username = #{username}
|
|||
|
</select>
|
|||
|
|
|||
|
<!--根据 email 查询用户信息-->
|
|||
|
<select id="selectByEmail" resultType="User">
|
|||
|
select <include refid="selectFields"></include>
|
|||
|
from user
|
|||
|
where email = #{email}
|
|||
|
</select>
|
|||
|
|
|||
|
<!--插入用户信息(注册)-->
|
|||
|
<insert id="insertUser" parameterType="User" keyProperty="id">
|
|||
|
insert into user (<include refid="insertFields"></include>)
|
|||
|
values(#{username}, #{password}, #{salt}, #{email}, #{type}, #{status}, #{activationCode}, #{headerUrl}, #{createTime})
|
|||
|
</insert>
|
|||
|
|
|||
|
<!--修改用户状态-->
|
|||
|
<update id="updateStatus">
|
|||
|
update user set status = #{status} where id = #{id}
|
|||
|
</update>
|
|||
|
|
|||
|
<!--修改用户头像-->
|
|||
|
<update id="updateHeader">
|
|||
|
update user set header_url = #{headerUrl} where id = #{id}
|
|||
|
</update>
|
|||
|
|
|||
|
<!--修改密码-->
|
|||
|
<update id="updatePassword">
|
|||
|
update user set password = #{password} where id = #{id}
|
|||
|
</update>
|
|||
|
|
|||
|
</mapper>
|
|||
|
```
|
|||
|
|
|||
|
### Service
|
|||
|
|
|||
|
```java
|
|||
|
@Service
|
|||
|
public class UserService {
|
|||
|
|
|||
|
@Autowired
|
|||
|
private UserMapper userMapper;
|
|||
|
|
|||
|
public User findUserById (int id) {
|
|||
|
return userMapper.selectById(id);
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
## Page 分页
|
|||
|
|
|||
|
```java
|
|||
|
/**
|
|||
|
* 封装分页相关的信息
|
|||
|
*/
|
|||
|
public class Page {
|
|||
|
|
|||
|
// 当前的页码
|
|||
|
private int current = 1;
|
|||
|
// 单页显示的帖子数量上限
|
|||
|
private int limit = 10;
|
|||
|
// 帖子总数(用于计算总页数)
|
|||
|
private int rows;
|
|||
|
// 查询路径(用于复用分页链接, 因为我们不只在首页中有分页,其他界面也会有分页)
|
|||
|
private String path;
|
|||
|
|
|||
|
public int getCurrent() {
|
|||
|
return current;
|
|||
|
}
|
|||
|
|
|||
|
public void setCurrent(int current) {
|
|||
|
if (current >= 1) {
|
|||
|
this.current = current;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public int getLimit() {
|
|||
|
return limit;
|
|||
|
}
|
|||
|
|
|||
|
public void setLimit(int limit) {
|
|||
|
if (current >= 1 && limit <= 100) {
|
|||
|
this.limit = limit;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public int getRows() {
|
|||
|
return rows;
|
|||
|
}
|
|||
|
|
|||
|
public void setRows(int rows) {
|
|||
|
if (rows >= 0) {
|
|||
|
this.rows = rows;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public String getPath() {
|
|||
|
return path;
|
|||
|
}
|
|||
|
|
|||
|
public void setPath(String path) {
|
|||
|
this.path = path;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 获取当前页的起始索引 offset
|
|||
|
* @return
|
|||
|
*/
|
|||
|
public int getOffset() {
|
|||
|
return current * limit - limit;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 获取总页数
|
|||
|
* @return
|
|||
|
*/
|
|||
|
public int getTotal() {
|
|||
|
if (rows % limit == 0) {
|
|||
|
return rows / limit;
|
|||
|
}
|
|||
|
else {
|
|||
|
return rows / limit + 1;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 获取分页栏起始页码
|
|||
|
* 分页栏显示当前页码及其前后两页
|
|||
|
* @return
|
|||
|
*/
|
|||
|
public int getFrom() {
|
|||
|
int from = current - 2;
|
|||
|
return from < 1 ? 1 : from;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 获取分页栏结束页码
|
|||
|
* @return
|
|||
|
*/
|
|||
|
public int getTo() {
|
|||
|
int to = current + 2;
|
|||
|
int total = getTotal();
|
|||
|
return to > total ? total : to;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
```
|
|||
|
|
|||
|
## Controller
|
|||
|
|
|||
|
```java
|
|||
|
@Controller
|
|||
|
public class HomeController {
|
|||
|
|
|||
|
@Autowired
|
|||
|
private DiscussPostSerivce discussPostSerivce;
|
|||
|
|
|||
|
@Autowired
|
|||
|
private UserService userService;
|
|||
|
|
|||
|
@GetMapping("/index")
|
|||
|
public String getIndexPage(Model model, Page page) {
|
|||
|
// 获取总页数
|
|||
|
page.setRows(discussPostSerivce.findDiscussPostRows(0));
|
|||
|
page.setPath("/index");
|
|||
|
|
|||
|
// 分页查询
|
|||
|
List<DiscussPost> list = discussPostSerivce.findDiscussPosts(0, page.getOffset(), page.getLimit());
|
|||
|
// 封装帖子和该帖子对应的用户信息
|
|||
|
List<Map<String, Object>> discussPosts = new ArrayList<>();
|
|||
|
if (list != null) {
|
|||
|
for (DiscussPost post : list) {
|
|||
|
Map<String, Object> map = new HashMap<>();
|
|||
|
map.put("post", post);
|
|||
|
User user = userService.findUserById(post.getUserId());
|
|||
|
map.put("user", user);
|
|||
|
discussPosts.add(map);
|
|||
|
}
|
|||
|
}
|
|||
|
model.addAttribute("discussPosts", discussPosts);
|
|||
|
return "index";
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
🚩 小 Tip:这里不用把 Page 放入 model(`model.addAttribute("page", page);`
|
|||
|
|
|||
|
因为在方法调用之前,Spring MVC 会自动实例化 Model 和 Page,并将 Page 注入 Model,所以,在 Thymeleaf 中可以直接访问 Page 对象中的数据
|
|||
|
|
|||
|
## 前端界面 index.html
|
|||
|
|
|||
|
```html
|
|||
|
th:each="map:${discussPosts}"
|
|||
|
```
|
|||
|
|
|||
|
表示将每次遍历 `discussPosts` 取出的变量称为 `map`
|
|||
|
|