ElementUI实现登录注册+axios全局配置+CORS跨域

一、搭建项目

1.1 安装 Element-UI

先确保是否安装了vue-cli脚手架工具 !!!

安装vue脚手架可以看看我的上一篇博客

构建好项目后通过npm安装element-ui

cd 项目根路径 #进入新建项目的根目录

npm install element-ui -S #安装element-ui模块

1.2 导入组件

打开 src目录下的main.js,该文件是项目的入口文件,所以在这里导入,其他组件均可使用,不用再导入。

javascript 复制代码
import Vue from 'vue'
 
//新添加1
import ElementUI from 'element-ui'
//新增加2,避免后期打包样式不同,要放在import App from './App';之前
import 'element-ui/lib/theme-chalk/index.css'
 
import App from './App'
import router from './router'
 
Vue.use(ElementUI)   //新添加3
Vue.config.productionTip = false

1.3 创建登录、注册界面

我在src目录下新建了一个views专门存放一些界面组件,界面可自己设计,以下是我编写的:

1. 创建用户登录组件Login.vue

javascript 复制代码
<template>
  <div class="login-wrap">
    <el-form class="login-container">
      <h1 class="title">用户登录</h1>
      <el-form-item label="">
        <el-input type="text" v-model="username" placeholder="登录账号" autocomplete="off"></el-input>
      </el-form-item>
      <el-form-item label="">
        <el-input type="password" v-model="password" placeholder="登录密码" autocomplete="off"></el-input>
      </el-form-item>
      <el-form-item>
        <el-button type="warning" style="width:100%;" @click="doSubmit()">提交</el-button>
      </el-form-item>
      <el-row style="text-align: center;margin-top:-10px">
        <el-link type="primary">忘记密码</el-link>
        <el-link type="primary" @click="gotoRegister()">用户注册</el-link>
      </el-row>
    </el-form>
  </div>
</template>
 
<script>
  export default {
    name: 'Login',
    data() {
      return {
        username: '',
        password: ''
      }
    },
    methods: {
      gotoRegister() {
        this.$router.push("/Register");
      }
    }
  }
</script>
 
<style scoped>
  .login-wrap {
   box-sizing: border-box;
   width: 100%;
   height: 100%;
   padding-top: 10%;
  background-color: #3b7cf5;
   background-repeat: no-repeat;
   background-position: center right;
   background-size: 100%;
  }
 
  .login-container {
   border-radius: 10px;
   margin: 0px auto;
   width: 350px;
   padding: 30px 35px 15px 35px;
   border: 1px solid #eaeaea;
   text-align: left;
   background-color: rgba(229, 229, 229, 0.8);
  }
 
  .title {
    margin: 0px auto 40px auto;
    text-align: center;
    color: #0b0b0b;
  }
</style>

创建用户注册组件Register.vue

javascript 复制代码
<template>
  <div class="login-wrap">
    <el-form class="login-container">
      <h1 class="title">用户注册</h1>
      <el-form-item label="">
        <el-input type="text" v-model="username" placeholder="注册账号" autocomplete="off"></el-input>
      </el-form-item>
      <el-form-item label="">
        <el-input type="password" v-model="password" placeholder="注册密码" autocomplete="off"></el-input>
      </el-form-item>
      <el-form-item>
        <el-button type="warning" style="width:100%;" @click="doSubmit()">提交</el-button>
      </el-form-item>
      <el-row style="text-align: center;margin-top:-10px">
        <el-link type="primary">忘记密码</el-link>
        <el-link type="primary" @click="gotoLogin()">用户注册</el-link>
      </el-row>
    </el-form>
  </div>
</template>
 
<script>
  export default {
    name: 'Register',
    data() {
      return {
        username: '',
        password: ''
      }
    },
    methods: {
      gotoLogin() {
        this.$router.push("/");
      }
    }
  }
</script>
 
<style scoped>
  .login-wrap {
    box-sizing: border-box;
    width: 100%;
    height: 100%;
    padding-top: 10%;
 
    background-color: #3b7cf5;
    background-repeat: no-repeat;
    background-position: center right;
    background-size: 100%;
  }
 
  .login-container {
    border-radius: 10px;
    margin: 0px auto;
    width: 350px;
    padding: 30px 35px 15px 35px;
    border: 1px solid #eaeaea;
    text-align: left;
    background-color: rgba(229, 229, 229, 0.8);
  }
 
  .title {
    margin: 0px auto 40px auto;
    text-align: center;
    color: #0b0b0b;
  }
