VueSPA(项目登陆前后台实现)

一路踩坑的博主):一定要细心不然BUG会让你活活气死

1.vue+elementUI完成注册及登陆

1.1. vue怎么引入和配置使用element-ui框架
1.1.1 使用vue-cli脚手架工具创建一个vue项目
vue init webpack pro01

1.1.2 npm安装elementUI
cd pro01 #进入新建项目的根目录
npm install element-ui -S #安装element-ui模块

##重要的事情说三遍:在指定位置!!!在指定位置!!!在指定位置!!!~~~添加三行代码
1.1.3 在项目中src目录下找到main.js,并在指定位置添加三行代码(main.js是入口文件,所以在这里引入就行,页面就不用引入了)
import Vue from ‘vue’

import ElementUI from ‘element-ui’ //新添加1
import ‘element-ui/lib/theme-chalk/index.css’ //新添加2,避免后期打包样式不同,要放在import App from ‘./App’;之前

import App from ‘./App’
import router from ‘./router’

Vue.use(ElementUI) //新添加3
Vue.config.productionTip = false
在这里插入图片描述

1.1.4 测试
修改HelloWorld.vue添加elementUI组件查看效果
在这里插入图片描述

2. Vue+ElementUI设计登陆页面

注1:相关样式见资料“css.txt”

注2:

注2:auto-complete=“off”
autocomplete 属性是 HTML5 中的新属性,off-----禁用自动完成

登陆页面源码(一定要配置好VUE ELEMENT-UI组件):

	<template>
		<div>
			<el-form class="demo-ruleForm login-container">
	      <el-form-item style="text-align: center;"><h1>后台登陆</h1></el-form-item >
			  <el-form-item >
			    <el-input type="text" v-model="user.username"  placeholder="账号"></el-input>
			  </el-form-item>
			  <el-form-item >
			    <el-input type="password" v-model="user.password"  placeholder="密码"></el-input>
			  </el-form-item>
			    <el-button type="primary" style="position: absolute;" @click="dofh()">返回上一及</el-button>
	        <el-button type="warning" style="display:block;margin:0 auto"  @click="douser()">登陸</el-button>
	        <router-link class="register"  to="">快速注册</router-link>
			</el-form>
		</div>
	</template>
	
	<script>
		import axios from 'axios'
		import qs from 'qs'

export default {
name:'Login',
	data:function(){
		return {
		  user:{
			  username:null,
			  password:null
		  }
	}
},
methods:{
	douser:function(){
		console.log(JSON.stringify(this.user));
		let url = this.axios.urls.SYS_USER_LOGIN;
		console.log("url=%s"+url);
	/* axios.get(url, {//注意数据是保存到json对象的params属性
			params: params//属性
			  }).then((response)=> {//符号函数
				console.log(response);  this.$message('这是一条消息提示');
			  }).catch((error)=>  {
				console.log(error);
			  });
	}, */
	 this.axios.post(url, this.user).then((response)=> {//注意数据是保存到json对象
					if(response.data.code == 0){
						 this.$message(response.data.message),
          /* this.$message('恭喜你,这是一条成功消息') */
						 this.$router.push('/AppMain')
					}else{
						this.$message.error('错了哦,这是一条错误消息')
					}
			  }).catch((error)=>  {
				console.log(error);
			  });
	},
	dofh:function(){
		this.$router.go(-1);
	}
}
}
</script>

