【个人实践】基于SpringBoot+Thymeleaf+Mysql 的博客管理系统

1、前期分析
(1) 界面
  • 前端界面

前端使用网站下载的博客系统,主要任务实现后台 blog系统前端

界面:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述在这里插入图片描述

  • 后端界面

    后端界面同样是用网站模板 后端界面

在这里插入图片描述

(2) 功能分析
  • 主页分析

    • 首页该有的功能:

      1 统计信息 获取当前所有博客数,以及某一天起到当前天的天数

      2 推荐博客 点赞数最多的博客并且设置为可推荐状态

      3 最新发布 根据发布时间进行排序展示,并分类

      4 最新评论文章 根据评论时间进行排序展示

      5 搜索功能 模糊查询,根据文章内容和文章标题同时搜索

      6 博客详情 点击进入博客详情界面

      7 登陆

    • 列表页

      1 种类分类展示

      2 显示标签分类

      3 最新评论文章

      4 搜索

    • 详细页

      1 展示文章

      2 最新评论文章

      3 推荐文章(选择和该文章同一分类和标签下的文章进行推荐

      4 搜索

      5 评论

  • 用户分析

根据界面分析分为普通用户和管理员用户两种使用模式

未登录情况:

​ 可以浏览主页和博客详情,可以看到评论,可以点赞,但要发表评论和发表博客,需要登陆

普通用户:

​ 可以浏览主页、可以评论、可以发表博客

管理员:

​ 可以浏览主页、可以评论、可以发表博客、可以管理博客、可以管理用户

(3) 实体分析

用户(id 用户名 昵称 密码 头像 是否管理员 电话 创建时间 更新时间 博客集)

User(id username nickname password image admin phone createTime updateTime blogList)

博客(id 标题 内容 首图 点赞数 能否评论 是否推荐 评论数量 种类 标签集 评论集 创建时间 更新时间 评论更新时间 作者)

Blog(id title content firstImg praiseNum commentable Recommend countComment type Tags comments createTime updateTime commentUpdateTime author)

分类(id 名称 博客集)

Type(id name blogList)

标签(id 名称 博客集)

Tag (id name blogList)

评论(id 用户昵称 电话 内容 头像 创建时间 博客)

Comment(id nickname phone content image createTime blog)

(4)实体ER图、功能图
  • E-R图

在这里插入图片描述

  • 功能图

在这里插入图片描述

2、功能实现模块
(1) 登陆注册

界面展示:

在这里插入图片描述

在这里插入图片描述

功能介绍:

用户使用系统评论功能、管理员使用后台管理功能必须登录才能使用,注册功能部分默认注册的新用户为普通用户。

流程:新建User实体类 -> 新建UserDAO层接口继承JPA -> 新建Service业务层接口和实现方法 -> 新建控制层 -> 和前端数据交互。

(2) 个人信息管理

界面展示:

在这里插入图片描述

在这里插入图片描述

功能介绍:

包含基础信息修改和密码修改,基础信息修改部分将用户名和是否管理员设置为不可修改状态,修改密码时会在前端js中进行判断两次输入的密码是否一致。

流程: UserDAO层接口继承JPA -> 声明查找当前用户方法 -> 新建Service业务层接口和实现方法 -> 新建控制层监听路由 -> 和前端数据交互

(3) 后端管理

用户在登陆时会先根据在数据库中的信息判断当前是否是管理员,如果是即显示后台管理图标,否即没有权限进入后台

在这里插入图片描述

在这里插入图片描述

管理员后台系统

主页:

在这里插入图片描述

目前用户的CRUD和博客的CRUD功能都已实现,还在主页显示处当前数据库的博客数量、用户数量和评论数量,点赞数量是一个假数据,点赞的功能目前还有一些问题。

流程:在dao层声明用户、博客、评论继承jpa方法,再在业务层声明查询方法,最后在controller层中调用几种方法并将获取到的信息储存到model中,跳转到该html界面进行显示

(4) 管理员端用户信息管理

点击主页的用户管理即可跳转到当前界面(由于给前端添加图标的时候只在主页试验了一下,忘记在每个页面加上了)

用户信息管理里的功能主要有:新增用户、编辑用户、删除用户,查询用户功能在前端模板中已经实现了,新增用户的方法和之前注册一样,编辑用户需要先根据该用户id进行查询,并将查询到的信息显示到界面中,点击提交按钮,在控制器中判断当前用户是否id为空,为空则为新增用户调用注册方法,不是为空则更新一些数据(更新时间等)对数据库进行更新操作。

在这里插入图片描述

新增用户:

在这里插入图片描述

编辑用户:

在这里插入图片描述

(5) 新增博客

在新增博客界面将标签、分类、博客都放到一个界面中进行添加操作,点击相应板块的添加按钮实现相应的功能。

新增博客、新增分类信息、新增标签信息等都是和注册功能类似,都是html界面 -> controller -> Service -> Dao。

此处的博客文本使用了一个工具类MarkdownUtils。
在这里插入图片描述

在这里插入图片描述

(6) 博客管理

主要功能:博客编辑、博客删除、跳转到博客添加;分类编辑、删除、跳转到添加;标签编辑、删除、跳转到添加;

和用户管理原理一样、先查询到该id下的信息,进行编辑、判断id、保存。

在这里插入图片描述

在这里插入图片描述

(7) 博客修改页

主要流程:获取当前博客id -> controller使用根据id查询功能 -> Service使用查询功能 -> dao使用查询返回结果 ->controller保存结果到一个blog对象中 -> 前端显示该blog对象参数 -> 修改 -> 保存

在这里插入图片描述

(8) 博客图廊

图廊功能是根据每条博客中的图片显示,点击图片进入相应的新闻详情界面

主要实现方法:将数据库中blog的image属性放到一个list中,再在前端遍历显示该list

跳转到的详情界面由于部分数据没有删除,所有存在很多假数据。

在这里插入图片描述
在这里插入图片描述

(9) 博客详情页

该部分是前端的博客详情界面,根据点击的博客按钮进行查询显示,在标题下显示更新时间、作者、分类、点赞数量、评论数等,右边根据最新评论时间进行排序显示,还可以查询当前新闻的评论,按更新时间进行显示
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

(10) 首页三模块功能
  • 最新发布

    根据博客的更新时间进行排序,每篇博客在编辑时都会刷新更新时间

  • 推荐文章

    更具博客的推荐属性进行排序,但由于界面设计,所以这里只能显示一篇,即推荐状态下最近更新的一篇博客

  • 最新评论文章

    在博客实体中加入了评论更新时间属性,即用来存放最后一次评论的时间,根据该时间进行排序显示

在这里插入图片描述

在这里插入图片描述

(11) 列表页

列表页其实和主页差不多,只不过这里显示了当前数据库中的所有标签信息(404是假数据)
在这里插入图片描述

(12)错误界面

当界面发生错误的时候(例如评论时是未登录状态),会显示错误界面,错误界面的好处就是对用户更加友好
在这里插入图片描述

(13) 评论功能

评论板块会显示在每个blog的下方,不论是否登录都会看到该博客的评论信息,但是要发表评论必须是登陆状态,登录状态下会自动在昵称和电话输入框下显示当前用户信息。

在这里插入图片描述

在这里插入图片描述

(14) 登录拦截 / 异常处理

登录拦截主要是防止用户直接进入后端管理界面,在登陆拦截时拦截了所有的未登录状态下包含/admin的所有路径,进入管理员界面需要登陆、判断是否是管理员是的话给进入后台接口,进入后台管理。

异常处理即前面的404界面部分,用一个友好的界面反馈到系统中。

3、重要代码
(1)前端部分

​ 前端部分涉及到的代码非常多,上传到了github,文末贴出github地址,主要目录如下
在这里插入图片描述

(2)实体类
  • Blog类

    @Entity
    @Table(name = "b_blog")
    public class Blog {
    
        @Id //主键标识
        @GeneratedValue(strategy = GenerationType.IDENTITY)  //自增
        private Long id;
        private String title;
        private String content;
        private String firstImg;
        private Integer praiseNum;
        private boolean commentabled;
        private boolean recommend; //推荐
        private Integer countComment;//评论数
    
        @ManyToOne  //分类集
        private Type type;
    
        @ManyToMany(cascade = CascadeType.PERSIST)   //标签集 指定级联  给当前设置的实体操作另一个实体的权限
        private List<Tag> tags = new ArrayList<>();
    
        @ManyToOne  //作者
        private User user;
    
        private String author;
    
        @Transient  //表示不会在数据库中生成这个字段  只存在于本实体中
        private String tagIds;
    
        public Blog() {
        }
    
        @Temporal(TemporalType.TIMESTAMP) //指定时间戳
        private Date createTime;
        @Temporal(TemporalType.TIMESTAMP) //指定时间戳
        private Date updateTime;
        @Temporal(TemporalType.TIMESTAMP) //指定时间戳
        private Date commentUpdateTime;
    
        //对一对多的标签进行处理  如一个博客有id为12345的tag  初始化为 1,2,3,4,5
        public void init(){
            this.tagIds = tagsToIds(this.getTags());
        }
    
        private String tagsToIds(List<Tag> tags){
            if(!tags.isEmpty()){
                StringBuffer ids = new StringBuffer();
                boolean flag = false;
                for(Tag tag:tags){
                    if(flag){
                        ids.append(",");
                    }else{
                        flag = true;
                    }
                    ids.append(tag.getId());
                }
                return ids.toString();
            }else{
                return tagIds;
            }
        }
    }
    //手动添加setter and getter  和 toString
    
  • User类

    @Entity
    @Table(name = "b_user")
    public class User {
        @Id //主键标识
        @GeneratedValue(strategy = GenerationType.IDENTITY)  //自增
        private Long id;
        private String username;
        private String nickname;
        private String password;
        private String image;
        private Boolean admin;
        private String phone;
        @Temporal(TemporalType.TIMESTAMP) //指定时间戳
        private Date createTime;
        @Temporal(TemporalType.TIMESTAMP) //指定时间戳
        private Date updateTime;
    
        //一对多关系的新闻
        @OneToMany(mappedBy = "user")
        private List<Blog> blogList = new ArrayList<>();
        //手动添加setter and getter  和 toString
    }
    
  • Type类

@Entity
@Table(name = "b_type")
public class Type {

    @Id
    @GeneratedValue(strategy =  GenerationType.IDENTITY)  //自增
    private Long id;
    @NotBlank(message = "分类名称不能为空")
    private String name;

    @OneToMany(mappedBy = "type")
    private List<Blog> blogList = new ArrayList<>();
    //手动添加setter and getter  和 toString
}
  • Tag类
@Entity
@Table(name = "b_tag")
public class Tag {

    @Id
    @GeneratedValue(strategy =  GenerationType.IDENTITY)  //自增
    private Long id;
    @NotBlank(message = "标签名称不能为空")
    private String name;

    @ManyToMany(mappedBy = "tags")
    private List<Blog> blogList = new ArrayList<>();
    //手动添加setter and getter  和 toString
}
  • Comment类
@Entity
@Table(name = "b_comment")
public class Comment {

    @Id //主键标识
    @GeneratedValue(strategy = GenerationType.IDENTITY)  //自增
    private Long id;
    private String nickname;
    private String phone;
    private String content;
    private String image;//头像
    @Temporal(TemporalType.TIMESTAMP)
    private Date createTime;

    @ManyToOne
    private Blog blog;

    //管理员评论
    private boolean adminComment;
    //手动添加setter and getter  和 toString
}
(3)Dao层

因为很多方法是封装好在JPA中的了,所以不需要太多的方法声明

BlogRepository:

public interface BlogRepository extends JpaRepository<Blog,Long> {

    //找到推荐状态下最新更新的
    @Query("select  b from  Blog b where b.recommend = true")
    List<Blog> findTop(Pageable pageable);

    //找到评论时间排序的博客
    @Query("select b from Blog b")
    List<Blog> findTopByCommentUpdateTime(Pageable pageable);
}

CommentRepository:

public interface CommentRepository extends JpaRepository<Comment,Long> {

    List<Comment> findByBlogId(Long id, Sort sort);

    //查当前博客下有多少评论
    @Query("select count(c) from Comment c where blog_id = ?1")
    Integer countCommentsByBlogId(Long id);
}

TagRepository:

public interface TagRepository extends JpaRepository<Tag,Long> {
    //根据标签下的博客数排
    @Query("select t from Tag t")
    List<Tag> findTop(Pageable pageable);
}

TypeRepository:

public interface TypeRepository extends JpaRepository<Type,Long> {
}

UserRepository:

public interface UserRepository extends JpaRepository<User, Long> {

    //登陆操作   根据同户名和密码返回数据库的数据
    User findByUsernameAndPassword(String username,String password);
    //注册操作  查找当前用户名是否存在
    User findByUsername(String username);
    //输入用户名或昵称内容查询
    @Query("select u from User u where u.username like ?1 or u.nickname like ?1")
    Page<User> findByQuery(String query, Pageable pageable);
}
(4)Service层

BlogService:

public interface BlogService {
    //保存博客(更新更新时间)
    Blog saveBlog(Blog blog);
    //保存博客(更新评论时间)
    Blog saveBlogByCommentTime(Blog blog);
    //列出所有博客
    List<Blog> listBlog();
    //获取博客跳转
    Blog getAndConvert(Long id);
    //根据id删除博客
    void deleteById(Long id);
    //根据id查询博客
    Blog findById(Long id);
    //更新用户个人信息
    Blog updateBlog(Long id,Blog blog);
    //分页列出所有博客
    Page<Blog> listBlog (Pageable pageable);
    //推荐博客
    List<Blog> recommendBlogTop();
    //评论时间排序博客
    List<Blog> commentBlogTop();
}

BlogServiceImpl:

@Service
public class BlogServiceImpl implements BlogService {

    @Autowired
    private BlogRepository blogRepository;

    @Autowired
    private CommentRepository commentRepository;

    @Override
    public Blog saveBlog(Blog blog) {
        blog.setUpdateTime(new Date());
        return blogRepository.save(blog);
    }

    @Override
    public Blog saveBlogByCommentTime(Blog blog) {
        blog.setCommentUpdateTime(new Date());
        return blogRepository.save(blog);
    }

    @Override
    public List<Blog> listBlog() {
        return blogRepository.findAll();
    }

    @Override
    public Blog getAndConvert(Long id) {
        Blog blog = blogRepository.findById(id).orElse(null);
        if(blog==null){
            System.out.println("该博客不存在");
        }
        Blog blog1 = new Blog();
        blog1.setCountComment(commentRepository.countCommentsByBlogId(id));
        BeanUtils.copyProperties(blog,blog1);
        String content = blog1.getContent();
        blog1.setContent(MarkdownUtils.markdownToHtmlExtensions(content));
        return blog1;
    }

    @Override
    public void deleteById(Long id) {
        blogRepository.deleteById(id);
    }

    @Override
    public Blog findById(Long id) {
        return blogRepository.findById(id).orElse(null);
    }

    @Override
    public Blog updateBlog(Long id, Blog blog) {
        Blog blog1 = blogRepository.findById(id).orElse(null);
        if(blog1==null){
            System.out.println("获取更新对象失败");
        }else{
            blog.setUpdateTime(new Date());
            BeanUtils.copyProperties(blog,blog1, MyBeanUtils.getNullPropertyNames(blog));

        }
        return blogRepository.save(blog1);
    }

    @Override
    public Page<Blog> listBlog(Pageable pageable) {
        return blogRepository.findAll(pageable);
    }

    @Override
    public List<Blog> recommendBlogTop() {
        Sort sort =Sort.by(Sort.Direction.DESC,"updateTime");
        Pageable pageable = PageRequest.of(0,1,sort);
        return blogRepository.findTop(pageable);
    }

    @Override
    public List<Blog> commentBlogTop() {
        Sort sort = Sort.by(Sort.Direction.DESC,"commentUpdateTime");
        Pageable pageable = PageRequest.of(0,5,sort);
        return blogRepository.findTopByCommentUpdateTime(pageable);
    }
}

UserService:

public interface UserService {

    //登陆操作  检查用户名和密码是否一致
    User checkUser(String username,String password);
    //根据用户名查找用户
    User findUserByUserName(String username);
    //注册
    void register(User user);
    //获取用户个人信息
    User getUserInfo(Long id);
    //更新用户个人信息
    User updateUser(Long id,User user);
    //分页展示所有用户信息
    Page<User> listUser(Pageable pageable);
    //根据用户id删除用户
    void deleteByUserId(Long id);
    //根据内容搜索
    Page<User> listUser(String query,Pageable pageable);

}

UserServiceImpl:

@Service
public class UserServiceImpl implements UserService {

    //注入dao层
    @Autowired
    private UserRepository userRepository;

    @Override
    public User checkUser(String username, String password) {
        return userRepository.findByUsernameAndPassword(username,password);
    }

    @Override
    public User findUserByUserName(String username) {
        return userRepository.findByUsername(username);
    }

    @Override
    public void register(User user) {
        user.setAdmin(false);  //注册默认为普通用户
        user.setCreateTime(new Date());
        user.setUpdateTime(new Date());
        userRepository.save(user);
    }

    @Override
    public User getUserInfo(Long id) {
        return userRepository.findById(id).orElse(null);
    }

    @Override
    public User updateUser(Long id, User user) {
        User user1 = userRepository.findById(id).orElse(null);
        if(user1 == null){
            System.out.println("获取更新对象失败");
        }else{
            BeanUtils.copyProperties(user,user1, MyBeanUtils.getNullPropertyNames(user));
            user1.setUpdateTime(new Date());
        }
        return userRepository.save(user1);
    }

    @Override
    public Page<User> listUser(Pageable pageable) {
        return userRepository.findAll(pageable);
    }

    @Override
    public void deleteByUserId(Long id) {
        userRepository.deleteById(id);
    }

    @Override
    public Page<User> listUser(String query, Pageable pageable) {
        return userRepository.findByQuery(query,pageable);
    }
}

TypeService:

public interface TypeService {

    //查找所有type
    List<Type> listType();
    //保存分类
    void saveType(Type type);
    //根据id查询分类
    Type findById(Long id);
    //更新分类
    Type updateType(Long id,Type type);
    //根据id删除分类
    void deleteById(Long id);
}

TypeServiceImpl:

@Service
public class TypeServiceImpl implements TypeService {

    @Autowired
    private TypeRepository typeRepository;

    @Override
    public List<Type> listType() {
        return typeRepository.findAll();
    }

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

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

    @Override
    public Type updateType(Long id, Type type) {
        Type type1 = typeRepository.findById(id).orElse(null);
        if(type1==null){
            System.out.println("获取更新对象失败");
        }else{
            BeanUtils.copyProperties(type,type1, MyBeanUtils.getNullPropertyNames(type));
        }
        return typeRepository.save(type1);
    }

    @Override
    public void deleteById(Long id) {
        typeRepository.deleteById(id);
    }
}

TagService:

public interface TagService {

    //查找所有Tag
    List<Tag> listTag();
    //查找所有Tag(新建时)
    List<Tag> listTag(String ids);
    //保存标签
    void saveTag(Tag tag);
    //根据id查询标签
    Tag findById(Long id);
    //更新分类
    Tag updateTag(Long id,Tag type);
    //根据id删除标签
    void deleteById(Long id);
    //查询所有Tag
    List<Tag> listTagTop(Integer size);
}

TagServiceImpl:

@Service
public class TagServiceImpl implements TagService {

    @Autowired
    private TagRepository tagRepository;

    @Override
    public List<Tag> listTag() {
        return tagRepository.findAll();
    }

    @Override
    public List<Tag> listTag(String ids) {
        return tagRepository.findAllById(convertToList(ids));
    }

    @Override
    public void saveTag(Tag tag) {
        tagRepository.save(tag);
    }

    @Override
    public Tag findById(Long id) {
        return tagRepository.findById(id).orElse(null);
    }

    @Override
    public Tag updateTag(Long id, Tag tag) {
        Tag tag1 = tagRepository.findById(id).orElse(null);
        if(tag1==null){
            System.out.println("获取更新对象失败");
        }else{
            BeanUtils.copyProperties(tag,tag1, MyBeanUtils.getNullPropertyNames(tag));

        }
        return tagRepository.save(tag1);
    }

    @Override
    public void deleteById(Long id) {
        tagRepository.deleteById(id);
    }

    @Override
    public List<Tag> listTagTop(Integer size) {
        Sort sort =Sort.by(Sort.Direction.DESC,"blogList.size");
        Pageable pageable = PageRequest.of(0,size,sort);
        return tagRepository.findTop(pageable);
    }

    //将接收到的ids字符串转成int类型tagid集合
    private List<Long> convertToList(String ids){
        System.out.println("service接收的ids为:"+ ids);
        List<Long> list = new ArrayList<>();
        if(!"".equals(ids) && ids!=null){
            String[] idArray = ids.split(",");
            for(int i=0;i<idArray.length;i++){
                list.add(new Long(idArray[i]));
            }
        }
        System.out.println("service处理完成后的id list为:"+list);
        return list;
    }
}

CommentService:

public interface CommentService {
    //发表评论
    Comment saveComment(Comment comment);
    //展示所有评论
    List<Comment> listCommentByBlogId(Long blogId);

    //计算所有评论数
    Integer countComment(Long id);
    //计算所有评论
    Long countSumComment();
}

CommentServiceImpl:

@Service
public class CommentServiceImpl implements CommentService {

    @Autowired
    private CommentRepository commentRepository;

    @Override
    public Comment saveComment(Comment comment) {
        return commentRepository.save(comment);
    }

    @Override
    public List<Comment> listCommentByBlogId(Long blogId) {
        Sort sort =Sort.by("createTime");
        List<Comment> commentList =commentRepository.findByBlogId(blogId,sort);
        System.out.println("运行到listCommentByNewId"+commentList);
        List<Comment> commentsView = new ArrayList<>();
        for(Comment comment:commentList){
            Comment c = new Comment();
            BeanUtils.copyProperties(comment,c);
            commentsView.add(c);
        }
        return commentsView;
    }

    @Override
    public Integer countComment(Long id) {
        System.out.println(id);
        System.out.println(commentRepository.countCommentsByBlogId(id));
        return commentRepository.countCommentsByBlogId(id);
    }

    @Override
    public Long countSumComment() {
        return commentRepository.count();
    }

}
(5)Controller层

web -> admin目录下:

BlogController:

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

    @Autowired
    private TypeService typeService;
    @Autowired
    private TagService tagService;
    @Autowired
    private BlogService blogService;

    @RequestMapping("/blogList")
    public String showBlog(Model model){
        model.addAttribute("types",typeService.listType());
        model.addAttribute("tags",tagService.listTag());
        model.addAttribute("blogs",blogService.listBlog());
        return "admin/blogList";
    }

    //后台添加博客信息  可添加博客、分类、标签
    @GetMapping("/blogAdd")
    public String Add(Model model){
        System.out.println("此时为新增");
        model.addAttribute("addType",new Type());
        model.addAttribute("addTag",new Tag());
        model.addAttribute("addBlog",new Blog());
        setTypeAndTag(model);
        return "admin/blogAdd";
    }

    //新增和编辑分类
    @PostMapping("/type/save")
    public String saveType(Type type, RedirectAttributes attributes, HttpSession session){
        System.out.println("接收到的type信息"+type);
        Type type1;
        if(type.getId()==null){ //新增
            System.out.println("新增分类");
            typeService.saveType(type);
            attributes.addFlashAttribute("message","新增操作成功!");
        }else{ //为更新
            type1 = typeService.updateType(type.getId(),type);
            session.setAttribute("type",type1);
            System.out.println("修改成功");
            attributes.addFlashAttribute("message","操作成功!");
        }

        return "redirect:/admin/blogList";
    }
    //新增和编辑分类
    @PostMapping("/tag/save")
    public String saveTag(Tag tag, RedirectAttributes attributes, HttpSession session){
        System.out.println("接收到的type信息"+tag);
        Tag tag1;
        if(tag.getId()==null){ //新增
            System.out.println("新增分类");
            tagService.saveTag(tag);
            attributes.addFlashAttribute("message","新增操作成功!");
        }else {
            //为更新
            tag1 = tagService.updateTag(tag.getId(),tag);
            session.setAttribute("tag",tag1);
            System.out.println("修改成功");
            attributes.addFlashAttribute("message","操作成功!");
        }
        return "redirect:/admin/blogList";
    }


    //用来在修改和新增news页面显示所有type和tag的
    public void setTypeAndTag(Model model){
        model.addAttribute("types",typeService.listType());
        model.addAttribute("tags",tagService.listTag());
    }

    //新增博客
    @PostMapping("/blog/save")
    public String saveBlog(Blog blog,RedirectAttributes attributes,HttpSession session){
        System.out.println("接收到的blog信息为:"+blog);
        Blog blog1;
        if(blog.getId()==null){  //为新增
            System.out.println("新增博客");
            User user = (User) session.getAttribute("user");
            blog.setUser(user);//设置作者
            blog.setAuthor(user.getNickname());
            blog.setCreateTime(new Date()); //设置初始创建时间
            blog.setPraiseNum(0);   //设置初始点赞数0
            blog.setCountComment(0);//
            blog.setTags(tagService.listTag(blog.getTagIds()));
            blog.setCountComment(0);
            System.out.println(blog.getTags());
            blogService.saveBlog(blog);
            attributes.addFlashAttribute("message","新增博客成功");
        }else{  //为更新
            blog1 = blogService.updateBlog(blog.getId(),blog);
            session.setAttribute("blog",blog1);
            System.out.println("修改成功");
            attributes.addFlashAttribute("message","操作成功!");

        }
        return "redirect:/admin/blogList";
    }

    //图片展示区域
    @RequestMapping("/gallery")
    public String showGallery(Model model){
        model.addAttribute("blogs",blogService.listBlog());
        return "admin/gallery";
    }

    //展示点击的博客
    @RequestMapping("/blog/{id}")
    public String news(@PathVariable Long id, Model model){
        Blog blog = blogService.getAndConvert(id);
        model.addAttribute("blog",blog);
        System.out.println("------"+blog.getTags());
        return "admin/blogShow";
    }

    //删除点击的博客
    @RequestMapping("/{id}/blogDelete")
    public String blogDelete(@PathVariable Long id,RedirectAttributes attributes){
        System.out.println("待删除的id:"+id);
        blogService.deleteById(id);
        attributes.addFlashAttribute("message","删除成功");
        return "redirect:/admin/blogList";
    }

    //更新点击的博客
    @RequestMapping("/{id}/blogUpdate")
    public String blogUpdate(@PathVariable Long id,Model model){
        System.out.println("待更新的id:"+id);
        Blog blog = blogService.findById(id);
        model.addAttribute("addType",new Type());
        model.addAttribute("addTag",new Tag());
        model.addAttribute("addBlog",blog);
        setTypeAndTag(model);
        return "admin/blogAdd";
    }

    //更新点击的分类
    @RequestMapping("/{id}/typeUpdate")
    public String typeUpdate(@PathVariable Long id,Model model){
        System.out.println("待更新的id:"+id);
        Type type = typeService.findById(id);
        model.addAttribute("addType",type);
        model.addAttribute("addTag",new Tag());
        model.addAttribute("addBlog",new Blog());
        setTypeAndTag(model);
        return "admin/blogAdd";
    }

    //更新点击的分类
    @RequestMapping("/{id}/tagUpdate")
    public String tagUpdate(@PathVariable Long id,Model model){
        System.out.println("待更新的id:"+id);
        Tag tag = tagService.findById(id);
        model.addAttribute("addType",new Type());
        model.addAttribute("addTag",tag);
        model.addAttribute("addBlog",new Blog());
        setTypeAndTag(model);
        return "admin/blogAdd";
    }

    //删除点击的分类
    @RequestMapping("/{id}/typeDelete")
    public String typeDelete(@PathVariable Long id,RedirectAttributes attributes){
        System.out.println("待删除的id:"+id);
        typeService.deleteById(id);
        attributes.addFlashAttribute("message","删除成功");
        return "redirect:/admin/blogList";
    }

    //删除点击的博客
    @RequestMapping("/{id}/tagDelete")
    public String tagDelete(@PathVariable Long id,RedirectAttributes attributes){
        System.out.println("待删除的id:"+id);
        tagService.deleteById(id);
        attributes.addFlashAttribute("message","删除成功");
        return "redirect:/admin/blogList";
    }
}

