vue+elementui+springboot构建简单的前后端分离框架项目
- 1.安装node.js
- 2.安装cnpm
- 3.安装vue-cli
- 4.创建Vue项目
- 5.安装相关组件
- 5.1 安装element-ui
- 5.2 安装axios
- 5.3 安装vue-router
- 5.4 安装qs
- 5.5 安装Vuex
- 6.IDEA安装Vue.js插件
- 7.IDEA新建一个空项目
- 8.引入新建的vue项目
- 9.新建springboot项目
- 10.简单的前后端交互实现
- 10.1 编写vue项目
- 10.2 编写springboot项目
- 11.可能遇到的问题
- 11.1 No 'Access-Control-Allow-Origin' header is present on the requested resource.
- 补充
- 补充1 同源与跨域
相关文章链接:
Win10安装Node.js
Eclipse与IDEA创建一个Maven的Java Web项目
观前提示:
本文所使用的IDEA版本为ultimate 2019.1,JDK版本为1.8.0_141。
1.安装node.js
参考文章:Win10安装Node.js
2.安装cnpm
因为npm安装插件是从国外服务器下载,受网络影响大,可能出现异常,所以我们要安装淘宝镜像的cnpm。
执行命令
npm install -g cnpm --registry=http://registry.npm.taobao.org
执行命令
cnpm -v
可以查看cnpm的版本
3.安装vue-cli
执行命令
cnpm install -g @vue/cli
执行命令
vue -V
可以查看安装的版本
4.创建Vue项目
执行命令
vue create 项目名
选择默认即可
进入项目中cd vuedemo
执行命令
npm run serve
访问一下
项目创建成功。
5.安装相关组件
5.1 安装element-ui
cnpm install element-ui --save
5.2 安装axios
Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js中。可以理解为ajax。
详情链接网址:axios
执行以下命令安装axios
cnpm install axios --save
5.3 安装vue-router
Vue Router 是 Vue.js 官方的路由管理器。
详情链接网址:Vue Router
执行以下命令安装vue-router
cnpm install vue-router --save
5.4 安装qs
qs可将对象序列化,防止传输到后台的数据接收不到。
执行以下命令安装qs
cnpm install qs --save
5.5 安装Vuex
Vuex是Vue.js应用程序的状态管理模式+库。它充当应用程序中所有组件的集中存储,其规则确保状态只能以可预测的方式进行更改。
详情链接网址:Vuex
执行以下命令安装Vuex
cnpm install vuex --save
6.IDEA安装Vue.js插件
点击File->Settings…
选择Plugins -> 搜索框输入vue -> Install -> OK -> 重启IDEA使插件生效。这里由于我已经安装过Vue.js插件了,所以显示Installed。
点击File -> Settings… -> Languages & Frameworks -> JavaScripts -> 在JavaScript language version选择ECMAScript 6 -> OK
7.IDEA新建一个空项目
选择Empty Project->Next
填写项目名称->Finish
8.引入新建的vue项目
在Project Structure中引入新建好的vue项目。
选择好项目后->默认第一项Create module from existing sources-Next
一直Next到Finish即可。
查看一下package.json文件,发现相关组件也是正常安装的。
运行项目
9.新建springboot项目
在Project Structure新建一个Springboot的Module
参考文章:Eclipse与IDEA创建一个Maven的Java Web项目第2.2.1章节
10.简单的前后端交互实现
10.1 编写vue项目
目录结构如下
编写 main.js,引入element-ui控件,router。
import Vue from 'vue'
import App from './App.vue'
import router from './router'
//引入element-ui控件
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.config.productionTip = false
//使用use命令后才起作用
Vue.use(ElementUI)
new Vue({
router,
render: h => h(App),
}).$mount('#app')
编写 App.vue。
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<router-view/>
</div>
</template>
<script>
export default {
name: 'App',
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
编写router文件夹下的 index.js
import Vue from 'vue'
import Router from 'vue-router'
//使用懒加载的方式来引入,只有路由被访问的时候才加载
import home from '@/components/Home'
import login from '@/components/Login'
Vue.use(Router)
let router = new Router({
routes: [
{
path:'/',
name :'login',
component:login
},
{
path:'/login',
name :'login',
component:login
},
{
path:'/home',
name :'home',
component:home
}
]
})
export default router
编写登录页面 Login.vue
<template>
<el-form ref='AccountFrom' :model='account' :rules='rules' lable-position='left' lable-width='0px' class='demo-ruleForm login-container'>
<h3 class="title">登录系统首页</h3>
<el-form-item prop="username">
<el-input type="text" v-model="account.username" auto-complete="off" placeholder="账号"></el-input>
</el-form-item>
<el-form-item prop="pwd">
<el-input type="password" v-model="account.pwd" auto-complete="off" placeholder="密码"></el-input>
</el-form-item>
<el-checkbox v-model="checked" checked class="remember">记住密码</el-checkbox>
<el-form-item style="width:100%;">
<el-button type="primary" style="width:100%;" @click.native.prevent='handleLogin'>登录</el-button>
</el-form-item>
</el-form>
</template>
<script>
import axios from 'axios';
axios.defaults.baseURL = 'http://localhost:8090'
import qs from 'qs';
export default {
name: 'login',
data() {
return {
account: {
username: '',
pwd: ''
},
rules: {
username: [{
required: true,
message: '请输入账号',
trigger: 'blur'
}],
pwd: [{
required: true,
message: '请输入密码',
trigger: 'blur'
}]
},
checked: true
}
},
methods:{
handleLogin(){
this.$refs.AccountFrom.validate((valid)=>{
if(valid){
//将提交的数据进行封装
var param = {username : this.account.username,pwd:this.account.pwd};
axios.post("/system/login", qs.stringify(param)).then((result) => {
if(result.data.code == '200'){
//用vue路由跳转到后台主界面
this.$router.push({path:'/home'});
} else {
this.$message({
message:result.data.msg,
type:'error'
});
}
});
}else{
console.log('error submit');
return false;
}
});
}
}
}
</script>
<style>
body {
background: #DFE9FB;
}
.login-container {
width: 350px;
margin-left: 35%;
}
</style>
编写成功登陆页面 Home.vue
<template>
<div></div>
</template>
<script>
export default {
mounted: function () {
this.loadData();
},
methods: {
loadData() {
const h = this.$createElement;
this.$notify({
title: '标题名称',
message: h('i', { style: 'color: teal'}, '登录成功')
});
}
}
}
</script>
<style>
body {
background: #DFE9FB;
}
</style>
10.2 编写springboot项目
目录结构
pom.xml引入相关依赖
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.48</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.10</version>
</dependency>
编写 application.properties
#服务端口配置
server.port=8090
#数据库连接配置
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test?useSSL=false&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=root
#Mybatis配置
mybatis.mapper-locations=classpath:mapper/**.xml
编写 DemoApplication.java
package com.example.demo;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan("com.example.demo.dao")
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
编写 CorsFilter.java 解决跨域问题
package com.example.demo.filter;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
public class CorsFilter implements Filter{
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) servletResponse;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, PATCH, DELETE, PUT");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requseted-With, Content-Type, Accept");
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
}
}
编写 LoginController.java
package com.example.demo.controller;
import com.example.demo.model.User;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/system")
public class LoginController {
@Autowired
private UserService userService;
@PostMapping("/login")
public Map<String, Object> Login(User user){
Map<String, Object> result = new HashMap<>();
User user1 = userService.selectByNameAndPWD(user);
if(user1 == null ){
result.put("code", 500);
result.put("msg", "登录失败");
return result;
}
result.put("code", 200);
result.put("msg", "登录成功");
return result;
}
}
编写 UserService.java
package com.example.demo.service;
import com.example.demo.dao.UserMapper;
import com.example.demo.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public User selectByNameAndPWD(User user){
return userMapper.selectByNameAndPWD(user);
}
}
编写 UserMapper.java
package com.example.demo.dao;
import com.example.demo.model.User;
import org.springframework.stereotype.Repository;
@Repository
public interface UserMapper {
User selectByNameAndPWD(User user);
}
编写 User.java
package com.example.demo.model;
public class User {
private String id;
private String username;
private String pwd;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
}
编写 UserMapper.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.dao.UserMapper">
<select id="selectByNameAndPWD" resultType="com.example.demo.model.User" parameterType="com.example.demo.model.User">
select
id,username,pwd
from user
where username = #{username}
and pwd = #{pwd}
</select>
</mapper>
11.可能遇到的问题
11.1 No ‘Access-Control-Allow-Origin’ header is present on the requested resource.
如果遇到以下问题,那就是你没有处理跨域问题。
参考 第10.2节中 编写 CorsFilter.java 解决跨域问题 编写一个过滤器即可。
补充
补充1 同源与跨域
同源:协议、域名、端口均相同即为同源。
跨域:协议、域名、端口只要有一项不同即为跨域。
例:http://www.baidu.com,http://
为协议,www.baidu.com
为域名,80
为端口(默认端口可以省略)。
一下为是否与http://demo/login
同源的例子
http://demo/usr 同源
https://demo/usr 不同源,协议不同
http://a.demo/usr 不同源,域名不同
http://demo:8082/usr 不同源,端口不同