<style>
  .register{
      display: block;
      text-align: center;
      text-decoration: none;
  }
	.login-wrap {
		box-sizing: border-box;
		width: 100%;
		height: 100%;
		padding-top: 10%;
		background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+Cjxzdmcgd2lkdGg9IjEzNjFweCIgaGVpZ2h0PSI2MDlweCIgdmlld0JveD0iMCAwIDEzNjEgNjA5IiB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPgogICAgPCEtLSBHZW5lcmF0b3I6IFNrZXRjaCA0Ni4yICg0NDQ5NikgLSBodHRwOi8vd3d3LmJvaGVtaWFuY29kaW5nLmNvbS9za2V0Y2ggLS0+CiAgICA8dGl0bGU+R3JvdXAgMjE8L3RpdGxlPgogICAgPGRlc2M+Q3JlYXRlZCB3aXRoIFNrZXRjaC48L2Rlc2M+CiAgICA8ZGVmcz48L2RlZnM+CiAgICA8ZyBpZD0iQW50LURlc2lnbi1Qcm8tMy4wIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj4KICAgICAgICA8ZyBpZD0i6LSm5oi35a+G56CB55m75b2VLeagoemqjCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTc5LjAwMDAwMCwgLTgyLjAwMDAwMCkiPgogICAgICAgICAgICA8ZyBpZD0iR3JvdXAtMjEiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDc3LjAwMDAwMCwgNzMuMDAwMDAwKSI+CiAgICAgICAgICAgICAgICA8ZyBpZD0iR3JvdXAtMTgiIG9wYWNpdHk9IjAuOCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNzQuOTAxNDE2LCA1NjkuNjk5MTU4KSByb3RhdGUoLTcuMDAwMDAwKSB0cmFuc2xhdGUoLTc0LjkwMTQxNiwgLTU2OS42OTkxNTgpIHRyYW5zbGF0ZSg0LjkwMTQxNiwgNTI1LjE5OTE1OCkiPgogICAgICAgICAgICAgICAgICAgIDxlbGxpcHNlIGlkPSJPdmFsLTExIiBmaWxsPSIjQ0ZEQUU2IiBvcGFjaXR5PSIwLjI1IiBjeD0iNjMuNTc0ODc5MiIgY3k9IjMyLjQ2ODM2NyIgcng9IjIxLjc4MzA0NzkiIHJ5PSIyMS43NjYwMDgiPjwvZWxsaXBzZT4KICAgICAgICAgICAgICAgICAgICA8ZWxsaXBzZSBpZD0iT3ZhbC0zIiBmaWxsPSIjQ0ZEQUU2IiBvcGFjaXR5PSIwLjU5OTk5OTk2NCIgY3g9IjUuOTg3NDY0NzkiIGN5PSIxMy44NjY4NjAxIiByeD0iNS4yMTczOTEzIiByeT0iNS4yMTMzMDk5NyI+PC9lbGxpcHNlPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0zOC4xMzU0NTE0LDg4LjM1MjAyMTUgQzQzLjg5ODQyMjcsODguMzUyMDIxNSA0OC41NzAyMzQsODMuNjgzODY0NyA0OC41NzAyMzQsNzcuOTI1NDAxNSBDNDguNTcwMjM0LDcyLjE2NjkzODMgNDMuODk4NDIyNyw2Ny40OTg3ODE2IDM4LjEzNTQ1MTQsNjcuNDk4NzgxNiBDMzIuMzcyNDgwMSw2Ny40OTg3ODE2IDI3LjcwMDY2ODgsNzIuMTY2OTM4MyAyNy43MDA2Njg4LDc3LjkyNTQwMTUgQzI3LjcwMDY2ODgsODMuNjgzODY0NyAzMi4zNzI0ODAxLDg4LjM1MjAyMTUgMzguMTM1NDUxNCw4OC4zNTIwMjE1IFoiIGlkPSJPdmFsLTMtQ29weSIgZmlsbD0iI0NGREFFNiIgb3BhY2l0eT0iMC40NSI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik02NC4yNzc1NTgyLDMzLjE3MDQ5NjMgTDExOS4xODU4MzYsMTYuNTY1NDkxNSIgaWQ9IlBhdGgtMTIiIHN0cm9rZT0iI0NGREFFNiIgc3Ryb2tlLXdpZHRoPSIxLjczOTEzMDQzIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNNDIuMTQzMTcwOCwyNi41MDAyNjgxIEw3LjcxMTkwMTYyLDE0LjU2NDA3MDIiIGlkPSJQYXRoLTE2IiBzdHJva2U9IiNFMEI0QjciIHN0cm9rZS13aWR0aD0iMC43MDI2Nzg5NjQiIG9wYWNpdHk9IjAuNyIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2UtZGFzaGFycmF5PSIxLjQwNTM1Nzg5OTg3MzE1MywyLjEwODAzNjk1MzQ2OTk4MSI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik02My45MjYyMTg3LDMzLjUyMTU2MSBMNDMuNjcyMTMyNiw2OS4zMjUwOTUxIiBpZD0iUGF0aC0xNSIgc3Ryb2tlPSIjQkFDQUQ5IiBzdHJva2Utd2lkdGg9IjAuNzAyNjc4OTY0IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS1kYXNoYXJyYXk9IjEuNDA1MzU3ODk5ODczMTUzLDIuMTA4MDM2OTUzNDY5OTgxIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPGcgaWQ9Ikdyb3VwLTE3IiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMjYuODUwOTIyLCAxMy41NDM2NTQpIHJvdGF0ZSgzMC4wMDAwMDApIHRyYW5zbGF0ZSgtMTI2Ljg1MDkyMiwgLTEzLjU0MzY1NCkgdHJhbnNsYXRlKDExNy4yODU3MDUsIDQuMzgxODg5KSIgZmlsbD0iI0NGREFFNiI+CiAgICAgICAgICAgICAgICAgICAgICAgIDxlbGxpcHNlIGlkPSJPdmFsLTQiIG9wYWNpdHk9IjAuNDUiIGN4PSI5LjEzNDgyNjUzIiBjeT0iOS4xMjc2ODA3NiIgcng9IjkuMTM0ODI2NTMiIHJ5PSI5LjEyNzY4MDc2Ij48L2VsbGlwc2U+CiAgICAgICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xOC4yNjk2NTMxLDE4LjI1NTM2MTUgQzE4LjI2OTY1MzEsMTMuMjE0MjgyNiAxNC4xNzk4NTE5LDkuMTI3NjgwNzYgOS4xMzQ4MjY1Myw5LjEyNzY4MDc2IEM0LjA4OTgwMTE0LDkuMTI3NjgwNzYgMCwxMy4yMTQyODI2IDAsMTguMjU1MzYxNSBMMTguMjY5NjUzMSwxOC4yNTUzNjE1IFoiIGlkPSJPdmFsLTQiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDkuMTM0ODI3LCAxMy42OTE1MjEpIHNjYWxlKC0xLCAtMSkgdHJhbnNsYXRlKC05LjEzNDgyNywgLTEzLjY5MTUyMSkgIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPC9nPgogICAgICAgICAgICAgICAgPC9nPgogICAgICAgICAgICAgICAgPGcgaWQ9Ikdyb3VwLTE0IiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgyMTYuMjk0NzAwLCAxMjMuNzI1NjAwKSByb3RhdGUoLTUuMDAwMDAwKSB0cmFuc2xhdGUoLTIxNi4yOTQ3MDAsIC0xMjMuNzI1NjAwKSB0cmFuc2xhdGUoMTA2LjI5NDcwMCwgMzUuMjI1NjAwKSI+CiAgICAgICAgICAgICAgICAgICAgPGVsbGlwc2UgaWQ9Ik92YWwtMiIgZmlsbD0iI0NGREFFNiIgb3BhY2l0eT0iMC4yNSIgY3g9IjI5LjExNzY0NzEiIGN5PSIyOS4xNDAyNDM5IiByeD0iMjkuMTE3NjQ3MSIgcnk9IjI5LjE0MDI0MzkiPjwvZWxsaXBzZT4KICAgICAgICAgICAgICAgICAgICA8ZWxsaXBzZSBpZD0iT3ZhbC0yIiBmaWxsPSIjQ0ZEQUU2IiBvcGFjaXR5PSIwLjMiIGN4PSIyOS4xMTc2NDcxIiBjeT0iMjkuMTQwMjQzOSIgcng9IjIxLjU2ODYyNzUiIHJ5PSIyMS41ODUzNjU5Ij48L2VsbGlwc2U+CiAgICAgICAgICAgICAgICAgICAgPGVsbGlwc2UgaWQ9Ik92YWwtMi1Db3B5IiBzdHJva2U9IiNDRkRBRTYiIG9wYWNpdHk9IjAuNCIgY3g9IjE3OS4wMTk2MDgiIGN5PSIxMzguMTQ2MzQxIiByeD0iMjMuNzI1NDkwMiIgcnk9IjIzLjc0MzkwMjQiPjwvZWxsaXBzZT4KICAgICAgICAgICAgICAgICAgICA8ZWxsaXBzZSBpZD0iT3ZhbC0yIiBmaWxsPSIjQkFDQUQ5IiBvcGFjaXR5PSIwLjUiIGN4PSIyOS4xMTc2NDcxIiBjeT0iMjkuMTQwMjQzOSIgcng9IjEwLjc4NDMxMzciIHJ5PSIxMC43OTI2ODI5Ij48L2VsbGlwc2U+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTI5LjExNzY0NzEsMzkuOTMyOTI2OCBMMjkuMTE3NjQ3MSwxOC4zNDc1NjEgQzIzLjE2MTYzNTEsMTguMzQ3NTYxIDE4LjMzMzMzMzMsMjMuMTc5NjA5NyAxOC4zMzMzMzMzLDI5LjE0MDI0MzkgQzE4LjMzMzMzMzMsMzUuMTAwODc4MSAyMy4xNjE2MzUxLDM5LjkzMjkyNjggMjkuMTE3NjQ3MSwzOS45MzI5MjY4IFoiIGlkPSJPdmFsLTIiIGZpbGw9IiNCQUNBRDkiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8ZyBpZD0iR3JvdXAtOSIgb3BhY2l0eT0iMC40NSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTcyLjAwMDAwMCwgMTMxLjAwMDAwMCkiIGZpbGw9IiNFNkExQTYiPgogICAgICAgICAgICAgICAgICAgICAgICA8ZWxsaXBzZSBpZD0iT3ZhbC0yLUNvcHktMiIgY3g9IjcuMDE5NjA3ODQiIGN5PSI3LjE0NjM0MTQ2IiByeD0iNi40NzA1ODgyNCIgcnk9IjYuNDc1NjA5NzYiPjwvZWxsaXBzZT4KICAgICAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTAuNTQ5MDE5NjA4LDEzLjYyMTk1MTIgQzQuMTIyNjI2ODEsMTMuNjIxOTUxMiA3LjAxOTYwNzg0LDEwLjcyMjcyMiA3LjAxOTYwNzg0LDcuMTQ2MzQxNDYgQzcuMDE5NjA3ODQsMy41Njk5NjA5NSA0LjEyMjYyNjgxLDAuNjcwNzMxNzA3IDAuNTQ5MDE5NjA4LDAuNjcwNzMxNzA3IEwwLjU0OTAxOTYwOCwxMy42MjE5NTEyIFoiIGlkPSJPdmFsLTItQ29weS0yIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgzLjc4NDMxNCwgNy4xNDYzNDEpIHNjYWxlKC0xLCAxKSB0cmFuc2xhdGUoLTMuNzg0MzE0LCAtNy4xNDYzNDEpICI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDwvZz4KICAgICAgICAgICAgICAgICAgICA8ZWxsaXBzZSBpZD0iT3ZhbC0xMCIgZmlsbD0iI0NGREFFNiIgY3g9IjIxOC4zODIzNTMiIGN5PSIxMzguNjg1OTc2IiByeD0iMS42MTc2NDcwNiIgcnk9IjEuNjE4OTAyNDQiPjwvZWxsaXBzZT4KICAgICAgICAgICAgICAgICAgICA8ZWxsaXBzZSBpZD0iT3ZhbC0xMC1Db3B5LTIiIGZpbGw9IiNFMEI0QjciIG9wYWNpdHk9IjAuMzUiIGN4PSIxNzkuNTU4ODI0IiBjeT0iMTc1LjM4MTA5OCIgcng9IjEuNjE3NjQ3MDYiIHJ5PSIxLjYxODkwMjQ0Ij48L2VsbGlwc2U+CiAgICAgICAgICAgICAgICAgICAgPGVsbGlwc2UgaWQ9Ik92YWwtMTAtQ29weSIgZmlsbD0iI0UwQjRCNyIgb3BhY2l0eT0iMC4zNSIgY3g9IjE4MC4wOTgwMzkiIGN5PSIxMDIuNTMwNDg4IiByeD0iMi4xNTY4NjI3NSIgcnk9IjIuMTU4NTM2NTkiPjwvZWxsaXBzZT4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMjguOTk4NTM4MSwyOS45NjcxNTk4IEwxNzEuMTUxMDE4LDEzMi44NzYwMjQiIGlkPSJQYXRoLTExIiBzdHJva2U9IiNDRkRBRTYiIG9wYWNpdHk9IjAuOCI+PC9wYXRoPgogICAgICAgICAgICAgICAgPC9nPgogICAgICAgICAgICAgICAgPGcgaWQ9Ikdyb3VwLTEwIiBvcGFjaXR5PSIwLjc5OTk5OTk1MiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTA1NC4xMDA2MzUsIDM2LjY1OTMxNykgcm90YXRlKC0xMS4wMDAwMDApIHRyYW5zbGF0ZSgtMTA1NC4xMDA2MzUsIC0zNi42NTkzMTcpIHRyYW5zbGF0ZSgxMDI2LjYwMDYzNSwgNC42NTkzMTcpIj4KICAgICAgICAgICAgICAgICAgICA8ZWxsaXBzZSBpZD0iT3ZhbC03IiBzdHJva2U9IiNDRkRBRTYiIHN0cm9rZS13aWR0aD0iMC45NDExNzY0NzEiIGN4PSI0My44MTM1NTkzIiBjeT0iMzIiIHJ4PSIxMS4xODY0NDA3IiByeT0iMTEuMjk0MTE3NiI+PC9lbGxpcHNlPgogICAgICAgICAgICAgICAgICAgIDxnIGlkPSJHcm91cC0xMiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMzQuNTk2Nzc0LCAyMy4xMTExMTEpIiBmaWxsPSIjQkFDQUQ5Ij4KICAgICAgICAgICAgICAgICAgICAgICAgPGVsbGlwc2UgaWQ9Ik92YWwtNyIgb3BhY2l0eT0iMC40NSIgY3g9IjkuMTg1MzQ3MTgiIGN5PSI4Ljg4ODg4ODg5IiByeD0iOC40NzQ1NzYyNyIgcnk9IjguNTU2MTQ5NzMiPjwvZWxsaXBzZT4KICAgICAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTkuMTg1MzQ3MTgsMTcuNDQ1MDM4NiBDMTMuODY1NzI2NCwxNy40NDUwMzg2IDE3LjY1OTkyMzUsMTMuNjE0MzE5OSAxNy42NTk5MjM1LDguODg4ODg4ODkgQzE3LjY1OTkyMzUsNC4xNjM0NTc4NyAxMy44NjU3MjY0LDAuMzMyNzM5MTU2IDkuMTg1MzQ3MTgsMC4zMzI3MzkxNTYgTDkuMTg1MzQ3MTgsMTcuNDQ1MDM4NiBaIiBpZD0iT3ZhbC03Ij48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPC9nPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0zNC42NTk3Mzg1LDI0LjgwOTY5NCBMNS43MTY2NjA4NCw0Ljc2ODc4OTQ1IiBpZD0iUGF0aC0yIiBzdHJva2U9IiNDRkRBRTYiIHN0cm9rZS13aWR0aD0iMC45NDExNzY0NzEiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8ZWxsaXBzZSBpZD0iT3ZhbCIgc3Ryb2tlPSIjQ0ZEQUU2IiBzdHJva2Utd2lkdGg9IjAuOTQxMTc2NDcxIiBjeD0iMy4yNjI3MTE4NiIgY3k9IjMuMjk0MTE3NjUiIHJ4PSIzLjI2MjcxMTg2IiByeT0iMy4yOTQxMTc2NSI+PC9lbGxpcHNlPgogICAgICAgICAgICAgICAgICAgIDxlbGxpcHNlIGlkPSJPdmFsLUNvcHkiIGZpbGw9IiNGN0UxQUQiIGN4PSIyLjc5NjYxMDE3IiBjeT0iNjEuMTc2NDcwNiIgcng9IjIuNzk2NjEwMTciIHJ5PSIyLjgyMzUyOTQxIj48L2VsbGlwc2U+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTM0LjYzMTI0NDMsMzkuMjkyMjcxMiBMNS4wNjM2NjY2Myw1OS43ODUwODIiIGlkPSJQYXRoLTEwIiBzdHJva2U9IiNDRkRBRTYiIHN0cm9rZS13aWR0aD0iMC45NDExNzY0NzEiPjwvcGF0aD4KICAgICAgICAgICAgICAgIDwvZz4KICAgICAgICAgICAgICAgIDxnIGlkPSJHcm91cC0xOSIgb3BhY2l0eT0iMC4zMyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTI4Mi41MzcyMTksIDQ0Ni41MDI4NjcpIHJvdGF0ZSgtMTAuMDAwMDAwKSB0cmFuc2xhdGUoLTEyODIuNTM3MjE5LCAtNDQ2LjUwMjg2NykgdHJhbnNsYXRlKDExNDIuNTM3MjE5LCAzMjcuNTAyODY3KSI+CiAgICAgICAgICAgICAgICAgICAgPGcgaWQ9Ikdyb3VwLTE3IiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxNDEuMzMzNTM5LCAxMDQuNTAyNzQyKSByb3RhdGUoMjc1LjAwMDAwMCkgdHJhbnNsYXRlKC0xNDEuMzMzNTM5LCAtMTA0LjUwMjc0MikgdHJhbnNsYXRlKDEyOS4zMzM1MzksIDkyLjUwMjc0MikiIGZpbGw9IiNCQUNBRDkiPgogICAgICAgICAgICAgICAgICAgICAgICA8Y2lyY2xlIGlkPSJPdmFsLTQiIG9wYWNpdHk9IjAuNDUiIGN4PSIxMS42NjY2NjY3IiBjeT0iMTEuNjY2NjY2NyIgcj0iMTEuNjY2NjY2NyI+PC9jaXJjbGU+CiAgICAgICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0yMy4zMzMzMzMzLDIzLjMzMzMzMzMgQzIzLjMzMzMzMzMsMTYuODkwMDExMyAxOC4xMDk5ODg3LDExLjY2NjY2NjcgMTEuNjY2NjY2NywxMS42NjY2NjY3IEM1LjIyMzM0NDU5LDExLjY2NjY2NjcgMCwxNi44OTAwMTEzIDAsMjMuMzMzMzMzMyBMMjMuMzMzMzMzMywyMy4zMzMzMzMzIFoiIGlkPSJPdmFsLTQiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDExLjY2NjY2NywgMTcuNTAwMDAwKSBzY2FsZSgtMSwgLTEpIHRyYW5zbGF0ZSgtMTEuNjY2NjY3LCAtMTcuNTAwMDAwKSAiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8L2c+CiAgICAgICAgICAgICAgICAgICAgPGNpcmNsZSBpZD0iT3ZhbC01LUNvcHktNiIgZmlsbD0iI0NGREFFNiIgY3g9IjIwMS44MzMzMzMiIGN5PSI4Ny41IiByPSI1LjgzMzMzMzMzIj48L2NpcmNsZT4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTQzLjUsODguODEyNjY4NSBMMTU1LjA3MDUwMSwxNy42MDM4NTQ0IiBpZD0iUGF0aC0xNyIgc3Ryb2tlPSIjQkFDQUQ5IiBzdHJva2Utd2lkdGg9IjEuMTY2NjY2NjciPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTcuNSwzNy4zMzMzMzMzIEwxMjcuNDY2MjUyLDk3LjY0NDk3MzUiIGlkPSJQYXRoLTE4IiBzdHJva2U9IiNCQUNBRDkiIHN0cm9rZS13aWR0aD0iMS4xNjY2NjY2NyI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwb2x5bGluZSBpZD0iUGF0aC0xOSIgc3Ryb2tlPSIjQ0ZEQUU2IiBzdHJva2Utd2lkdGg9IjEuMTY2NjY2NjciIHBvaW50cz0iMTQzLjkwMjU5NyAxMjAuMzAyMjgxIDE3NC45MzU0NTUgMjMxLjU3MTM0MiAzOC41IDE0Ny41MTA4NDcgMTI2LjM2Njk0MSAxMTAuODMzMzMzIj48L3BvbHlsaW5lPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xNTkuODMzMzMzLDk5Ljc0NTM4NDIgTDE5NS40MTY2NjcsODkuMjUiIGlkPSJQYXRoLTIwIiBzdHJva2U9IiNFMEI0QjciIHN0cm9rZS13aWR0aD0iMS4xNjY2NjY2NyIgb3BhY2l0eT0iMC42Ij48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTIwNS4zMzMzMzMsODIuMTM3MjEwNSBMMjM4LjcxOTQwNiwzNi4xNjY2NjY3IiBpZD0iUGF0aC0yNCIgc3Ryb2tlPSIjQkFDQUQ5IiBzdHJva2Utd2lkdGg9IjEuMTY2NjY2NjciPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMjY2LjcyMzQyNCwxMzIuMjMxOTg4IEwyMDcuMDgzMzMzLDkwLjQxNjY2NjciIGlkPSJQYXRoLTI1IiBzdHJva2U9IiNDRkRBRTYiIHN0cm9rZS13aWR0aD0iMS4xNjY2NjY2NyI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxjaXJjbGUgaWQ9Ik92YWwtNSIgZmlsbD0iI0MxRDFFMCIgY3g9IjE1Ni45MTY2NjciIGN5PSI4Ljc1IiByPSI4Ljc1Ij48L2NpcmNsZT4KICAgICAgICAgICAgICAgICAgICA8Y2lyY2xlIGlkPSJPdmFsLTUtQ29weS0zIiBmaWxsPSIjQzFEMUUwIiBjeD0iMzkuMDgzMzMzMyIgY3k9IjE0OC43NSIgcj0iNS4yNSI+PC9jaXJjbGU+CiAgICAgICAgICAgICAgICAgICAgPGNpcmNsZSBpZD0iT3ZhbC01LUNvcHktMiIgZmlsbC1vcGFjaXR5PSIwLjYiIGZpbGw9IiNEMURFRUQiIGN4PSI4Ljc1IiBjeT0iMzMuMjUiIHI9IjguNzUiPjwvY2lyY2xlPgogICAgICAgICAgICAgICAgICAgIDxjaXJjbGUgaWQ9Ik92YWwtNS1Db3B5LTQiIGZpbGwtb3BhY2l0eT0iMC42IiBmaWxsPSIjRDFERUVEIiBjeD0iMjQzLjgzMzMzMyIgY3k9IjMwLjMzMzMzMzMiIHI9IjUuODMzMzMzMzMiPjwvY2lyY2xlPgogICAgICAgICAgICAgICAgICAgIDxjaXJjbGUgaWQ9Ik92YWwtNS1Db3B5LTUiIGZpbGw9IiNFMEI0QjciIGN4PSIxNzUuNTgzMzMzIiBjeT0iMjMyLjc1IiByPSI1LjI1Ij48L2NpcmNsZT4KICAgICAgICAgICAgICAgIDwvZz4KICAgICAgICAgICAgPC9nPgogICAgICAgIDwvZz4KICAgIDwvZz4KPC9zdmc+);
		/* background-color: #112346; */
		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;
	background: #fff;
	border: 1px solid #eaeaea;
	text-align: left;
	box-shadow: 0 0 20px 2px rgba(0, 0, 0, 0.1);
}

