总结日志
- 学习如何创建第一个项目,显示帖子。从数据段DAO获取数据,然后到Service服务端,然后到Controller控制端生成页面。
目录 总结日志DAO 数据部分Service 服务部分Controller 控制的页面内容
简要流程如上所示。DB代表数据容器,储存的数据。我们一次按照从DAO到Service到Controller构建项目
DAO 数据部分
-
首先需要在entity目录下新建一个对象为DiscussPost,用来储存从SQL中获得的信息,并使用ALT+insert组合键构Set方法和Get方法以及String方法。
-
在DAO下新建一个接口对象Mapper
@Mapper // 扫描 装配
public interface DiscussPostMapper {
// 有时需要传参,有时不需要,因为看评论不需要搜id,但是看自己发布过的帖子,需要id
// 通过sql动态条件
// 还要考虑分页, sql种需要起始行号和最多的一页条数,offset和limit
List selectDiscussPosts(int userId, int offset, int limit);
// 查询总行数
// 如果需要sql动态的拼一个条件,并且方法只有一个参数,则参数必须取别名,否则报错
// 使用@Param注解来起别名
int selectDiscussPostRows(@Param(“userId”) int userId); //Param给参数取个别名
}
第一个函数负责获取某个用户的评论情况,或者在不传入userId(=0)时,显示所有的帖子
第二个函数负责获取某个用户的所有评论的行数 (Typora shift+tab可以删除前面的空格) -
有Mapper.xml支持对应的接口来实现SQL对象获取内容
<?xml version="1.0" encoding="UTF-8" ?>
<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"> <!-- 判断传入的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 服务部分
@Service
public class DiscussPostService {
@Autowired // 注入依赖关系
private DiscussPostMapper discussPostMapper;
public List<DiscussPost> findDiscussPosts(int userId, int offset, int limit) {
return discussPostMapper.selectDiscussPosts(userId, offset, limit);
}
public int findDiscussPostRows(int userId) {
return discussPostMapper.selectDiscussPostRows(userId);
}
}
服务部分获取来自DAO的mapper对象,并注入依赖。随后返回这个mapper对象从数据段获取的内容
Controller 控制的页面内容
为了合理的显示页面中,每页只有十条评论,因此还需要一个page对象在entity中
public class Page {
//当前的页码
private int current = 1;
// 页面显示上限
private int limit = 10;
// 数据的总数用于计算总页数
private int rows;
// 查询路径 用来复用分页的连接
private String path;
// 还有额外的set与get方法,不显示
}
上面这个就是page对象
@Controller
public class HomeController {
@Autowired
private DiscussPostService discussPostService;
@Autowired
private UserService userService;
@RequestMapping(path = "/index", method = RequestMethod.GET)
public String getIndexPage(Model model, Page page){
// 方法调用之前,spring MVC会自动实例化model和page,还会将page注入给model
// 所以thymyleaf种可以直接访问page对象中的数据
page.setRows(discussPostService.findDiscussPostRows(0));
page.setPath("/index");
List<DiscussPost> list = discussPostService.findDiscussPosts(0, page.getOffset(), page.getLimit());// 代表Service获取到了DAO的数据
List<Map<String, Object>> discussPosts = new ArrayList<>();
if(list!= null){
for(DiscussPost post : list){
// 按照k-v情况将评论与用户信息装进一个list map中
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操作,才可以被后面的html访问到具体数据内容
model.addAttribute("discussPosts", discussPosts);
return "/index";
}
}
首先需要注入依赖两个对象,因为我们还需要获取用户的名称等User sql中的内容,所以有两个Service对象。
设置需要显示的页面的评论条数。返回值为String,对应的页面的地址
<!-- 帖子列表 -->
<ul class="list-unstyled">
<li class="media pb-3 pt-3 mb-3 border-bottom" th:each="map:${discussPosts}">
<!--这个 th:each="map:${discussPosts}" 就是model.addAttribute的内容 -->
<a href="site/profile.html">
<img th:src="${map.user.headerUrl}" class="mr-4 rounded-circle" alt="用户头像" style="width:50px;height:50px;">
</a>
<div class="media-body">
<h6 class="mt-0 mb-3">
<a href="#" th:utext="${map.post.title}">备战春招,面试刷题跟他复习,一个月全搞定!</a>
<span class="badge badge-secondary bg-primary" th:if="${map.post.type==1}">置顶</span>
<span class="badge badge-secondary bg-danger" th:if="${map.post.status==1}">精华</span>
</h6>
<div class="text-muted font-size-12">
<u class="mr-3" th:utext="${map.user.username}">寒江雪</u> 发布于 <b th:text="${#dates.format(map.post.createTime,'yyyy-MM-dd HH:mm:ss')}">2019-04-15 15:32:18</b>
<ul class="d-inline float-right">
<li class="d-inline ml-2">赞 11</li>
<li class="d-inline ml-2">|</li>
<li class="d-inline ml-2">回帖 7</li>
</ul>
</div>
</div>
</li>
</ul>
<!-- 分页 -->
<nav class="mt-5" th:if="${page.rows>0}">
<!-- 没有数据就不显示-->
<ul class="pagination justify-content-center">
<li class="page-item">
<a class="page-link" th:href="@{${page.path}(current=1)}">首页</a>
</li>
<li th:class="|page-item ${page.current==1?'disabled':''}|">
<!-- page-item代表是翻页的按钮,但是还有变量值,所以用两个竖线画出来,如果等于1就不能点,让disable,如果不等于1,则啥也不加,空 -->
<a class="page-link" th:href="@{${page.path}(current=${page.current-1})}">上一页</a></li>
<li th:class="|page-item ${i==page.current?'active':''}|" th:each="i:${#numbers.sequence(page.from,page.to)}">
<a class="page-link" href="#" th:text="${i}">1</a>
<!-- 将页码点亮 active 关键词 -->
</li>
<li th:class="|page-item ${page.current==page.total?'disabled':''}|">
<a class="page-link" th:href="@{${page.path}(current=${page.current+1})}">下一页</a>
</li>
<li class="page-item">
<a class="page-link" th:href="@{${page.path}(current=${page.total})}">末页</a>
</li>
</ul>
</nav>
- 声明了th语法,使用$符号表示获取的变量,这是一个each的循环语句,从discussposts得到数据,并装进一个map中(语义对齐),注意这个discussPosts是java中最后addAttribute的内容。
置顶代表用th的判断语句,来决定这个要不要加置顶或者精华的标签。
2019-04-15 15:32:18返回时间的格式
后半部分是分页内容,可以复用的内容~
HTML 中 @后面是填写路径的,$后面是填写变量数据的,#{}是mapper中的写法