服务器端
服务器端项目初始化
- start.spring.io生成项目
- 添加三个依赖,web,mybatis,mysql
- Idea软件 open,找到项目文件,导入
- 逆向工程生成mybatis资源
- 逆向工程的 公司.项目名 和初始化的 公司.项目名相同
- 逆向工程生成mybatis资源从src/main/java/com复制到初始化项目对应的src/main/java/ 和 src/main/resources 文件下
- 删除src/main/java/…/mapper 下的 xml
- 只保留复制过来的静态资源中 src/main/resources/…/mapper 下的xml文件
- 配置连接数据库文件application.yml
- 建立controller包,添加方法select查询数据库User数据
- 添加包扫描,运行 ```java package com.tedu.shop.controller;
@RestController public class UserController { @Autowired UserMapper userMapper;
@RequestMapping("/selectAll")
public List<User> selectAll(){
List<User> list = userMapper.selectByExample(null);
return list;
}
}
- 证明环境成功
<a name="lnlJu"></a>
### 服务器端实现
<a name="AYdf0"></a>
#### 管理员模块
- js不支持一个网站访问另一个网站
- 协议不一样 [http://www.baidu.com](http://www.baidu.com/) [https://www.baidu.com](https://www.baidu.com/) 不是同一个网站
- 端口号不一样 [http://www.baidu.com:8080](http://www.baidu.com:8080/) [http://www.baidu.com:1314](http://www.baidu.com:1314/) 不是同一个网站
- 域名不一样 [http://www.tedu.cn](http://www.tedu.cn/) [http://ww.baidu.com](http://ww.baidu.com/) 不是同一个网站
- 报错:has been blocked by CORS policy: No 'Access-Control-Allow-Origin'
解决方法是在controller中的方法上面加一个@ crossOrigin,加在类上也可以,但最好是加方法上
```java
package com.tedu.yourshop.controller;
//管理员
@RestController
public class AdminController {
@Autowired
AdminMapper adminMapper;
@RequestMapping("/admin/login")
//允许别的网站通过js访问我,跨域访问,加在类上或者方法上的注解
@CrossOrigin
public Admin login(Admin admin){
AdminExample adminExample = new AdminExample();
AdminExample.Criteria criteria = adminExample.or();
criteria.andAdminNameEqualTo(admin.getAdminName());
criteria.andAdminPasswordEqualTo(admin.getAdminPassword());
List<Admin> list = adminMapper.selectByExample(adminExample);
//首先判断非空,防止使用集合资源出现空指针异常
if(list!=null && list.size()>=1){
Admin dbAdmin = list.get(0);
dbAdmin.setAdminPassword("");
return dbAdmin;
}else {
return null;
}
}
}
用户模块
package com.tedu.yourshop.controller;
//用户
@RestController
public class UserController {
@Autowired
UserMapper userMapper;
//传入参数用属性,传入一个以上参数,能用对象用对象
@RequestMapping("/user/register")
@CrossOrigin
public String register(User user){
UserExample userExample = new UserExample();
UserExample.Criteria criteria = userExample.or();
criteria.andUsernameEqualTo(user.getUsername());
List<User> list = userMapper.selectByExample(userExample);
if(list!=null && list.size()==0){
int count = userMapper.insertSelective(user);
if(count>=1){
return "注册成功!";
}else {
return "注册失败!";
}
}else {
return "用户重复,重新输入!";
}
}
@RequestMapping("/user/login")
@CrossOrigin
public String login(User user){
UserExample userExample = new UserExample();
UserExample.Criteria criteria = userExample.or();
criteria.andUsernameEqualTo(user.getUsername());
criteria.andPasswordEqualTo(user.getPassword());
List<User> list = userMapper.selectByExample(userExample);
if(list!=null && list.size()>=1){
return "登录成功!";
}else {
return "登录失败!";
}
}
}
商品分类
package com.tedu.yourshop.controller;
//商品分类
@RestController
@CrossOrigin
public class CategoryController {
@Autowired
CategoryMapper categoryMapper;
@RequestMapping("/category/selectAll")
public List<Category> selectAll(){
List<Category> list = categoryMapper.selectByExample(null);
return list;
}
}
商品模块
package com.tedu.yourshop.controller;
//商品
@RestController
@CrossOrigin
public class ItemController {
@Autowired
ItemMapper itemMapper;
//更新商品
@RequestMapping("item/updateItem")
public String updateItem(Item item){
int count = itemMapper.updateByPrimaryKeySelective(item);
if(count>=1){
return "修改商品成功!";
}else {
return "修改商品失败!";
}
}
//删除商品
@RequestMapping("/item/deleteItem")
public String deleteItem(Integer itemId){
int count = itemMapper.deleteByPrimaryKey(itemId);
if(count>=1){
return "删除商品成功!";
}else {
return "删除商品失败!";
}
}
//查询全部商品
@RequestMapping("/item/selectAll")
public List<Item> selectAll(){
List<Item> list = itemMapper.selectByExample(null);
return list;
}
// http://localhost:8088/item/insertItem?categoryId=2&itemName=huawei&itemPrice=567&itemDesc=huawei&itemImage=98.jpg
//添加商品
@RequestMapping("/item/insertItem")
public String insertItem(Item item){
int count = itemMapper.insertSelective(item);
if(count>=1){
return "添加商品成功!";
}else {
return "添加商品失败!";
}
}
//通过商品编号查询商品
@RequestMapping("/item/selectItemByItemId")
public Item selectItemByItemId(Integer itemId){
Item item = itemMapper.selectByPrimaryKey(itemId);
return item;
}
//通过分类ID查询商品
@RequestMapping("/Item/selectByCategoryId")
public List<Item> selectByCategoryId(Integer categoryId){
ItemExample itemExample = new ItemExample();
ItemExample.Criteria criteria = itemExample.or();
criteria.andCategoryIdEqualTo(categoryId);
List<Item> list = itemMapper.selectByExample(itemExample);
return list;
}
}
客户端
- 模板
mounted()
加载页面自动执行这个方法
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="js/axios.min.js" type="text/javascript"></script>
<script src="js/vue.js" type="text/javascript"></script>
</head>
<body>
<div id="app">
</div>
<script>
var config={
el:"#app",
data:{},
methods:{
},
mounted:function(){
console.log("mounted()");
}
}
var vue = new Vue(config);
</script>
</body>
</html>
后台管理
管理员登录
登录成功进入后台主页面
- adminLogin.html
- v-model
- 双向绑定
- v-on:click
- 点击事件
- axios
- 连接服务器,get方式请求
location.href
- 页面跳转
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>管理员登录</title>
<script src="js/axios.min.js" type="text/javascript"></script>
<script src="js/vue.js" type="text/javascript"></script>
</head>
<body>
<div id="app">
<h1>管理员登录</h1>
用户名:<input v-model="adminName"><br>
密码:<input v-model="adminPassword"> <br>
<button v-on:click="login">登录</button>
</div>
<script>
var config={
el:"#app",
data:{
adminName:null,
adminPassword:null,
},
methods:{
login:function(){
debugger;
var serverUrl="http://localhost:8088/admin/login?adminName="+this.adminName+"&adminPassword="+this.adminPassword;
console.log(serverUrl);
axios.get(serverUrl)
.then(function(response){
var admin = response.data;
if(admin.adminId){
window.alert("管理员登录成功");
location.href="index.html";
}
})
.catch(function(e){
window.alert("联网失败!");
console.log(e);
})
}
},
mounted:function(){
console.log("mounted()");
}
}
var vue = new Vue(config);
</script>
</body>
</html>
后台主页面
- 页面跳转
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>后台管理主页</title>
</head>
<body>
<a href="user.html">用户管理</a>
<a href="item.html">商品管理</a>
</body>
</html>
商品管理
商品的增加、删除、修改,查询
- item.html
- v-bind
- 强制绑定
- v-for
- 循环
- window.confirm
- 弹窗确认操作
- itemCategoryId表示此时用户选中的商品ID
- categoryList
- 服务器返回的商品分类数据集合
-
‘update.html?itemId=’ 表示字符串
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>商品管理</title>
<script src="js/axios.min.js" type="text/javascript"></script>
<script src="js/vue.js" type="text/javascript"></script>
</head>
<body>
<div id="app">
分类:<select v-model="itemCategoryId">
<!-- itemCategoryId默认是获得选择框里面的值(文字),
绑定id后v-bind:value="category.categoryId",itemCategoryId得到的就是文字对应的ID了
后面就根据它插入商品分类-->
<option v-for="category in categoryList" v-bind:value="category.categoryId">
{{category.categoryName}}
</option>
</select><br>
名称:<input v-model="itemName"><br>
价格:<input v-model="itemPrice"><br>
描述:<input v-model="itemDesc"><br>
图片:<input v-model="itemImage"><br>
<button v-on:click="addItem()">添加</button><br>
<table border="2">
<tr>
<td>商品编号</td>
<td>商品名称</td>
<td>商品价格</td>
<td>删除</td>
<td>修改</td>
</tr>
<tr v-for="item in itemList">
<td>{{item.itemId}}</td>
<td>{{item.itemName}}</td>
<td>{{item.itemPrice}}</td>
<!-- v-on:click不仅仅是用在按钮上 -->
<td v-on:click="deleteItem(item.itemId)">删除</td>
<!-- 强制绑定为地址 -->
<td><a v-bind:href="'update.html?itemId='+item.itemId">修改</a></td>
</tr>
</table>
</div>
<script>
var config={
el:"#app",
data:{
itemCategoryId:null,
categoryList:[],
itemName:"",
itemPrice:"",
itemDesc:"",
itemImage:"",
itemList:[],
},
methods:{
findCategory:function(){
// debugger;
var serverUrl="http://localhost:8088/category/selectAll";
console.log(serverUrl);
var vue = this;
axios.get(serverUrl)
.then(function(response){
vue.categoryList = response.data;
})
.catch(function(e){
window.alert("联网失败");
console.log(e);
})
},
findAllItem:function(){
// debugger;
var serverUrl="http://localhost:8088/item/selectAll";
console.log(serverUrl);
var vue = this;
axios.get(serverUrl)
.then(function(response){
// debugger;
console.log(response.data);
vue.itemList = response.data;
})
.catch(function(e){
window.alert("联网失败");
console.log(e);
})
},
addItem:function(){
// debugger;
var serverUrl="http://localhost:8088/item/insertItem?categoryId="+this.itemCategoryId
+"&itemName="+this.itemName
+"&itemPrice="+this.itemPrice
+"&itemDesc="+this.itemDesc
+"&itemImage="+this.itemImage;
// console.log(serverUrl);
var vue = this;
axios.get(serverUrl)
.then(function(response){
window.alert("添加商品成功");
vue.findAllItem();
})
.catch(function(e){
window.alert("联网失败");
console.log(e);
})
},
deleteItem:function(itemId){
// debugger;
var result = window.confirm("是否确认删除");
if(result){
var serverUrl = "http://localhost:8088/item/deleteItem?itemId="+itemId;
console.log(serverUrl);
var vue = this;
axios.get(serverUrl)
.then(function(response){
window.alert(response.data);
vue.findAllItem();
})
.catch(function(e){
window.alert("联网失败");
console.log(e);
})
}
}
},
mounted:function(){
console.log("mounted()");
this.findCategory();
this.findAllItem();
}
}
var vue = new Vue(config);
</script>
</body>
</html>
修改
update.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>更新</title>
<script src="js/axios.min.js" type="text/javascript"></script>
<script src="js/vue.js" type="text/javascript"></script>
</head>
<body>
<div id="app">
分类:<select v-model="itemCategoryId">
<option v-for="category in categoryList" v-bind:value="category.categoryId">
{{category.categoryName}}
</option>
</select>
<br>
商品名称:<input v-model="item.itemName"><br>
商品价格:<input v-model="item.itemPrice"><br>
商品描述:<input v-model="item.itemDesc"><br>
商品图片:<input v-model="item.itemImage"><br>
<button v-on:click="updateItem()">更新</button><br>
<br>
<a href="item.html">商品管理</a>
</div>
<script>
var config={
el:"#app",
data:{
itemCategoryId:null,
categoryList:[],
item:{
}
},
methods:{
//负责select的分类数据显示
findCategory:function(){
// debugger;
var serverUrl="http://localhost:8088/category/selectAll";
console.log(serverUrl);
var vue = this;
axios.get(serverUrl)
.then(function(response){
vue.categoryList = response.data;
})
.catch(function(){
window.alert("联网失败!");
console.log(e);
})
},
//负责商品信息显示,地址栏的数据不同,导致分类的的显示值也跟着更改
findItemById:function(itemId){
debugger;
var serverUrl = "http://localhost:8088/item/selectItemByItemId?itemId="+itemId;
console.log(serverUrl);
var vue = this;
axios.get(serverUrl)
.then(function(response){
// debugger;
vue.item =response.data;
//通过商品ID查到商品信息,获得商品的分类ID,修改itemCategoryId的值,相互绑定更改页面显示
vue.itemCategoryId=vue.item.categoryId;
})
.catch(function(e){
//刚打开页面出现联网失败,是因为地址栏没有输入参数地址 ?itemId=2
window.alert("联网失败!");
console.log(e);
})
},
//负责商品的修改,双向绑定的是itemCategoryId,所以url中写的是this.itemCategoryId
updateItem:function(){
debugger;
var serverUrl = "http://localhost:8088/item/updateItem?itemId="+this.item.itemId
+"&categoryId="+this.itemCategoryId
+"&itemName="+this.item.itemName
+"&itemPrice="+this.item.itemPrice
+"&itemDesc="+this.item.itemDesc
+"&itemImage="+this.item.itemImage;
console.log(serverUrl);
console.log(this.itemCategoryId);
console.log(this.item.categoryId);
// console拷贝url到浏览器测试url是否正确
axios.get(serverUrl)
.then(function(response){
window.alert(response.data);
})
.catch(function(e){
window.alert("联网失败!");
console.log(e);
})
}
},
mounted:function(){
console.log("mounted()");
// 调用方法
this.findCategory();
//获得地址栏数据 ?itemId=2 获得值2作为方法findItemById的参数
var p=location.search;
p=p.substr(1);
var strArray = p.split("=");
var itemId=strArray[1];
this.findItemById(itemId);
}
}
var vue = new Vue(config);
</script>
</body>
</html>
用户管理
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>用户管理</title>
</head>
<body>
用户管理,待完善
</body>
</html>
前台页面
主页面
- 注册、登录
- 点击不同的商品分类,显示不同的商品(电脑、手机)
- 点击不同的商品,显示商品详情
注意 v-bind:src 与 v-bind:href的不同
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="js/axios.min.js" type="text/javascript"></script>
<script src="js/vue.js" type="text/javascript"></script>
</head>
<body>
<div id="app">
<a href="register.html">注册</a><br>
<a href="login.html">登录</a>
<table>
<tr>
<!--无意中出现动画效果: <td v-for="category in categoryList" v-bind:src="findItemByCategoryId(category.categoryId)">{{category.categoryName}}</td> -->
<td v-for="category in categoryList" v-on:click="findItemByCategoryId(category.categoryId)">{{category.categoryName}}</td>
</tr>
</table>
<table>
<tr v-for="item in itemList">
<td><a v-bind:href="'detail.html?itemId='+item.itemId"> <img v-bind:src="item.itemImage" width="100" height="100">
{{item.itemName}}</a></td>
</tr>
</table>
</div>
<script>
var config={
el:"#app",
data:{
categoryList:[],
itemList:[]
},
methods:{
//将商品分类渲染到页面
findCategory:function(){
// debugger;
var serverUrl = "http://localhost:8088/category/selectAll";
var vue = this;
axios.get(serverUrl)
.then(function(response){
debugger;
vue.categoryList = response.data;
})
.catch(function(e){
window.alert("联网失败");
console.log(e);
})
},
//点击不同的分类,显示不同的商品信息
findItemByCategoryId:function(itemId){
debugger;
var serverUrl = "http://localhost:8088/Item/selectByCategoryId?categoryId="+itemId;
// console.log(serverUrl);
var vue = this;
axios.get(serverUrl)
.then(function(response){
debugger;
vue.itemList = response.data;
})
.catch(function(e){
window.alert("联网失败");
console.log(e);
})
}
},
mounted:function(){
console.log("mounted()");
this.findCategory();
this.findItemByCategoryId(1);
}
}
var vue = new Vue(config);
</script>
</body>
</html>
注册
vue中,div里面用{{}}取属性值;script用this取属性值
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="js/axios.min.js" type="text/javascript"></script>
<script src="js/vue.js" type="text/javascript"></script>
</head>
<body>
<div id="app">
用户名:<input v-model="username"><br>
密码:<input v-model="password"><br>
确认密码:<input v-model="newPassword"><br>
<button v-on:click="register()">注册</button>
<a href="index.html">主页</a>
</div>
<script>
var config={
el:"#app",
data:{
username:"",
password:"",
newPassword:""
},
methods:{
register:function(){
if(this.username != this.newPassword){
window.alert("两次密码不一致!");
return;
}
var serverUrl = "http://localhost:8088/user/register?username="+this.username+"&password="+this.password;
// console.log(serverUrl);
axios.get(serverUrl)
.then(function(response){
window.alert(response.data);
})
.catch(function(e){
window.alert("联网失败");
console.log(e);
})
}
},
mounted:function(){
console.log("mounted()");
}
}
var vue = new Vue(config);
</script>
</body>
</html>
登录
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="js/axios.min.js" type="text/javascript"></script>
<script src="js/vue.js" type="text/javascript"></script>
</head>
<body>
<div id="app">
<h1>登录</h1>
用户名:<input v-model="username"><br>
密码:<input v-model="password"><br>
<button v-on:click="login()">登录</button>
</div>
<script>
var config={
el:"#app",
data:{
username:"",
password:"",
},
methods:{
login:function(){
var serverUrl = "http://localhost:8088/user/login?username="+this.username+"&password="+this.password;
// console.log(serverUrl);
axios.get(serverUrl)
.then(function(response){
window.alert(response.data);
location.href="index.html";
})
.catch(function(e){
window.alert("联网失败");
console.log(e);
})
}
},
mounted:function(){
console.log("mounted()");
}
}
var vue = new Vue(config);
</script>
</body>
</html>
商品详情
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script src="js/axios.min.js" type="text/javascript"></script> <script src="js/vue.js" type="text/javascript"></script> </head> <body> <div id="app"> <img v-bind:src="item.itemImage"><br> {{item.itemName}}<br> {{item.itemPrice}}<br> {{item.itemDesc}}<br> 评论 </div> <script> var config={ el:"#app", data:{ item:null }, methods:{ }, mounted:function(){ console.log("mounted()"); var address = location.search; address = address.substr(1); var addArray = address.split("="); var itemId = addArray[1]; var serverUrl = "http://localhost:8088/item/selectItemByItemId?itemId="+itemId; // console.log(serverUrl); var vue = this; axios.get(serverUrl) .then(function(response){ vue.item = response.data; }) .catch(function(e){ window.alert("联网失败"); console.log(e); }) } } var vue = new Vue(config); </script> </body> </html>
https://gitee.com/revolutionary_base/project/tree/master/shop
常见问题
- 假如你认为项目是完全正确的,并且出现了 url…datasource错误
- 那么项目右键 rebuild