spring boot + Vue + iView前后端分离架构(Mac版) – (五)前后端交互
一、使用axios实现跨域请求
在前端项目hep-admin-web中的 src
下创建lib
目录,该目录主要用于存放axios
封装的实现,并创建axios.js
和api.request.js
文件。
axios.js
import Axios from 'axios';
import {Message} from 'iview';
class httpRequest {
constructor() {
this.options = {
method: '',
url: ''
};
// 存储请求队列
this.queue = {};
}
// 销毁请求实例
destroy(url) {
delete this.queue[url];
const queue = Object.keys(this.queue);
return queue.length;
}
// 请求拦截
interceptors(instance, url) {
// 添加请求拦截器
instance.interceptors.request.use(config => {
// 在往后端发送请求的时候,还没有发送之前的处理,
// 比如我们需要往我们的请求的header里面添加一些token或者其他信息的时候可以在此处进行相应的操作处理
console.log('请求拦截')
return config
}, error => {
// 对请求错误做些什么
return Promise.reject(error);
})
// 添加响应拦截器
instance.interceptors.response.use((res) => {
// 已经完成了和后端的交互,此处已经获取到了后端返回的请求了,
// 可以在此处做权限的验证拦截,比如用户非法登录的时候可以在此处重定向到登录页面
let {data} = res;
console.log('响应拦截'+res)
return data;
}, (error) => {
Message.error('服务内部错误');
// 对响应错误做点什么
return Promise.reject(error);
})
}
// 创建实例
create() {
let conf = {
// 远程请求的服务的地址
baseURL: "http://127.0.0.1:80",
// 超时时间
timeout: 5000,
headers: {
// 设置前端的跨域
'Access-Control-Allow-Origin': '*',
// 数据的提交方式为form的方式提交,若需要使用json的模式提交则将Content-Type值改为如下
// application/json; charset=utf-8
'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8',
'X-URL-PATH': location.pathname
}
};
return Axios.create(conf);
}
// 请求实例
request(options) {
let instance = this.create();
this.interceptors(instance, options.url);
options = Object.assign({}, options);
this.queue[options.url] = instance;
return instance(options);
}
}
export default httpRequest;
api.request.js
import HttpRequest from './axios';
const axios = new HttpRequest();
export default axios;
二、后端项目访问接口实现
在后端项目的UserController
中增加UserLoing
方法接口。设置账户admin/123456
默认可以登录,其余都拦截。
package com.huerpu.admin.web.core.controller;
import com.huerpu.admin.web.core.entity.User;
import com.huerpu.admin.web.core.service.UserService;
import io.swagger.annotations.ApiOperation;
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.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@ApiOperation(value = "Save Hep user")
@PostMapping("save")
public void getUserLists(User user){
userService.save(user);
}
@ApiOperation("User Login")
@PostMapping("login")
public User UserLoing(@RequestParam(name = "loginAccount") String loginAccount,
@RequestParam(name = "loginPassword") String loginPassword){
User user = new User();
user.setUser_password(loginPassword);
user.setUser_name(loginAccount);
if("admin".equals(loginAccount) && "123456".equals(loginPassword)){
user.setRoleResult("haveRole");
}else{
user.setRoleResult("noRole");
}
System.out.println(user);
return user;
}
}
在entity
目录中的User
类中,设置一个字段roleResult
用于判断是否有权限,其值设置为haveRole
则有权限登录。
/**
* 用户登录返回值,haveRole证明登录成功
*/
private String roleResult;
public String getRoleResult() {
return roleResult;
}
public void setRoleResult(String roleResult) {
this.roleResult = roleResult;
}
为了设置允许跨域访问,在controller
同级目录下,创建一个config
目录,在config
目录创建CorsConfig.java
文件。
package com.huerpu.admin.web.core.controller.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CorsConfig {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedHeaders("*")
.allowedMethods("*")
.allowedOrigins("*");
}
};
}
}
三、前后端交互 – 前端实现
在前端项目hep-admin-web的src-->api
目录下创建base.js
,在src-->api-->sys-->user
目录下创建user.api.js
。
base.js
中涵盖一个通用的远程服务调用类。user.api.js
用于和后端项目交互。
base.js
import axios from '../lib/api.request';
import qs from 'qs';
// 通用的远程访问的方法
export function fetch(url, params = {}) {
return axios.request({
// 响应的后端的接口的地址,不包含http://127.0.0.1:80这一部分,因此这一部分我们已经在axios.js中配置了
url: url,
// 由于我们的数据的提交方式是form的方式提交,因此需要对入参建转换
data:qs.stringify(params),
// 数据请求的方式为post
method: 'post'
});
}
user.api.js
import {fetch} from '../../base';
// 实现用户登录
export const login = params => {
// /user/login这个就是后台的controller方法里的响应的地址,params就是我们的入参
return fetch('/user/login',params);
};
修改login.vue
文件,在loginSystem
中认证登录,也就是后端传过来的User
类中的roleResult
字段,当其为haveRole
时,即可登录放行,否则显示登录密码错误。
login.vue
<template>
<div class="layout">
<Layout>
<Header class="layout-header" id="layout-header-scroll">
<Menu mode="horizontal" theme="dark" active-name="1">
<div class="layout-logo">
<img height="50px" width="50px" src="../../assets/logo.png"/>
</div>
<div class="layout-nav">
<language @on-lang-change="setLanguage" style="margin-right: 10px;" :lang="local"/>
</div>
<div class="layout-nav">
<MenuItem name="1" style="font-size: 30px;">
欢迎使用沪尔浦后台管理系统
</MenuItem>
</div>
</Menu>
</Header>
<Content :style="{ background: '#fff', minHeight: '500px'}">
<div style="float: right;margin: 100px 100px 0">
<Card title="欢迎登录沪尔浦后台管理系统">
<Form ref="loginForm" :model="loginForm" :rules="loginFormRule">
<div>
<FormItem prop="loginAccount">
账号:<Input v-model="loginForm.loginAccount" prefix="ios-contact"
:placeholder="$t('login.loginAccount')"
style="width: 200px;"/>
</FormItem>
<FormItem prop="loginPassword">
密码:<Input v-model="loginForm.loginPassword" prefix="ios-compass" type="password"
:placeholder="$t('login.loginPassword')" style="width: 200px;"/>
</FormItem>
</div>
</Form>
<div style="margin-top: 20px;">
<Button type="primary" @click="loginSystem" :long=true>登录</Button>
</div>
</Card>
</div>
</Content>
</Layout>
</div>
</template>
<script>
import Language from '../../components/language';
import { login } from '../../api/sys/user/user.api';
export default {
components: {
Language
},
data() {
return {
local: localStorage.getItem("lang"),
loginForm: {
loginAccount: '',
loginPassword: ''
},
loginFormRule: {
loginAccount: [
{required: true, message: '请输入账号', trigger: 'blur'},
{type: 'string', max: 30, message: '账号允许输入最大长度为30个字符', trigger: 'blur'}
],
loginPassword: [
{required: true, message: '请输入密码', trigger: 'blur'},
{type: 'string', max: 50, message: '密码允许输入最大长度为50个字符', trigger: 'blur'}
]
}
}
},
methods: {
loginSystem() {
this.$refs['loginForm'].validate((valid) => {
if (valid) {
login(this.loginForm).then(res=>{
console.info(res);
if(res.roleResult=='haveRole'){
this.$router.push({
name: 'main'
})
}else{
this.$Message.error('账号密码错误!');
}
})
}
})
},
setLanguage(lang) {
this.local = lang
localStorage.setItem('lang', lang)
}
},
mounted() {
}
}
</script>
<style scoped>
.layout-header {
position: relative;
z-index: 999;
height: 60px;
}
.layout {
border: 1px solid #d7dde4;
background: #f5f7f9;
position: relative;
border-radius: 4px;
overflow: hidden;
}
.layout-nav {
width: auto;
float: right;
margin: 0 auto;
margin-right: 20px;
}
.layout-logo {
width: 100px;
height: 30px;
border-radius: 10px;
float: left;
position: relative;
left: 20px;
top: 5px;
}
</style>
四、启动前端项目、后端项目验证。
前端、后端项目目录结构如下:
访问登录页面http://127.0.0.1:8080/#/login
,验证只有admin/123456
可以登录,其余账户均显示密码错误,没有登录跳转。