ManageController:

@Controller
@RequestMapping("/admin")
public class ManageController {
    @Autowired
    private UserService userService;
    @Autowired
    private BlogService blogService;
    @Autowired
    private CommentService commentService;

    //后台主页
    @RequestMapping("/manage")
    public String toManage(Model model,Pageable pageable,HttpSession session){
        model.addAttribute("totalUser",userService.listUser(pageable).getTotalElements());
        model.addAttribute("totalBlog",blogService.listBlog(pageable).getTotalElements());
        model.addAttribute("totalComment",commentService.countSumComment());
        model.addAttribute("user",session.getAttribute("user")); //添加当前用户信息
        System.out.println(model.getAttribute("user"));
        return "admin/manageIndex";
    }

    //后台用户展示界面
    @RequestMapping("/userList")
    public String showUsers(@PageableDefault(size = 50,sort = {"updateTime"},direction = Sort.Direction.DESC)
                            Pageable pageable, Model model){
        model.addAttribute("page",userService.listUser(pageable));

        return "admin/userList";
    }

    //后台编辑用户信息
    @GetMapping("/userChange/{id}/toUpdate")
    public String toUpdate(@PathVariable Long id,Model model){
        User user = userService.getUserInfo(id);
        model.addAttribute("updateUser", user);
        return "admin/userChange";
    }

