• SpringBoot学习笔记-项目初始化


    笔记内容转载自 AcWing 的 SpringBoot 框架课讲义,课程链接:AcWing SpringBoot 框架课

    1. 概念与项目介绍

    本次开发的项目名称为 King of Bots,在本地采用 IDEA 开发,项目前后端分离,可以部署在不同的服务器上,前端使用 Vue 开发,后端使用 SpringBoot 开发。

    用户通过客户端(Client)向服务器端(Server)发送一个 URL 请求,服务器端接收到请求后会向客户端返回一个 Web 页面(本质上是返回一个 HTML 字符串,浏览器会将这个字符串解析成网页)。

    前后端分离是指客户端第一次访问项目时就从 Web 服务器端获取到所有静态文件,然后每次给后端发送请求时后端只返回数据,然后由前端根据数据进行渲染(动态拼接字符串)页面。

    MVC,全称为 Model-View-Controller(模型-视图-控制器),是一种软件架构模式,其目标是将软件的用户界面(即前台页面)和业务逻辑分离,使代码具有更高的可扩展性、可复用性、可维护性以及灵活性。以下是对 MVC 各部分的详细解释:

    • 模型(Model):模型是应用程序中用于处理应用程序数据逻辑的部分。通常模型对象负责在数据库中存取数据。模型就是业务流程/状态的处理以及业务规则的制定。
    • 视图(View):视图是应用程序中处理数据显示的部分。通常视图是依据模型数据创建的。视图(View)代表用户交互界面,对于 Web 应用来说,可以概括为 HTML 界面,但有可能为 XHTML、XML 和 Applet。
    • 控制器(Controller):控制器是应用程序中处理用户交互的部分。通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据。控制可以理解为从用户接收请求,将模型与视图匹配在一起,共同完成用户的请求。

    2. 创建SpringBoot项目后端

    首先我们创建项目的主目录 king_of_bots,然后可以初始化一下 Git。

    然后使用 IDEA 在 king_of_bots 目录下创建项目的后端,在新建项目的界面中可以在左侧看到 Spring Initializr,里面提供了一个官方网址:Spring Initializr,但是这个网站有时候可能不稳定连不上,如果连不上可以换成 https://start.aliyun.com,但是可能版本会稍微旧一点。

    项目配置内容中的组(Group)名设置为 com.kob,工件(Artifact)名设置为 backend,即表示我们项目的后端,使用 JDK 1.8 的版本,类型(Type)处选择 Maven 管理项目。点击下一步后选择 SpringBoot 版本为 2.7.X,如果用 SpringBoot 3 需要 Java 17,依赖选上 Web 中的 Spring Web 即可,然后可以再选上 Template Engines 中的 Thymeleaf(只是用于演示前后端不分离的写法)。最后点击创建即可。

    第一次创建好项目后还需要一段时间安装相关的环境,src/main/java/com.kob.backend 中即可看到我们后端项目的入口文件 BackendApplication,运行后可以看到输出显示将服务启动到了本地的8080端口,这时我们访问 http://localhost:8080/,看到 Whitelabel Error Page 页面说明启动成功了。

    3. 前后端不分离开发方式

    我们之前说过客户端的一个 URL 请求一般就是对应后端的一个函数调用,我们在 com.kob.backend 包下新建一个 controller 包,用来存储我们所有的后端函数。

    假设我们现在要创建一个对战页面,我们就在 controller 包中继续创建一个 pk 包,然后在该包下创建 IndexController.java 文件。如果需要将函数变成 URL 对应的函数需要加上 @Controller 注解,我们这个 Controller 的所有函数应该都在 http://localhost:8080/pk/ 链接下,因此我们可以加上 @RequestMapping 注解设置父目录:

    package com.kob.backend.controller.pk;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    @Controller
    @RequestMapping("/pk/")
    public class IndexController {
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    如果我们的函数想要返回一个页面,需要把页面创建在 /src/main/resources/templates 目录下,我们先在该目录下创建 pk 目录,然后进去创建一个 index.html

    DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Titletitle>
    head>
    <body>
        <h1>Hello World!h1>
    body>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    我们每个函数都可以返回一个 HTML 文件的路径,这个路径从 templates 目录后开始写,对于每个函数都可以指定 @RequestMapping 注解,例如 @RequestMapping("index/") 就表示访问 http://localhost:8080/pk/index/ 会调用这个函数,我们实现不加任何子目录的链接返回 index.html

    package com.kob.backend.controller.pk;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    @Controller
    @RequestMapping("/pk/")
    public class IndexController {
        @RequestMapping("")
        public String index() {
            return "pk/index.html";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    现在我们重启一下项目,然后访问 http://localhost:8080/pk/ 即可看到我们的页面。

    假设我们有一张图片 logo.png 存放在 resources 目录下的 static/image 目录中,那么我们可以在 index.html 中使用(注意路径从 static 目录后开始写):

    DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Titletitle>
    head>
    <body>
        <div style="text-align: center">
            <img src="/image/logo.png" alt="">
        div>
    body>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    4. 前后端分离开发方式

    如果是前后端分离的开发方式,那么后端就不再是返回一个 HTML 页面了,而是返回一些数据。

    pk 包下创建一个 BotInfoController 类,表示返回 Bot 信息,这时我们需要用的是 @RestController 注解:

    package com.kob.backend.controller.pk;
    
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    @RequestMapping("/pk/")
    public class BotInfoController {
        @RequestMapping("getbotinfo/")
        public String getBotInfo() {
            return "Bot 1";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    现在访问链接 http://localhost:8080/pk/getbotinfo/ 即可看到网页显示的字符串信息。

    resources 目录下可以看到一个 application.properties 文件,如果是用 Spring 的默认网址创建的项目,这个文件内容是空的,如果是用阿里云的网址创建项目那么这个文件会自带一些内容,其中有个 server.port=8080 表示项目启动的端口号,我们可以修改这个端口号,防止和 Vue 的默认端口冲突。现在我们的该文件是空的,因此直接加一行 server.port=3000 即可。

    5. 创建Vue项目前端

    我们的前端使用 Vue 在 VS Code 中开发,Vue 的安装配置以及基本教程可见:Web 学习笔记-Vue3(环境配置、概念、整体布局设计)

    我们通过 Vue UI 在项目根目录下创建 Vue 前端项目,我们先创建 Web 端名为 web,创建好后记得装上插件 vue-routervuex 以及依赖 bootstrapjquery。然后再创建 AcApp 端名为 acapp,AcApp 端只需要安装一个 vuex 插件即可。

    使用 VS Code 打开 web 目录,先将 src/router/index.js 中的 createWebHashHistory 改成 createWebHistory,这样网页的链接就可以不用加上 #。然后我们删去没用的代码,将 src/views 以及 src/components 目录下的文件删去,App.vue 改成以下内容:

    <template>
      <div>Hello World!div>
      <router-view/>
    template>
    
    <style>
    style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    然后将 src/router/index.js 改成以下内容:

    import { createRouter, createWebHistory } from "vue-router";
    
    const routes = [];
    
    const router = createRouter({
      history: createWebHistory(),
      routes,
    });
    
    export default router;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    现在运行一下 Web 端代码(在 Vue UI 中的 Tasks 选项卡中)即可成功运行。

    6. 前后端通信

    我们在 BotInfoController 中返回一个 Map 对象的信息:

    package com.kob.backend.controller.pk;
    
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import java.util.HashMap;
    import java.util.Map;
    
    @RestController
    @RequestMapping("/pk/")
    public class BotInfoController {
        @RequestMapping("getbotinfo/")
        public Map<String, String> getBotInfo() {
            Map<String, String> bot = new HashMap<>();
            bot.put("name", "tiger");
            bot.put("rating", "1500");
            return bot;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    然后我们在前端 App.vue 中使用 Ajax 向这个链接发起请求,获得数据后显示出来:

    <template>
      <div>
        <div>Bot 名字:{{ bot_name }}div>
        <div>Bot 战斗力:{{ bot_rating }}div>
      div>
      <router-view />
    template>
    
    <script>
    import $ from "jquery";
    import { ref } from "vue";
    
    export default {
      name: "App",
      setup() {
        let bot_name = ref("");
        let bot_rating = ref("");
    
        $.ajax({
          url: "http://localhost:3000/pk/getbotinfo/",
          type: "GET",
          success: (resp) => {
            console.log(resp);
          },
        });
    
        return {
          bot_name,
          bot_rating,
        };
      },
    };
    script>
    
    <style>style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    这时候我们打开浏览器的控制台,应该会看到出现了跨域问题:Access to XMLHttpRequest at 'http://localhost:3000/pk/getbotinfo/' ......,这是因为我们的前端在8080端口,而后端在3000端口,因此两个域名不一样导致跨域问题。

    在后端的根包 com.kob.backend 下创建一个 config 包,然后在这个包中创建一个 CorsConfig 类,内容如下:

    package com.kob.backend.config;
    
    import org.springframework.context.annotation.Configuration;
    
    import javax.servlet.*;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    @Configuration
    public class CorsConfig implements Filter {
        @Override
        public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
            HttpServletResponse response = (HttpServletResponse) res;
            HttpServletRequest request = (HttpServletRequest) req;
    
            String origin = request.getHeader("Origin");
            if (origin != null) {
                response.setHeader("Access-Control-Allow-Origin", origin);
            }
    
            String headers = request.getHeader("Access-Control-Request-Headers");
            if (headers != null) {
                response.setHeader("Access-Control-Allow-Headers", headers);
                response.setHeader("Access-Control-Expose-Headers", headers);
            }
    
            response.setHeader("Access-Control-Allow-Methods", "*");
            response.setHeader("Access-Control-Max-Age", "3600");
            response.setHeader("Access-Control-Allow-Credentials", "true");
    
            chain.doFilter(request, response);
        }
    
        @Override
        public void init(FilterConfig filterConfig) {
        }
    
        @Override
        public void destroy() {
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    此时重启一下后端再去网页的控制台查看即可看到返回的 resp 内容。

    如果添加了以上代码无法解决跨域问题可以尝试改成以下代码:

    package com.kob.backend.config;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.cors.CorsConfiguration;
    import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
    import org.springframework.web.filter.CorsFilter;
    
    @Configuration
    public class CorsConfig{
        @Bean
        public CorsFilter corsFilter() {
            final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
            final CorsConfiguration corsConfiguration = new CorsConfiguration();
    
            corsConfiguration.setAllowCredentials(true);  // 是否允许请求带有验证信息
            corsConfiguration.addAllowedOriginPattern("*");  // 允许访问的客户端域名
            corsConfiguration.addAllowedHeader("*");  // 允许服务端访问的客户端请求头
            corsConfiguration.addAllowedMethod("*");  // 允许访问的方法名,GET POST等
    
            urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
            return new CorsFilter(urlBasedCorsConfigurationSource);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    现在我们即可在前端接收数据并在网页中显示出来:

    <template>
      <div>
        <div>Bot 名字:{{ bot_name }}div>
        <div>Bot 战斗力:{{ bot_rating }}div>
      div>
      <router-view />
    template>
    
    <script>
    import $ from "jquery";
    import { ref } from "vue";
    
    export default {
      name: "App",
      setup() {
        let bot_name = ref("");
        let bot_rating = ref("");
    
        $.ajax({
          url: "http://localhost:3000/pk/getbotinfo/",
          type: "GET",
          success: (resp) => {
            bot_name.value = resp.name;
            bot_rating.value = resp.rating;
          },
        });
    
        return {
          bot_name,
          bot_rating,
        };
      },
    };
    script>
    
    <style>style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    最后我们再理一下运行流程,首先用户访问 http://localhost:8080/ 进入前端的 Web 页面,这时候浏览器就会将 Vue 的所有前端静态文件缓存下来,然后浏览器就会执行到 Ajax 请求的代码,向后端发送一个请求,后端根据请求的地址 http://localhost:3000/pk/getbotinfo/ 去查找 Controller 所匹配的路径,找到 getBotInfo() 方法后就会返回一个 Map 对象至前端,这个对象包含 namerating 数据,浏览器接收到数据后就会将前端页面的 bot_namebot_rating 更新成传过来的值。

    我们在 web/src/assets 目录下创建 images 目录,弄一个背景图片放进去,然后在 App.vue 中添加背景:

    <template>
      ...
    template>
    
    <script>
      ...
    script>
    
    <style>
    body {
      background-image: url("@/assets/images/background.png");
      background-size: cover;
    }
    style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
  • 相关阅读:
    Android Parcelable反序列化漏洞分析与利用
    抽象之美——万物皆可设计
    R语言实操记录——获取包的三种渠道及安装包的三种方式
    微服务项目:尚融宝(44)(核心业务流程:借款申请(1))
    [附源码]计算机毕业设计JAVA家乡旅游文化推广系统
    文心一言 VS 讯飞星火 VS chatgpt (116)-- 算法导论10.3 1题
    详解IPD需求分析工具$APPEALS
    SWAT-MODFLOW地表水与地下水耦合
    【Javascript保姆级教程】显示类型转换和隐式类型转换
    mysql的高阶语句
  • 原文地址:https://blog.csdn.net/m0_51755720/article/details/134333676