服务器端
服务器端项目初始化
- 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,加在类上也可以,但最好是加方法上```javapackage com.tedu.yourshop.controller;//管理员@RestControllerpublic class AdminController {@AutowiredAdminMapper adminMapper;@RequestMapping("/admin/login")//允许别的网站通过js访问我,跨域访问,加在类上或者方法上的注解@CrossOriginpublic 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;//用户@RestControllerpublic class UserController {@AutowiredUserMapper userMapper;//传入参数用属性,传入一个以上参数,能用对象用对象@RequestMapping("/user/register")@CrossOriginpublic 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")@CrossOriginpublic 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@CrossOriginpublic class CategoryController {@AutowiredCategoryMapper categoryMapper;@RequestMapping("/category/selectAll")public List<Category> selectAll(){List<Category> list = categoryMapper.selectByExample(null);return list;}}
商品模块
package com.tedu.yourshop.controller;//商品@RestController@CrossOriginpublic class ItemController {@AutowiredItemMapper 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=2window.alert("联网失败!");console.log(e);})},//负责商品的修改,双向绑定的是itemCategoryId,所以url中写的是this.itemCategoryIdupdateItem: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
