【SpringBoot搭建個人博客】- 分類管理(六)

博客地址:ONESTARの客棧

源碼領取方式一:

  • 掃一掃文末二維碼,關注公衆號【編程日刊】,後臺回覆【博客】,即可領取源碼

源碼領取方式二:

歡迎給star以鼓勵(^_−)☆

本文將從MVC架構,分類的新增、編輯修改、刪除來講述SpringBoot搭建個人博客的分類管理

1.持久層接口

正常情況下自己寫代碼的時候是一個一個功能來完成,爲了方便書寫,這裏就將分類管理中所有功能一次列出來。

分析:

問:持久層需要哪些接口?

答:分類管理有查詢分類、保存分類、修改編輯分類、刪除分類、因此需要有getAllType、saveType、updateType、deleteType接口

問:分類可是會涉及到多表查詢的,光這些接口夠了嗎?編輯修改分類的時候如何判斷是修改的哪個分類?跳轉修改頁面時如何將要修改的參數獲取到前端頁面?分類頁面顯示的時候需要顯示博客信息,要如何將博客和分類一起顯示出來?這些都是需要解決的問題,不過這裏只解決分類管理的問題,多表問題後面遇到了再來解決。

答:根據功能來看,光以上接口肯定是不夠的,還要有:

  • getTypeByName():修改分類時根據分類名稱來查詢分類
  • getType():跳轉修改分類頁面時根據id查詢分類

在dao包下創建TypeDao分類持久層接口,代碼如下

package com.star.dao;

import com.star.entity.Type;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;

import java.util.List;

/**
 * @Description: 分類持久層接口
 * @Date: Created in 20:21 2020/6/1
 * @Author: ONESTAR
 * @QQ羣: 530311074
 * @URL: https://onestar.newstar.net.cn/
 */
@Mapper
@Repository
public interface TypeDao {

    //新增保存分類
    int saveType(Type type);

    //根據id查詢分類
    Type getType(Long id);

    //查詢所有分類
    List<Type> getAllType();

    //根據分類名稱查詢分類
    Type getTypeByName(String name);

    //編輯修改分類
    int updateType(Type type);

    //刪除分類
    void deleteType(Long id);

}

2.分類管理mapper

分析:

問:分類的mapper裏面需要哪些SQL?

答:根據需求來:增、刪、改、查,根據持久層的接口,查詢需要有根據id查詢分類、查詢所有分類、根據分類名稱查詢分類

在mapper文件夾下創建TypeDao.xml文件,編寫SQL,如下:

