ブログ管理システム | SpringBoot+Vue+ElementUIをベースとした個人ブログシステムの設計・実装

著者ホームページ:プログラミングコンパス

著者について: Java 分野の質の高いクリエイター、CSDN ブログの専門家、Nuggets の招待著者、長年の建築設計経験、Tencent Classroom の常駐講師

主な内容:Javaプロジェクト、卒業設計、履歴書テンプレート、教材、面接質問バンク、技術相互支援

お気に入り、いいね、迷わず作者フォローすると良いです

記事の最後にあるソースコードを入手してください 

商品番号:BS-PT-089

1. プロジェクトの紹介

インターネットの急速な台頭により、インターネットは徐々に人々が日常生活で通信するための主要な媒体となり、具体的な通信方法は技術の進歩に合わせて常に更新されています。以前は、人々は自分のブログを持っていなかったので、インスタント メッセージング ソフトウェアやフォーラムへの投稿など、分散的で整理されていない方法でしか自分の考えや感情を表現できませんでしたが、これらの方法は操作が複雑でした。個人情報の保護性能はあまり強くありません。したがって、インターネット上でのブログの普及により、人々はブログを通じて自分の考えや感情を表現し、自分自身を示し、より多くの人に自分を知ってもらうことができる、言論の自由のある無制限の個人的な日記であると言えます。人々がライティング レベルを向上させるための訓練基地として、また言葉を表現するためのネットワーク キャリアとして、ブログは自己感情や人生の表現に焦点を当てています。定期的にブログを書くことで、ブロガーのライティング スキルを非常に早く磨き、自分のイデオロギーをより深く鋭くすることができます。

ブログ (ウェブログとも呼ばれる) は、通常は個人によって管理され、新しい記事を随時公開する Web サイトです。ブログの記事は通常、公開時刻に応じて新しいものから古いものへ逆順に並べられます。多くのブログは特定のトピックに関する解説やニュースの提供に重点を置いていますが、個人的な日記として機能するブログもあります。一般的なブログは、テキスト、画像、他のブログや Web サイトへのリンク、その他の関連するトピックベースのメディアを組み合わせています。読者にインタラクティブな方法でコメントを残してもらえることは、多くのブログにとって重要な要素です。ブログのコンテンツのほとんどはテキストベースであり、ブログはソーシャル メディア ネットワークの一部です。

大手Webサイトにはそれぞれ独自のブログシステムがありますが、機能は異なり、限られているため、当社独自のブログシステムを実現するために、機能はシンプル、ページは美しく、人気のブログシステムに合わせてより便利になるよう努めています。

図 1 に示すように、フロント デスクには 5 つのモジュールが含まれています。

ユーザーログイン:ブログシステムを利用する前にログインと登録が必要です 登録方法は携帯電話番号登録とメールアドレス登録です 登録後、ログイン時に認証コードの認証が必要です 認証に成功した場合のみブログにアクセスできますホームページ。

ブログページの表示:ホームページにはみんなのブログ情報が表示され、キーワードによるブログの検索、ブログへのコメント、お気に入りのブログのブックマーク、タイプ別のブログの検索、ランキングで質の高いブログを見ることができます。

パーソナルセンター: パーソナルセンターでは、個人情報、注文管理、ウォレット管理、自身のブログが表示され、個人情報では閲覧記録の閲覧、携帯電話番号、メールアドレス、パスワードなどの変更、IDカード認証の追加が可能です。ここ。注文管理とは、有料ブログや広告を購入した記録です。ウォレットでは、残高の確認、現金のチャージ、引き出しが可能で、現金の引き出しはキャッシュ カードで行われます。

ブログを公開する: ブログを公開する前に、まずブログのカテゴリを選択する必要があります。カテゴリの下に新しいブログを追加し、ブログに写真を追加することもできます。ブログを追加した後、課金するかどうかを選択できます。 。

広告モジュール: ユーザーがブログを読むと近くに広告が表示されるお得な機能です。ユーザーはお金を出して広告を消すことができます。

図 2 に示すように、背景には 6 つのモジュールが含まれています。

ユーザー管理: 管理者は、新しいユーザーの追加、ユーザーの変更、ユーザーの削除、およびユーザー情報の照会を行うことができます。ユーザーは自分自身を登録することも、管理者が手動で登録することもできます。ユーザー名を繰り返すことはできません。ユーザーがパスワードを忘れた場合は、管理者にパスワードを問い合わせることができます。 .リセット。

ブログのレビュー: ユーザーが投稿したブログは管理者がレビューする必要があり、一部の違法な情報や暴力的なコンテンツは表示できません。レビューに合格した後、管理者は投稿を手動で公開できます。レビューが失敗した場合は、ユーザーに次のメッセージが表示されます。そしてレビューは失敗します。

広告管理: 管理者は、ブログのホームページに広告を追加したり、広告を削除および変更したり、広告を表示したりできます。

ブログ管理: 管理者は、ユーザーが投稿したブログの削除、ユーザーのブログの変更、ブログのクエリを実行できます。

注文管理: ユーザーがお金を出して有料ブログや広告を購入すると、未払い注文が生成され、ユーザーが支払いを完了すると有料注文に変更され、ホームページでブログを閲覧したり、広告を削除したりすることができます。 。

チャージと出金の審査: ユーザーが出金をクリックした後、出金金額を選択して出金を開始します。この時点で出金審査ステータスに入り、バックグラウンドがそれを受け取ります。管理者の審査ステータスが合格に変更されると、ユーザーの出金金額は銀行カードに入金でき、管理者はいつでも審査状況を確認できます。

1. 技術的要件

(1) 技術導入計画

ブログシステムはフロントエンドとバックエンドの分離技術を採用しています フロントエンドにはvueフレームワーク、css、js、htmlなどを使用しています 開発ツールはWebStormを使用しています キャッシュはredisとRESP可視化を使用しています道具。

バックエンドには、スキャフォールディングを迅速に開発するために SpringBoot を使用しました。使用した開発ツールは IDEA、使用したデータベースは MySql、視覚化ツールは Navicat でした。

フロントエンドとバックエンドの対話とは、フロントエンドが Ajax を使用してドメインを越えてバックエンドからデータにアクセスし、データを取得した後にフロントエンドに戻ることを意味します。

(2) システムテスト計画

IDEA 開発ツール、Java 言語、Mysql データベース、および Vue フレームワークの詳細な学習と使用のための情報を収集します。システム分析により、ブログシステムは詳細に分類され、設計されます。システム設計、詳細設計に従い、各機能のシステム実現を行います。規定に従ってシステムの完全なテストを実施し、既存の問題点を見つけ出し、ブログシステムをさらに改善します。

2. 職務要件

(1) 技術的な実現可能性:

Vue+SpringBoot を使用して、プロジェクトのフロントエンドとバックエンドの開発を実現します。Vue は、ユーザー インターフェイスを構築するための進歩的なフレームワークです。他の大きなフレームワークとは異なり、Vue は下から上にレイヤーごとに適用されるように設計されています。Vue のコア ライブラリはビュー レイヤーのみに焦点を当てており、使いやすいだけでなく、サードパーティのライブラリや既存のプロジェクトとの統合も簡単です。一方、最新のツールチェーンやさまざまなサポート ライブラリと組み合わせると、Vue は複雑なシングルページ アプリケーションを実行することもできます。Vue は双方向のデータ バインディングを使用します。つまり、データが変更されるとビューも変更され、ビューが変更されるとデータも同期して変更されます。これが Vue の本質です。SpringBoot は、現在のインターネット バックエンド開発において、JavaEE が支配的な地位を占めています。JavaEE 開発の場合、推奨されるフレームワークは Spring フレームワークです。従来の Spring 開発では、Spring フレームワークを実行するにはビジネスに依存しない多数の XML 構成を使用する必要があり、多くの開発者から批判されてきました。Spring アプリケーションの開発をさらに簡素化するために、SpringBoot が誕生しました。その設計目的は、Spring アプリケーションの構築および開発プロセスをさらに簡素化することです。Spring Boot を使用すると、「実行するだけ」できるスタンドアロンの実稼働グレードの Spring ベースのアプリケーションを簡単に作成できます。Spring プラットフォームとサードパーティ ライブラリを厳密に分析して、簡単に開始できるようにしました。ほとんどの Spring Boot アプリケーションには最小限の Spring 構成が必要です。したがって、このテクノロジーは完全に実行可能です。

第二に、環境の紹介

ロケール: Java: jdk1.8

データベース: MySQL: mysql5.7

アプリケーションサーバー: Tomcat: tomcat8.5.31

開発ツール: IDEA または eclipse

背景開発技術: springboot+mybatis

フロントエンド開発テクノロジー: vue+elementUI

三、システム表示

ブログフロントデスク

 ユーザー登録とログイン

 

 携帯電話認証コードによるログイン:

 

このブログの特徴は、有料ブログ記事と無料ブログ記事を設定でき、有料ブログ記事を閲覧するには個人アカウントから料金を引き落とす必要があることです。

 パーソナルセンターでは、自分の銀行カードをバインドして、オンラインでのチャージや現金引き出しを行うことができます

 撤退

 

ブログ投稿を公開するときに有料または無料を選択できます

 カテゴリ別に閲覧する

 リーダーボードを読む

 私のコレクション

 閲覧履歴

 パーソナルセンター

バックグラウンドログイン

 

 統計

 ユーザー管理

 ブログ管理

 カテゴリー管理

 リチャージ記録

 現金引き出しのレビュー

 注文管理

 フロントエンドカルーセル広告画像管理

4番目、コアコード表示

package com.dys.controller;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dys.R.R;
import com.dys.pojo.Classification;
import com.dys.pojo.Posts;
import com.dys.service.ClassificationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/classification")
public class ClassificationController {

    @Autowired
    private ClassificationService classificationService;

    /**
     * 前端
     * 查询所有的分类信息
     * @return
     */
    @PostMapping
    public R getClassification(){
        List<Classification> list = classificationService.list(null);
        System.out.println("数据"+list);
        return R.ok(list);
    }

    /**
     * 条件分页查询,根据传来的条件去找到对应的数据
     * @param page  分页
     * @param search    条件
     * @return R
     */
    @GetMapping("/selectClassification")
    public R selectClassification(Page<Classification> page,@RequestParam String search){
        Page<Classification> classificationPage = classificationService.selectClassification(page, search);
        return R.ok(classificationPage);
    }

    /**
     * 新增分类
     * @param classification 分类对象
     * @return R
     */
    @PostMapping("/addClassification")
    public R addClassification(@RequestBody Classification classification){
        boolean isOk = classificationService.addClassification(classification);
        return isOk ? R.ok() : R.error();
    }

    /**
     * 修改分类
     * @param classification 分类对象
     * @return R
     */
    @PostMapping("/updateClassification")
    public R updateClassification(@RequestBody Classification classification){
        boolean isOk = classificationService.updateClassification(classification);
        return isOk ? R.ok() : R.error();
    }

    /**
     * 删除分类
     * 注:删除分类的同时还要删除有这个分类对应的博客
     * 在根据博客id删除收藏,历史记录,排行榜里面的对应的博客信息
     * 在根据博客里面的用户id删除对应的创作博客信息
     * @param id 分类ID
     * @return R
     */
    @DeleteMapping("/deleteClassification/{id}")
    public R deleteClassification(@PathVariable String id){
        boolean isOk = classificationService.deleteClassification(id);
        return isOk ? R.ok() : R.error();
    }

    /**
     * 后端
     * 图表数据查询,先查询出所有的分类ID
     * 在根据ID去博客表找对应的博客的数量
     * 返回每个分类有多少个博客
     * @return R
     */
    @GetMapping("/selectEChartsData")
    public R selectEChartsData(){
        List<Classification> list = classificationService.selectEChartsData();
        return R.ok(list);
    }

}
package com.dys.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dys.R.R;
import com.dys.mapper.CollectionMapper;
import com.dys.pojo.Collection;
import com.dys.pojo.Posts;
import com.dys.service.CollectionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/collection")
public class CollectionController {

    @Autowired
    private CollectionService collectionService;

    /**
     * 新增收藏记录
     * @param collection
     * @return
     */
    @PostMapping("/addCollection")
    public R addCollection(@RequestBody Collection collection){
        //加上@RequestBody后可以接收前端传来的数据,把数据新增到数据库中
//        boolean isOk = collectionService.saveCollection(collection);
        //返回数据,当数据为真时返回成功,为假时返回失败
//        return isOk ? R.ok() : R.error("已经收藏过了");
        //TODO
        collectionService.save(collection);
        String id = collection.getId();
        return R.ok(id);
    }

    /**
     * 删除收藏记录
     * @param id
     * @return
     */
    @DeleteMapping("/deleteCollection/{id}")
    public R deleteCollection(@PathVariable String id){
//        Collection collection = new Collection();
//        collection.setUsersId(usersId);
//        collection.setPostsId(postsId);
//        boolean isOk = collectionService.deleteCollection(collection);
        boolean isOk = collectionService.removeById(id);
        return isOk ? R.ok() : R.error();
    }

    /**
     * 查询是否收藏
     * @param collection
     * @return
     */
    @PostMapping("/listCollection")
    public R listCollection(@RequestBody Collection collection){
        LambdaQueryWrapper<Collection> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Collection::getUsersId,collection.getUsersId()).eq(Collection::getPostsId,collection.getPostsId());
        return R.ok(collectionService.getOne(wrapper));
    }

    /**
     * 根据用户id查询所有已收藏的博客
     * 上面是数据没分页,下面是将数据分页
     * @param id
     * @return
     */
//    @PostMapping("/listAllCollection/{id}")
//    public R listAllCollection(@PathVariable String id){
//        return R.ok(collectionService.listAllCollection(id));
//    }
    @GetMapping("/listAllCollection/{id}")
    public R listAllCollection(Page<Collection> page,@PathVariable String id){
        page.addOrder(OrderItem.desc("create_time"));
        return R.ok(collectionService.listAllCollection(page,id));
    }

}
package com.dys.controller;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dys.R.R;
import com.dys.pojo.Classification;
import com.dys.pojo.Posts;
import com.dys.pojo.dto.PostsDTO;
import com.dys.service.ClassificationService;
import com.dys.service.PostsService;
import com.dys.service.UsersService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.Comparator;
import java.util.List;

@RestController
@RequestMapping("/posts")
public class PostsController {

    /**
     * 博客表
     */
    @Resource
    private PostsService postsService;

    /**
     * 分类表
     */
    @Autowired
    private ClassificationService classificationService;

    /**
     * 用户表
     */
    @Autowired
    private UsersService usersService;

    /**
     * 后台
     * 条件分页查询
     * @param page      分页类,获取里面三个值:total:一共有多少个数据,size:每页可以存放的数据条数,current:当前是第几页
     * @param search    搜索的关键字
     * @return  R
     */
    @GetMapping("/postsPagingQuery")
    public R postsPagingQuery(Page<Posts> page, @RequestParam String search){
//        //mybatis-plus中的条件构造器,需要用到Lambda语法,使用Wrapper
//        LambdaQueryWrapper<Posts> lambdaQueryWrapper = new LambdaQueryWrapper<>();
//        //调用了like方法,实现模糊查询,lambda表达式查询条件,::获取实体类中的方法         ::--》Java8后:获取方法
//        //StrUtil--》一个工具类,isNotEmpty和isNotBlank都是非空判断的方法(isNotBlank会排除空格,isNotEmpty不会排除空格)
        if (search == null){

        }
//        lambdaQueryWrapper.like(StrUtil.isNotBlank(search),Posts::getTitle,search);
//        //按照修改时间降序排列
//        Page<Posts> postsPage = page.addOrder(OrderItem.desc("update_time"));
//        //mybatis-plus好用自带的分页的方法,可以传两个参数(分页的起始位置,结束位置),接收前端传来的参数,查询的数量
//        Page<Posts> servicePosts = postsService.page(postsPage, lambdaQueryWrapper);
//
//        List<Posts> records = servicePosts.getRecords();
//        records.forEach(item->{
//            //TODO 填充typeName
//            String typeName = classificationService.getTypeNameByTypeId(item.getClassificationId());
//            String usersName = usersService.getUserNameByUsersId(item.getUsersId());
//            item.setTypeName(typeName);
//            item.setUsersName(usersName);
//        });
//        //返回数据
//        return R.ok(servicePosts);

        Page<Posts> postsPage = postsService.postsPagingQuery(page, search);
        List<Posts> records = postsPage.getRecords();
        records.forEach(item->{
            //TODO 填充typeName
            String typeName = classificationService.getTypeNameByTypeId(item.getClassificationId());
            String usersName = usersService.getUserNameByUsersId(item.getUsersId());
            item.setTypeName(typeName);
            item.setUsersName(usersName);
        });
        return R.ok(postsPage);
    }