.title {
	margin: 0px auto 40px auto;
	text-align: center;
	color: #505458;
}
.hhh{
	margin-bottom: center;
}
</style>

实现登陆页面需要配置router/index.js:

	import Vue from 'vue'
	import Router from 'vue-router'
	import Login from '@/views/Login'
	import Main from '@/views/Main'
	import AppMain from '@/vue/AppMain'//动态树页面
	import User from '@/vue/User'//动态树子页面
	import Uilr from '@/vue/Uilr'//动态树子页面
	import Role from '@/vue/Role'//动态树子页面
	
	
	
	Vue.use(Router)
	
	export default new Router({
	  routes: [
			{
				path: '/',
				name: 'Main',
				component: Main
			},
			{
				path: '/Login',
				name: 'Login',
				component: Login
			},
			{
				path: '/AppMain',
				name: 'AppMain',
				component: AppMain,
	      children:[
	        {
	          path: 'Uilr',
	          name: 'Uilr',
	          component: Uilr
	      },{
	          path: 'User',
	          name: 'User',
	          component: User
	      },{
	          path: 'Role',
	          name: 'Role',
	          component: Role
	      }]
			}]
	})

在cmd输入:npm run dev启动项目在这里插入图片描述

在这里插入图片描述

3. 后台交互(axios/qs/vue-axios)

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

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

  2.GET提交
  axios.get('/user', {//注意数据是保存到json对象的params属性
    params: {
      ID: 12345
    }
  }).then((response)=> {
    console.log(response);
  }).catch((error)=>  {
    console.log(error);
  });

  3.POST提交
  axios.post('/user', {//注意数据是直接保存到json对象
    firstName: 'Fred',
    lastName: 'Flintstone'
  }).then((response)=> {
    console.log(response);
  }).catch((error) =>{
    console.log(error);
  });
  
  ==登陆页面源码里面直接可以参考:==
  ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200510213106867.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NTA2NzEyMA==,size_16,color_FFFFFF,t_70)

  注1:axios跨域问题
       会一直报错:“http://127.0.0.1:8848' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header”
       因为使用了前后端分离开发,跨域访问了,解决方案:需要配置tomcat允许跨域访问,
       tomcat跨域配置方法很多,但最简单的方式是自己写一个过滤器CorsFilter实现,添加一个响应头
       Access-Control-Allow-Origin即可
       httpResponse.addHeader("Access-Control-Allow-Origin", "*");//*表示任何域名
       httpResponse.addHeader("Access-Control-Allow-Origin", "http://localhost:80"); 

  Access-Control-Allow-Origin:*                           #则允许所有域名的脚本访问该资源。
   Access-Control-Allow-Origin:https://www.fujieace.com    #允许特定的域名访问 

