建站笔记(十二)-其他页面显示

建站笔记(十二)

其他页面显示

参考笔记原文链接

​ 由于剩下的页面显示比较简单,本文将把剩下的前端页面显示都讲述一下,分别有:分类页面显示、时间轴页面显示、音乐盒页面显示、友人帐页面显示、照片墙页面显示、关于我页面显示由于留言功能和评论功能基本一样,不懂的可以参考这篇文章(SpringBoot和Mybatis实现评论楼中楼功能(一张表搞定)),最后就是搜索博客页面展示。

一、分类页面显示

当博客开发到这里了,很多功能都是相通的,后端管理基本上就是增删改查、前端显示基本上就是返回model,只是处理起来会有些细微的差别,分类页面显示也是一样,根据页面功能来看,需要查询出所有分类和该分类下文章数目。

1. 持久层接口

这里需要两个接口,一个查询分类和该分类下博客数目(getAllTypeAndBlog)、一个是查询博客文章列表(getByTypeId),查询分类和该分类下博客数目是和分类相关的,就放在分类的Dao里面,查询博客文章列表是和博客相关的,就放在博客的Dao里面。

  • 在TypeDao接口中添加:
//查询所有分类
List<Type> getAllTypeAndBlog();
  • 在BlogDao接口中添加:
//根据TypeId查询博客列表,显示在分类页面
List<FirstPageBlog> getByTypeId(Long typeId);

2. mapper

跟持久层接口对应,博客和分类是多对一的关系,一篇博客对应一个分类,一个分类可以对应多篇博客,因此要用Mybatis的多表查询

  • TypeDao
<resultMap id="type" type="com.cbx.entity.Type">
    <id property="id" column="tid"/>
    <result property="name" column="name"/>
    <collection property="blogs" ofType="com.cbx.entity.Blog">
        <id property="id" column="bid"/>
        <result property="title" column="title"/>
        <result property="typeId" column="type_id"/>
    </collection>
</resultMap>
<!--查询分类-->
<select id="getAllTypeAndBlog" resultMap="type">
    select t.id tid, t.name, b.id bid, b.title,b.type_id
    from myblog.t_type t,myblog.t_blog b
    where t.id = b.type_id
</select>
  • BlogDao
<!--根据TypeId查询博客列表,显示在分类页面-->
<select id="getByTypeId" resultMap="firstPageBlog">
    select b.id,b.title,b.first_picture, b.views, b.comment_count, b.update_time, b.description,t.name ,u.nickname, u.avatar
    from myblog.t_blog b, myblog.t_type t,myblog.t_user u
    where b.type_id = t.id and u.id = b.user_id and b.type_id = #{typeId} order by b.update_time desc
</select>

3. 业务层

  • TypeService接口
//查询所有分类
List<Type>getAllTypeAndBlog();
  • TypeServiceImpl接口实现
@Transactional
@Override
public List<Type> getAllTypeAndBlog() {
    return typeDao.getAllTypeAndBlog();
}
  • BlogService接口
//根据TypeId查询博客列表,显示在分类页面
List<FirstPageBlog> getByTypeId(Long typeId);
  • BlogServiceImpl接口实现
//分类页面查询
@Override
public List<FirstPageBlog> getByTypeId(Long typeId) {
    return blogDao.getByTypeId(typeId);
}

4. 控制器

在controller包下创建TypeShowController类:

package com.cbx.controller;

import com.cbx.entity.Type;
import com.cbx.queryvo.FirstPageBlog;
import com.cbx.service.BlogService;
import com.cbx.service.TypeService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.List;

/**
 * @author cbx
 * @date 2022/3/3
 * @apiNote 分类页面控制器
 * {id}:当id为-1时,表示从首页导航栏进入分类页面,默认第一个分类显示颜色
 *
 * getAllTypeAndBlog:查询分类名称和博客信息,前端统计出该分类下博客数量
 *
 * getByTypeId:查询博客列表
 */
@Controller
public class TypeShowController {

    @Autowired
    private BlogService blogService;

    @Autowired
    private TypeService typeService;

    // 分页查询分类
    @GetMapping("/types/{id}")
    public String types(@RequestParam(defaultValue = "1",value = "pageNum")Integer pageNum, @PathVariable Long id, Model model){
        List<Type> types = typeService.getAllTypeAndBlog();

        // id为-1表示从首页导航栏点击进入分类页面
        if (id == -1){
            id = types.get(0).getId();
        }
        model.addAttribute("types",types);
        List<FirstPageBlog> blogs = blogService.getByTypeId(id);

        PageHelper.startPage(pageNum,10000);
        PageInfo<FirstPageBlog> pageInfo = new PageInfo<>(blogs);
        model.addAttribute("pageInfo",pageInfo);
        model.addAttribute("activeTypeId",id);
        return "types";
    }

}

