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_friend
        where id = #{id};
    </select>

    <!--修改友链-->
    <update id="updateFriendLink" parameterType="FriendLink">
        update t_friend
        set blogaddress = #{blogaddress},blogname=#{blogname},pictureaddress=#{pictureaddress}
        where id=#{id};
    </update>

    <delete id="deleteFriendLink">
        delete
        from t_friend
        where 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 {

    @Autowired
    private FriendLinkDao FriendLinkDao;

    @Override
    public List<FriendLink> listFriendLink() {
        return FriendLinkDao.listFriendLink();
    }

    @Override
    public int saveFriendLink(FriendLink friendLink) {
        return FriendLinkDao.saveFriendLink(friendLink);
    }

    @Override
    public FriendLink getFriendLinkByBlogaddress(String blogaddress) {
        return FriendLinkDao.getFriendLinkByBlogaddress(blogaddress);
    }

    @Override
    public FriendLink getFriendLink(Long id) {
        return FriendLinkDao.getFriendLink(id);
    }

    @Override
    public int updateFriendLink(FriendLink friendLink) {
        return FriendLinkDao.updateFriendLink(friendLink);
    }

    @Override
    public 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 {

    @Autowired
    private 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 传对应的 friendlink
        FriendLink 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_picture
        set pictureaddress = #{pictureaddress},picturename=#{picturename},picturedescription=#{picturedescription},picturetime=#{picturetime}
        where id=#{id};
    </update>

    <!--删除照片-->
    <delete id="deletePicture">
        delete
        from t_picture
        where 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 {

    @Autowired
    private PictureDao pictureDao;

    @Override
    public List<Picture> listPicture() {
        return pictureDao.listPicture();
    }

    @Override
    public int savePicture(Picture picture) {
        return pictureDao.savePicture(picture);
    }

    @Override
    public Picture getPicture(Long id) {
        return pictureDao.getPicture(id);
    }

    @Override
    public int updatePicture(Picture picture) {
        return pictureDao.updatePicture(picture);
    }

    @Override
    public 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 {

    @Autowired
    private 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接口即可。


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


效果示例图

在这里插入图片描述

在这里插入图片描述


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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
核心功能 文章/图片/视频发布、喜欢、统计阅读次数。 文章标签tag功能、支持按tag分类 文章支持ueditor/markdown编辑器切换(后台配置) 评论功能,支持回复,支持表情。 第三方(微博、QQ)登录。 lucene实现的站内搜索。 响应式布局 支持用户订阅 先看效果图 SpringBoot开发非常美观的java博客系统(包含后台管理功能) SpringBoot开发非常美观的java博客系统(包含后台管理功能) SpringBoot开发非常美观的java博客系统(包含后台管理功能) http://localhost:8080/admin/group/list SpringBoot开发非常美观的java博客系统(包含后台管理功能) SpringBoot开发非常美观的java博客系统(包含后台管理功能)SpringBoot开发非常美观的java博客系统(包含后台管理功能) 技术选型: JDK8 数据库MySQL 主框架 (Spring-bootSpring-data-jpa) 安全权限 Shiro 搜索工具 Lucene 缓存 Ehcache 视图模板 Freemarker 其它 Jsoup、fastjson jQuery、Seajs Bootstrap 前端框架 UEditor/Markdown编辑器 font-Awesome 字体/图标 准备工作(sql文件在项目里面) 安装 Jdk8 安装 Maven 准备 IDE (如果你不看源码,可以忽略下面的步骤,直接通过Maven编译war包:mvn clean package -DskipTests) IDE 需要配置的东西 编码方式设为UTF-8 配置Maven 设置Jdk8 关于这些配置,网上有一大把的资料,所以此处不再重复。 获取代码导入到IDE 下载代码 导入到IDE的时候请选择以Maven的方式导入 项目配置参考 系统配置手册 配置完毕 启动项目,在控制台看到Mblog加载完毕的信息后,表示启动成功 打开浏览器输入:http//localhost/mblog/ (此处仅是示例,具体具体端口因人而异),访问成功即部署完毕 后台管理的地址是 /admin, 如果你是管理员账号点导航栏的头像会看到"后台管理" 启动成功后,你应该去后台的系统配置里配置你的网站信息等。 常见问题总结 进入系统后, 菜单加载不出来, 那应该是你没有导 db_init.sql 点标签显示乱码, 请设置Tomcat的 URIEncoding 为 UTF-8 项目截图 SpringBoot开发非常美观的java博客系统(包含后台管理功能) 转自:https://gitee.com/mtons/mblog SpringBoot开发非常美观的java博客系统(包含后台管理功能) 注意: 一、java main方式运行mblog-web下的BootApplication.java时抛出异常的解决方案 Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean. SpringBoot开发非常美观的java博客系统(包含后台管理功能) 注释掉后下面图片的这段后,记得maven要重新reimport SpringBoot开发非常美观的java博客系统(包含后台管理功能) SpringBoot开发非常美观的java博客系统(包含后台管理功能) 否则maven依赖不生效还是会抛出以上的异常 二、第三方登录点击后无响应,那是因为第三方开放平台回调的url失效导致,需要你去对应的第三方开放平台注册app后获取对应的oauth帐号 SpringBoot开发非常美观的java博客系统(包含后台管理功能) 三、idea以maven项目导入该项目后,发现没有maven的依赖包时,需要对每个maven module进行clear和install,并且注意maven的依赖顺序 SpringBoot开发非常美观的java博客系统(包含后台管理功能) SpringBoot开发非常美观的java博客系统(包含后台管理功能) 四、访问地址是http://localhost:8080 登录时,帐号,密码只要自己找个密码,然后md5下在更新到db中即可登录成功。 比如:zuidaima 111111,md5后密码是 3931MUEQD1939MQMLM4AISPVNE,md5的javaSpringBoot开发非常美观的java博客系统(包含后台管理功能) SpringBoot开发非常美观的java博客系统(包含后台管理功能)

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值