<?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.star.dao.TypeDao">

    <!--新增保存分類-->
    <insert id="saveType" parameterType="com.star.entity.Type">
        insert into myblog.t_type values (#{id},#{name});
    </insert>

    <!--根據id查詢分類-->
    <select id="getType" resultType="com.star.entity.Type">
        select id,name from myblog.t_type where id = #{id}
    </select>

    <!--查詢所有分類-->
    <select id="getAllType" resultType="com.star.entity.Type">
        select * from myblog.t_type
    </select>

    <!--根據分類名稱來查詢-->
    <select id="getTypeByName" resultType="com.star.entity.Type">
        select * from myblog.t_type where name = #{name}
    </select>

    <!--編輯修改分類-->
    <update id="updateType" parameterType="com.star.entity.Type">
        update myblog.t_type set name = #{name} where id = #{id}
    </update>

    <!--刪除分類-->
    <delete id="deleteType" >
        delete from myblog.t_type where id = #{id}
    </delete>

</mapper>

講解:

  • parameterType屬性:用於指定傳入參數的類型,傳入的是一個類的對象,所以寫全類名

  • resultType屬性:用於指定結果集的類型

  • #{ } 字符:代表佔位符,類似 jdbc 中的 ?,用於執行語句時替換實際的數據

3.分類管理業務層

分類業務層接口

這裏和持久層接口是一樣的,就不做分析,在service包下創建TypeService接口,代碼如下:

package com.star.service;

import com.star.entity.Type;

import java.util.List;

/**
 * @Description: 分類業務層接口
 * @Date: Created in 11:41 2020/6/2
 * @Author: ONESTAR
 * @QQ羣: 530311074
 * @URL: https://onestar.newstar.net.cn/
 */
public interface TypeService {

    //新增保存分類
    int saveType(Type type);

    //根據id查詢分類
    Type getType(Long id);

    //查詢所有分類
    List<Type> getAllType();

    //根據分類名稱查詢分類
    Type getTypeByName(String name);

    //編輯修改分類
    int updateType(Type type);

    //刪除分類
    void deleteType(Long id);
    
}

接口實現類

沒啥好分析的,直接調用持久層接口,在Impl包下創建TypeServiceImpl類實現TypeService接口,代碼如下:

package com.star.service.Impl;

import com.star.dao.TypeDao;
import com.star.entity.Type;
import com.star.service.TypeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * @Description: 分類業務層接口實現類
 * @Date: Created in 13:32 2020/6/2
 * @Author: ONESTAR
 * @QQ羣: 530311074
 * @URL: https://onestar.newstar.net.cn/
 */
@Service
public class TypeServiceImpl implements TypeService {

    @Autowired
    private TypeDao typeDao;

    @Transactional
    @Override
    public int saveType(Type type) {
        return typeDao.saveType(type);
    }

    @Transactional
    @Override
    public Type getType(Long id) {
        return typeDao.getType(id);
    }

    @Transactional
    @Override
    public List<Type> getAllType() {
        return typeDao.getAllType();
    }

    @Override
    public Type getTypeByName(String name) {
        return typeDao.getTypeByName(name);
    }

    @Transactional
    @Override
    public int updateType(Type type) {
        return typeDao.updateType(type);
    }

    @Transactional
    @Override
    public void deleteType(Long id) {
        typeDao.deleteType(id);
    }
}

講解:

  • @Service註解:用於標註業務層組件

  • @Autowired註解:@Autowired表示被修飾的類需要注入對象,spring會掃描所有被@Autowired標註的類,然後根據類型在ioc容器中找到匹配的類注入

  • @Transactional註解:實現事務操作

4.分類管理控制器

分析:

問:分類管理控制器需要考慮哪些功能?

答:基本的增、刪、改、查功能

問:增刪改查夠了嗎?爲了有良好的體驗,前端頁面顯示的時候需要能夠分頁顯示,操作成功後在前端有信息提示,並需要做重複判斷,這些要如何實現呢?

答:分頁顯示使用PageHelper插件具體使用可以參考:SpringBoot引入Pagehelper分頁插件 ,前端信息提示可以用model.addAttribute,重複添加使用@Valid註解:請求數據校驗,再做一個邏輯判斷就可以了

添加PageHelper分頁插件,在pom.xml中添加:

<!--引入分頁插件-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.2.12</version>
        </dependency>

在admin包下創建TypeController控制器類,代碼如下:

package com.star.controller.admin;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.star.entity.Type;
import com.star.service.TypeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import java.util.List;

/**
 * @Description:
 * @Date: Created in 14:56 2020/6/2
 * @Author: ONESTAR
 * @QQ羣: 530311074
 * @URL: https://onestar.newstar.net.cn/
 */
@Controller
@RequestMapping("/admin")
public class TypeController {

    @Autowired
    private TypeService typeService;

    //    分頁查詢分類列表
    @GetMapping("/types")
    public String list(Model model, @RequestParam(defaultValue = "1",value = "pageNum") Integer pageNum){
        //按照排序字段 倒序 排序
        String orderBy = "id desc";
        PageHelper.startPage(pageNum,10,orderBy);
        List<Type> list = typeService.getAllType();
        PageInfo<Type> pageInfo = new PageInfo<Type>(list);
        model.addAttribute("pageInfo",pageInfo);
        return "admin/types";
    }

    //    返回新增分類頁面
    @GetMapping("/types/input")
    public String input(Model model){
        model.addAttribute("type", new Type());
        return "admin/types-input";
    }

    //  新增分類
    @PostMapping("/types")
    public String post(@Valid Type type, RedirectAttributes attributes) {
        Type type1 = typeService.getTypeByName(type.getName());
        if (type1 != null) {
            attributes.addFlashAttribute("message", "不能添加重複的分類");
            return "redirect:/admin/types/input";
        }
        int t = typeService.saveType(type);
        if (t == 0) {
            attributes.addFlashAttribute("message", "新增失敗");
        } else {
            attributes.addFlashAttribute("message", "新增成功");
        }
        return "redirect:/admin/types";
    }

    //    跳轉修改分類頁面
    @GetMapping("/types/{id}/input")
    public String editInput(@PathVariable Long id, Model model) {
        model.addAttribute("type", typeService.getType(id));
        return "admin/types-input";
    }

    //    編輯修改分類
    @PostMapping("/types/{id}")
    public String editPost(@Valid Type type, RedirectAttributes attributes) {
        Type type1 = typeService.getTypeByName(type.getName());
        if (type1 != null) {
            attributes.addFlashAttribute("message", "不能添加重複的分類");
            return "redirect:/admin/types/input";
        }
        int t = typeService.updateType(type);
        if (t == 0 ) {
            attributes.addFlashAttribute("message", "編輯失敗");
        } else {
            attributes.addFlashAttribute("message", "編輯成功");
        }
        return "redirect:/admin/types";
    }

    //    刪除分類
    @GetMapping("/types/{id}/delete")
    public String delete(@PathVariable Long id,RedirectAttributes attributes) {
        typeService.deleteType(id);
        attributes.addFlashAttribute("message", "刪除成功");
        return "redirect:/admin/types";
    }

}

講解:

  • @Controller註解:用於標註控制層組件
  • @RequestMapping("/admin"):建立請求URL和處理方法之間的對應關係
  • @GetMapping註解:一個組合註解,是@RequestMapping(method = RequestMethod.GET)的縮寫,用於將HTTP get請求映射到特定處理程序的方法註解
  • @PostMapping註解:一個組合註解,是@RequestMapping(method = RequestMethod.POST)的縮寫,用於將HTTP post請求映射到特定處理程序的方法註解
  • @Valid註解:請求數據校驗,用來判斷是否有重複的分類
  • @PathVariable註解:獲取URL中的數據
  • attributes.addFlashAttribute:相當於重定向後,在URL後面拼接了參數,這樣在重定向之後的頁面後者控制器再去獲取URL後年的參數就可以了

5.前後端交互

1.新增:

<a href="#" th:href="@{/admin/types/input}">
        <button type="button" class="ui teal button m-mobile-wide m-margin-top"><i class="pencil icon"></i>新增</button>
</a>

2.編輯刪除:

<a href="#" th:href="@{/admin/types/{id}/input(id=${type.id})}" class="ui mini teal basic button">編輯</a>
<a href="#" th:href="@{/admin/types/{id}/delete(id=${type.id})}"  onclick="return confirm('確定要刪除該分類嗎?三思啊! 刪了可就沒了!')" class="ui mini red basic button">刪除</a>

3.查詢分類列表:

<a href="#" th:href="@{/admin/types}" class="teal active item">列表</a>

4.分頁:

<div class="ui inverted divided stackable grid">
    <div class="three wide column" align="center">
      <a class="item" th:href="@{/admin/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> 頁,有 <span th:text="${pageInfo.total}"></span> 個分類</p>
    </div>
    
    <div class="three wide column" align="center">
      <a class="item" th:href="@{/admin/types(pageNum=${pageInfo.hasNextPage}?${pageInfo.nextPage}:${pageInfo.pages})}" th:unless="${pageInfo.isLastPage}">下一頁</a>
    </div>
</div>

運行代碼,訪問:http://localhost:8080/admin ,登錄後,點擊分類管理,進入分類管理頁面,可以對分類進行增、刪、改、查

目錄結構如下:

至此,分類管理實現完成,下一篇將講述博客管理

【點關注,不迷路,歡迎持續關注本站】


image

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章