    //后台添加用户信息
    @GetMapping("/userAdd")
    public String Add(Model model){
        System.out.println("此时为新增");
        model.addAttribute("addUser",new User());
        return "admin/userAdd";
    }

    //保存修改后的用户信息
    @PostMapping("/user/save")
    public String save(User user, RedirectAttributes attributes, HttpSession session){
        System.out.println("接收到的用户信息"+user);
        User user1;
        if(user.getId()==null){ //没有找到该用户  为新增
            userService.register(user);
            System.out.println("此时执行新增用户");
            attributes.addFlashAttribute("message","新增操作成功!");
        }else{
            user1 = userService.updateUser(user.getId(),user);
            session.setAttribute("updateUser",user1);
            System.out.println("此时执行修改用户");
            attributes.addFlashAttribute("message","编辑操作成功!");
        }
        return "redirect:/admin/userList";
    }

    //后台删除用户信息
    @GetMapping("/{id}/delete")
    public String deleteById(@PathVariable Long id,RedirectAttributes attributes){
        System.out.println("待删除的id"+id);
        userService.deleteByUserId(id);
        attributes.addFlashAttribute("message","删除成功");
        return "redirect:/admin/userList";
    }

    //后台用户搜索功能
    @RequestMapping("/search")
    public String Search(@PageableDefault(size = 5,sort = {"updateTime"},direction = Sort.Direction.DESC)Pageable pageable,
                         @RequestParam String query,Model model){
        System.out.println(query);
        model.addAttribute("page",userService.listUser("%"+query+"%",pageable));
        System.out.println(model.getAttribute("page"));
        model.addAttribute("query",query);
        return "admin/userList";
    }
}