讲解:

{id}:当id为-1时,表示从首页导航栏进入分类页面,默认第一个分类显示颜色

getAllTypeAndBlog:查询分类名称和博客信息,前端统计出该分类下博客数量

getByTypeId:查询博客列表

5. 前后端交互

  • 分类统计
<div class="ui labeled button m-margin-tb-tiny" th:each="type : ${types}">
  <a href="#" th:href="@{/types/{id}(id=${type.id})}" class="ui basic  button" th:classappend="${type.id==activeTypeId} ? 'teal'" th:text="${type.name}">好文</a>
  <div class="ui basic  left pointing label" th:classappend="${type.id==activeTypeId} ? 'teal'" th:text="${#arrays.length(type.blogs)}">22</div>
</div>
  • 分类列表
<div class="ui padded vertical segment m-padded-tb-large" th:each="blog : ${pageInfo.list}">
  <div class="ui middle aligned mobile reversed stackable grid" >
    <div class="eleven wide column">
      <h3 class="ui header" ><a href="#" th:href="@{/blog/{id}(id=${blog.id})}" target="_blank" class="m-black m-title-font" th:text="${blog.title}">xxx</a></h3>
      <p class="m-text" th:text="|${blog.description}......|">xxx</p>
      <div class="ui grid">
        <div class="eleven wide column">
          <div class="ui mini horizontal link list">
            <div class="item">
              <img src="../static/images/me.jpg" th:src="@{${blog.avatar}}"  alt="" class="ui avatar image">
              <div class="content"><a href="#" th:href="@{/about}" target="_blank" class="header" th:text="${blog.nickname}" >xxx</a></div>
            </div>
            <div class="item">
              <i class="calendar icon"></i><span th:text="${#dates.format(blog.updateTime,'yyyy-MM-dd')}">2022-03-03</span>
            </div>
            <div class="item">
              <i class="eye icon"></i> <span th:text="${blog.views}">2222</span>
            </div>
            <div class="item">
              <i class="comment outline icon"></i> <span th:text="${blog.commentCount}">2222</span>
            </div>
          </div>
        </div>
        <div class="right aligned five wide column">
          <a href="#" target="_blank" class="ui teal basic label m-padded-tiny m-text-thin" th:text="${blog.typeName}">好文</a>
        </div>
      </div>
    </div>
    <div class="five wide column">
      <a href="#" th:href="@{/blog/{id}(id=${blog.id})}" target="_blank">
        <img src="../static/images/backimg1.jpg" th:src="@{${blog.firstPicture}}"  alt="" class="ui rounded image">
      </a>
    </div>
  </div>
</div>
  • 分页显示
<div class="ui bottom attached segment m-opacity stackable grid">
  <div class="three wide column" align="center">
    <a class="item" th:href="@{/types(pageNum=${pageInfo.hasPreviousPage}?${pageInfo.prePage}:1)}" th:unless="${pageInfo.isFirstPage}">上一页</a>
  </div>

  <div class="ten wide column" align="center">
    <p> <span th:text="${pageInfo.pageNum}"></span> / <span th:text="${pageInfo.pages}"></span> </p>
  </div>

  <div class="three wide column" align="center">
    <a class="item" th:href="@{/types(pageNum=${pageInfo.hasNextPage}?${pageInfo.nextPage}:${pageInfo.pages})}" th:unless="${pageInfo.isLastPage}">下一页</a>
  </div>
</div>

6. 运行访问

运行项目,访问 http://localhost:8080/ ,点击导航栏的分类,可以看到分类信息和分类博客列表

二、时间轴页面显示

时间轴页面显示只要显示博客标题和时间,因此可以直接共用BlogDao中的持久层接口中的查询博客管理列表方法getAllBlog,只需要编写控制层代码即可,在controller包下创建ArchiveShowController类:

package com.cbx.controller;

import com.cbx.queryvo.BlogQuery;
import com.cbx.service.BlogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

import java.util.List;

/**
 * @author cbx
 * @date 2022/3/3
 * @apiNote 时间轴页面显示控制器
 */
@Controller
public class ArchiveShowController {

    @Autowired
    private BlogService blogService;

