SpringBoot开源项目个人博客——(8)友链|相册管理

本文主要是介绍SpringBoot开源项目个人博客——(8)友链|相册管理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、友链管理

和分类一样,友链除了基本的增删查改,还要防止友链地址重复

详细分析可看oneStar的博客内容。


这里一次性展示接口的全部代码。

1.DAO持久层

dao包下创建FriendLinkDao接口。

@Mapper
@Repository
public interface FriendLinkDao {//查询友链管理列表List<FriendLink> listFriendLink();//新增友链int saveFriendLink(FriendLink friendLink);//根据网址查询友链FriendLink getFriendLinkByBlogaddress(String blogaddress);//防止重复//根据id查询友链FriendLink getFriendLink(Long id); //编辑时可传入对应分类//编辑修改友链int updateFriendLink(FriendLink friendLink);//删除友链void deleteFriendLink(Long id);
}

2.友链管理mapper

mapper文件夹下创建FriendLinkDao.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.hxj.dao.FriendLinkDao"><!--已经 进行驼峰 转换配置了,不用配置resultMap--><!--查询友链管理列表--><select id="listFriendLink" resultType="FriendLink">select *from t_friend ;</select><!--根据网址查询友链--><select id="getFriendLinkByBlogaddress" resultType="FriendLink">select *from t_friend where blogaddress = #{blogaddress};</select><!--新增友链--><insert id="saveFriendLink" parameterType="FriendLink">insert into t_friend (blogaddress, blogname, create_time, pictureaddress)values (#{blogaddress},#{blogname},#{createTime},#{pictureaddress});</insert><!--根据id查询友链--><select id="getFriendLink" resultType="FriendLink">select *from t_friendwhere id = #{id};</select><!--修改友链--><update id="updateFriendLink" parameterType="FriendLink">update t_friendset blogaddress = #{blogaddress},blogname=#{blogname},pictureaddress=#{pictureaddress}where id=#{id};</update><delete id="deleteFriendLink">deletefrom t_friendwhere id=#{id};</delete></mapper>

3.友链管理Service业务层

service包创建用户业务层接口FriendLinkService

public interface FriendLinkService {//查询友链管理列表List<FriendLink> listFriendLink();//新增友链int saveFriendLink(FriendLink friendLink);//根据网址查询友链FriendLink getFriendLinkByBlogaddress(String blogaddress);//根据id查询友链FriendLink getFriendLink(Long id);//编辑修改友链int updateFriendLink(FriendLink friendLink);//删除友链void deleteFriendLink(Long id);}

接口实现类impl

impl子包,在其中创建用户业务层接口实现类FriendLinkServiceImpl

@Service
public class FriendLinkServiceImpl implements FriendLinkService {@Autowiredprivate FriendLinkDao FriendLinkDao;@Overridepublic List<FriendLink> listFriendLink() {return FriendLinkDao.listFriendLink();}@Overridepublic int saveFriendLink(FriendLink friendLink) {return FriendLinkDao.saveFriendLink(friendLink);}@Overridepublic FriendLink getFriendLinkByBlogaddress(String blogaddress) {return FriendLinkDao.getFriendLinkByBlogaddress(blogaddress);}@Overridepublic FriendLink getFriendLink(Long id) {return FriendLinkDao.getFriendLink(id);}@Overridepublic int updateFriendLink(FriendLink friendLink) {return FriendLinkDao.updateFriendLink(friendLink);}@Overridepublic void deleteFriendLink(Long id) {FriendLinkDao.deleteFriendLink(id);}
}

4.友链管理Controller控制器

同理的页面跳转也使用了局部刷新,虽然冗余了点。

在这里插入图片描述

定义要更新区域成一个fragment:

分页前端改动:

<input type="hidden" name="page" >
...
...
...<div class="two wide column" align="center"><a class="item" style="cursor: pointer" onclick="page(this)" th:attr="data-page=1" th:unless="${pageInfo.isFirstPage}">首页</a>
</div><div class="two wide column" align="center"><a class="item" style="cursor: pointer" onclick="page(this)" th:attr="data-page=${pageInfo.hasPreviousPage}?${pageInfo.prePage}:1" th:unless="${pageInfo.isFirstPage}">上一页</a>
</div><div class="eight 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="two wide column " align="center"><a class="item" style="cursor: pointer" onclick="page(this)" th:attr="data-page=${pageInfo.hasNextPage}?${pageInfo.nextPage}:${pageInfo.pages}" th:unless="${pageInfo.isLastPage}">下一页</a>
</div><div class="two wide column " align="center"><a class="item" style="cursor: pointer" onclick="page(this)" th:attr="data-page=${pageInfo.pages}" th:unless="${pageInfo.isLastPage}">尾页</a>
</div>

JS部分新增:

      function page(obj) {$("[name='page']").val($(obj).data("page"));loaddata();}function loaddata() {$("#types-container").load(/*[[@{/admin/refreshType}]]*/"/admin/refreshType",{pageNum : $("[name='page']").val()});}

controller.admin包下,创建FriendLinkController,代码如下:

和oneStar博客不同的是,在修改友链时,地址的查重判断不判断本身的(只判断除自身外的其他友链是否重复即可)。

@Controller
@RequestMapping("/admin")
public class FriendLinkController {@Autowiredprivate FriendLinkService FriendLinkService;//友链管理界面@GetMapping("/friendlinks")public String list(Model model, @RequestParam(defaultValue = "1", value = "pageNum") Integer pageNum) {String orderBy = "create_time desc";PageHelper.startPage(pageNum, 5, orderBy);List<FriendLink> friendLinks = FriendLinkService.listFriendLink();PageInfo<FriendLink> pageInfo = new PageInfo<>(friendLinks);model.addAttribute("pageInfo", pageInfo);return "admin/friendlinks";}//有点冗余,不想优化, 有人看到可以自行优化@PostMapping("/refreshFriend")public String refreshFriend(Model model, @RequestParam(defaultValue = "1", value = "pageNum") Integer pageNum){String orderBy = "create_time desc";PageHelper.startPage(pageNum, 5, orderBy);List<FriendLink> friendLinks = FriendLinkService.listFriendLink();PageInfo<FriendLink> pageInfo = new PageInfo<>(friendLinks);model.addAttribute("pageInfo", pageInfo);return "admin/friendlinks :: friendlink-list";}//跳转到 新增页面@GetMapping("friendlinks/input")public String input(Model model) {model.addAttribute("friendLink", new FriendLink());return "admin/friendlinks-input";}//提交新增@PostMapping("/friendlinks")public String post(@Valid FriendLink friendLink, BindingResult result, RedirectAttributes attributes) {if(result.hasErrors()){//校验出来,发现问题,把message传前端System.out.println(result);return "admin/friendlinks-input";}FriendLink friendLink1 = FriendLinkService.getFriendLinkByBlogaddress(friendLink.getBlogaddress());if (friendLink1 != null) {attributes.addFlashAttribute("message", "不能添加相同地址的友链");return "redirect:/admin/friendlinks/input";}friendLink.setCreateTime(new Date());int i = FriendLinkService.saveFriendLink(friendLink);if (i == 0) {attributes.addFlashAttribute("message", "添加失败");} else {attributes.addFlashAttribute("message", "添加成功");}return "redirect:/admin/friendlinks";}//编辑 友链@GetMapping("/friendlinks/{id}/input")public String editInput(@PathVariable("id") Long id, Model model) {//根据id 传对应的 friendlinkFriendLink friendLink = FriendLinkService.getFriendLink(id);model.addAttribute("friendLink", friendLink);return "admin/friendlinks-input";}//提交修改友链@PostMapping("/friendlinks/{id}")public String editPost(@Valid FriendLink friendLink, BindingResult result, RedirectAttributes attributes) {if(result.hasErrors()){//校验出来,发现问题,把message传前端System.out.println(result);return "admin/friendlinks-input";}//友链的地址不能和 除自己之外的 重复(特判)FriendLink friendLink1 = FriendLinkService.getFriendLinkByBlogaddress(friendLink.getBlogaddress());if (friendLink1 != null) {if (friendLink1.getId().equals(friendLink.getId())) {//同一个就不用特判了} else {//如果是和不同 友链冲突attributes.addFlashAttribute("message", "不能添加重复的友链地址");return "redirect:/admin/friendlinks/{id}/input"; //回到新增(有id还是进 编辑)页面}}int i = FriendLinkService.updateFriendLink(friendLink);if (i == 0) {attributes.addFlashAttribute("message", "编辑失败");} else {attributes.addFlashAttribute("message", "编辑成功");}return "redirect:/admin/friendlinks"; //回到展示列表}//删除 友链@GetMapping("/friendlinks/{id}/delete")public String delete(@PathVariable("id") Long id, RedirectAttributes attributes) {FriendLinkService.deleteFriendLink(id);attributes.addFlashAttribute("message", "删除成功");return "redirect:/admin/friendlinks";}}

二、相册管理

同理,除了基本的增删查改,但不需要做图片链接的查重,有该需求者自行修改。

1.DAO持久层

dao包下创建PictureDao接口,代码如下:

@Mapper
@Repository
public interface PictureDao {//图片列表List<Picture> listPicture();//添加图片int savePicture(Picture picture);//根据id查询图片Picture getPicture(Long id);//编辑修改相册int updatePicture(Picture picture);//删除照片void deletePicture(Long id);
}

2.友链管理mapper

mapper文件夹下创建PictureDao.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.hxj.dao.PictureDao"><!--图片列表--><select id="listPicture" resultType="Picture">select *from t_picture ;</select><!--添加图片--><insert id="savePicture" parameterType="Picture">insert into t_picture (pictureaddress, picturedescription, picturename, picturetime)values (#{pictureaddress},#{picturedescription},#{picturename},#{picturetime});</insert><!--根据id查询图片--><select id="getPicture" resultType="Picture">select *from t_picture where  id = #{id};</select><!--编辑修改相册--><update id="updatePicture" parameterType="Picture">update t_pictureset pictureaddress = #{pictureaddress},picturename=#{picturename},picturedescription=#{picturedescription},picturetime=#{picturetime}where id=#{id};</update><!--删除照片--><delete id="deletePicture">deletefrom t_picturewhere id=#{id};</delete></mapper>

3.图片管理Service业务层

service包创建用户业务层接口PictureService

public interface PictureService {//图片列表List<Picture> listPicture();//添加图片int savePicture(Picture picture);//根据id查询图片Picture getPicture(Long id);//编辑修改相册int updatePicture(Picture picture);//删除照片void deletePicture(Long id);
}

接口实现类impl

impl子包,在其中创建用户业务层接口实现类PictureServiceImpl

@Service
public class PictureServiceImpl implements PictureService {@Autowiredprivate PictureDao pictureDao;@Overridepublic List<Picture> listPicture() {return pictureDao.listPicture();}@Overridepublic int savePicture(Picture picture) {return pictureDao.savePicture(picture);}@Overridepublic Picture getPicture(Long id) {return pictureDao.getPicture(id);}@Overridepublic int updatePicture(Picture picture) {return pictureDao.updatePicture(picture);}@Overridepublic void deletePicture(Long id) {pictureDao.deletePicture(id);}
}

4.图片管理Controller控制器

同理的页面跳转也使用了局部刷新,虽然冗余了点。

在这里插入图片描述

定义要更新区域成一个fragment:

分页前端改动:

<input type="hidden" name="page" >
...
...
...
<div class="two wide column" align="center"><a class="item" style="cursor: pointer" onclick="page(this)" th:attr="data-page=1" th:unless="${pageInfo.isFirstPage}">首页</a>
</div><div class="two wide column" align="center"><!--<a class="item" th:href="@{/admin/blogs(pageNum=${pageInfo.hasPreviousPage}?${pageInfo.prePage}:1)}" th:unless="${pageInfo.isFirstPage}">上一页</a>--><a class="item" style="cursor: pointer" onclick="page(this)" th:attr="data-page=${pageInfo.hasPreviousPage}?${pageInfo.prePage}:1" th:unless="${pageInfo.isFirstPage}">上一页</a>
</div><div class="eight 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="two wide column " align="center"><!--<a class="item" th:href="@{/admin/blogs(pageNum=${pageInfo.hasNextPage}?${pageInfo.nextPage}:${pageInfo.pages})}" th:unless="${pageInfo.isLastPage}">下一页</a>--><a class="item" style="cursor: pointer" onclick="page(this)" th:attr="data-page=${pageInfo.hasNextPage}?${pageInfo.nextPage}:${pageInfo.pages}" th:unless="${pageInfo.isLastPage}">下一页</a>
</div><div class="two wide column " align="center"><a class="item" style="cursor: pointer" onclick="page(this)" th:attr="data-page=${pageInfo.pages}" th:unless="${pageInfo.isLastPage}">尾页</a>
</div>
</div><div align="center"><a href="#" th:href="@{/admin/pictures/input}"><button type="button" class="ui teal button m-mobile-wide m-margin-top"><i class="pencil icon"></i>新增</button></a>
</div>

JS部分新增:

      function page(obj) {$("[name='page']").val($(obj).data("page"));loaddata();}function loaddata() {$("#picture-container").load(/*[[@{/admin/refreshPicture}]]*/"/admin/refreshPicture",{pageNum : $("[name='page']").val()});}

controller.admin包下,创建PictureController,代码如下:

@Controller
@RequestMapping("/admin")
public class PictureController {@Autowiredprivate PictureService pictureService;//图片 管理列表(分页)@GetMapping("/pictures")public String list(Model model,@RequestParam(defaultValue = "1",value = "pageNum") Integer pageNum){//已经规定按照数据库id降序String orderBy ="id desc";PageHelper.startPage(pageNum,2,orderBy);List<Picture> pictures = pictureService.listPicture();PageInfo<Picture> pageInfo = new PageInfo<>(pictures); //封装查询信息model.addAttribute("pageInfo", pageInfo);return "admin/pictures";}@PostMapping("/refreshPicture")public String refreshPicture(Model model,@RequestParam(defaultValue = "1",value = "pageNum") Integer pageNum){//已经规定按照数据库id降序String orderBy ="id desc";PageHelper.startPage(pageNum,2,orderBy);List<Picture> pictures = pictureService.listPicture();PageInfo<Picture> pageInfo = new PageInfo<>(pictures); //封装查询信息model.addAttribute("pageInfo", pageInfo);return "admin/pictures :: pictureList";}//进入新增页面@GetMapping("/pictures/input")public String input(Model model){model.addAttribute("picture", new Picture());return "admin/pictures-input";}//提交新增(先不做后端校验)@PostMapping("/pictures")public String post(@Valid Picture picture, BindingResult result, RedirectAttributes attributes){if(result.hasErrors()){return "admin/pictures-input";}int i = pictureService.savePicture(picture);if(i==0){attributes.addFlashAttribute("message","新增失败");}else {attributes.addFlashAttribute("message","新增成功");}return "redirect:/admin/pictures"; //返回列表}//进入修改界面@GetMapping("/pictures/{id}/input")public String editInput(@PathVariable("id")Long id,Model model){Picture picture = pictureService.getPicture(id);model.addAttribute("picture",picture);return "/admin/pictures-input";}//提交修改@PostMapping("/pictures/{id}")public String editPost(@Valid Picture picture, BindingResult result,RedirectAttributes attributes){if(result.hasErrors()){return "admin/pictures-input";}int i = pictureService.updatePicture(picture);if(i==0){attributes.addFlashAttribute("message","编辑失败");}else{attributes.addFlashAttribute("message","编辑成功");}return "redirect:/admin/pictures";}@GetMapping("/pictures/{id}/delete")public String delete(@PathVariable("id")Long id,RedirectAttributes attributes){pictureService.deletePicture(id);attributes.addFlashAttribute("message","删除成功");return "redirect:/admin/pictures";}
}

小结

至此,后台功能的实现已经全部完成

四个管理模块都能实现基本的【增删改查】功能,都是能局部刷新实现分页。

目前只有博客模块用到了搜索,其余模块没有,若想实现其余模块的搜索功能,可以仿照博客模块。改动前端和controller接口即可。


目前图像相关的都使用了项目内部的资源(若有图床也可以更换为远程资源)


效果示例图

在这里插入图片描述

在这里插入图片描述


下一阶段将开始进行前台功能的实现。

这篇关于SpringBoot开源项目个人博客——(8)友链|相册管理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/203667

相关文章

Java 正则表达式URL 匹配与源码全解析

《Java正则表达式URL匹配与源码全解析》在Web应用开发中,我们经常需要对URL进行格式验证,今天我们结合Java的Pattern和Matcher类,深入理解正则表达式在实际应用中... 目录1.正则表达式分解:2. 添加域名匹配 (2)3. 添加路径和查询参数匹配 (3) 4. 最终优化版本5.设计思

Java使用ANTLR4对Lua脚本语法校验详解

《Java使用ANTLR4对Lua脚本语法校验详解》ANTLR是一个强大的解析器生成器,用于读取、处理、执行或翻译结构化文本或二进制文件,下面就跟随小编一起看看Java如何使用ANTLR4对Lua脚本... 目录什么是ANTLR?第一个例子ANTLR4 的工作流程Lua脚本语法校验准备一个Lua Gramm

Java字符串操作技巧之语法、示例与应用场景分析

《Java字符串操作技巧之语法、示例与应用场景分析》在Java算法题和日常开发中,字符串处理是必备的核心技能,本文全面梳理Java中字符串的常用操作语法,结合代码示例、应用场景和避坑指南,可快速掌握字... 目录引言1. 基础操作1.1 创建字符串1.2 获取长度1.3 访问字符2. 字符串处理2.1 子字

Java Optional的使用技巧与最佳实践

《JavaOptional的使用技巧与最佳实践》在Java中,Optional是用于优雅处理null的容器类,其核心目标是显式提醒开发者处理空值场景,避免NullPointerExce... 目录一、Optional 的核心用途二、使用技巧与最佳实践三、常见误区与反模式四、替代方案与扩展五、总结在 Java

基于Java实现回调监听工具类

《基于Java实现回调监听工具类》这篇文章主要为大家详细介绍了如何基于Java实现一个回调监听工具类,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录监听接口类 Listenable实际用法打印结果首先,会用到 函数式接口 Consumer, 通过这个可以解耦回调方法,下面先写一个

使用Java将DOCX文档解析为Markdown文档的代码实现

《使用Java将DOCX文档解析为Markdown文档的代码实现》在现代文档处理中,Markdown(MD)因其简洁的语法和良好的可读性,逐渐成为开发者、技术写作者和内容创作者的首选格式,然而,许多文... 目录引言1. 工具和库介绍2. 安装依赖库3. 使用Apache POI解析DOCX文档4. 将解析

Java字符串处理全解析(String、StringBuilder与StringBuffer)

《Java字符串处理全解析(String、StringBuilder与StringBuffer)》:本文主要介绍Java字符串处理全解析(String、StringBuilder与StringBu... 目录Java字符串处理全解析:String、StringBuilder与StringBuffer一、St

springboot整合阿里云百炼DeepSeek实现sse流式打印的操作方法

《springboot整合阿里云百炼DeepSeek实现sse流式打印的操作方法》:本文主要介绍springboot整合阿里云百炼DeepSeek实现sse流式打印,本文给大家介绍的非常详细,对大... 目录1.开通阿里云百炼,获取到key2.新建SpringBoot项目3.工具类4.启动类5.测试类6.测

Spring Boot循环依赖原理、解决方案与最佳实践(全解析)

《SpringBoot循环依赖原理、解决方案与最佳实践(全解析)》循环依赖指两个或多个Bean相互直接或间接引用,形成闭环依赖关系,:本文主要介绍SpringBoot循环依赖原理、解决方案与最... 目录一、循环依赖的本质与危害1.1 什么是循环依赖?1.2 核心危害二、Spring的三级缓存机制2.1 三

使用Python构建一个Hexo博客发布工具

《使用Python构建一个Hexo博客发布工具》虽然Hexo的命令行工具非常强大,但对于日常的博客撰写和发布过程,我总觉得缺少一个直观的图形界面来简化操作,下面我们就来看看如何使用Python构建一个... 目录引言Hexo博客系统简介设计需求技术选择代码实现主框架界面设计核心功能实现1. 发布文章2. 加