UserController:

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

    //注入service层
    @Autowired
    private UserService userService;

    @GetMapping      //跳转到登陆界面
    public String loginPage(){
        return "admin/login";
    }

    //注册
    @PostMapping("/register")
    public String register(@RequestParam String username,@RequestParam String password,
                           @RequestParam String phone,@RequestParam String repassword,
                           RedirectAttributes attributes){
        if(password.equals(repassword)){    //两次密码一致
            User user = userService.findUserByUserName(username);
            if(user == null){  //当前用户名不存在
                User user1 = new User();
                user1.setUsername(username);
                user1.setPassword(password);

                user1.setPhone(phone);

                userService.register(user1);
                attributes.addFlashAttribute("message","注册成功!");
            }else{
                attributes.addFlashAttribute("message","用户名已存在!");
            }
        }

        return "redirect:/admin";
    }

    //登陆
    @PostMapping("/login")
    public String login(@RequestParam String username , @RequestParam String password,
                        HttpSession session, RedirectAttributes attributes,Model model) {
        User user =userService.checkUser(username,password);
        //验证
        if(user!=null){
            user.setPassword(null);
            if(user.getAdmin()){
                user.setAdmin(true);
            }
            System.out.println("登陆时user"+user);
            session.setAttribute("user",user);   //保存到session中传到前端
            return "redirect:/";
        }else {
            attributes.addFlashAttribute("message","用户名或密码错误");
            return "redirect:/admin";
        }
    }

    //注销
    @GetMapping("/logout")
    public String logout(HttpSession session){
        session.removeAttribute("user");
        return "redirect:/admin";
    }

    //修改个人信息 1 获取数据库中个人信息
    @GetMapping("/userinfo/{id}")
    public String toUpdate(@PathVariable Long id, Model model){
        User user = userService.getUserInfo(id);
        model.addAttribute("user",user);
        return "admin/userinfo";
    }

    //保存修改用户信息界面的表单
    @PostMapping("/userUpdate")
    public String update(User user,HttpSession session,RedirectAttributes attributes){
        User user1;
        if(user.getId()==null){ //没有找到该用户
            System.out.println("用户id没有传过来");
            attributes.addFlashAttribute("message","操作失败!");
            return "login";
        }else{
            user1 = userService.updateUser(user.getId(),user);
            session.setAttribute("user",user1);
            System.out.println("修改成功");
            attributes.addFlashAttribute("message","操作成功!");
        }
        return "admin/index";
    }

    //修改密码
    @RequestMapping("/userinfo/password")
    public String changePassword(@RequestParam String newPassword,
                                 User user,RedirectAttributes attributes,HttpSession session){

        User user2;
        if(user.getId()==null){ //没有找到该用户
            System.out.println("用户id没有传过来");
            attributes.addFlashAttribute("message","操作失败!");
        }else{
            user.setPassword(newPassword);
            user2 = userService.updateUser(user.getId(),user);
            session.setAttribute("user",user2);
            System.out.println("修改密码成功");
            attributes.addFlashAttribute("message","操作成功!");
        }
        return "admin/login";
    }
}