    @GetMapping("/archives")
    public String archive(Model model){
        List<BlogQuery> blogs = blogService.getAllBlog();
        model.addAttribute("blogs",blogs);
        return "archives";
    }
}
  • 前后端交互
<li class="" th:each="blog : ${blogs}">
  <div>
    <time th:text="${#dates.format(blog.createTime,'yyyy-MM-dd')}">2022/03/03</time>
    <div class="scientist" >
        <a href="#" target="_blank" th:href="@{/blog/{id}(id=${blog.id})}">
          <h3 class="state" style="text-align:center;font-size: 16px;color: #000;" th:text="${blog.title}">文章标题</h3>
        </a>
    </div>
  </div>
</li>
  • 运行访问 运行项目,访问 http://localhost:8080/ ,点击导航栏的时间轴,可以看到阶梯状左右分布、按照时间顺序排布的文章列表

三、音乐盒页面显示

音乐盒是一个静态页面,直接在控制器中返回页面就可以了

package com.cbx.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

/**
 * @author cbx
 * @date 2022/3/3
 * @apiNote 音乐盒页面显示控制器
 */
@Controller
public class MusicShowController {

    @GetMapping("/music")
    public String music(){
        return "music";
    }

}

四、友人帐页面显示

友人帐前端页面显示直接调用持久层的listFriendLink接口,只需编写控制层代码就可以了,在controller包下创建FriendsShowController类:

package com.cbx.controller;

import com.cbx.service.FriendService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

/**
 * @author cbx
 * @date 2022/3/3
 * @apiNote 友链显示控制器
 */
@Controller
public class FriendShowController {

    @Autowired
    private FriendService friendService;

    @GetMapping("/friends")
    public String friends(Model model){
        model.addAttribute("friendlinks",friendService.listFriendLink());
        return "friends";
    }

}
  • 前后端交互
<div class="m-margin-tb-tiny four wide column" th:each="friendlink : ${friendlinks}">
    <a href="#" class="class_outer" th:href="@{${friendlink.blogaddress}}" target="_blank">
        <div align="center">
            <div class="friends-link">
                <img src="../static/images/me.jpg" th:src="@{${friendlink.pictureaddress}}"  alt="" class="friends-link-image">
                <div class="m-margin-top">
                 <h4 class="m-font-size-text-friends m-margin-tb-tiny" th:text="${friendlink.blogname}">xxx</h4>
                </div>
            </div>
        </div>
    </a>
</div>
  • 运行访问

运行项目,访问 http://localhost:8080/ ,点击导航栏的友人帐,可以查看友链信息:

五、照片墙页面显示

照片墙页面显示直接调用持久层的listPicture接口,只需编写控制层代码就可以了,在controller包下创建PictureShowController类:

package com.cbx.controller;

import com.cbx.service.PictureService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

/**
 * @author cbx
 * @date 2022/3/3
 * @apiNote 照片墙页面显示控制器
 */
@Controller
public class PictureShowController {

    @Autowired
    private PictureService pictureService;

    @GetMapping("/picture")
    public String picture(Model model){
        model.addAttribute("pictures",pictureService.listPicture());
        return "picture";
    }

}
  • 前后端交互
<article class="thumb" th:each="picture : ${pictures}">
    <div class="ma5-gallery">
        <div class="rthumbnail">
            <a href="../static/images/backimg1.jpg" th:href="@{${picture.pictureaddress}}">
                <img class="picture-zmki_px" src="../static/images/backimg1.jpg" th:src="@{${picture.pictureaddress}}">
            </a>
            <div class="m-picture-text" th:text="${picture.picturename}">xxx</div>
            <div  class="rcaption">
                <div style="font-size: large;" th:text="${picture.picturename}">xxx</div>
                <div style="font-size: 16px" class="m-margin-top" th:text="${picture.picturetime}">2022-03-03 &nbsp;广州</div>
                <p style="font-size: 16px" th:text="${picture.picturedescription}">xxx</p>
            </div>
        </div>
    </div>
</article>
  • 运行访问

运行项目,访问 http://localhost:8080/ ,点击导航栏的照片墙,点击照片,可以查看照片信息:

六、关于我页面显示

关于我页面显示是一个静态页面,直接在控制器中返回页面就可以了

package com.cbx.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

/**
 * @author cbx
 * @date 2022/3/3
 * @apiNote
 */
@Controller
public class AboutShowController {

    @GetMapping("/about")
    public String about(){
        return "about";
    }

}
  • 运行访问

七、搜索博客页面展示

搜索页面就是从导航栏的搜索框输入搜索关键字,点击搜索,提交表单、返回搜索博客列表,跳转到搜索页展示

