SpringBoot搭建个人博客v1.0 - 分类管理功能实现(六)

博客管理需要用到 分类 和 标签 所以先做分类管理功能

一、创建持久层(Dao层)


创建接口 TypeRepository 继承 JpaRepository

public interface TypeRepository extends JpaRepository<Type, Long> {

    //根据名称查询Type
    Type findByName(String name);

    //根据每个分类大小由大到小排序取前6个
    @Query("select t from Type t")
    List<Type> findTop(Pageable pageable);

}

二、创建service层


1.定义分类业务层接口

创建分类接口TypeService,定义分类相关的方法

代码如下:


public interface TypeService {

    //新增 保存
    Type saveType(Type type);

    //根据id查询
    Type getType(Long id);

    //根据名字查询
    Type getTypeByName(String name);

    //分页查询
    Page<Type> listType(Pageable pageable);

    //查询全部
    List<Type> listType();

    List<Type> listTypeTop(Integer size);

    //更新
    Type updateType(Long id,Type type);

    //删除
    void deleteType(Long id);
}

2.创建接口的实现类

创建 TypeServiceImpl 实现 用户接口 TypeService
代码如下:

package com.example.service.impl;

import com.example.NotFoundException;
import com.example.dao.TypeRepository;
import com.example.po.Type;
import com.example.service.TypeService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
public class TypeServiceImpl implements TypeService {

    @Autowired
    private TypeRepository typeRepository;

    @Transactional
    @Override
    public Type saveType(Type type) {
        return typeRepository.save(type);
    }

    @Override
    public Type getType(Long id) {
        return typeRepository.findById(id).orElse(null);
    }

    /**
     * 根据名字查信息
     * @param name
     * @return
     */
    @Override
    public Type getTypeByName(String name) {
        return typeRepository.findByName(name);
    }

    /**
     * 分页查询
     * @param pageable
     * @return
     */
    @Transactional
    @Override
    public Page<Type> listType(Pageable pageable) {
        return typeRepository.findAll(pageable);
    }

    /**
     * 查询全部
     * @return
     */
    @Override
    public List<Type> listType() {
        return typeRepository.findAll();
    }

    /**
     * 博客页面   右上角 查询分类
     * @param size
     * @return
     */
    @Override
    public List<Type> listTypeTop(Integer size) {

        // 设置排序对象
        Sort sort = Sort.by(Sort.Direction.DESC,"blogs.size");
        Pageable pageable = PageRequest.of(0, size, sort);
        return typeRepository.findTop(pageable);
    }

    @Transactional
    @Override
    public Type updateType(Long id, Type type) {
        Type t = typeRepository.findById(id).orElse(null);  //根据id查询   存在就更新保存
        if (t ==null ){
            throw new NotFoundException("不存在该类型");
        }
        BeanUtils.copyProperties(type,t);   //将type值赋给t

        return typeRepository.save(t);
    }

    @Transactional
    @Override
    public void deleteType(Long id) {

        typeRepository.deleteById(id);
    }
}

分析:

  • @Service注解:用于标注业务层组件
  • @Autowired注解:@Autowired表示被修饰的类需要注入对象,spring会扫描所有被@Autowired标注的类,然后根据类型在ioc容器中找到匹配的类注入
  • @Transactional注解:实现事务操作

三、分类控制器

创建 TypeController 分类控制器,在这里实现分页查询、添加分类、保存分类、修改分类、删除分类功能,代码如下:

package com.example.web.admin;

import com.example.po.Type;
import com.example.service.TypeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.web.PageableDefault;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.validation.Valid;

@Controller
@RequestMapping("/admin")
public class TypeController {

    @Autowired
    private TypeService typeService;

    /**
     * 分页查询   (显示分类页面)
     * @param pageable
     * @param model
     * @return
     */
    @GetMapping("/types")
    public String types(@PageableDefault(size = 5,sort = {"id"},direction = Sort.Direction.DESC)  //设置pageable 设置排序方式
                                    Pageable pageable, Model model){   //pageable 是已经定义好的,有当前页,页容量,排序字段等属性

        model.addAttribute("page",typeService.listType(pageable));  //往前台传数据   记录页面信息
        return "admin/types";
    }