web目录下

CommentController:

@Controller
@RequestMapping
public class CommentController {

    @Autowired
    private CommentService commentService;
    @Autowired
    private BlogService blogService;

    @RequestMapping("/commentAdd")
    public String post(Comment comment, HttpSession session, Model model){
        System.out.println("接收到的comment信息为:"+comment);
        System.out.println(comment.toString());
        Blog blog = (Blog) session.getAttribute("blog");
        System.out.println("blog信息为:"+blog);
        Long blogId = blog.getId();
        System.out.println("blogId为:"+blogId);

        if(comment.getId()==null) {  //为新增
            comment.setBlog(blogService.findById(blogId));
            User user = (User) session.getAttribute("user");
            if (user.getAdmin()) {    //管理员
                comment.setAdminComment(true);
            }
            comment.setImage(user.getImage());
            comment.setCreateTime(new Date());
        }
        commentService.saveComment(comment);
        blog.setCountComment(commentService.countComment(blogId));
        blogService.saveBlogByCommentTime(blog);

        return "redirect:/toShow/"+blogId;

    }
    
}

IndexController:

@Controller
@RequestMapping("/")
public class IndexController {

    @Autowired
    private BlogService blogService;
    @Autowired
    private TypeService typeService;
    @Autowired
    private TagService tagService;
    @Autowired
    private CommentService commentService;

