Springboot+vue旅游项目小总结

此项目为一个springboot+vue入门级小项目,视频地址为:https://www.bilibili.com/video/BV1Nt4y127Jh

业务简单,对提升业务能力没什么大的帮助,更多的是可以熟悉开发流程和编码。

1.表结构

仅仅三张表,分别为用户表,省份表和景点表,其中省份表和景点表为一对多的关系。

用户表(t_user):

省份表(t_province):

景点表(t_place):

2.相关配置

server.port=8989
spring.application.name=travelsspring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/travels?characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=rootmybatis.mapper-locations=classpath:org/hz/travels/mapper/*.xml
mybatis.type-aliases-package=org.hz.travels.entity#图片存储到本地位置
spring.resources.static-locations=file:${upload.dir}
upload.dir=E://images

3.用户模块

注册模块–验证码

原始验证码的实现较为简单,通过验证码工具类生成一个验证码,通过 session.setAttribute(“code”, randomCode.toString());将code设置到session域中,当用户注册的时候,输入的验证码与session中的验证码进行比较即可。

**但是此项目由于使用的是前后端分离项目,前端采用vue+axios方式,axios底层封装了Ajax请求,但是Ajax请求是XMLHTTPRequest对象发起的而不是浏览器,导致每次请求都会生成一个seesion会话,这样当点击注册按钮之后,对生成一个新的会话,而这个新的会话中不存在“code”,所以在比对用户提交的验证码的时候就会出现异常。**原生Ajax的解决方法:提供了xhrFields: {withCredentials: true} 属性用于携带认证信息,即携带上一次请求生成的Cookie去发出请求,保证了Session的唯一性。

但是在axios中暂时知道怎么使用,所以此处先临时将验证码设置到了ServletContext对象中。

后端代码如下:

/*获取验证码,通过map将验证码的base64编码响应给客户端
*/
@GetMapping("getImage")public Map<String, String> getImage(HttpServletRequest request) throws IOException {Map<String, String> result = new HashMap<>();CreateImageCode createImageCode = new CreateImageCode();//获取验证码String securityCode = createImageCode.getCode();//验证码存入sessionString key = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());request.getServletContext().setAttribute(key, securityCode);//生成图片BufferedImage image = createImageCode.getBuffImg();//进行base64编码ByteArrayOutputStream bos = new ByteArrayOutputStream();ImageIO.write(image, "png", bos);//进行Base64的一个编码String string = Base64Utils.encodeToString(bos.toByteArray());result.put("key", key);result.put("image", string);return result;}

前端渲染:

动态绑定src

  <img :src="src" id="img-vcode" @click="getImage" :key="key">
const app = new Vue({el: "#app",data:{user:{},code:"",src:"",key:"",},methods:{getImage(){   //获取验证码_this  = this;axios.get("http://localhost:8989/user/getImage").then((res)=>{console.log(res.data.key);//绑定图片的src属性。_this.src = "data:image/png;base64,"+res.data.image;_this.key = res.data.key;});}},//生命周期函数,实例生成以后执行created(){this.getImage();//获取验证码}});

_this.src = “data:image/png;base64,”+res.data.image; //解码的时候必须指定前缀

_this.key = res.data.key; //这个key是后台设置的ServletContext

created(){
this.getImage(); //created()中方法在vue实例创建之前调用,即访问界面就加载验证码
}

注册模块–保存用户

<form action="province/provincelist.html" method="post"><label><div class="label-text">账&emsp;号:</div><input type="text" v-model="user.username" name="username"></label><label><div class="label-text">密&emsp;码:</div><input type="password" v-model="user.password" name="password"></label><label><div class="label-text">邮&emsp;箱:</div><input type="text" v-model="user.email" name="email"></label><img :src="src" id="img-vcode" @click="getImage" :key="key"><label><div class="label-text">验证码:</div><input type="text"  v-model="code" name="vcode" style="width: 100px"></label><button type="button" @click="saveUserInfo">提 交</button>&emsp;<a href="login.html">去登录</a></form>

使用v-model和this.user属性进行绑定,图片的绑定key属性

javacript代码:

const app = new Vue({el: "#app",data:{user:{},         //关联的用户对象code:"",         //用户输入的验证码src:"",             //绑定的src属性key:"",     //后台返回的时间戳key,前台重新提交,根据key判断ServletContext是否存在},methods:{saveUserInfo(){  //注册console.log(this.user.username + this.user.password + this.user.email);console.log(this.code);if(!this.user.username){alert('用户名不能为空!!!!');return;}if(!this.user.password){alert('密码不能为空!!!!');return;}//发送axiosaxios.post("http://localhost:8989/user/register?code="+this.code+"&key="+this.key,this.user).then((res)=>{console.log(res);if(res.data.state){alert(res.data.msg+",点击确定跳转到登录页面!!!");location.href='./login.html';}else{alert(res.data.msg);}});}},//生命周期函数,实例生成以后执行created(){this.getImage();//获取验证码}});

后端注册代码:

@PostMapping("register")public Result register(String code, String key, @RequestBody User user, HttpServletRequest request) {Result result = new Result();//获取ServletContex中存储的验证码String keyCode = (String) request.getServletContext().getAttribute(key);//验证try {if (code.equalsIgnoreCase(keyCode)) {//注册用户userService.register(user);result.setState(true);result.setMsg("注册成功!!!");} else {throw new RuntimeException("验证码错误!!!");}} catch (Exception e) {e.printStackTrace();//捕获异常信息,并将其设置到响应信息中result.setMsg(e.getMessage()).setState(false);}return result;}

4.省份模块

最终效果:

分页展示模块:

分页查询后端代码:

 @RequestMapping("findByPage")public Map<String ,Object> findByPage(Integer page,Integer rows){page = page == null ? 1 : page;rows = rows == null ? 4 : rows;HashMap<String, Object> map = new HashMap<>();//分页处理List<Province> provinces = provinceService.findByPage(page, rows);//计算总页数Integer totals = provinceService.findTotals();Integer totalPage = totals % rows == 0 ? totals / rows : totals / rows + 1;map.put("provinces", provinces);map.put("totals", totals);map.put("totalPage", totalPage);map.put("page", page);return map;}

使用map集合返回给前端,其中需要的数据有:

  1. page,当前页是第几页
  2. rows:每页显示多少条记录。
  3. totals:总共多少条记录
  4. totalPage:总共多少页
  5. province为返回的省份list集合。

分页查询Service层代码:

@Overridepublic List<Province> findByPage(Integer page, Integer rows) {//比如查询第1页,那么就查询的是limit 0,rowsint start = (page-1)*rows;return provinceMapper.findByPage(start,rows);}

UserMapping.xml代码:

<resultMap id="BaseResultMap" type="org.hz.travels.entity.Province" ><id column="id" property="id" jdbcType="INTEGER" /><result column="name" property="name" jdbcType="VARCHAR" /><result column="tags" property="tags" jdbcType="VARCHAR" /><result column="placecounts" property="placecounts" jdbcType="INTEGER" /></resultMap><select id="findByPage" resultType="Province">select id,name,tags,placecountsfrom t_provinceorder by placecountslimit #{start},#{rows}</select>

前端实现:

html:

<div id="pages">
<!-- 当page -->
<a href="javascript:;" @click="findAll(page-1)" v-if="page>1" class="page">&lt;上一页</a>
<a class="page" href="javascript:;" v-for="indexpage in totalPage" @click="findAll(indexpage)" v-text="indexpage"></a>
<a href="javascript:;" v-if="page<totalPage" @click="findAll(page+1)" class="page">下一页&gt;</a>
</div>

script代码:

const app = new Vue({el: "#app",data: {provinces: [],page: 1,       //第一次加载列表默认加载第一页数据rows: 2,      //指定每页加载两条数据totalPage: 0, //总共多少页totals: 0,       //共多少条数据},methods: {//用户点击第几页,就传这个页码的值去做请求。findAll(indexpage) { //查询所有if (indexpage) {this.page = indexpage;}_this = this;axios.get("http://localhost:8989/province/findByPage?page=" + this.page + "&rows=" + this.rows).then((res) => {_this.provinces = res.data.provinces;_this.page = res.data.page;_this.totalPage = res.data.totalPage;_this.totals = res.data.totals;});}},//vue实例化前加载列表created() {this.findAll();}})

修改省份信息:

业务代码比较简单,需要注意的只是前端的一点:

<a :href="'./updateprovince.html?id='+province.id">修改省份</a>

在省份列表界面点击修改,跳转到修改界面,传过去一个省份id。

在修改界面拿到这个id,进行修改操作,修改之前先要把该省份信息加载到修改界面:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CDfKsn0J-1592974475684)(E:\MarkDown\项目分析篇\2.springboot+vue旅游项目\images\img8.png)]

new Vue({el: "#app",data: {id: "",province: {}},methods: {findOneProvince(id) {_this = this;axios.get("http://localhost:8989/province/findOne?id=" + id).then((res) => {console.log(res.data);_this.province = res.data;});},updateProvince() {axios.post("http://localhost:8989/province/updateProvince", this.province).then((res) => {if (res.data.state) {alert(res.data.msg + ",点击确定回到主页!!!");location.href = './provincelist.html';} else{alert(res.data.msg);}});}},created() {this.id = location.href.substring(location.href.indexOf("=") + 1);this.findOneProvince(this.id);}})

5.景点模块

添加景点:

添加模块主要牵扯到文件上传的问题,另外需要更新省份的placeCount字段

后端代码如下:

 //将图片保存到本地位置
@Value("${upload.dir}")private String realPath;
@PostMapping("save")public Result save(MultipartFile pic,Place place) throws IOException {Result result=new Result();try {//对图片文件进行Base64的转化String picpath = Base64Utils.encodeToString(pic.getBytes());place.setPicpath(picpath);//处理文件上传String extension = FilenameUtils.getExtension(pic.getOriginalFilename());String newFileName = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + extension;//将这个文件写入到本地磁盘的具体位置pic.transferTo(new File(realPath,newFileName));Integer id = place.getProvince().getId();Province oneProvince = provinceService.findOneProvince(id);oneProvince.setPlacecounts(oneProvince.getPlacecounts()+1);//更新省份信息provinceService.updateProvince(oneProvince);placeService.save(place);result.setMsg("保存景点信息成功");}catch (Exception e){result.setMsg(e.getMessage());}return result;}

前端代码:

使用vue中的ref注册组件信息:

<input type="file" ref="myFile" id="imgfile" style="display: none" onchange="imgfileChange()">

由于使用了文件,所以提交的时候需要使用FormData的方式提交:script如下:

savePlaceInfo() { //保存景点的方法console.log(this.place);//拿到注册的组件let myFile = this.$refs.myFile;let files = myFile.files;let file = files[0];let formData = new FormData();formData.append("pic", file);formData.append("name", this.place.name);formData.append("hottime", this.place.hottime);formData.append("hotticket", this.place.hotticket);formData.append("dimticket", this.place.dimticket);formData.append("placedes", this.place.placedes);formData.append("province.id", 1);axios({method: 'post',url: 'http://localhost:8989/place/save',data: formData,headers: {'Content-Type': 'multipart/form-data'}}).then((res) => {console.log(res.data);if (res.data.state) {alert(res.data.msg + ",点击确定回到景点列表");location.href = "./viewspotlist.html?id=" + this.place.provinceid;} else {alert(res.data.msg + ",点击确定回到景点列表");}});
}

formData.append(“province.id”, 1); 外键关联属性绑定的时候使用这个

在添加的时候需要绑定省份id,绑定方法如下:

<select v-model="place.province.id"><option v-for="(pro,index) in provinces" :value="pro.id" v-text="pro.name"></option></select>

展示列表模块:

分页和省份列表一样,不同的是需要渲染一个base64的图片信息。

渲染的时候必须在属性前加上如下代码:

<td><img :src="'data:image/png;base64,'+place.picpath" class="viewspotimg"></td>

注:此文仅仅为个人的一些编码总结。

SpringBoot+vue旅游项目总结相关推荐

  1. Springboot vue旅游资讯网站管理系统

    旅游信息管理系统是对旅游信息资源进行管理的系统.随着旅游信息在种类和数量上的增多,以及涉及的方面相对较广,旅游信息的管理难度也在增大.伴随计算机的普及,人们也愿意并习惯通过计算机来获取信息资源,人们可 ...

  2. SpringBoot + Vue + nginx项目一起部署

    SpringBoot + Vue + nginx项目一起部署 SpringBoot + Vue 一起部署到 nginx 1.后端项目部署: (1)  Java项目打包上传到 服务器,开启服务 java ...

  3. springboot+vue计算机旅游管理系统 springboot+vue旅游网

    springboot+vue计算机旅游管理系统 springboot+vue旅游网 包含前台用户系统和后台管理系统 源码: vx:daihq713

  4. 基于springboot+vue物流项目

    基于springboot+vue物流项目 ✌全网粉丝20W+,csdn特邀作者.博客专家.CSDN新星计划导师.java领域优质创作者,博客之星.掘金/华为云/阿里云/InfoQ等平台优质作者.专注于 ...

  5. 踩坑之旅:springboot+vue+webpack项目实战(一)

    2019独角兽企业重金招聘Python工程师标准>>> 网上关于springboot的小项目很多,node.js+vue的项目也很多,但是好像没有两者合一的项目,最近在想实践下将两者 ...

  6. 开发一个springboot+vue的项目【增加铃声制作的功能】

    大家好呀,我是小孟! 参考的地址:https://github.com/Yin-Hongwei 前面小伙伴说要学习spring+vue的项目,我们录制了非常详细的教程,视频播放了突破了30w+,看来是 ...

  7. springboot + vue + elementUI项目实战——简洁清新的员工管理系统(一)

    springboot + vue + elementUI + mybatis + redis 清新的员工管理系统 前言   从这期,项目从需求分析开始,一步步实现一个老经典的清新的员工管理系统,适合有 ...

  8. B站云E办Springboot+vue——前端项目完整版(含源码)

    一.项目简介 项目背景:受疫情的影响,许多企业由线上办公转为线下办公.随着线上办公的人数的增多,线上办公的优点逐步凸显:通过实现工作流程的自动化.节省企业办公费用.实现绿色办公,同时提升办公效率. 项 ...

  9. Java Springboot+vue毕业项目实战-疫情防疫信息管理系统

    主要技术实现:文末获取源码联系 Java.springmvc.VUE.node.js.mybatis.mysql.tomcat.jquery.layui.bootstarp.JavaScript.ht ...

最新文章

  1. 为什么Scrum模式适合软件开发?
  2. mysql8.0 服务移除_Linux下彻底删除Mysql 8.0服务的方法
  3. 重温.NET下Assembly的加载过程 ASP.NET Core Web API下事件驱动型架构的实现(三):基于RabbitMQ的事件总线...
  4. Day10-Python3基础-协程、异步IO、redis缓存、rabbitMQ队列
  5. GMIS 2017大会戴文渊演讲:构建AI商业大脑
  6. Sun过去的世界中的JDK 11和代理
  7. Java 最常见 200+ 面试题全解析:面试必备
  8. cemtos7重置mysql root,Centos7重置MySQL8.0 root密码
  9. 如何在Mac上设置QLab工作区
  10. 【劲峰论道时空分析技术-学习笔记】4 如何度量时空变化
  11. IIS_PHP5.3.x zend guard loader 的配置方法
  12. 最新Java开发毕业论文参考文献干货满满
  13. 故障模块名称kernelbase.dll_OBDII(OBD2)故障码库P0700P0799
  14. mysql手册06_触发器
  15. Bus error 问题原因
  16. 什么是web前端?前端可以做什么?html5有什么用?
  17. 【C语言小游戏】计算器
  18. 基于51单片机的智能红外遥控防雨晾衣架 雨滴光强检测系统proteus仿真原理图PCB
  19. 又一款开源客服系统开放了
  20. 最常用的酒店IPTV系统实施方案

热门文章

  1. mlf机器人无限制格斗_2017FMB无限制机器人格斗比赛视频-2017极战 FMB 无限制机器人格斗大赛视频高清版 - 极光站...
  2. 基于STM32F103单片机智能风扇 手机蓝牙无线控制系统
  3. 超人前传 主题曲 Save Me (转载)
  4. 解析STEAM教育理念下美术作业设计生活化
  5. Kafka到底有多高可靠?
  6. FBA发货限制大改革,准备好的货还敢发吗?
  7. Uni-app 实现md5加密
  8. 【开发工具----Matlab】Matlab7.0(R14)注册码
  9. ARM寄存器(R13/R14/R15)
  10. JS 设置定时器和清除定时器