    /**
     *   添加分类名称   (跳转页面)
     * @return  返回新增页面
     */
    @GetMapping("/types/input")
    public String input(Model model){
        model.addAttribute("type",new Type());  //
        return "admin/types-input";
    }

    /**
     *  跳转修改分类名称   (根据id跳转页面)
     * @param id
     * @param model
     * @return
     */
    @GetMapping("/types/{id}/input")
    public String editInput(@PathVariable Long id, Model model){   // @PathVariable  接收id
        model.addAttribute("type",typeService.getType(id));  //查询需要
        return "admin/types-input";
    }

    /**
     * 保存分类名称    (请求 实现保存)
     * @param type
     * @param result
     * @param attributes
     * @return
     */
    @PostMapping("/types")
    public String post(@Valid Type type, BindingResult result,RedirectAttributes attributes){  // @Valid验证注解  BindingResult校验参数必须跟在Valid后面

        Type type1 = typeService.getTypeByName(type.getName());   //根据名字查询该分类是否存在
        if (type1!=null){
            result.rejectValue("name","nameError","不能添加重复的分类");
        }

        if (result.hasErrors()){
            return "admin/types-input";
        }
        Type t = typeService.saveType(type);
        if (t == null ){
            attributes.addFlashAttribute("message","新增失败");
            //如果 t 为空 则新增失败
        }else{
            attributes.addFlashAttribute("message","新增成功");
        }
        return "redirect:/admin/types";

    }

    /**
     * 更新分类名称   (请求 实现更新)
     * @param type
     * @param result
     * @param id
     * @param attributes
     * @return
     */

    @PostMapping("/types/{id}")
    public String editPost(@Valid Type type, BindingResult result,
                          @PathVariable Long id, RedirectAttributes attributes){

        //查询type是否存在
        Type type1 = typeService.getTypeByName(type.getName());
        if (type1!=null){
            result.rejectValue("name","nameError","不能添加重复的分类");
        }

        if (result.hasErrors()){
            return "admin/types-input";
        }
        Type t = typeService.updateType(id,type);
        if (t == null ){
            attributes.addFlashAttribute("message","更新失败");
            //如果 t 为空 则新增失败
        }else{
            attributes.addFlashAttribute("message","更新成功");
        }
        return "redirect:/admin/types";
    }

    /**
     * 删除分类   (请求)
     * @param id
     * @param attributes
     * @return
     */
    @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后年的参数就可以了

四、前后端交互


1.点击分类

<a href="#" th:href="@{/admin/types}" class=" m-item item m-mobile-hide" th:classappend="${n==2} ? 'active'"><i class="idea icon"></i>分类</a>

2.新增

<a href="#" th:href="@{/admin/types/input}"  class="ui mini right floated teal basic button">新增</a>

3.编辑、删除

 <a href="#" th:href="@{/admin/types/{id}/input(id=${type.id})}" class="ui mini teal basic button">编辑</a>  <!--点击时传递id给后台进行编辑跳转-->
 <a href="#" th:href="@{/admin/types/{id}/delete(id=${type.id})}" class="ui mini red basic button">删除</a>

4.分页

 <div class="ui mini pagination menu" th:if="${page.totalPages}>1">   <!--totalPages存在才显示-->
	<a th:href="@{/admin/types(page=${page.number}-1)}" class="  item" th:unless="${page.first}">上一页</a>
	<a th:href="@{/admin/types(page=${page.number}+1)}" class=" item" th:unless="${page.last}">下一页</a>
</div>

5.操作提示

 <div class="ui success message" th:unless="${#strings.isEmpty(message)}">
	<i class="close icon"></i>
	<div class="header">提示:</div>
	<p th:text="${message}">恭喜,操作成功!</p>
 </div>

标签页面与分类页面相似不做另外的描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值