    //主页
    @RequestMapping("/")
    public String index(@PageableDefault(size = 4,sort = {"updateTime"},direction = Sort.Direction.DESC)
                        Pageable pageable, Model model, HttpSession session){

        model.addAttribute("page",blogService.listBlog(pageable));
        session.setAttribute("totalBlogNum",blogService.listBlog(pageable).getTotalElements());
        model.addAttribute("types",typeService.listType());
        model.addAttribute("pageByCommentUpdateTime",blogService.commentBlogTop());
        //获取推荐状态文章
        model.addAttribute("recommendBlog",blogService.recommendBlogTop());
        return "index";
    }

    //列表页
    @RequestMapping("/toList")
    public String list(@PageableDefault(size = 6,sort = {"updateTime"},direction = Sort.Direction.DESC)
                       Pageable pageable,Model model){
        model.addAttribute("page",blogService.listBlog(pageable));
        model.addAttribute("tags",tagService.listTagTop(7));
        model.addAttribute("pageByCommentUpdateTime",blogService.commentBlogTop());
        for(int i=0;i<6;i++) {
            System.out.println(tagService.listTagTop(6).get(i).getBlogList().size());
        }
        return "list";
    }

    //详情页
    @RequestMapping("/toShow/{id}")
    public String show(@PathVariable Long id,Model model,HttpSession session){
        Blog blog = blogService.getAndConvert(id);

        model.addAttribute("blog",blog);
        session.setAttribute("blog",blog);
        model.addAttribute("comments",commentService.listCommentByBlogId(id));
        model.addAttribute("pageByCommentUpdateTime",blogService.commentBlogTop());

        //新建一个评论对象,传到后端装
        Comment comment = new Comment();
        User user = (User) session.getAttribute("user");
        if(user!=null) {
            comment.setImage(user.getImage());
            comment.setNickname(user.getNickname());
            comment.setPhone(user.getPhone());
        }
        model.addAttribute("commentAdd",comment);

        System.out.println(blog.getTags());
        return "show";
    }

}
(6)工具类

