springboot+vue-cli前后端分离demo(含踩坑记)
Posted hans774882968
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了springboot+vue-cli前后端分离demo(含踩坑记)相关的知识,希望对你有一定的参考价值。
整个demo由两个项目组成,后端项目基于springboot,前端项目基于vue-cli。整个demo基于idea。
后端项目
前置操作:配置maven。maven可以用来管理jar包。虽然不太准确,但萌新暂时可以把maven与python的pip、nodejs的npm类比。先咕着吧~
配置好maven,就开始创建项目。File==>New==>Project,创建一个Spring Boot项目。项目名“springbootdemo”。
如果遇到显示无法连接到http://start.spring.io,或者是连接超时的问题:
如上图,打开settings,点击check connection,在输入框输入http://start.spring.io,等一会儿,出现connection successful就解决啦~
后面就是一些选项,没啥坑,略。项目结构如图
然后我们会在右下角看到正在下载Spring Boot包相关的依赖,等它下载完就好~
值得注意的是,如果后续需要引入其他的包,需要修改pom.xml,然后等右下角出现一个提示框,点击”import changes“。
- |.idea: idea项目目录,这里主要存放Intellij Idea的项目配置文件,不能删除。git的时候不要push这里的东西~
- |.mvn: 可以删除
- |src/main/java: 程序开发以及主程序入口
- |src/main/resources: 配置文件
- |src/test/java 测试程序
- |.gitignore git的ignore文件
- |boot-example.iml Intellij Idea项目配置文件
- |HELP.md 帮助文档,可以删除
- |mvnw 可以删除
- |mvnw.cmd 可以删除
- |pom.xml Maven的pom文件
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>net.wsw</groupId>
<artifactId>springbootdemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springbootdemo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--配置thymeleaf-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
其中spring-boot-starter-web是启动web服务必不可少的。spring-boot-starter-thymeleaf是模板引擎。
新建NewController.java。与SpringbootdemoApplication.java处于同一目录。
package net.wsw.springbootdemo;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class NewController {
@RequestMapping("/hw")
public String hw() {
return "hello world!";
}
@RequestMapping("/")
public String index() {
return "hello index!";
}
}
接下来就可以点击SpringbootdemoApplication.java的绿色箭头,运行web项目。没有报错的话命令行大概长这样
如果杯具地8080端口被占用了(比如我),就需要改默认端口qwq。打开src/main/resources/application.properties,加一行
server.port=8088
配置thymeleaf(可选)
thymeleaf是模板引擎,在前后端分离开发的大背景下貌似没啥用的样子……但作为demo还是可以配置一下。
pom.xml新增
<!--配置thymeleaf-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
等右下角出现一个提示框,点击”import changes“。
application.properties新增
# thymeleaf
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.check-template-location=true
spring.thymeleaf.suffix=.html
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.servlet.content-type=text/html
spring.thymeleaf.mode=HTML5
spring.thymeleaf.cache=false
classpath:/templates/的路径在这个demo指的是”target/classes/templates/“,属于默认设置。
在src/main/resources下新建templates文件夹,然后新建upload.html
<!DOCTYPE html>
<html xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title th:text="${title}"></title>
</head>
<body>
<h1 th:text="${title}"></h1>
<form action="/upload_img" method="post" enctype="multipart/form-data">
<p><input type="file" name="file" /></p>
<p><input type="submit" value="提交" /></p>
</form>
</body>
</html>
这里我们用模板引擎来做一个上传文件的demo。
新建UploadFileController.java
package net.wsw.springbootdemo;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
@Controller
public class UploadFileController {
@RequestMapping("/upload")
public String upload(Model model) {
model.addAttribute("title", "上传图片demo");
return "upload";
}
@RequestMapping(value = "/upload_img", method = RequestMethod.POST)
@ResponseBody
public String uploadImg(@RequestParam("file") MultipartFile file) {
if (file == null || file.isEmpty()) {
return "上传失败!请选择文件!";
}
File path = null;
try {
path = new File(ResourceUtils.getURL("classpath:").getPath());
File upload = new File(path.getAbsolutePath(), "static/img/");
if (!upload.exists()) {
upload.mkdirs();
}
File fileUp = new File(upload.getAbsolutePath() + "/" + file.getOriginalFilename());
file.transferTo(fileUp);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return "上传成功!";
}
}
值得注意的是,因为controller接收的参数名是file,html文件的input[type=“file”]必须保证name=“file”。
运行后端项目,上传一个文件,去看target/classes/static/img(如果原先该路径不存在,controller的代码会去新建),可以发现那个文件。
如果命令行报错是”没有接收到参数“,那是因为没有保证name=“file”。
前端项目
下载node.js并配置环境变量:略。
改成淘宝源
npm config set registry https://registry.npm.taobao.org
看现在是哪个源
npm config get registry
全局安装vue-cli
npm install -g vue-cli
查看vue脚手架是否已经安装成功
vue -V
接下来开始创建项目!项目名“sbdemo_frontend”。
可以用命令行创建,但是我们有idea这么好用的IDE,就可以免去命令行创建的痛苦啦!
Create New Project==>Static Web==>Vue.js……等等,static web那怎么没有vue.js呢?原来需要先下载插件!
1、settings==>Languages & Frameworks==>js语言版本选择es6。
2、settings==>Plugins,查找vue.js并安装。如图
接下来再去看看static web,发现已经可以选择vue.js啦~
后续就是一些选项,来源是在命令行构建项目时的那些选项。没啥坑点,略了。中间有一步,选择运行npm install则不需要自己专门再去一趟命令行啦~等待下载完毕所需依赖即可。
项目运行
npm run dev
值得注意的是vue-cli项目自带热部署。
项目结构如图
接下来设置eslint(可选)
ESLint是一个语法规则和代码风格的检查工具,可以用来保证写出语法正确、风格统一的代码。使用它可以避免低级错误和统一代码的风格。
打开settings,在搜索框搜索“eslint”,把“Enable”勾选上。
然后设置代码格式化快捷键。File==>Settings==>Keymap,搜索 Fix ESLint Problems。
Java已经占有一个代码格式化快捷键“Ctrl+Shift+L”,因此我们另设一个“Ctrl+Alt+;”。如图
终于开始写代码啦!
1、后端项目新建LoginController.java。与SpringbootdemoApplication.java处于同一目录。
package net.wsw.springbootdemo;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.HashMap;
import java.util.Map;
@Controller
public class LoginController {
@RequestMapping("/login")
@ResponseBody
public Map login(String username, String password) {
// response.setHeader("Access-Control-Allow-Origin", "*");// 部分浏览器需加
Map<String, Object> mp = new HashMap<>();
String u = "admin";
String p = "admin";
if (u.equals(username) && p.equals(password)) {
mp.put("code", 200);
} else {
mp.put("code", -1);
}
return mp;
}
}
2、前端和后端两个项目如何交互。
在开发的时候,前端有一个前端的服务器(nginx),后端有另一个后端的服务器(Tomcat)。开发前端内容的时候,可以把前端的请求通过前端服务器转发给后端(称为反向代理),这样就能实时观察结果,并且不需要知道后端怎么实现,而只需要知道接口提供的功能,两边的开发人员就可以各司其职了。
正向代理就是,你要访问一个网站,比如“xxx”,然后发现访问不到,于是你访问了一个能访问到“xxx”的代理服务器,让它帮你拿到你想浏览的页面。
反向代理就是,你访问了一个网站,你以为它是“xxx”,但其实它是“yy”,“yy”知道你其实是想找"xxx",就取回“xxx”的内容给你看。作为用户的你,是不知道有这个过程的,这么做是为了保护服务器,不暴露服务器的真实地址。
有一张示意图描述这两个过程
3、前端项目删除HelloWorld.vue,新建Index.vue和Login.vue
Index.vue
<template>
<router-link to="/login">点击登录</router-link>
</template>
<script>
export default {
name: 'Index'
}
</script>
<style scoped>
a {
color: #42b983;
}
</style>
Login.vue
<template>
<div class="login">
<p class="info">{{ info }}</p>
<p>用户名:<input v-model="loginForm.username" type="text" name="username" /></p>
<p>密码:<input v-model="loginForm.password" type="password" name="password" /></p>
<button @click="login">登录</button>
</div>
</template>
<script>
export default {
name: 'Login',
data () {
return {
loginForm: {
username: '',
password: ''
},
info: ''
}
},
methods: {
login () {
this.$axios.get('/login', {
params: {
username: this.loginForm.username,
password: this.loginForm.password
}
}).then(res => {
let dat = res.data
if (dat.code === 200) {
this.info = '登录成功'
} else {
this.info = '登录失败'
}
})
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
font-weight: normal;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
</style>
src/router/index.js修改路由。
import Vue from 'vue'
import Router from 'vue-router'
import Index from '@/components/Index'
import Login from '@/components/Login'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'Index',
component: Index
},
{
path: '/login',
name: 'Login',
component: Login
}
]
})
此时运行前端项目,可以发现除了login表单点击登录按钮后报错以外,其他均已work。
4、值得注意的是,前端项目的路由和后端项目的路由是两套系统。前端项目为了能够使用axios向后端项目发请求,需要设置反向代理。
src/main.js
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
// 设置反向代理,前端请求默认发送到 http://localhost:8083/api
import axios from 'axios'
axios.defaults.baseURL = 'http://localhost:8083/api'
// 全局注册,之后可在其他组件中通过 this.$axios 发送数据
Vue.prototype.$axios = axios
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el以上是关于springboot+vue-cli前后端分离demo(含踩坑记)的主要内容,如果未能解决你的问题,请参考以下文章