1. 持久层接口

这里只需要一个接口,搜索博客列表(getSearchBlog),返回的实体对象跟FisrtPageBlog最新博客一样

  • 在BlogDao里添加
// 搜索博客列表
List<FirstPageBlog> getSearchBlog(String query);

2. mapper

mapper里的sql语句跟搜素管理博客列表相似

  • 在BlogDao.xml里添加
<!--搜索博客列表-->
<select id="getSearchBlog" resultMap="firstPageBlog">
    <bind name="pattern" value="'%' + query + '%'"/>
    select b.id,b.title,b.first_picture,b.views,b.comment_count,b.update_time,b.description,
    t.name,
    u.nickname,u.avatar
    from myblog.t_blog b,myblog.t_type t,myblog.t_user u
    where b.type_id = t.id and u.id = b.user_id and (b.title like #{pattern} or b.content like #{pattern})
    order by b.update_time desc
</select>

3. 业务层

  • 在BlogService里添加
//搜索博客列表
List<FirstPageBlog> getSearchBlog(String query);
  • 在BlogServiceImpl里添加
@Override
public List<FirstPageBlog> getSearchBlog(String query) {
    return blogDao.getSearchBlog(query);
}

4. 控制器

  • 在IndexController里添加
// 搜索博客
@PostMapping("/search")
public String search(Model model,@RequestParam(defaultValue = "1",value = "pageNum")Integer pageNum,
                     @RequestParam String query){
    PageHelper.startPage(pageNum,1000);
    List<FirstPageBlog> searchBlog = blogService.getSearchBlog(query);
    PageInfo<FirstPageBlog> pageInfo = new PageInfo<>(searchBlog);
    model.addAttribute("pageInfo",pageInfo);
    model.addAttribute("query",query);
    return "search";
}

5. 前后端交互

<!--中间内容-->
<div  class="m-margin-">
  <div class="ui container">
    <!--header-->
    <div class="ui top attached segment">
      <div class="ui middle aligned two column grid">
        <div class="column">
          <h3 class="ui teal header">検索結果</h3>
        </div>
        <div class="right aligned column">
          共 <h2 class="ui orange header m-inline-block m-text-thin" th:text="${pageInfo.total}"> 14 </h2> 个
        </div>
      </div>
    </div>

    <div class="ui top attached segment">
      <div class="ui padded vertical segment m-padded-tb-large" th:each="blog : ${pageInfo.list}">
        <div class="ui middle aligned mobile reversed stackable grid" >
          <div class="eleven wide column">
            <h3 class="ui header" ><a href="#" th:href="@{/blog/{id}(id=${blog.id})}" target="_blank" class="m-black m-title-font" th:text="${blog.title}">xxx</a></h3>
            <p class="m-text m-margin-top-max" th:text="|${blog.description}......|">xxx</p>
            <div class="ui grid m-margin-top-max">
              <div class="eleven wide column">
                <div class="ui mini horizontal link list">
                  <div class="item">
                    <img src="../static/images/me.jpg" th:src="@{${blog.avatar}}"  alt="" class="ui avatar image">
                    <div class="content"><a href="#" th:href="@{/about}" target="_blank" class="header" th:text="${blog.nickname}" >oneStar</a></div>
                  </div>
                  <div class="item">
                    <i class="calendar icon"></i><span th:text="${#dates.format(blog.updateTime,'yyyy-MM-dd')}">2022-03-03</span>
                  </div>
                  <div class="item">
                    <i class="eye icon"></i> <span th:text="${blog.views}">2222</span>
                  </div>
                </div>
              </div>
              <div class="right aligned five wide column">
                <a href="#" target="_blank" class="ui teal basic label m-padded-tiny m-text-thin" th:text="${blog.typeName}">好文</a>
              </div>
            </div>
          </div>

          <!--博文首图-->
          <div class="five wide column">
            <a href="#" th:href="@{/blog/{id}(id=${blog.id})}" target="_blank">
              <img src="../static/images/backimg1.jpg" th:src="@{${blog.firstPicture}}"  alt="" class="ui rounded image">
            </a>
          </div>

        </div>
      </div>
    </div>

6. 运行访问

至此,整个博客开发完成,包括后台管理和前端页面显示,下一篇将讲述部署上线相关内容

end
  • 作者:AWhiteElephant(联系作者)
  • 发表时间:2022-03-14 22:41
  • 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)
  • 转载声明:如果是转载栈主转载的文章,请附上原文链接
  • 评论