MarkdownUtils:

public class MarkdownUtils {


    /**
     * markdown格式转换成HTML格式
     * @param markdown
     * @return
     */
    public static String markdownToHtml(String markdown) {
        Parser parser = Parser.builder().build();
        Node document = parser.parse(markdown);
        HtmlRenderer renderer = HtmlRenderer.builder().build();
        return renderer.render(document);
    }

    /**
     * 增加扩展[标题锚点,表格生成]
     * Markdown转换成HTML
     * @param markdown
     * @return
     */
    public static String markdownToHtmlExtensions(String markdown) {
        //h标题生成id
        Set<Extension> headingAnchorExtensions = Collections.singleton(HeadingAnchorExtension.create());
        //转换table的HTML
        List<Extension> tableExtension = Arrays.asList(TablesExtension.create());
        Parser parser = Parser.builder()
                .extensions(tableExtension)
                .build();
        Node document = parser.parse(markdown);
        HtmlRenderer renderer = HtmlRenderer.builder()
                .extensions(headingAnchorExtensions)
                .extensions(tableExtension)
                .attributeProviderFactory(new AttributeProviderFactory() {
                    public AttributeProvider create(AttributeProviderContext context) {
                        return new CustomAttributeProvider();
                    }
                })
                .build();
        return renderer.render(document);
    }