CorsFilter源码:

package com.zking.login.sys.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.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 配置tomcat允许跨域访问
 * 
 * @author Administrator
 *
 */
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 httpResponse = (HttpServletResponse) servletResponse;
//
// // Access-Control-Allow-Origin就是我们需要设置的域名
// // Access-Control-Allow-Headers跨域允许包含的头。
// // Access-Control-Allow-Methods是允许的请求方式
// httpResponse.addHeader("Access-Control-Allow-Origin", "*");// *,任何域名
// httpResponse.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT,
// DELETE");
// // httpResponse.setHeader("Access-Control-Allow-Headers", "Origin,
// // X-Requested-With, Content-Type, Accept");
//
// // 允许请求头Token
// httpResponse.setHeader("Access-Control-Allow-Headers",
// "Origin,X-Requested-With, Content-Type, Accept, Token");
// HttpServletRequest req = (HttpServletRequest) servletRequest;
// System.out.println("Token=" + req.getHeader("Token"));
// if("OPTIONS".equals(req.getMethod())) {
// return;
// }
//
//
// filterChain.doFilter(servletRequest, servletResponse);
// }

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
		throws IOException, ServletException {
	HttpServletResponse resp = (HttpServletResponse) servletResponse;
	HttpServletRequest req = (HttpServletRequest) servletRequest;

	// Access-Control-Allow-Origin就是我们需要设置的域名
	// Access-Control-Allow-Headers跨域允许包含的头。
	// Access-Control-Allow-Methods是允许的请求方式
	resp.setHeader("Access-Control-Allow-Origin", "*");// *,任何域名
	resp.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE");
	resp.setHeader("Access-Control-Allow-Headers", "Origin,X-Requested-With, Content-Type, Accept");

	// 允许请求头Token
	// httpResponse.setHeader("Access-Control-Allow-Headers","Origin,X-Requested-With,
	// Content-Type, Accept, Token");
	// System.out.println("Token=" + req.getHeader("Token"));

	if ("OPTIONS".equals(req.getMethod())) {// axios的ajax会发两次请求,第一次提交方式为:option,直接返回即可
		return;
	}
	filterChain.doFilter(servletRequest, servletResponse);
}