</style>

注1:<style scoped>

在vue组件中,在style标签上添加scoped属性,以表示它的样式作用于当下的模块,很好的实现了样式私有化的目的

注2:auto-complete="off"

autocomplete 属性是 HTML5 中的新属性,off-----禁用自动完成

2. 配置路由

javascript 复制代码
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
// 导入Login登录组件
import Login from '@/views/Login'
// 导入Register注册组件
import Register from '@/views/Register'
 
Vue.use(Router)
 
export default new Router({
  routes: [
    {
      path: '/',
      name: 'Login',
      component: Login
    },{
      path: '/Register',
      name: 'Register',
      component: Register
    }
  ]
})

3. 运行效果

在项目根目录执行 npm run dev指令

界面效果:

二、后台交互

2.1 引入axios

axios是vue2提倡使用的轻量版的ajax。它是基于promise的HTTP库。它会从浏览器中创建XMLHttpRequests,与Vue配合使用非常好。

Tips:vue.js有著名的全家桶系列:vue-router,vuex, vue-resource,再加上构建工具vue-cli,就是一个完整的vue项目的核心构成。 其中vue-resource是Vue.js的一款插件,它可以通过XMLHttpRequest或JSONP发起请求并处理响应,但在vue更新到2.0之后,作者就宣告不再对vue-resource更新,而是推荐的axios

安装指令:

npm i axios -S

2.2 添加vue-axios的全局配置

Axios是一个基于Promise 用于浏览器和 nodejs 的 HTTP 客户端,本质上也是对原生XHR的封装,只不过它是Promise的实现版本,符合最新的ES规范。

vue-axios是在axios基础上扩展的插件,在Vue.prototype原型上扩展了$http等属性,可以更加方便的使用axios。

通过vue-axios实现对axios的轻量封装:

第一步: 下载安装vue-axiosqs

npm i vue-axios -S

qs库用于解决POST请求问题,因为POST提交的参数的格式是Request Payload,这样后台取不到数据的。
npm install qs -S

**第二步:**导入api模块,添加axios的全局配置

在SPA项目的src目录下添加api模块,其中api模块包含了action.js(针对后台请求接口的封装定义 )和http.js(针对axios的全局配置)两个文件。

  • action.js
javascript 复制代码
/**
 * 对后台请求的地址的封装,URL格式如下:
 * 模块名_实体名_操作
 */
export default {
	'SERVER': 'http://localhost:8080/ssm_vue', //服务器
	'SYSTEM_USER_DOLOGIN': '/user/userLogin', //登陆
	'SYSTEM_USER_DOREG': '/user/userRegister', //注册
	'getFullPath': k => { //获得请求的完整地址,用于mockjs测试时使用
		return this.SERVER + this[k];
	}
}

对后台请求的地址的封装,URL格式:模块名实体名操作

2.2 ssm项目准备 (后端)

2.2.1 准备数据表
2.2.2 导入ssm项目

可以创建一个新项目连接数据库自动生成代码,并修改jdk和maven路径

2.2.3 编写控制器
java 复制代码
package com.zking.ssm.controller;

import com.zking.ssm.service.IUserService;
import com.zking.ssm.util.JsonResponseBody;
import com.zking.ssm.util.PageBean;
import com.zking.ssm.vo.UserVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.zking.ssm.jwt.*;

@Controller
@RequestMapping("/user")
public class UserController {

    @Autowired
    private IUserService userService;

    @RequestMapping("/userLogin")
    @ResponseBody
    public JsonResponseBody<?> userLogin(UserVo userVo, HttpServletResponse response){
        if(userVo.getUsername().equals("lwh")&&userVo.getPassword().equals("123")){
            //私有要求claim
//            Map<String,Object> json=new HashMap<String,Object>();
//            json.put("username", userVo.getUsername());
            //生成JWT,并设置到response响应头中
//            String jwt=JwtUtils.createJwt(json, JwtUtils.JWT_WEB_TTL);
//            response.setHeader(JwtUtils.JWT_HEADER_KEY, jwt);
            return new JsonResponseBody<>("用户登陆成功!",true,0,null);
        }else{
            return new JsonResponseBody<>("用户名或密码错误!",false,0,null);
        }
    }