    /**
     * 处理标签的属性
     */
    static class CustomAttributeProvider implements AttributeProvider {
        @Override
        public void setAttributes(Node node, String tagName, Map<String, String> attributes) {
            //改变a标签的target属性为_blank
            if (node instanceof Link) {
                attributes.put("target", "_blank");
            }
            if (node instanceof TableBlock) {
                attributes.put("class", "ui celled table");
            }
        }
    }


    public static void main(String[] args) {
        String table = "| hello | hi   | 哈哈哈   |\n" +
                "| ----- | ---- | ----- |\n" +
                "| 斯维尔多  | 士大夫  | f啊    |\n" +
                "| 阿什顿发  | 非固定杆 | 撒阿什顿发 |\n" +
                "\n";
        String a = "[imCoding 爱编程](http://www.lirenmi.cn)";
        System.out.println(markdownToHtmlExtensions(a));
    }

}

MyBeanUtils:

public class MyBeanUtils {

    public static String[] getNullPropertyNames(Object source){

        BeanWrapper beanWrapper = new BeanWrapperImpl(source);
        PropertyDescriptor pds[] = beanWrapper.getPropertyDescriptors();
        List<String> nullPropertyNames = new ArrayList<>();
        for(PropertyDescriptor pd:pds){
            String propertyName = pd.getName();
            if(beanWrapper.getPropertyValue(propertyName)==null){
                nullPropertyNames.add(propertyName);
            }
        }
        return nullPropertyNames.toArray(new String[nullPropertyNames.size()]);
    }

}
(7)异常处理

exception -> NotFoundException:

@ResponseStatus(HttpStatus.NOT_FOUND)
public class NotFoundException extends RuntimeException{

    public NotFoundException() {
    }

    public NotFoundException(String message) {
        super(message);
    }

    public NotFoundException(String message, Throwable cause) {
        super(message, cause);
    }

}

handler -> ControllerExceptionHandler:

@ControllerAdvice  //对全局异常做处理
public class ControllerExceptionHandler {

    //日志打印
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @ExceptionHandler(Exception.class)
    public ModelAndView exceptionHandler(HttpServletRequest request,Exception e) throws Exception{
        logger.error("Request: URL: {},Exception: {}",request.getRequestURI(),e);
        if(AnnotationUtils.findAnnotation(e.getClass(),ResponseStatus.class)!=null){
            throw e;
        }
        ModelAndView mv = new ModelAndView();
        mv.addObject("url",request.getRequestURI());
        mv.addObject("exception",e);
        mv.setViewName("404");
        return mv;
    }

}
(8)登录拦截

interceptor ->

LoginInterceptor:

public class LoginInterceptor extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("调用了吗");
        if(request.getSession().getAttribute("user")==null){
            response.sendRedirect("/admin");
            return false;
        }
        return true;
    }

}

WebConfig:

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //允许放行
        registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/admin/**","/toIndex")
                .excludePathPatterns("/admin")
                .excludePathPatterns("/admin/login");
    }
}

GitHub地址:https://github.com/tengsss/QX_Blog_SpringBoot.git

  • 4
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值