@Override
public void destroy() {

}
}

在Web.xml配置:(后面会提供源码)
在这里插入图片描述

注2:axios.get提交没有问题,axios.post提交后台接收不到数据
因为POST提交的参数的格式是Request Payload,这样后台取不到数据的(详情见资料“05 Vue中axios踩坑之路-POST传参 - RainSun - CSDN博客.mht”),
解决方案:使用qs.js库,将{a:‘b’,c:‘d’}转换成’a=b&c=d’
在这里插入图片描述

注3:为简化axios使用,还可以使用axios全局配置及拦截器,详情见资料“api/http.js”
axios.defaults.baseURL = ‘https://api.example.com’;
//axios.defaults.headers.common[‘Authorization’] = AUTH_TOKEN;//自定义请求头,添加认证令牌
axios.defaults.headers.post[‘Content-Type’] = ‘application/x-www-form-urlencoded’;

http.js源码:

	/**
	 * vue项目对axios的全局配置
	 */
	import axios from 'axios'
	import qs from 'qs'
	
	//引入action模块,并添加至axios的类属性urls上
	import action from '@/api/action'
	axios.urls = action
	
	// axios默认配置
	axios.defaults.timeout = 10000; // 超时时间
	// axios.defaults.baseURL = 'http://localhost:8080/j2ee15'; // 默认地址
	axios.defaults.baseURL = action.SERVER;
	
	//整理数据
	// 只适用于 POST,PUT,PATCH,transformRequest` 允许在向服务器发送前,修改请求数据
	axios.defaults.transformRequest = function(data) {
		data = qs.stringify(data);
		return data;
	};
	
	
	// 请求拦截器
	axios.interceptors.request.use(function(config) {
		return config;
	}, function(error) {
		return Promise.reject(error);
	});
	
	// 响应拦截器
	axios.interceptors.response.use(function(response) {
		return response;
	}, function(error) {
		return Promise.reject(error);
	});
	
	// // 路由请求拦截
	// // http request 拦截器
	// axios.interceptors.request.use(
	// 	config => {
	// 		//config.data = JSON.stringify(config.data);  
	// 		//config.headers['Content-Type'] = 'application/json;charset=UTF-8';
	// 		//config.headers['Token'] = 'abcxyz';
	// 		//判断是否存在ticket,如果存在的话,则每个http header都加上ticket
	// 		// if (cookie.get("token")) {
	// 		// 	//用户每次操作,都将cookie设置成2小时
	// 		// 	cookie.set("token", cookie.get("token"), 1 / 12)
	// 		// 	cookie.set("name", cookie.get("name"), 1 / 12)
	// 		// 	config.headers.token = cookie.get("token");
	// 		// 	config.headers.name = cookie.get("name");
	// 		// }
	// 		return config;
	// 	},
	// 	error => {
	// 		return Promise.reject(error.response);
	// 	});
	
	// // 路由响应拦截
	// // http response 拦截器
	// axios.interceptors.response.use(
	// 	response => {
	// 		if (response.data.resultCode == "404") {
	// 			console.log("response.data.resultCode是404")
	// 			// 返回 错误代码-1 清除ticket信息并跳转到登录页面
	// 			//      cookie.del("ticket")
	// 			//      window.location.href='http://login.com'
	// 			return
	// 		} else {
	// 			return response;
	// 		}
	// 	},
	// 	error => {
	// 		return Promise.reject(error.response) // 返回接口返回的错误信息
	// 	});

export default axios;

注4:为方便开发,建议对请求地址进行封装,详情见资料“api/action.js”
action.js源码:

 /**
 * 对后台请求的地址的封装,URL格式如下:
 * 模块名_实体名_操作
 */
export default {
	//服务器
	'SERVER': 'http://localhost:8080/vueSPA',

	//用户管理
	'SYS_USER_LOGIN': '/sys/userAction.action', //登陆
	/* 'SYS_USER_DOREG': '/sys/userAction_doReg.action', //注册
	'SYS_USER_LIST': '/sys/userAction_list.action', //用户查询
	'SYS_USER_DORESETPWD': '/sys/userAction_doResetPwd.action', //重置密码 */

	//文章管理
	'SYS_ARTICLES_ADD': '/sys/articlesAction_add.action',
	'SYS_ARTICLES_EDIT': '/sys/articlesAction_edit.action',
	'SYS_ARTICLES_DEL': '/sys/articlesAction_del.action',
	'SYS_ARTICLES_LOAD': '/sys/articlesAction_load.action',
	'SYS_ARTICLES_LIST': '/sys/articlesAction_list.action',

	//菜单管理
	'SYS_TREENODE_BOOTS': '/sys/TreeNodeAction_Boots.action',//动态树action

	//获得请求的完整地址,用于mockjs测试时使用
	'getFullPath': k => {
		return this.SERVER + this[k];
	}
}

注5:_~~~~为进一步简化开发,将action.js的URL地址封装到axios.urls属性上

在这里插入图片描述
3.2 qs

  qs.js它是一个url参数转化的js库。用法就两个:
  var obj = qs.parse('a=b&c=d');  //将URL解析成对象的形式:{a:'b',c:'d'}
  var str = qs.stringify(obj);    //将对象 序列化成URL的形式,以&进行拼接:a=b&c=d'

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

3.4 axios/qs/vue-axios安装及使用步骤
1.安装
npm install axios -S
npm install qs -S
npm install vue-axios -S

2.修改main.js文件
#import axios from ‘axios’
#import qs from ‘qs’
import axios from ‘@/api/http’ #vue项目对axios的全局配置
import VueAxios from ‘vue-axios’
Vue.use(VueAxios,axios)
在这里插入图片描述

