The notes are reproduced from AcWing’s SpringBoot Framework course handouts, course link:AcWing SpringBoot Framework course.
CONTENTS
1. Concept and project introduction
The name of the project developed this time is King of Bots. It is developed locally using IDEA. The front and back ends of the project are separated and can be deployed on different servers. The front end is developed using Vue and the back end is developed using SpringBoot.
The user sends a URL request to the server through the client. After receiving the request, the server will return a Web page to the client (essentially returning an HTML string, and the browser will parse the string into a web page).
The separation of front-end and back-end means that when the client accesses the project for the first time, it obtains all static files from the Web server, and then the back-end only returns data every time it sends a request to the back-end, and then the front-end renders according to the data (dynamically splicing characters string) page.
MVC, the full name of Model-View-Controller (Model-View-Controller), is a software architecture pattern. Its goal is to separate the user interface (i.e., the front page) of the software from the business logic, so that the code has higher reliability. Scalability, reusability, maintainability and flexibility. Here is a detailed explanation of the various parts of MVC:
- Model: A model is the part of an application that handles the logic of application data. Typically model objects are responsible for accessing data in the database. The model is the processing of business processes/states and the formulation of business rules.
- View: The view is the part of the application that handles data display. Typically views are created from model data. View represents the user interaction interface. For web applications, it can be summarized as an HTML interface, but it may be XHTML, XML and Applet.
- Controller: The controller is the part of the application that handles user interaction. Typically the controller is responsible for reading data from the view, controlling user input, and sending data to the model. Control can be understood as receiving requests from users, matching models and views together, and jointly completing the user's requests.
2. Create SpringBoot project backend
First we create the main directory of the project king_of_bots
, and then we can initialize Git.
Then use IDEA to create the backend of the project in the king_of_bots
directory. In the new project interface, you can see Spring Initializr
on the left, which provides I have created an official website: Spring Initializr, but sometimes this website may be unstable and cannot be connected. If it cannot be connected, you can change it to < a i=5>, but the version may be slightly older. https://start.aliyun.com
The group name in the project configuration content is set to com.kob
, and the artifact name is set to backend
, which means that the background of our project On the client side, use JDK 1.8 version, select Maven
for Type (Type) to manage the project. Click Next and select the SpringBoot version 2.7. way of writing). Finally click Create.
After creating the project for the first time, it will take some time to install the relevant environment. src/main/java/com.kob.backend
You can see the entry file of our back-end projectBackendApplication
, after running, you can see the output showing that the service is started to the local port 8080. At this time, we visit http://localhost:8080/
and see the Whitelabel Error Page
page indicating that the startup was successful.
3. Development method without separation of front-end and back-end
We have said before that a URL request from the client is generally a function call corresponding to the backend. We create a new package under the com.kob.backend
package and use to store all our backend functions. controller
Suppose we want to create a battle page now, we will continue to create a package in the controller
package, and then create it under this package a> file. If you need to turn a function into a URL, the corresponding function needs to be annotated with . All functions of our Controller should be under the link, so we can add Annotation sets parent directory:pk
IndexController.java
@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 {
}
If our function wants to return a page, the page needs to be created in the /src/main/resources/templates
directory. We first create the pk
directory in this directory. Then go in and create aindex.html
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>Hello World!</h1>
</body>
</html>
Each of our functions can return the path of an HTML file. This path is written starting from the templates
directory. For each function, we can specify @RequestMapping
Annotation, for example, @RequestMapping("index/")
means that accessing http://localhost:8080/pk/index/
will call this function. We implement a link without adding any subdirectories and return 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";
}
}
Now we restart the project and visit http://localhost:8080/pk/
to see our page.
Suppose we have a picturelogo.png
stored in the directory under the resources
directory, then we can < Used in /span> directory): (note that the path starts after the static/image
index.html
static
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div style="text-align: center">
<img src="/image/logo.png" alt="">
</div>
</body>
</html>
4. Separate front-end and back-end development methods
If it is a development method that separates the front and back ends, then the back end no longer returns an HTML page, but returns some data.
Create a class under the pk
package to return Bot information. At this time, we need to use Note:BotInfoController
@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";
}
}
Visit the link now http://localhost:8080/pk/getbotinfo/
to see the string information displayed on the web page.
You can see a file in the resources
directory. If the project is created using Spring's default URL, the content of this file will be empty. If you use Alibaba Cloud's URL to create a project, then this file will come with some content. Among them, represents the port number for project startup. We can modify this port number to prevent it from being used with Vue's default port. conflict. Now our file is empty, so just add a line . application.properties
server.port=8080
server.port=3000
5. Create Vue project front-end
Our front-end is developed in VS Code using Vue. The installation configuration and basic tutorials of Vue can be found at:Web study notes-Vue3 (environment configuration, concepts, overall layout design)< /span>.
We create a Vue front-end project in the project root directory through Vue UI. We first create a Web client nameweb
. After creation, remember to install the plug-invue-router
and vuex
and depends on bootstrap
and jquery
. Then create an AcApp client named acapp
, and the AcApp client only needs to install one vuex
plug-in.
Use VS Code to open the web
directory, first change in src/router/index.js
to , so that the link to the web page does not need to be added . Then we delete the useless code, delete the files in the and directories, and change to the following content: createWebHashHistory
createWebHistory
#
src/views
src/components
App.vue
<template>
<div>Hello World!</div>
<router-view/>
</template>
<style>
</style>
Then change src/router/index.js
to the following:
import {
createRouter, createWebHistory } from "vue-router";
const routes = [];
const router = createRouter({
history: createWebHistory(),
routes,
});
export default router;
Now run the web side code (in the Tasks tab in Vue UI) and it will run successfully.
6. Front-end and back-end communication
We return the information of a object in 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;
}
}
Then we use Ajax in the front end App.vue
to initiate a request to this link, and display the data after obtaining it:
<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>
At this time, when we open the browser console, we should see a cross-domain problem:Access to XMLHttpRequest at 'http://localhost:3000/pk/getbotinfo/' ......
. This is because our front end is on port 8080 and the back end is on port 3000. , so the two domain names are different, causing cross-domain problems.
Create a package under the root package of the backendcom.kob.backend
, and then create a class in this package , the content is as follows: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() {
}
}
At this time, restart the backend and check the console of the web page to see the returned resp
content.
If adding the above code cannot solve the cross-domain problem, you can try changing it to the following code:
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);
}
}
Now we can receive the data on the front end and display it on the web page:
<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>
Finally, let’s take a look at the running process. First, the user visitshttp://localhost:8080/
to enter the front-end Web page. At this time, the browser will cache all the front-end static files of Vue, and then the browser The Ajax request code will be executed and a request will be sent to the backend. The backend will search for the path matched by the Controller based on the requested addresshttp://localhost:3000/pk/getbotinfo/
and find the getBotInfo()
method. Then a Map
object will be returned to the front end. This object contains name
and rating
data. After the browser receives the data, it will Update the bot_name
and bot_rating
of the front-end page to the passed values.
We create the directory under the web/src/assets
directory, put a background image in it, and then add it in Background:images
App.vue
<template>
...
</template>
<script>
...
</script>
<style>
body {
background-image: url("@/assets/images/background.png");
background-size: cover;
}
</style>