基于Vue+SpringBoot+MySQL实现个人博客系统(二)

文章目录


 实现个人博客的步骤如下:

一.设计数据库模型:首先需要设计博客数据库模型,包括博客文章、评论、分类、标签等表的设计。可以使用MySQL Workbench等工具进行建模,也可以手动编写SQL语句创建表。

下面是一个简单的数据库模型设计,包括以下表:

  1. 文章表(article):存储博客文章的信息,包括文章ID、文章标题、文章内容、发布时间、最后修改时间、文章所属分类ID等字段。

  2. 评论表(comment):存储博客文章的评论信息,包括评论ID、评论内容、评论时间、评论人昵称、评论人邮箱、评论人网址、评论所属文章ID等字段。

  3. 分类表(category):存储博客文章的分类信息,包括分类ID、分类名称等字段。

  4. 标签表(tag):存储博客文章的标签信息,包括标签ID、标签名称等字段。

  5. 文章-分类关联表(article_category):存储文章和分类之间的关联关系,包括文章ID和分类ID两个字段。

  6. 文章-标签关联表(article_tag):存储文章和标签之间的关联关系,包括文章ID和标签ID两个字段。

下面是数据库模型设计的SQL语句:

CREATE TABLE `article` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '文章ID',
  `title` varchar(255) DEFAULT NULL COMMENT '文章标题',
  `content` longtext COMMENT '文章内容',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `update_time` datetime DEFAULT NULL COMMENT '修改时间',
  `category_id` int(11) DEFAULT NULL COMMENT '文章所属分类ID',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='文章表';

CREATE TABLE `comment` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '评论ID',
  `content` longtext COMMENT '评论内容',
  `create_time` datetime DEFAULT NULL COMMENT '评论时间',
  `nickname` varchar(255) DEFAULT NULL COMMENT '评论人昵称',
  `email` varchar(255) DEFAULT NULL COMMENT '评论人邮箱',
  `website` varchar(255) DEFAULT NULL COMMENT '评论人网址',
  `article_id` int(11) DEFAULT NULL COMMENT '评论所属文章ID',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='评论表';

CREATE TABLE `category` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '分类ID',
  `name` varchar(255) DEFAULT NULL COMMENT '分类名称',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='分类表';

CREATE TABLE `tag` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '标签ID',
  `name` varchar(255) DEFAULT NULL COMMENT '标签名称',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='标签表';

CREATE TABLE `article_category` (
  `article_id` int(11) NOT NULL COMMENT '文章ID',
  `category_id` int(11) NOT NULL COMMENT '分类ID',
  PRIMARY KEY (`article_id`,`category_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='文章分类关联表';

CREATE TABLE `article_tag` (
  `article_id` int(11) NOT NULL COMMENT '文章ID',
  `tag_id` int(11) NOT NULL COMMENT '标签ID',
  PRIMARY KEY (`article_id`,`tag_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='文章标签关联表';

以上是一个简单的博客数据库模型设计,可以根据实际需求进行调整和优化。

二.搭建后端环境:使用Spring Boot框架搭建后端环境,包括配置Maven、集成MyBatis、配置数据库连接等。可以使用IDEA等开发工具进行开发。

下面是使用Spring Boot框架搭建后端环境的步骤:

1.安装Java开发环境:在电脑上安装JDK开发环境,建议使用JDK8及以上版本。

下面是安装Java开发环境的步骤:

1. 下载JDK安装包:在Oracle官网下载对应操作系统的JDK安装包([https://www.oracle.com/java/technologies/javase-downloads.html ↗](https://www.oracle.com/java/technologies/javase-downloads.html))。

2. 安装JDK:运行下载的JDK安装包,按照提示完成JDK的安装。如果是Windows系统,可以选择默认安装路径。

3. 配置环境变量:将JDK的安装路径配置到系统环境变量中,包括JAVA_HOME、CLASSPATH、PATH三个环境变量。

   - JAVA_HOME:JDK的安装路径,例如:C:\Program Files\Java\jdk1.8.0_221
   
   - CLASSPATH:Java类库搜索路径,一般设置为当前目录,例如:.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar
   
   - PATH:系统执行命令的搜索路径,需要在原有的路径后面添加JDK的bin目录,例如:%PATH%;%JAVA_HOME%\bin

4. 验证JDK安装:打开命令行窗口,输入java -version命令,查看是否输出了JDK版本信息,如果输出了,则说明JDK安装成功。

安装Java开发环境可能会因操作系统不同而略有差异,以上步骤仅供参考。

2.安装Maven:Maven是一个构建工具,可以自动管理Java项目中的依赖关系和构建过程,建议安装最新版本的Maven。

下面是安装Maven的步骤:

1. 下载Maven安装包:在Apache官网下载最新版本的Maven安装包([https://maven.apache.org/download.cgi ↗](https://maven.apache.org/download.cgi))。

2. 解压Maven安装包:将下载的Maven安装包解压到任意目录下,例如:C:\apache-maven-3.8.3。

3. 配置环境变量:将Maven的bin目录添加到系统环境变量的PATH中,例如:%PATH%;C:\apache-maven-3.8.3\bin。

4. 验证Maven安装:打开命令行窗口,输入mvn -v命令,查看是否输出了Maven版本信息,如果输出了,则说明Maven安装成功。

安装Maven可能会因操作系统不同而略有差异,以上步骤仅供参考。

3.创建Spring Boot项目:可以使用Spring Initializr创建Spring Boot项目,选择Maven项目、选择相应的Spring Boot版本、选择Web、MyBatis等相关依赖。

下面是使用Spring Initializr创建Spring Boot项目的步骤:

1. 打开Spring Initializr:在浏览器中打开Spring Initializr([https://start.spring.io/ ↗](https://start.spring.io/))。

2. 选择项目配置:选择Maven项目、选择相应的Spring Boot版本、选择Web、MyBatis等相关依赖,可以根据实际需求进行选择。

3. 生成项目:点击“Generate”按钮,生成项目的压缩包。

4. 解压项目:将生成的项目压缩包解压到任意目录下,例如:C:\springboot-project。

5. 导入项目:使用IDEA等开发工具,导入解压后的项目,即可开始开发。

创建Spring Boot项目的具体步骤可能会因开发工具不同而略有差异,以上步骤仅供参考。

4.配置数据库连接:在application.properties或application.yml文件中配置数据库连接信息,包括数据库URL、用户名、密码等。

下面是在Spring Boot项目中配置数据库连接的步骤:

  1. 在项目的src/main/resources目录下创建application.properties或application.yml文件,用于存储配置信息。

  2. 在配置文件中添加数据库连接信息,例如:

    # MySQL数据库连接信息
    spring.datasource.url=jdbc:mysql://localhost:3306/blog?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
    spring.datasource.username=root
    spring.datasource.password=123456
    spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
    ```
    
    其中,spring.datasource.url属性指定数据库的URL,spring.datasource.username和spring.datasource.password属性指定数据库的用户名和密码,spring.datasource.driver-class-name属性指定数据库驱动的类名。
    
    
  3. 保存配置文件,重启项目,即可使用配置的数据库连接信息连接到相应的数据库。

以上是在Spring Boot项目中配置数据库连接的基本步骤,可以根据实际需求进行调整和优化。

5.配置MyBatis:在application.properties或application.yml文件中配置MyBatis相关信息,包括MyBatis配置文件路径、Mapper文件路径等。

下面是在Spring Boot项目中配置MyBatis的步骤:

  1. 在项目的src/main/resources目录下创建mybatis-config.xml文件,用于存储MyBatis的配置信息。

  2. 在配置文件中添加MyBatis配置信息,例如:

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
        <settings>
            <setting name="cacheEnabled" value="true" />
            <setting name="lazyLoadingEnabled" value="true" />
            <setting name="aggressiveLazyLoading" value="true" />
        </settings>
    </configuration>
    ```
    
    其中,settings节点中可以配置MyBatis的各种设置,例如是否启用缓存、是否启用延迟加载等。
    
    
  3. 在配置文件中添加Mapper文件的路径信息,例如:

    mybatis.mapper-locations=classpath:mapper/*.xml
    

    其中,mybatis.mapper-locations属性指定Mapper文件的路径,可以使用通配符指定多个Mapper文件。

  4. 在Spring Boot的配置文件中添加MyBatis相关的配置信息,例如:

    # MyBatis配置文件路径
    mybatis.config-location=classpath:mybatis-config.xml
    

    其中,mybatis.config-location属性指定MyBatis的配置文件路径。

  5. 在Mapper接口中使用@Mapper注解,告诉Spring Boot需要将该接口注册为Mapper。

  6. 在Mapper XML文件中编写SQL语句,实现与数据库的交互操作。

以上是在Spring Boot项目中配置MyBatis的基本步骤,可以根据实际需求进行调整和优化。

6.编写实体类:根据数据库模型设计,编写与数据库表对应的实体类。

下面是编写实体类的基本步骤:

  1. 根据数据库模型设计,确定实体类的属性和对应的数据库表字段。

  2. 在项目的src/main/java目录下创建实体类的包,例如com.example.demo.entity。

  3. 在实体类的包中创建与数据库表对应的实体类,例如User类。

  4. 在实体类中添加属性和对应的getter/setter方法,例如:

    public class User {
        private Long id;
        private String name;
        private Integer age;
        // 省略getter/setter方法
    }
    ````
    
    其中,id、name、age属性对应数据库表中的id、name、age字段。
    
    
  5. (可选)使用注解或XML方式实现实体类和数据库表之间的映射关系,例如:

    • 使用注解方式:

      @TableName("user")
      public class User {
          @TableId(value = "id", type = IdType.AUTO)
          private Long id;
          @TableField("name")
          private String name;
          @TableField("age")
          private Integer age;
          // 省略getter/setter方法
      }
      
    • 使用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.example.demo.mapper.UserMapper">
          <resultMap id="userMap" type="com.example.demo.entity.User">
              <id column="id" property="id"/>
              <result column="name" property="name"/>
              <result column="age" property="age"/>
          </resultMap>
      </mapper>
      

以上是编写实体类的基本步骤,可以根据实际需求进行调整和优化。

7.编写Mapper类:编写Mapper接口和Mapper XML文件,实现与数据库的交互操作,包括增删改查等。

编写Mapper类,需要分别编写Mapper接口和Mapper XML文件,实现与数据库的交互操作,包括增删改查等。

以下是一个可能的示例:

  1. ArticleMapper接口
public interface ArticleMapper {
    // 根据ID查询文章信息及其所属分类和标签信息
    Article findArticleById(int id);
    // 查询所有文章信息及其所属分类和标签信息
    List<Article> findAllArticles();
    // 新增文章信息
    int addArticle(Article article);
    // 更新文章信息
    int updateArticle(Article article);
    // 删除文章信息
    int deleteArticle(int id);
}
  1. ArticleMapper XML文件
<!-- namespace指定Mapper接口所在的包名和接口名 -->
<mapper namespace="com.example.mapper.ArticleMapper">
    <!-- 根据ID查询文章信息及其所属分类和标签信息 -->
    <select id="findArticleById" resultType="com.example.bean.Article">
        SELECT a.id, a.title, a.content, a.create_time, a.update_time, c.id AS category_id, c.name AS category_name,
            GROUP_CONCAT(t.id ORDER BY t.id SEPARATOR ',') AS tag_ids, GROUP_CONCAT(t.name ORDER BY t.id SEPARATOR ',') AS tag_names
        FROM article a
        LEFT JOIN article_category ac ON a.id = ac.article_id
        LEFT JOIN category c ON ac.category_id = c.id
        LEFT JOIN article_tag at ON a.id = at.article_id
        LEFT JOIN tag t ON at.tag_id = t.id
        WHERE a.id = #{id}
    </select>

    <!-- 查询所有文章信息及其所属分类和标签信息 -->
    <select id="findAllArticles" resultType="com.example.bean.Article">
        SELECT a.id, a.title, a.content, a.create_time, a.update_time, c.id AS category_id, c.name AS category_name,
            GROUP_CONCAT(t.id ORDER BY t.id SEPARATOR ',') AS tag_ids, GROUP_CONCAT(t.name ORDER BY t.id SEPARATOR ',') AS tag_names
        FROM article a
        LEFT JOIN article_category ac ON a.id = ac.article_id
        LEFT JOIN category c ON ac.category_id = c.id
        LEFT JOIN article_tag at ON a.id = at.article_id
        LEFT JOIN tag t ON at.tag_id = t.id
        GROUP BY a.id
    </select>

    <!-- 新增文章信息 -->
    <insert id="addArticle" parameterType="com.example.bean.Article">
        INSERT INTO article(title, content, create_time, update_time)
        VALUES(#{title}, #{content}, #{createTime}, #{updateTime})
    </insert>
    <insert id="addArticleCategory" parameterType="java.util.Map">
        INSERT INTO article_category(article_id, category_id)
        VALUES(#{articleId}, #{categoryId})
    </insert>
    <insert id="addArticleTag" parameterType="java.util.Map">
        INSERT INTO article_tag(article_id, tag_id)
        VALUES(#{articleId}, #{tagId})
    </insert>

    <!-- 更新文章信息 -->
    <update id="updateArticle" parameterType="com.example.bean.Article">
        UPDATE article
        SET title = #{title}, content = #{content}, update_time = #{updateTime}
        WHERE id = #{id}
    </update>
    <delete id="deleteArticleCategory" parameterType="int">
        DELETE FROM article_category WHERE article_id = #{id}
    </delete>
    <delete id="deleteArticleTag" parameterType="int">
        DELETE FROM article_tag WHERE article_id = #{id}
    </delete>

    <!-- 删除文章信息 -->
    <delete id="deleteArticle" parameterType="int">
        DELETE FROM article WHERE id = #{id}
    </delete>
</mapper>

上述示例代码中,Mapper接口中定义了增删改查等方法,对应的Mapper XML文件中定义了对应的SQL语句,使用#{}占位符来引用方法参数或实体类属性,使用resultType指定查询结果的返回类型。同时,为了处理多对多关系,SQL语句中使用了LEFT JOIN和GROUP_CONCAT等关键字,将文章与分类、标签等信息查询出来,并使用Map参数来实现多表数据的插入操作。

8.编写Service类:编写Service类,实现业务逻辑的处理,并调用Mapper类中的方法实现数据的读写操作。

编写Service类,需要实现业务逻辑的处理,并调用Mapper类中的方法实现数据的读写操作。

以下是一个可能的示例:

  1. ArticleService类
@Service
public class ArticleService {
    @Autowired
    private ArticleMapper articleMapper;
    @Autowired
    private CategoryMapper categoryMapper;
    @Autowired
    private TagMapper tagMapper;

    // 新增文章信息
    public boolean addArticle(Article article, List<Integer> categoryIds, List<Integer> tagIds) {
        // 新增文章信息
        int rows = articleMapper.addArticle(article);
        if (rows <= 0) {
            return false;
        }

        // 新增文章分类关联信息
        for (Integer categoryId : categoryIds) {
            Map<String, Integer> map = new HashMap<>();
            map.put("articleId", article.getId());
            map.put("categoryId", categoryId);
            articleMapper.addArticleCategory(map);
        }

        // 新增文章标签关联信息
        for (Integer tagId : tagIds) {
            Map<String, Integer> map = new HashMap<>();
            map.put("articleId", article.getId());
            map.put("tagId", tagId);
            articleMapper.addArticleTag(map);
        }

        return true;
    }

    // 更新文章信息
    public boolean updateArticle(Article article, List<Integer> categoryIds, List<Integer> tagIds) {
        // 更新文章信息
        int rows = articleMapper.updateArticle(article);
        if (rows <= 0) {
            return false;
        }

        // 删除文章分类关联信息
        articleMapper.deleteArticleCategory(article.getId());

        // 新增文章分类关联信息
        for (Integer categoryId : categoryIds) {
            Map<String, Integer> map = new HashMap<>();
            map.put("articleId", article.getId());
            map.put("categoryId", categoryId);
            articleMapper.addArticleCategory(map);
        }

        // 删除文章标签关联信息
        articleMapper.deleteArticleTag(article.getId());

        // 新增文章标签关联信息
        for (Integer tagId : tagIds) {
            Map<String, Integer> map = new HashMap<>();
            map.put("articleId", article.getId());
            map.put("tagId", tagId);
            articleMapper.addArticleTag(map);
        }

        return true;
    }

    // 删除文章信息
    public boolean deleteArticle(int id) {
        // 删除文章信息
        int rows = articleMapper.deleteArticle(id);
        if (rows <= 0) {
            return false;
        }

        // 删除文章分类关联信息
        articleMapper.deleteArticleCategory(id);

        // 删除文章标签关联信息
        articleMapper.deleteArticleTag(id);

        return true;
    }

    // 根据ID查询文章信息及其所属分类和标签信息
    public Article findArticleById(int id) {
        Article article = articleMapper.findArticleById(id);
        if (article != null) {
            // 查询文章所属的分类信息
            List<Category> categories = categoryMapper.findCategoriesByArticleId(article.getId());
            article.setCategories(categories);

            // 查询文章所属的标签信息
            List<Tag> tags = tagMapper.findTagsByArticleId(article.getId());
            article.setTags(tags);
        }
        return article;
    }

    // 查询所有文章信息及其所属分类和标签信息
    public List<Article> findAllArticles() {
        List<Article> articles = articleMapper.findAllArticles();
        if (articles != null && !articles.isEmpty()) {
            for (Article article : articles) {
                // 查询文章所属的分类信息
                List<Category> categories = categoryMapper.findCategoriesByArticleId(article.getId());
                article.setCategories(categories);

                // 查询文章所属的标签信息
                List<Tag> tags = tagMapper.findTagsByArticleId(article.getId());
                article.setTags(tags);
            }
        }
        return articles;
    }
}

上述示例代码中,ArticleService类中注入了ArticleMapper、CategoryMapper和TagMapper等Mapper类,通过调用Mapper类中的方法实现对数据库的增删改查等操作,并在此基础上实现了业务逻辑的处理。在新增和更新文章信息时,通过调用articleMapper的addArticleCategory和addArticleTag方法,新增文章与分类、标签之间的关联信息;在更新文章信息时,先删除原有的分类、标签关联信息,再新增新的分类、标签关联信息;在删除文章信息时,同样需要删除文章与分类、标签之间的关联信息。在查询文章信息时,通过调用categoryMapper和tagMapper的方法查询文章所属的分类和标签信息,并将查询结果设置到Article对象的categories和tags属性中,返回给调用方。

  1. 编写Controller类:编写Controller类,处理HTTP请求,调用Service类中的方法返回相应的数据。

  2. 启动项目:使用IDEA等开发工具启动项目,测试接口是否正常。

    编写Controller类,处理HTTP请求,调用Service类中的方法返回相应的数据。

    以下是一个可能的示例:

    1. ArticleController类
    @RestController
    @RequestMapping("/articles")
    public class ArticleController {
        @Autowired
        private ArticleService articleService;
    
        // 新增文章信息
        @PostMapping("")
        public ResponseEntity<?> addArticle(@RequestBody Article article, @RequestParam List<Integer> categoryIds, @RequestParam List<Integer> tagIds) {
            boolean result = articleService.addArticle(article, categoryIds, tagIds);
            if (result) {
                return ResponseEntity.ok().build();
            } else {
                return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
            }
        }
    
        // 更新文章信息
        @PutMapping("/{id}")
        public ResponseEntity<?> updateArticle(@PathVariable int id, @RequestBody Article article, @RequestParam List<Integer> categoryIds, @RequestParam List<Integer> tagIds) {
            article.setId(id);
            boolean result = articleService.updateArticle(article, categoryIds, tagIds);
            if (result) {
                return ResponseEntity.ok().build();
            } else {
                return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
            }
        }
    
        // 删除文章信息
        @DeleteMapping("/{id}")
        public ResponseEntity<?> deleteArticle(@PathVariable int id) {
            boolean result = articleService.deleteArticle(id);
            if (result) {
                return ResponseEntity.ok().build();
            } else {
                return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
            }
        }
    
        // 根据ID查询文章信息及其所属分类和标签信息
        @GetMapping("/{id}")
        public ResponseEntity<?> findArticleById(@PathVariable int id) {
            Article article = articleService.findArticleById(id);
            if (article != null) {
                return ResponseEntity.ok(article);
            } else {
                return ResponseEntity.notFound().build();
            }
        }
    
        // 查询所有文章信息及其所属分类和标签信息
        @GetMapping("")
        public ResponseEntity<?> findAllArticles() {
            List<Article> articles = articleService.findAllArticles();
            return ResponseEntity.ok(articles);
        }
    }
    

    上述示例代码中,ArticleController类处理了HTTP请求,并通过调用ArticleService类中的方法返回相应的数据。在新增、更新和删除文章信息时,通过@RequestBody注解将请求体中的JSON数据转化为Article对象,并通过@RequestParam注解获取请求参数中的categoryIds和tagIds,传递给ArticleService类中的方法进行处理。在查询文章信息时,通过@PathParm注解获取请求参数中的文章ID,并通过调用ArticleService类中的方法获取文章信息。最后,通过ResponseEntity对象返回HTTP响应,其中ok()方法返回状态码200,notFound()方法返回状态码404。

以上是使用Spring Boot框架搭建后端环境的基本步骤,可以根据实际需求进行调整和优化。

9.编写对应的代码生成器

​ 代码生成器可以根据数据库表结构自动生成Model、Mapper、Service、Controller等类的代码,提高开发效率和代码质量。以下是一个可能的示例:

  1. CodeGenerator类
public class CodeGenerator {
    private static final String DRIVER_CLASS_NAME = "com.mysql.cj.jdbc.Driver";
    private static final String DATABASE_URL = "jdbc:mysql://localhost:3306/test?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8";
    private static final String USER_NAME = "root";
    private static final String PASSWORD = "123456";
    private static final String BASE_PACKAGE = "com.example.demo";
    private static final String MAPPER_PACKAGE = "mapper";
    private static final String SERVICE_PACKAGE = "service";
    private static final String CONTROLLER_PACKAGE = "controller";
    private static final String MODEL_PACKAGE = "model";
    private static final String MAPPER_SUFFIX = "Mapper";
    private static final String SERVICE_SUFFIX = "Service";
    private static final String CONTROLLER_SUFFIX = "Controller";
    private static final String MODEL_SUFFIX = "";

    public static void main(String[] args) throws Exception {
        // 创建FreeMarker配置对象
        Configuration cfg = new Configuration(Configuration.VERSION_2_3_28);
        // 设置FreeMarker模板文件所在目录
        cfg.setClassForTemplateLoading(CodeGenerator.class, "/templates");

        // 初始化数据源
        DataSource dataSource = createDataSource();

        // 获取数据库中所有的表名
        List<String> tableNames = getTableNames(dataSource);

        // 循环处理每个表
        for (String tableName : tableNames) {
            // 获取表的元数据信息
            List<ColumnMetaData> columnMetaDatas = getTableMetaData(dataSource, tableName);

            // 生成Mapper接口文件
            generateMapper(cfg, tableName, columnMetaDatas);

            // 生成Model类文件
            generateModel(cfg, tableName, columnMetaDatas);

            // 生成Service类文件
            generateService(cfg, tableName, columnMetaDatas);

            // 生成Controller类文件
            generateController(cfg, tableName, columnMetaDatas);
        }
    }

    // 创建数据源
    private static DataSource createDataSource() {
        HikariConfig config = new HikariConfig();
        config.setDriverClassName(DRIVER_CLASS_NAME);
        config.setJdbcUrl(DATABASE_URL);
        config.setUsername(USER_NAME);
        config.setPassword(PASSWORD);

        HikariDataSource dataSource = new HikariDataSource(config);
        return dataSource;
    }

    // 获取所有表名
    private static List<String> getTableNames(DataSource dataSource) throws SQLException {
        List<String> tableNames = new ArrayList<>();

        try (Connection connection = dataSource.getConnection()) {
            DatabaseMetaData metaData = connection.getMetaData();
            ResultSet resultSet = metaData.getTables(null, null, null, new String[]{"TABLE"});
            while (resultSet.next()) {
                String tableName = resultSet.getString("TABLE_NAME");
                tableNames.add(tableName);
            }
        }

        return tableNames;
    }

    // 获取表的元数据信息
    private static List<ColumnMetaData> getTableMetaData(DataSource dataSource, String tableName) throws SQLException {
        List<ColumnMetaData> columnMetaDatas = new ArrayList<>();

        try (Connection connection = dataSource.getConnection()) {
            DatabaseMetaData metaData = connection.getMetaData();
            ResultSet resultSet = metaData.getColumns(null, null, tableName, null);
            while (resultSet.next()) {
                String columnName = resultSet.getString("COLUMN_NAME");
                String columnType = resultSet.getString("TYPE_NAME");
                String columnComment = resultSet.getString("REMARKS");
                boolean isNullable = resultSet.getBoolean("NULLABLE");
                columnMetaDatas.add(new ColumnMetaData(columnName, columnType, columnComment, isNullable));
            }
        }

        return columnMetaDatas;
    }

    // 生成Mapper接口文件
    private static void generateMapper(Configuration cfg, String tableName, List<ColumnMetaData> columnMetaDatas) throws IOException, TemplateException {
        Map<String, Object> model = new HashMap<>();
        model.put("package", BASE_PACKAGE + "." + MAPPER_PACKAGE);
        model.put("tableName", tableName);
        model.put("modelName", toCamelCase(tableName, true) + MODEL_SUFFIX);
        model.put("columns", columnMetaDatas);

        String fileName = toCamelCase(tableName, true) + MAPPER_SUFFIX + ".java";
        generateFile(cfg, model, "mapper.ftl", fileName);
    }

    // 生成Model类文件
    private static void generateModel(Configuration cfg, String tableName, List<ColumnMetaData> columnMetaDatas) throws IOException, TemplateException {
        Map<String, Object> model = new HashMap<>();
        model.put("package", BASE_PACKAGE + "." + MODEL_PACKAGE);
        model.put("tableName", tableName);
        model.put("modelName", toCamelCase(tableName, true) + MODEL_SUFFIX);
        model.put("columns", columnMetaDatas);

        String fileName = toCamelCase(tableName, true) + MODEL_SUFFIX + ".java";
        generateFile(cfg, model, "model.ftl", fileName);
    }

    // 生成Service类文件
    private static void generateService(Configuration cfg, String tableName, List<ColumnMetaData> columnMetaDatas) throws IOException, TemplateException {
        Map<String, Object> model = new HashMap<>();
        model.put("package", BASE_PACKAGE + "." + SERVICE_PACKAGE);
        model.put("tableName", tableName);
        model.put("modelName", toCamelCase(tableName, true) + MODEL_SUFFIX);
        model.put("mapperName", toCamelCase(tableName, true) + MAPPER_SUFFIX);
        model.put("serviceSuffix", SERVICE_SUFFIX);
        model.put("columns", columnMetaDatas);

        String fileName = toCamelCase(tableName, true) + SERVICE_SUFFIX + ".java";
        generateFile(cfg, model, "service.ftl", fileName);
    }

    // 生成Controller类文件
    private static void generateController(Configuration cfg, String tableName, List<ColumnMetaData> columnMetaDatas) throws IOException, TemplateException {
        Map<String, Object> model = new HashMap<>();
        model.put("package", BASE_PACKAGE + "." + CONTROLLER_PACKAGE);
        model.put("tableName", tableName);
        model.put("modelName", toCamelCase(tableName, true) + MODEL_SUFFIX);
        model.put("serviceName", toCamelCase(tableName, true) + SERVICE_SUFFIX);
        model.put("controllerSuffix", CONTROLLER_SUFFIX);
        model.put("columns", columnMetaDatas);

        String fileName = toCamelCase(tableName, true) + CONTROLLER_SUFFIX + ".java";
        generateFile(cfg, model, "controller.ftl", fileName);
    }

    // 生成文件
    private static void generateFile(Configuration cfg, Map<String, Object> model, String templateFileName, String outputFileName) throws IOException, TemplateException {
        Template template = cfg.getTemplate(templateFileName);
        File outputDir = new File("src/main/java/" + BASE_PACKAGE.replace('.', '/') + "/" + templateFileName.replace(".", "/") + "/");
        if (!outputDir.exists()) {
            outputDir.mkdirs();
        }
        File outputFile = new File(outputDir, outputFileName);
        Writer writer = new FileWriter(outputFile);
        template.process(model, writer);
        writer.close();
    }

    // 将下划线命名转换为驼峰命名
    private static String toCamelCase(String str, boolean capitalizeFirstLetter) {
        StringBuilder sb = new StringBuilder();
        boolean capitalize = capitalizeFirstLetter;
        for (int i = 0; i < str.length(); i++) {
            char ch = str.charAt(i);
            if (ch == '_') {
                capitalize = true;
            } else {
                if (capitalize) {
                    sb.append(Character.toUpperCase(ch));
                    capitalize = false;
                } else {
                    sb.append(ch);
                }
            }
        }
        return sb.toString();
    }
}

上述示例代码中,CodeGenerator类根据数据库表结构自动生成Model、Mapper、Service、Controller等类的代码。在main方法中,首先创建FreeMarker配置对象,然后初始化数据源,获取数据库中所有的表名,循环处理每个表,依次生成Mapper接口文件、Model类文件、Service类文件和Controller类文件。在生成每个类文件时,使用FreeMarker模板引擎读取对应的模板文件,并根据模板中的变量生成代码文件。其中,模板文件中的变量包括包名、表名、类名、属性名、方法名等信息。生成的类文件存储在src/main/java目录下,按照包名和类名的层次结构进行组织。

三.实现后端接口:根据前面设计的数据库模型,实现相应的后端接口,包括博客文章的增删改查、评论的增删改查等。

实现后端接口需要使用一个Web框架,如SpringMVC、SpringBoot等。以下是一个可能的示例,使用SpringBoot框架和MyBatis持久化框架:

1.定义实体类

public class Blog {
    private Long id;
    private String title;
    private String content;
    private Date createTime;
    private Date updateTime;
    private List<Comment> comments;
    // getter/setter省略
}

public class Comment {
    private Long id;
    private Long blogId;
    private String content;
    private Date createTime;
    private Date updateTime;
    // getter/setter省略
}

2.定义Mapper接口

@Mapper
public interface BlogMapper {
    Blog findById(Long id);
    List<Blog> findAll();
    List<Blog> findByTitle(String title);
    void save(Blog blog);
    void update(Blog blog);
    void deleteById(Long id);
}

@Mapper
public interface CommentMapper {
    Comment findById(Long id);
    List<Comment> findByBlogId(Long blogId);
    void save(Comment comment);
    void update(Comment comment);
    void deleteById(Long id);
}

3.定义Service接口

public interface BlogService {
    Blog findById(Long id);
    List<Blog> findAll();
    List<Blog> findByTitle(String title);
    void save(Blog blog);
    void update(Blog blog);
    void deleteById(Long id);
}

public interface CommentService {
    Comment findById(Long id);
    List<Comment> findByBlogId(Long blogId);
    void save(Comment comment);
    void update(Comment comment);
    void deleteById(Long id);
}

4.实现Service接口

@Service
@Transactional
public class BlogServiceImpl implements BlogService {
    @Autowired
    private BlogMapper blogMapper;
    @Autowired
    private CommentMapper commentMapper;

    @Override
    public Blog findById(Long id) {
        Blog blog = blogMapper.findById(id);
        if (blog != null) {
            List<Comment> comments = commentMapper.findByBlogId(id);
            blog.setComments(comments);
        }
        return blog;
    }

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

    @Override
    public List<Blog> findByTitle(String title) {
        return blogMapper.findByTitle(title);
    }

    @Override
    public void save(Blog blog) {
        blog.setCreateTime(new Date());
        blog.setUpdateTime(new Date());
        blogMapper.save(blog);
    }

    @Override
    public void update(Blog blog) {
        blog.setUpdateTime(new Date());
        blogMapper.update(blog);
    }

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

@Service
@Transactional
public class CommentServiceImpl implements CommentService {
    @Autowired
    private CommentMapper commentMapper;

    @Override
    public Comment findById(Long id) {
        return commentMapper.findById(id);
    }

    @Override
    public List<Comment> findByBlogId(Long blogId) {
        return commentMapper.findByBlogId(blogId);
    }

    @Override
    public void save(Comment comment) {
        comment.setCreateTime(new Date());
        comment.setUpdateTime(new Date());
        commentMapper.save(comment);
    }

    @Override
    public void update(Comment comment) {
        comment.setUpdateTime(new Date());
        commentMapper.update(comment);
    }

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

5.定义Controller类

@RestController
@RequestMapping("/api/blogs")
public class BlogController {
    @Autowired
    private BlogService blogService;

    @GetMapping("/{id}")
    public ResponseEntity<Blog> getBlogById(@PathVariable Long id) {
        Blog blog = blogService.findById(id);
        if (blog != null) {
            return ResponseEntity.ok(blog);
        } else {
            return ResponseEntity.notFound().build();
        }
    }

    @GetMapping
    public ResponseEntity<List<Blog>> getAllBlogs() {
        List<Blog> blogs = blogService.findAll();
        return ResponseEntity.ok(blogs);
    }

    @PostMapping
    public ResponseEntity<Void> createBlog(@RequestBody Blog blog) {
        blogService.save(blog);
        return ResponseEntity.created(URI.create("/api/blogs/" + blog.getId())).build();
    }

    @PutMapping("/{id}")
    public ResponseEntity<Void> updateBlog(@PathVariable Long id, @RequestBody Blog blog) {
        Blog existingBlog = blogService.findById(id);
        if (existingBlog != null) {
            blog.setId(id);
            blogService.update(blog);
            return ResponseEntity.noContent().build();
        } else {
            return ResponseEntity.notFound().build();
           }

    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteBlog(@PathVariable Long id) {
        Blog existingBlog = blogService.findById(id);
        if (existingBlog != null) {
            blogService.deleteById(id);
            return ResponseEntity.noContent().build();
        } else {
            return ResponseEntity.notFound().build();
        }
    }
}

@RestController
@RequestMapping("/api/comments")
public class CommentController {
    @Autowired
    private CommentService commentService;

    @GetMapping("/{id}")
    public ResponseEntity<Comment> getCommentById(@PathVariable Long id) {
        Comment comment = commentService.findById(id);
        if (comment != null) {
            return ResponseEntity.ok(comment);
        } else {
            return ResponseEntity.notFound().build();
        }
    }

    @GetMapping("/blog/{blogId}")
    public ResponseEntity<List<Comment>> getCommentsByBlogId(@PathVariable Long blogId) {
        List<Comment> comments = commentService.findByBlogId(blogId);
        return ResponseEntity.ok(comments);
    }

    @PostMapping
    public ResponseEntity<Void> createComment(@RequestBody Comment comment) {
        commentService.save(comment);
        return ResponseEntity.created(URI.create("/api/comments/" + comment.getId())).build();
    }

    @PutMapping("/{id}")
    public ResponseEntity<Void> updateComment(@PathVariable Long id, @RequestBody Comment comment) {
        Comment existingComment = commentService.findById(id);
        if (existingComment != null) {
            comment.setId(id);
            commentService.update(comment);
            return ResponseEntity.noContent().build();
        } else {
            return ResponseEntity.notFound().build();
        }
    }

    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteComment(@PathVariable Long id) {
        Comment existingComment = commentService.findById(id);
        if (existingComment != null) {
            commentService.deleteById(id);
            return ResponseEntity.noContent().build();
        } else {
            return ResponseEntity.notFound().build();
        }
    }
}

6.测试接口

可以使用Postman等工具测试上述接口的正确性和可用性。例如,可以发送以下HTTP请求:

GET /api/blogs/1

返回响应:

{
    "id": 1,
    "title": "My First Blog",
    "content": "This is my first blog post.",
    "createTime": "2021-01-01T00:00:00Z",
    "updateTime": "2021-01-01T00:00:00Z",
    "comments": [
        {
            "id": 1,
            "blogId": 1,
            "content": "Great post!",
            "createTime": "2021-01-02T00:00:00Z",
            "updateTime": "2021-01-02T00:00:00Z"
        },
        {
            "id": 2,
            "blogId": 1,
            "content": "I disagree with your point.",
            "createTime": "2021-01-03T00:00:00Z",
            "updateTime": "2021-01-03T00:00:00Z"
        }
    ]
}

四.搭建前端环境:使用Vue框架搭建前端环境,可以使用Vue CLI等工具进行创建。

使用Vue CLI搭建前端环境的步骤如下:

1.安装Node.js

Vue CLI需要Node.js环境,可以从Node.js官网下载并安装对应操作系统的Node.js版本。

2.安装Vue CLI

打开命令行工具(如Windows上的cmd或PowerShell、macOS上的终端),运行以下命令安装Vue CLI:

npm install -g @vue/cli

该命令会在全局范围内安装Vue CLI。

3.创建新的Vue项目

在命令行工具中进入要创建Vue项目的目录,运行以下命令:

vue create my-project

其中,my-project是项目的名称,可以根据实际情况进行修改。

在运行命令后,Vue CLI会提示选择要使用的特性,如Babel、TypeScript、CSS预处理器等。按照需要进行选择或保持默认设置即可。

4.运行Vue项目

在项目目录下,运行以下命令启动本地开发服务器:

npm run serve

该命令会启动本地的开发服务器,并在浏览器中打开网页。在开发过程中,可以在编辑器中修改代码并保存,浏览器会自动刷新并显示最新的页面。

五.实现前端页面:根据设计的页面原型,使用Vue框架实现前端页面,包括博客列表、博客详情、评论列表、分类标签等。

以下是一个可能的示例,使用Vue框架和Axios库进行实现:

1.安装Axios

Axios是一个基于Promise的HTTP库,用于发送Ajax请求。在命令行工具中运行以下命令安装Axios:

npm install axios

2.定义Vue组件

在Vue项目的src/components目录下,定义以下组件:

BlogList.vue:用于显示博客列表。代码如下:

<template>
  <div>
    <h2>Blog List</h2>
    <ul>
      <li v-for="blog in blogs" :key="blog.id">
        <router-link :to="{ name: 'BlogDetail', params: { id: blog.id } }">{{ blog.title }}</router-link>
        <p>{{ blog.content }}</p>
        <span>{{ blog.createTime }}</span>
      </li>
    </ul>
  </div>
</template>

<script>
import axios from 'axios';

export default {
  data() {
    return {
      blogs: [],
    };
  },
  mounted() {
    axios.get('/api/blogs').then((response) => {
      this.blogs = response.data;
    });
  },
};
</script>

BlogDetail.vue:用于显示单篇博客的详情和评论列表。代码如下:

<template>
  <div>
    <h2>{{ blog.title }}</h2>
    <p>{{ blog.content }}</p>
    <span>{{ blog.createTime }}</span>
    <h3>Comments</h3>
    <ul>
      <li v-for="comment in comments" :key="comment.id">
        <p>{{ comment.content }}</p>
        <span>{{ comment.createTime }}</span>
      </li>
    </ul>
  </div>
</template>

<script>
import axios from 'axios';

export default {
  data() {
    return {
      blog: null,
      comments: [],
    };
  },
  mounted() {
    const id = this.$route.params.id;
    axios.get(`/api/blogs/${id}`).then((response) => {
      this.blog = response.data;
      this.comments = this.blog.comments;
    });
  },
};
</script>

TagList.vue:用于显示博客的分类标签。代码如下:

<template>
  <div>
    <h2>Tags</h2>
    <ul>
      <li v-for="tag in tags" :key="tag">
        <router-link :to="{ name: 'BlogList', query: { tag: tag } }">{{ tag }}</router-link>
      </li>
    </ul>
  </div>
</template>

<script>
import axios from 'axios';

export default {
  data() {
    return {
      tags: [],
    };
  },
  mounted() {
    axios.get('/api/tags').then((response) => {
      this.tags = response.data;
    });
  },
};
</script>

3.定义Vue路由

在Vue项目的src/router/index.js文件中,定义以下路由:

import Vue from 'vue';
import VueRouter from 'vue-router';
import BlogList from '@/components/BlogList.vue';
import BlogDetail from '@/components/BlogDetail.vue';

Vue.use(VueRouter);

const routes = [
  {
    path: '/',
    redirect: '/blogs',
  },
  {
    path: '/blogs',
    name: 'BlogList',
    component: BlogList,
  },
  {
    path: '/blogs/:id',
    name: 'BlogDetail',
    component: BlogDetail,
  },
];

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes,
});

export default router;

4.在Vue项目的src/App.vue文件中,添加以下代码:

<template>
  <div id="app">
    <div>
      <router-link to="/blogs">Blog List</router-link>
      <router-link to="/tags">Tags</router-link>
    </div>
    <router-view />
  </div>
</template>

<script>
export default {
  name: 'App',
};
</script>

5.运行Vue项目

在命令行工具中运行以下命令启动本地开发服务器:

npm run serve

在浏览器中打开http://localhost:8080 ↗,即可看到博客列表和分类标签。点击博客标题或分类标签,可以进入博客详情或显示对应标签的博客列表。

六.集成后端接口:在前端页面中集成后端接口,通过axios等工具调用后端接口获取数据展示在页面上。

在前端页面中集成后端接口,可以通过axios等工具调用后端接口获取数据展示在页面上。以下是一个可能的示例:

1.定义后端接口

在后端(例如Node.js)中,定义以下接口:

GET /api/blogs:获取博客列表
GET /api/blogs/:id:获取指定id的博客
GET /api/tags:获取博客分类标签列表

在接口中,可以返回JSON格式的数据,例如:

[
  {
    "id": 1,
    "title": "My First Blog",
    "content": "This is my first blog",
    "createTime": "2022-01-01T00:00:00.000Z",
    "tags": ["tag1", "tag2"],
    "comments": [
      {
        "id": 1,
        "content": "Great blog",
        "createTime": "2022-01-02T00:00:00.000Z"
      },
      {
        "id": 2,
        "content": "Nice work",
        "createTime": "2022-01-03T00:00:00.000Z"
      }
    ]
  },
  {
    "id": 2,
    "title": "My Second Blog",
    "content": "This is my second blog",
    "createTime": "2022-01-04T00:00:00.000Z",
    "tags": ["tag2", "tag3"],
    "comments": [
      {
        "id": 3,
        "content": "Keep going",
        "createTime": "2022-01-05T00:00:00.000Z"
      }
    ]
  }
]

2.在前端页面中调用后端接口

在Vue项目的src/components目录中,修改之前定义的组件,使用axios库调用后端接口获取数据。例如,在BlogList.vue组件中,可以修改mounted方法如下:

mounted() {
  axios.get('/api/blogs').then((response) => {
    this.blogs = response.data;
  }).catch((error) => {
    console.error(error);
  });
}

在BlogDetail.vue组件中,可以修改mounted方法如下:

mounted() {
  const id = this.$route.params.id;
  axios.get(`/api/blogs/${id}`).then((response) => {
    this.blog = response.data;
    this.comments = this.blog.comments;
  }).catch((error) => {
    console.error(error);
  });
}

在TagList.vue组件中,可以修改mounted方法如下:

mounted() {
  axios.get('/api/tags').then((response) => {
    this.tags = response.data;
  }).catch((error) => {
    console.error(error);
  });
}

3.运行Vue项目并测试

在命令行工具中运行以下命令启动本地开发服务器:

npm run serve

在浏览器中打开http://localhost:8080 ↗,即可看到博客列表和分类标签。点击博客标题或分类标签,可以进入博客详情或显示对应标签的博客列表。在后端接口返回的JSON数据中,可以包含博客内容、分类标签、评论等信息,前端页面可以根据需要进行展示。

七.部署上线:将前端页面和后端接口部署到服务器上,可以使用Nginx等工具进行部署和代理。

将前端页面和后端接口部署到服务器上,可以使用Nginx等工具进行部署和代理。以下是一个可能的示例:

1.部署后端接口

将后端接口部署到服务器上,可以使用PM2等工具进行管理和启动。例如,在服务器上创建一个名为myapp的目录,将后端代码上传到该目录下,然后使用以下命令安装PM2并启动应用:

npm install pm2 -g
pm2 start index.js --name myapp

其中,index.js是后端代码的入口文件,myapp是应用的名称。使用pm2 logs myapp命令可以查看应用的日志。

2.部署前端页面

在本地使用npm run build命令可以将Vue项目打包成静态文件,然后将打包后的文件上传到服务器上。例如,在服务器上创建一个名为myapp的目录,将打包后的文件上传到该目录下。在Nginx配置文件中添加以下配置:

server {
  listen 80;
  server_name myapp.com;
  root /path/to/myapp/dist;
  index index.html;

  location / {
    try_files $uri $uri/ /index.html;
  }
}

其中,myapp.com是域名或服务器IP地址,/path/to/myapp是前端页面的根目录。在location / {}中,try_files指令用于尝试访问请求的文件或目录,如果不存在则返回index.html文件。

3.配置反向代理

如果前端页面和后端接口部署在不同的服务器上,可以使用Nginx等工具进行反向代理。例如,在前端服务器上的Nginx配置文件中,可以添加以下配置:

server {
  listen 80;
  server_name myapp.com;
  root /path/to/myapp/dist;
  index index.html;

  location /api/ {
    proxy_pass http://backend-server/;
  }

  location / {
    try_files $uri $uri/ /index.html;
  }
}

其中,myapp.com是域名或服务器IP地址,/path/to/myapp是前端页面的根目录,backend-server是后端接口的地址。在location /api/ {}中,proxy_pass指令用于将请求转发到后端接口。在location / {}中,try_files指令用于尝试访问请求的文件或目录,如果不存在则返回index.html文件。

4.重启Nginx和PM2

在修改Nginx配置文件或部署新的代码后,需要重启Nginx和PM2才能使更改生效。可以使用以下命令重启Nginx和PM2:

nginx -s reload
pm2 restart myapp

其中,myapp是应用的名称。使用pm2 logs myapp命令可以查看应用的日志。

实现个人博客需要前后端技术的综合运用,需要具备一定的数据库、后端、前端开发经验。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
毕业设计 基于springboot mysql Vue系统开发,供参考,提供说明材料+源代码 毕业设计 基于springboot mysql Vue系统开发,供参考,提供说明材料+源代码 毕业设计 基于springboot mysql Vue系统开发,供参考,提供说明材料+源代码 毕业设计 基于springboot mysql Vue系统开发,供参考,提供说明材料+源代码 毕业设计 基于springboot mysql Vue系统开发,供参考,提供说明材料+源代码 毕业设计 基于springboot mysql Vue系统开发,供参考,提供说明材料+源代码 毕业设计 基于springboot mysql Vue系统开发,供参考,提供说明材料+源代码 毕业设计 基于springboot mysql Vue系统开发,供参考,提供说明材料+源代码 毕业设计 基于springboot mysql Vue系统开发,供参考,提供说明材料+源代码 毕业设计 基于springboot mysql Vue系统开发,供参考,提供说明材料+源代码 毕业设计 基于springboot mysql Vue系统开发,供参考,提供说明材料+源代码 毕业设计 基于springboot mysql Vue系统开发,供参考,提供说明材料+源代码 毕业设计 基于springboot mysql Vue系统开发,供参考,提供说明材料+源代码 毕业设计 基于springboot mysql Vue系统开发,供参考,提供说明材料+源代码 毕业设计 基于springboot mysql Vue系统开发,供参考,提供说明材料+源代码 毕业设计 基于springboot mysql Vue系统开发,供参考,提供说明材料+源代码 毕业设计 基于springboot mysql Vue系统开发,供参考,提供说明材料+源代码 毕业设计 基于springboot mysql Vue系统开发,供参考,提供说明材料+源代码 毕业设计 基于springboot mysql Vue系统开发,供参考,提供说明材料+源代码 毕业设计 基于springboot mysql Vue系统开发,供参考,提供说明材料+源代码 毕业设计 基于springboot mysql Vue系统开发,供参考,提供说明材料+源代码
基于VueSpringBootMySQL的音乐播放管理系统可通过以下方式实现: 1. 使用Vue框架搭建前端界面:前端界面可以包括登录注册页面、音乐列表页面、音乐播放页面等。通过Vue的组件化开发,可以方便地实现页面的可复用性和交互性。 2. 使用SpringBoot框架搭建后端服务:后端服务主要负责接受前端的请求并进行处理,包括用户登录注册、音乐列表获取、音乐播放控制等。通过SpringBoot的注解驱动开发,可以简化开发流程。 3. 使用MySQL数据库存储数据:在MySQL中创建音乐、用户等相关数据表,通过SpringBoot的JPA或MyBatis等持久层框架实现与数据库的交互。例如,将音乐信息存储在音乐表中,包括音乐名称、歌手、时长等。 4. 用户登录注册功能:前端通过Vue的表单组件收集用户提供的账号和密码等信息,将其发送给后端进行验证。后端通过操作MySQL数据库中的用户表,判断用户是否存在以及密码是否正确,返回验证结果给前端。 5. 音乐列表获取功能:前端通过发送请求到后端的接口获取音乐列表数据。后端通过查询MySQL数据库中的音乐表,将查询结果返回给前端前端可以通过Vue的列表渲染功能将音乐列表展示出来。 6. 音乐播放控制功能:前端通过点击音乐列表中的音乐项,发送请求到后端的接口以获取音乐的播放地址。后端通过查询MySQL数据库中的音乐表,将音乐的播放地址返回给前端前端可以通过Vue的音乐播放组件实现音乐的播放控制,包括播放、暂停、调整音量等操作。 通过以上步骤,可以实现一个基于VueSpringBootMySQL的音乐播放管理系统。该系统可以实现用户登录注册、音乐列表获取和音乐播放控制等功能,为用户提供清晰便捷的音乐播放体验。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值