3.之后就可以直接在Vue组件文件的methods里使用了
this.axios.get(url,{params:{id:1,name:‘zs’}}).then((response)=>{
this.newsList=response.data.data;
}).catch((response)=>{
console.log(response);
});

在这里插入图片描述
附录一:ES6的语法箭头函数,详情见资料“03 箭头函数 - 廖雪峰的官方网站.mht”
doSomething(function(a){…});
doSomething((a)=>{});
在这里插入图片描述

4.后台实现流程:

-----Postman //测试
Action UserAction//功能层
-----junit //测试
service IUserService UserService//服务层
dao IUserDAO UserDao //DAO层
model User.hbm.xml //实体类映射文件
db //数据库

源码后面有:
在这里插入图片描述

spring.base.xml配置连接池
在这里插入图片描述

实体类源码:

package com.zking.login.sys.model;

import java.io.Serializable;
import java.sql.Timestamp;

import com.zking.login.base.model.BaseModel;

public class LoginUser extends BaseModel {
	
private Long userid;
private String username;
private String password;

private String salt;
private Integer locked;
private Timestamp createDatetime;

public LoginUser() {
}

public Long getUserid() {
	return userid;
}

public void setUserid(Long userid) {
	this.userid = userid;
}

public String getUsername() {
	return username;
}

public void setUsername(String username) {
	this.username = username;
}

public String getPassword() {
	return password;
}

public void setPassword(String password) {
	this.password = password;
}

public String getSalt() {
	return salt;
}

public void setSalt(String salt) {
	this.salt = salt;
}

public Integer getLocked() {
	return locked;
}

public void setLocked(Integer locked) {
	this.locked = locked;
}

public Timestamp getCreateDatetime() {
	return createDatetime;
}

public void setCreateDatetime(Timestamp createDatetime) {
	this.createDatetime = createDatetime;
}

@Override
public String toString() {
	return "LoginUser [userid=" + userid + ", username=" + username + ", password=" + password + ", salt=" + salt
			+ ", locked=" + locked + ", createDatetime=" + createDatetime + "]";
}
}

实体映射文件源码:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
	<class name="com.zking.login.sys.model.LoginUser" table="t_sys_user">
		<id name="userid" type="java.lang.Long" column="user_id">
			<generator class="native"  /><!-- 由数据库管理自增长 -->
		</id>
		<property name="username" type="java.lang.String" column="username" />
		<property name="password" type="java.lang.String" column="password" />
		<property name="salt" type="java.lang.String" column="salt" />
		<property name="locked" type="java.lang.Integer" column="locked" insert="false" />
		<property name="createDatetime" type="java.sql.Timestamp" column="create_datetime" insert="false" update="false" />
	</class>
</hibernate-mapping>

在这里插入图片描述

UserDAO源码:

package com.zking.login.sys.dao.impl;

import java.util.HashMap;
import java.util.Map;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.query.Query;
import org.springframework.orm.hibernate5.HibernateCallback;

import com.zking.login.base.dao.BaseDao;
import com.zking.login.sys.dao.IUserDao;
import com.zking.login.sys.model.LoginUser;

public class UserDaoimpl extends BaseDao implements IUserDao {

@Override
public LoginUser load(LoginUser user) {
	return this.getHibernateTemplate().execute(new HibernateCallback<LoginUser>() {
		@Override
		public LoginUser doInHibernate(Session session) throws HibernateException {
			Query query = session.createQuery("from LoginUser u where u.username = :username");//查询出结果放进json中
			query.setString("username", user.getUsername());//把json转为string类型
			LoginUser u = (LoginUser) query.uniqueResult();//query内部一个方法
			return u;
		}
	});
}

}

继承类源码BaseDao:

package com.zking.login.base.dao;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.query.Query;
import org.springframework.orm.hibernate5.HibernateCallback;
import org.springframework.orm.hibernate5.support.HibernateDaoSupport;

import com.zking.login.base.util.PageBean;


public class BaseDao extends HibernateDaoSupport implements Serializable {

private static final long serialVersionUID = 1619854797335382396L;

private Logger log = LogManager.getLogger(BaseDao.class);

public BaseDao() {
	super();
}

/**
 * 通用赋值方法
 * 
 * @param query
 * @param args
 */
@SuppressWarnings({ "unused", "rawtypes" })
private void setParameters(Query query, Map<String, Object> args) {
	if (null == args || 0 == args.size()) {
		return;
	}
	log.info("hql查询参数为:" + args);

	String name = null;
	Object value = null;
	for (Map.Entry<String, Object> entry : args.entrySet()) {
		name = entry.getKey();// min,uname
		value = entry.getValue();// 1000f,'z%'
		// query.setFloat(name, value);
		// query.setString(name, value);
		// query.setParameter(param, value);//8+1
		if (value instanceof Collection) {// List和Set
			query.setParameterList(name, (Collection) value);
		} else if (value instanceof Object[]) {
			query.setParameterList(name, (Object[]) value);
		} else {
			query.setParameter(name, value);
		}
	}
}

@SuppressWarnings({ "rawtypes", "unchecked" })
public List executeQuery(final String hql, final Map<String, Object> args, final PageBean pageBean) {
	// Session session =
	// this.getHibernateTemplate().getSessionFactory().openSession();

	return (List) this.getHibernateTemplate().execute(new HibernateCallback() {
		@Override
		public Object doInHibernate(Session session) throws HibernateException {
			// 1. 查满足条件的总记录数
			Query query = null;
			if (null != pageBean && pageBean.isPagination()) {
				String countHql = getCountHql(hql);
				log.info("countHql[" + countHql + "]");
				query = session.createQuery(countHql);
				setParameters(query, args);// 给占位符赋值
				Object total = query.uniqueResult();
				pageBean.setTotal(total.toString());
			}
			// 2. 查满足条件并指定页码 的记录
			log.info("countHql[" + hql + "]");
			query = session.createQuery(hql);
			if (null != pageBean && pageBean.isPagination()) {
				query.setFirstResult(pageBean.getStartIndex());
				query.setMaxResults(pageBean.getRows());
			}
			setParameters(query, args);// 给占位符赋值
			List list = query.list();
			return list;
		}
	});
}
// from Account a where 1=1 OrDer by a.balance desc
// from Account a where 1=1
// select a.userName from Account a where 1=1 OrDer by a.balance desc
// select count(*) from Account a where 1=1

/**
 * 将普通的hql转换成查总记录数的hql
 * 
 * @param hql
 * @return
 */
private static String getCountHql(String hql) {
	String newHql = new String(hql).toUpperCase();
	int start = newHql.indexOf("FROM ");
	int end = newHql.indexOf("ORDER BY");
	if (-1 == end) {
		newHql = "select count(*) " + hql.substring(start);
	} else {
		newHql = "select count(*) " + hql.substring(start, end);
	}
	return newHql;
}

// public static void main(String[] args) {
// String hql2 = "from Order o where o.orderId in (1,2,3,5)";// (:orderIds)
// String hql = "select a.userName from Account a where 1=1 and a.balance >=
// :min order by a.balance";
// System.out.println(getCountHql(hql));
// }
}

接口类IUserDAO:
在这里插入图片描述

UserService:

package com.zking.login.sys.service.impl;

import java.util.List;

import com.zking.login.base.service.BaseService;
import com.zking.login.sys.dao.IUserDao;
import com.zking.login.sys.model.LoginUser;
import com.zking.login.sys.service.IUserService;
import com.zking.login.sys.util.PageBean;

public class UserService extends BaseService  implements IUserService{
	
private IUserDao userdao;

public UserService() {
}
public IUserDao getUserdao() {
	return userdao;
}

public void setUserdao(IUserDao userdao) {
	this.userdao = userdao;
}

@Override
public LoginUser load(LoginUser loginUser) {
	return userdao.load(loginUser);
}

}

