博客地址:ONESTARの客栈
源码领取方式一:
- 扫一扫文末二维码,关注公众号【编程日刊】,后台回复【博客】,即可领取源码
源码领取方式二:
以jpa为持久层源码地址:https://github.com/oneStarLR/myblog-jpa
以mybatis为持久层源码地址:https://github.com/oneStarLR/myblog-mybaits
欢迎给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 ,登录后,点击分类管理,进入分类管理页面,可以对分类进行增、删、改、查
目录结构如下:
至此,分类管理实现完成,下一篇将讲述博客管理
【点关注,不迷路,欢迎持续关注本站】
【SpringBoot搭建个人博客】- 分类管理(六)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.