    /**
     * 博客数据按浏览量排序
     * @param posts
     * @return
     */
    @GetMapping("/getPostsAndViews")
    public R getPostsAndViews(Posts posts){
//        //按照浏览量降序排列
//        Page<Posts> postsPage = page.addOrder(OrderItem.desc("views"));
//        //mybatis-plus好用自带的分页的方法,可以传两个参数(分页的起始位置,结束位置),接收前端传来的参数,查询的数量
//        Page<Posts> servicePosts = postsService.page(postsPage);
        List<Posts> list = postsService.list();
        //list.sort(Comparator.comparing(Posts::getViews).reversed());     .reversed() --》 根据条件进行降序排序
        list.sort(Comparator.comparing(Posts::getViews).reversed());
        //返回数据
        return R.ok(list);
    }


    /**
     * 查看博客详情,多表查询,根据用户id,类型id查询对应的名字
     * @param id
     * @return
     */
    @GetMapping("/{id}/{isStatus}")
    public R getPostsId(@PathVariable boolean isStatus,@PathVariable String id){
//        Posts byId = postsService.getByIdWithTypeNameUsersName(id);
        PostsDTO byId = postsService.getByIdWithTypeNameUsersName(isStatus,id);
        return R.ok(byId);
    }

    /**
     * 根据分类id查询对应的分类数据
     * @param id
     * @return
     */
    @GetMapping("/classificationByIdData/{id}")
    public R classificationByIdData(Page<Posts> page,@PathVariable String id){
//        List<Posts> typeData = postsService.getByIdWithTypeData(page,id);
        Page<PostsDTO> typeData = postsService.getByIdWithTypeData(page,id);
        return R.ok(typeData);
    }

    /**
     * 新增方法
     * @param posts     Posts实体类
     * @return      R
     */
    @PostMapping
    public R savePosts(@RequestBody Posts posts){
        //加上@RequestBody后可以接收前端传来的数据,把数据新增到数据库中
        boolean isOk = postsService.save(posts);
        //返回数据,当数据为真时返回成功,为假时返回失败
        return isOk ? R.ok() : R.error();
    }

    /**
     * 修改方法
     * @param posts     Posts实体类
     * @return      R
     */
    @PatchMapping("/updatePosts")
    public R updatePosts(@RequestBody Posts posts){
        boolean isOk = postsService.updateById(posts);
        return isOk ? R.ok() : R.error();
    }

    /**
     * 删除博客,删除博客的同时要删除历史记录中的博客和收藏的博客
     * @param id        Posts实体类
     * @return      R
     */
    @DeleteMapping("/{id}")
    public R deletePosts(@PathVariable String id){
        boolean isOk = postsService.deletePosts(id);
        return isOk ? R.ok() : R.error();
    }

    /**
     * 前端
     * 条件分页查询根据用户ID查找自己创作的博客
     * @param id 用户ID
     * @param postsPage 分页
     * @param search 搜索条件
     * @return  R
     */
    @GetMapping("/selectBlogById")
    public R selectBlogById(Page<Posts> postsPage,@RequestParam String id,@RequestParam String search){
        Page<Posts> page = postsService.selectBlogById(postsPage, id, search);
        return R.ok(page);
    }

}

V. プロジェクトの概要

このプロジェクトは、ブログプラットフォームシステムを開発、実装しました。従来のブログシステムと比較して、有料ブログ投稿の機能を実現できます。著者は、CSDNのような有料の知識ベースのブログ投稿に課金することで、一定の利益を得ることができます。出版と同様に、有料ブログやコラムなど、この企画の実現が何かの参考になれば幸いです。

おすすめ

転載: blog.csdn.net/whirlwind526/article/details/128693557