IUserSerivce:
在这里插入图片描述
把DAO,Service配置到Spring(容器)中:

spring.sys.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
	<!-- 登陆 -->
	<bean id="userdao" class="com.zking.login.sys.dao.impl.UserDaoimpl" 
		parent="baseDAO">
	</bean>
	<bean id="userService" class="com.zking.login.sys.service.impl.UserService">
		<property name="userdao">
			<ref bean="userdao"/>
		</property>
	</bean>
	<!-- 树形菜单后台 -->
	<bean id="treenodedao" class="com.zking.login.sys.dao.impl.TreeNodeDAOimpl" 
		parent="baseDAO">
	</bean>
	<bean id="treenodeService" class="com.zking.login.sys.service.impl.TreeNodeServiceimpl">
		<property name="treenodedao">
			<ref bean="treenodedao"/>
		</property>
	</bean>
	
	<!-- 登陆 -->
	 <bean id="userAction" scope="prototype" class="com.zking.login.sys.action.UserAction">
		<property name="userService">
			<ref bean="userService" />
		</property>
	</bean>
	<!-- 树形菜单后台 -->
	<bean id="TreeNodeAction" scope="prototype" class="com.zking.login.sys.action.TreeNodeAction">
		<property name="treenodeService">
			<ref bean="treenodeService"/>
		</property>
	</bean> 
</beans>

spring.base.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
		
	<!-- 配置c3p0连接池 -->
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="driverClass" value="com.mysql.jdbc.Driver" />
		<property name="jdbcUrl"
			value="jdbc:mysql://localhost:3306/hjj?useUnicode=true&amp;characterEncoding=UTF-8&amp;useSSL=false" />
		<property name="user" value="root" />
		<property name="password" value="123" />

		<!--连接池中保留的最小连接数。 -->
		<property name="minPoolSize" value="2" />

		<!--连接池中保留的最大连接数。Default: 15 -->
		<property name="maxPoolSize" value="10" />

		<!--初始化时获取的连接数,取值应在minPoolSize与maxPoolSize之间。Default: 3 -->
		<property name="initialPoolSize" value="3" />

		<!--最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 -->
		<property name="maxIdleTime" value="60" />

		<!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 -->
		<property name="acquireIncrement" value="5" />

		<!--JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。但由于预缓存的statements 属于单个connection而不是整个连接池。 
			所以设置这个参数需要考虑到多方面的因素。如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default: 
			0 -->
		<property name="maxStatements" value="0" />

		<!--每60秒检查所有连接池中的空闲连接。Default: 0 -->
		<property name="idleConnectionTestPeriod" value="60" />

		<!--定义在从数据库获取新连接失败后重复尝试的次数。Default: 30 -->
		<property name="acquireRetryAttempts" value="30" />

		<!--获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常。但是数据源仍有效 保留,并在下次调用getConnection()的时候继续尝试获取连接。 
			如果设为true,那么在尝试 获取连接失败后该数据源将申明已断开并永久关闭。Default: false -->
		<property name="breakAfterAcquireFailure" value="true" />

		<!--因性能消耗大请只在需要的时候使用它。如果设为true那么在每个connection提交的 时候都将校验其有效性。建议使用idleConnectionTestPeriod 
			或automaticTestTable 等方法来提升连接测试的性能。Default: false -->
		<property name="testConnectionOnCheckout" value="false" />
	</bean>

	<!-- hibernate与spring集成 -->
	<bean id="sessionFactory"
		class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
		<!-- 指定数据源 -->
		<property name="dataSource">
			<ref bean="dataSource" />
		</property>
		<!-- 指定hibernate相关属性 -->
		<property name="hibernateProperties">
			<props>
				<prop key="dialect">org.hibernate.dialect.MySQLDialect</prop>
				<prop key="hibernate.show_sql">true</prop>
				<prop key="hibernate.format_sql">true</prop>
				<prop key="hibernate.use_sql_comments">true</prop>
				<prop key="hibernate.cache.use_second_level_cache">true</prop>
				<prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory
				</prop>
				<prop key="hibernate.cache.use_query_cache">true</prop>
			</props>
		</property>
		<!-- 指定实体映射文件 -->
		<property name="mappingResources">
			<list>
				<value>mapping/LoginUser.hbm.xml</value>
				<value>mapping/TreeNode.hbm.xml</value>
			</list>
		</property>
	</bean>

	<!-- hibernateTemplate -->
	<bean id="hibernateTemplate" class="org.springframework.orm.hibernate5.HibernateTemplate">
		<property name="sessionFactory">
			<ref bean="sessionFactory" />
		</property>
	</bean>

	<!--声明式事务配置开始 -->
	<!--1) 开启自动代理 -->
	<aop:aspectj-autoproxy />

	<!--2) 事务管理器 begin/commit/rollback -->
	<bean id="transactionManager"
		class="org.springframework.orm.hibernate5.HibernateTransactionManager">
		<property name="sessionFactory" ref="sessionFactory" />
	</bean>

	<!--3) 定义事务特性 -->
	<!-- 环绕通知 -->
	<tx:advice id="txAdvice" transaction-manager="transactionManager">
		<tx:attributes>
			<tx:method name="add*" propagation="REQUIRED" />
			<tx:method name="edit*" propagation="REQUIRED" />
			<tx:method name="del*" propagation="REQUIRED" />
			<tx:method name="load*" propagation="REQUIRED" read-only="true" />
			<tx:method name="list*" propagation="REQUIRED" read-only="true" />
			<tx:method name="do*" propagation="REQUIRED" />
		</tx:attributes>
	</tx:advice>

	<!-- 代理=目标+通知 -->
	<!--4) 定义切入点 -->
	<aop:config>
		<!-- pointcut属性用来定义一个切入点,分成四个部分理解 [* ][*..][*Service][.*(..)] -->
		<!-- A: 返回类型,*表示返回类型不限 -->
		<!-- B: 包名,*..表示包名不限 -->
		<!-- C: 类或接口名,*Service表示类或接口必须以Service结尾 -->
		<!-- D: 方法名和参数,*(..)表示方法名不限,参数类型和个数不限 -->
		<!-- 表达式用来查找目标对象 -->
		<aop:advisor advice-ref="txAdvice" pointcut="execution(* *..*Service.*(..))" />
	</aop:config>
	<!-- 声明式事务配置结束 -->
	
	<!-- base模块配置 -->
	<bean id="baseDAO" class="com.zking.login.base.dao.BaseDao">
		<property name="hibernateTemplate">
			<ref bean="hibernateTemplate" />
		</property>
	</bean>
</beans>

配置到spring中:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
	<import resource="spring-base.xml"/>
	<import resource="spring-sys.xml"/>
	
</beans>

junit测试:

在这里插入图片描述
IUserServiceTest :

package com.zking.login.sys.service;

import static org.junit.Assert.*;

import org.junit.Before;
import org.junit.Test;

import com.zking.login.sys.model.LoginUser;
import com.zking.login.sys.service.impl.BaseTestCase;

public class IUserServiceTest extends BaseTestCase {

private IUserService userservice;
	
	private LoginUser user;
	
	@Before
	public void before() {
		user = new LoginUser();
		userservice = (IUserService) this.getBean("userService");
	}

	@Test
	public void testLoad() {
		user.setUsername("zs");
		LoginUser u = userservice.load(user);
		System.out.println(u);
	}

}

继承类BaseTestCase:

package com.zking.login.sys.service.impl;

import static org.junit.Assert.*;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;


public class BaseTestCase {
	private static ApplicationContext context;
	static {
		context =new ClassPathXmlApplicationContext("classpath:spring.xml");
	}
	protected Object getBean(String name) {
		return context.getBean(name);
	} 
}

测试结果:
在这里插入图片描述

然后写UserAction:

package com.zking.login.sys.action;

import com.opensymphony.xwork2.ModelDriven;
import com.zking.login.base.action.BaseAction;
import com.zking.login.sys.model.LoginUser;
import com.zking.login.sys.service.IUserService;
import com.zking.login.sys.util.JsonData;

public class UserAction extends BaseAction implements ModelDriven<LoginUser>{
	
	private static final long serialVersionUID = 1L;

	private IUserService userService;
	
	private LoginUser user = new LoginUser();
	
	public UserAction() {
		
	}
	public IUserService getUserService() {
		return userService;
	}
	public void setUserService(IUserService userService) {
		this.userService = userService;
	}
	@Override
	public LoginUser getModel() {
		return user;
	}
	
	public String execute() {
		System.out.println(request.getMethod());
		System.out.println("后台Action"+this.user);
		JsonData jsonData = new JsonData();
		
		LoginUser u = userService.load(user);
		if(u != null && u.getPassword().equals(user.getPassword())) {
			jsonData.setCode(0);
			jsonData.setMessage("登陆成功");
		}else {
			jsonData.setCode(-1);
			jsonData.setMessage("账号或密码错误");
		}
		this.writeJson(jsonData);
		return null;
	}
}

配置Action到spring.sys.xml配置文件中:
在这里插入图片描述

启动Tomcat发布项目使用Postman测试:
在这里插入图片描述
成功后:
1)启动前端vue项目
-----MVVM(前后台分离)
2)启动Tomcat后台项目
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
成功前后台分离成功(下一集:动态树后台实现)

后台util工具类提供:

1.中文乱码器 EncodingFiter:

package com.zking.login.sys.util;

import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

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.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 中文乱码处理
 * 
 */
public class EncodingFiter implements Filter {

	private String encoding = "UTF-8";// 默认字符集

	public EncodingFiter() {
		super();
	}

	public void destroy() {
	}

	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		HttpServletRequest req = (HttpServletRequest) request;
		HttpServletResponse res = (HttpServletResponse) response;

		// 中文处理必须放到 chain.doFilter(request, response)方法前面
		res.setContentType("text/html;charset=" + this.encoding);
		if (req.getMethod().equalsIgnoreCase("post")) {
			req.setCharacterEncoding(this.encoding);
		} else {
			Map map = req.getParameterMap();// 保存所有参数名=参数值(数组)的Map集合
			Set set = map.keySet();// 取出所有参数名
			Iterator it = set.iterator();
			while (it.hasNext()) {
				String name = (String) it.next();
				String[] values = (String[]) map.get(name);// 取出参数值[注:参数值为一个数组]
				for (int i = 0; i < values.length; i++) {
					values[i] = new String(values[i].getBytes("ISO-8859-1"),
							this.encoding);
				}
			}
		}

		chain.doFilter(request, response);
	}

	public void init(FilterConfig filterConfig) throws ServletException {
		String s = filterConfig.getInitParameter("encoding");// 读取web.xml文件中配置的字符集
		if (null != s && !s.trim().equals("")) {
			this.encoding = s.trim();
		}
	}

	}

2.服务器返回给客户端的JSONDATA格式的数据:

package com.zking.login.sys.util;

import java.io.Serializable;
import java.util.HashMap;

/**
 * 服务器返回给客户端的JSON格式的数据
 *
 */
public class JsonData extends HashMap<String, Object> implements Serializable {

	private static final long serialVersionUID = -8855960778711040221L;

	private static final String CODE_KEY = "code";// 操作代码 0 成功 非0 失败
	private static final String MESSAGE_KEY = "message";// 操作消息
	private static final String RESULT_KEY = "result";// 结果集
	private static final String PAGE_KEY = "page";// 页码
	private static final String ROWS_KEY = "rows";// 每页行数/页大小
	private static final String TOTAL_KEY = "total";// 总记录数

	public JsonData() {
		super();
		this.put(CODE_KEY, 0);// 默认操作成功
	}

	public void setCode(Integer code) {
		this.put(CODE_KEY, code);
	}

	public void setMessage(String message) {
		this.put(MESSAGE_KEY, message);
	}

	public void setResult(Object result) {
		this.put(RESULT_KEY, result);
	}

	public void setPage(Integer page) {
		this.put(PAGE_KEY, page);
	}

	public void setRows(Integer rows) {
		this.put(ROWS_KEY, rows);
	}

	public void setTotal(Integer total) {
		this.put(TOTAL_KEY, total);
	}

	}

3.后期用到的分页PageBean :

package com.zking.login.sys.util;

import java.util.Map;

import javax.servlet.http.HttpServletRequest;

public class PageBean {

	private int page = 1;// 页码
	private int rows = 10;// 行数/页大小
	private int total = 0;// 总记录数

	private boolean pagination = true;// 默认分页

	private String url;// 上一次请求的地址
	private Map<String, String[]> parameterMap;// 上一次请求的所有参数

	public PageBean() {
		super();
	}

	/**
	 * 对分页bean进行初始化
	 * 
	 * @param request
	 */
	public void setRequest(HttpServletRequest request) {
		// 公共参数
		this.setPage(request.getParameter("page"));
		this.setRows(request.getParameter("rows"));
		this.setPagination(request.getParameter("pagination"));

		// 请求地址和请求参数
		this.setUrl(request.getContextPath() + request.getServletPath());
		this.setParameterMap(request.getParameterMap());
	}

	public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public Map<String, String[]> getParameterMap() {
		return parameterMap;
	}

	public void setParameterMap(Map<String, String[]> parameterMap) {
		this.parameterMap = parameterMap;
	}

	public int getPage() {
		return page;
	}

	public void setPage(int page) {
		this.page = page;
	}

	public void setPage(String page) {
		if (null != page && !"".equals(page.trim())) {
			this.page = Integer.parseInt(page);
		}
	}

	public int getRows() {
		return rows;
	}

	public void setRows(int rows) {
		this.rows = rows;
	}

	public void setRows(String rows) {
		if (null != rows && !"".equals(rows.trim())) {
			this.rows = Integer.parseInt(rows);
		}
	}

	public int getTotal() {
		return total;
	}

	public void setTotal(int total) {
		this.total = total;
	}

	public void setTotal(String total) {
		this.total = Integer.parseInt(total);
	}

	public boolean isPagination() {
		return pagination;
	}

	public void setPagination(boolean pagination) {
		this.pagination = pagination;
	}

	public void setPagination(String pagination) {
		if ("false".equals(pagination)) {
			this.pagination = false;
		}
	}

	/**
	 * 下一页
	 * 
	 * @return
	 */
	public int getNextPage() {
		int nextPage = page + 1;
		if (nextPage > this.getMaxPage()) {
			nextPage = this.getMaxPage();
		}
		return nextPage;
	}

	/**
	 * 上一页
	 * 
	 * @return
	 */
	public int getPreviousPage() {
		int previousPage = page - 1;
		if (previousPage < 1) {
			previousPage = 1;
		}
		return previousPage;
	}

	/**
	 * 最大页码
	 * 
	 * @return
	 */
	public int getMaxPage() {
		return total % rows == 0 ? total / rows : total / rows + 1;
	}

	/**
	 * 起始记录的下标
	 * 
	 * @return
	 */
	public int getStartIndex() {
		return (page - 1) * rows;
	}

	@Override
	public String toString() {
		return "PageBean [page=" + page + ", rows=" + rows + ", total=" + total + ", pagination=" + pagination + "]";
	}

}
  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值