    @RequestMapping("/queryUserPager")
    @ResponseBody
    public JsonResponseBody<List<Map<String,Object>>>
            queryUserPager(UserVo userVo, HttpServletRequest request){
        try {
            PageBean pageBean=new PageBean();
            pageBean.setRequest(request);
            List<Map<String, Object>> users = userService.queryUserPager(userVo, pageBean);
            return new JsonResponseBody<>("OK",true,pageBean.getTotal(),users);
        } catch (Exception e) {
            e.printStackTrace();
            return new JsonResponseBody<>("分页查询用户信息失败!",false,0,null);
        }

    }





    //注册方法
    @RequestMapping("/userRegister")
    @ResponseBody
    public JsonResponseBody<?> userRegister(UserVo user, HttpServletResponse response) {
        int i = userService.insertSelectives(user);
        if (i > 0) {
            return new JsonResponseBody<>("用户注册成功!", true, 0, null);
        } else {
            return new JsonResponseBody<>("用户注册失败!", false, 0, null);
        }
    }

}

2.3 前端编写

  1. Login.vue 提交按钮的监听函数中加入发送get请求的代码:
html 复制代码
<template>
    <div class="login-wrap">
      <el-form class="login-container">
        <h1 class="title">用户登录</h1>
        <el-form-item label="">
          <el-input type="text" v-model="username" placeholder="登录账号" autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item label="">
          <el-input type="password" v-model="password" placeholder="登录密码" autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item>
          <el-button type="warning" style="width:100%;" @click="doSubmit()">提交</el-button>
        </el-form-item>
        <el-row style="text-align: center;margin-top:-10px">
          <el-link type="primary">忘记密码</el-link>
          <el-link type="primary" @click="gotoRegister()">用户注册</el-link>
        </el-row>
      </el-form>
    </div>
  </template>
   
   <script>
   export default {
     name: 'Login',
     data() {
       return {
         username: '',
         password: ''
       }
     },
     methods: {
       gotoRegister() {
         this.$router.push("/Register");
       },
       doSubmit() {
         //定义后台登录方法连接地址
         let url = this.axios.urls.SYSTEM_USER_DOLOGIN;
         //获取数据
         let params = {
           username: this.username,
           password: this.password
         };
         /* get请求进行参数传递 */
         this.axios.get(url, {params:params}).then(r => {
           console.log(r);
            //判断是否登录成功
            if (r.data.success) {
              //利用ElementUI信息提示组件返回登录信息
              this.$message({
                message: r.data.msg,
                type: 'success'
              });
              //登陆成功,返回指定界面
              this.$route.push('主界面');
            } else {
              //弹出登录失败信息
              this.$message.error(r.data.msg);
            }
          }).catch(e => {
            //异常信息
          });
  
         /* post请求方式 */
         /* this.axios.post(url, params).then(r => {
           console.log(r);
           //判断是否登录成功
           if (r.data.success) {
             //利用ElementUI信息提示组件返回登录信息
             this.$message({
               message: r.data.msg,
               type: 'success'
             });
             //登陆成功,返回指定界面
             this.$route.push('主界面');
           } else {
             //弹出登录失败信息
             this.$message.error(r.data.msg);
           }
         }).catch(function(error) {
           console.log(error);
         }); */
       }
     }
   }
 </script>
   
  <style scoped>
    .login-wrap {
     box-sizing: border-box;
     width: 100%;
     height: 100%;
     padding-top: 10%;
    background-color: #3b7cf5;
     background-repeat: no-repeat;
     background-position: center right;
     background-size: 100%;
    }
   
    .login-container {
     border-radius: 10px;
     margin: 0px auto;
     width: 350px;
     padding: 30px 35px 15px 35px;
     border: 1px solid #eaeaea;
     text-align: left;
     background-color: rgba(229, 229, 229, 0.8);
    }
   
    .title {
      margin: 0px auto 40px auto;
      text-align: center;
      color: #0b0b0b;
    }
  </style>
  1. Register.vue 提交按钮的监听函数中加入发送post请求的代码:
html 复制代码
<template>
    <div class="login-wrap">
      <el-form class="login-container">
        <h1 class="title">用户注册</h1>
        <el-form-item label="">
          <el-input type="text" v-model="username" placeholder="注册账号" autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item label="">
          <el-input type="password" v-model="password" placeholder="注册密码" autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item>
          <el-button type="warning" style="width:100%;" @click="doSubmit()">提交</el-button>
        </el-form-item>
        <el-row style="text-align: center;margin-top:-10px">
          <el-link type="primary">忘记密码</el-link>
          <el-link type="primary" @click="gotoLogin()">用户登录</el-link>
        </el-row>
      </el-form>
    </div>
  </template>
   
   <script>
   export default {
     name: 'Register',
     data() {
       return {
         username: '',
         password: ''
       }
     },
     methods: {
       gotoLogin() {
         this.$router.push("/");
       },
       doSubmit() {
         //定义后台注册方法连接地址
         let url = this.axios.urls.SYSTEM_USER_DOREG;
         //获取数据
         let params = {
           username: this.username,
           password: this.password
         };
  
         /* post请求方式 */
         this.axios.post(url, params).then(r => {
           //判断是否注册成功
           if (r.data.success) {
             //利用ElementUI信息提示组件返回登录信息
             this.$message({
               message: r.data.msg,
               type: 'success'
             });
             //注册成功,返回指定界面
             //this.$route.push('主界面');
           } else {
             //弹出注册失败信息
             this.$message.error(r.data.msg);
           }
         }).catch(function(error) {
           console.log(error);
         });
       }
     },
   }
 </script>
  <style scoped>
    .login-wrap {
      box-sizing: border-box;
      width: 100%;
      height: 100%;
      padding-top: 10%;
   
      background-color: #3b7cf5;
      background-repeat: no-repeat;
      background-position: center right;
      background-size: 100%;
    }
   
    .login-container {
      border-radius: 10px;
      margin: 0px auto;
      width: 350px;
      padding: 30px 35px 15px 35px;
      border: 1px solid #eaeaea;
      text-align: left;
      background-color: rgba(229, 229, 229, 0.8);
    }
   
    .title {
      margin: 0px auto 40px auto;
      text-align: center;
      color: #0b0b0b;
    }
  </style>

2.4 登入测试

1. 启动ssm项目,部署tomcat服务器

2. 运行vue项目 ------ 指令:npm run dev

注: 项目运行时默认使用的是8080端口,如果其他程序也使用该端口则会引发冲突,如果tomcat默认使用的也是8080,为避免冲突需要改变端口号。
打开项目目录下config/index.js文件,修改dev部分的port即可

运行项目:

目前我有个问题,就是我在发送请求的时候,报出了个跨域的问题,但是我明明配置了,上网查了一下,说是有可能是配置过滤器的顺序问题,但是我改了之后还是一样,这里我还是记录一下,有没有大佬知道的 错误信息

三、CORS跨域

3.1 跨域请求问题

因为我们采用的是前后端分离的方式进行开发,前端和后端分别泡在不同的服务器上,基于安全性考虑,浏览器有同源策略,所以出现了跨域问题。

同源策略[same origin policy]是浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源。 同源策略是浏览器安全的基石。

3.2 跨域问题处理

解决方案:

需要配置tomcat允许跨域访问,tomcat跨域配置方法很多,在学springboot之前最简单的方式是自己写一个过滤器CorsFilter实现,添加一个响应头Access-Control-Allow-Origin即可

java 复制代码
package com.zking.ssm.util;
 
import java.io.IOException;
 
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
 
/**
 * 配置tomcat允许跨域访问
 * 
 * @author Administrator
 *
 */
public class CorsFilter2 implements Filter {
 
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
	}
 
	@Override
	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
			throws IOException, ServletException {
		HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;
 
		// Access-Control-Allow-Origin就是我们需要设置的域名
		// Access-Control-Allow-Headers跨域允许包含的头。
		// Access-Control-Allow-Methods是允许的请求方式
		httpResponse.setHeader("Access-Control-Allow-Origin", "*");// *,任何域名
		httpResponse.setHeader("Access-Control-Allow-Headers", "responseType,Origin, X-Requested-With, Content-Type, Accept");
		httpResponse.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE");
 
		//允许客户端处理一个新的响应头jwt
		//httpResponse.setHeader("Access-Control-Expose-Headers", "jwt,Content-Disposition");
		filterChain.doFilter(servletRequest, servletResponse);
	}
 
	@Override
	public void destroy() {
 
	}
}

web.xml 配置请求拦截

XML 复制代码
  <!--CrosFilter跨域过滤器-->
  <filter>
    <filter-name>corsFilter</filter-name>
    <filter-class>com.zking.ssm.util.CorsFilter2</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>corsFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
相关推荐
崔庆才丨静觅7 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60618 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了8 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅8 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅9 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅9 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment9 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅9 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊9 小时前
jwt介绍
前端
爱敲代码的小鱼10 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax