校园二手商品在线交易网站的设计与实现简单总结
1.项目架构
Spring Boot + Thymeleaf + Mybatis
2.功能模块
(1)前台功能模块
- 用户模块:注册(上传头像)、登录(后可以实时显示出用户上传的头像)、更新个人信息、退出登录
- 商品模块:商品首页、分类分页查看商品、查看商品的详情、模糊搜索商品、发布二手商品(上传商品的图片)并删除
- 购物车模块:购物车中添加商品、查看购物车(可以显示出购物车中的商品数量)、删除购物车中的某件商品
- 地址模块:添加地址、删除地址、查询地址、修改地址
- 订单模块:下单(增加订单、增加订单详情)、查询订单(卖出订单+购买订单)、订单发货收货、取消订单
- 支付模块:使用支付宝沙箱环境进行支付
- 收藏模块:添加收藏、查看收藏、删除收藏
- 留言模块:添加留言、查询留言
(2)后台功能模块
主要实现用户模块、商品模块、订单模块、分类模块、系统管理。
- 用户模块:分页查看所有用户(可以设置每页显示条数)(显示的用户按照注册时间降序排列)、按照用户的用户名或者学校对用户进行模糊搜索、单选或多选删除用户、修改某个用户的信息。
- 商品模块:分页查看所有发布的商品(可以设置每页显示条数)(显示的商品按照注册时间降序排列)、按照商品名称或者商品分类对商品进行模糊搜索、单选或多选删除商品(管理员删除是将商品的状态修改为3表示删除)、修改某个商品的信息。
- 订单模块:分页查看所有的订单(可以设置每页显示条数)(显示的订单按照下单时间降序排列)、按照订单编号对订单进行搜索、单选或多选删除订单信息、修改某个订单的信息、查看某个订单的详情。
- 分类模块:对已有商品分类进行修改、添加新的商品分类。
- 系统管理:登录、对个人的基本信息(登录名称和邮箱)进行修改。对密码进行修改。安全退出。
3.实现业务逻辑:

4.自定义拦截器
4.1.实现HandlerInterceotor接口
(1)preHandler(),return 的是boolean,true时,不拦截请求;false时,拦截请求。请求前执行。
(2)postHandler()请求后执行。
(3)afterCompletion()响应页面渲染后执行。
4.2.注册拦截器
自定义类:
(1)实现WebMvcConfigurer接口
(2)加上注解,@SpringBootConfiguration//Spring Boot的配置类,标注在某个类上,表示这是一个Spring Boot的配置类
(3)在addInterceptors(InterceptorRegistry registry)方法中注册拦截器,方法中通过registry.addInterceptor(portalLoginCheckInterceptor)//括号中的是拦截器
.addPathPatterns("/portal/user/**")//添加需要拦截的路径
.excludePathPatterns(excludeUrl);//排除不需要拦截的路径
注意:如果注册了多个拦截器,则按照拦截器的顺序执行,先注册的先执行
5.连接支付宝网站支付的沙箱环境
5.1.在pom.xml文件中添加依赖

5.2.创建AlipayConfig.java文件
5.3.把demo中alipay.trade.page.pay.jsp改成controller控制层代码
支付接口调用流程
调用顺序如下:
- 商户系统请求支付宝接口alipay.trade.page.pay,支付宝对商户请求参数进行校验,而后重新定向至用户登录页面。
- 用户确认支付后,支付宝通过get请求returnUrl(商户入参传入),返回同步返回参数。
- 交易成功后,支付宝通过post请求notifyUrl(商户入参传入),返回异步通知参数。
若由于网络等问题异步通知没有到达,商户可自行调用交易查询接口alipay.trade.query进行查询,根据查询接口获取交易以及支付信息(商户也可以直接调用查询接口,不需要依赖异步通知)。
6.图片上传
页面的三个条件:
(1)必须指定method属性为post
(2)必须指定enctype属性为multipart/form-data
(3)使用类型为file的标签,供用户选择文件
在业务方法中添加MultipartFile类型的形参,调用transferTo()方法,并生成唯一的文件名。
//获取原始文件名String originalFilename = file.getOriginalFilename(); // xxx.png//获取扩展名String extend = originalFilename.substring(originalFilename.lastIndexOf("."));//重新生成唯一的文件名String newName = UUID.randomUUID().toString();File file1 = new File(uploadPath,newName + extend);try {file.transferTo(file1);//保存文件user.setPhoto(newName + extend);} catch (IOException e) {e.printStackTrace();}
静态资源的设置:
一、spring boot项目中上传图片到本项目的路径下,需要重启项目才能显示图片解决方法
(1)application-dev.yml文件中设置上传文件的路径
(2)在controller层,获取在yml文件中的路径
(3)在新建的配置文件中映射图片的静态路径
addResourceHandler()里配置需要映射的文件夹,此处代表映射文件夹img/commodity下的所有资源。
addResourceLocations()配置文件夹在系统中的路径,使用绝对路径,格式为“file:你的路径”
二、spring boot项目部署到阿里云服务器上显示上传图片
(1)application-prod.yml文件中设置上传文件的路径
上传的文件的路径写的是绝对路径,在Linux环境下,要创建出对应的目录
(2)在controller层,获取在yml文件中的路径(同上)
(3)在新建的配置文件中映射图片的静态路径(同上不需要修改)
7.Springboot中PageHelper分页查询使用方法(mybatis+thymeleaf)
一:导入依赖
com.github.pagehelper pagehelper-spring-boot-starter 1.2.13
二:配置yml文件中PageHelper的属性
pagehelper: #分页插件helper-dialect: mysqlreasonable: truesupport-methods-arguments: trueparams:
三:在controller类中使用
1.在查询方法上调用PageHelper.startPage()方法,设置分页的页数和每页信息数,
2.将查询出来的结果集用PageInfo的构造函数初始化为一个分页结果对象
3.将分页结果对象存入model,返回前端页面
四:前端展示分页主要是thymeleaf的使用。
8.如何实现下单?

如何进行一些批量操作:
delete from collectwhere collectionid in#{collectionid}
9.地址的三级联动?
实现思路:
1.创建省市县三级地址,分别采用下列方式表示
省份:使用一维数组
城市:使用二维数组,和一维数组省份对应
区/县:使用三维数组,和二维数组城市对应
2.创建HTML文件,然后创建三个select选择框,分别代表省市县
3.创建实现联动的js文件,然后按照下面步骤实现
(1)获取三个select对象
- 设置省份
遍历省份数组
创建option对象
将option对象加追加到select中
- 设置城市
获取已经选择的省份下标
根据省份下标遍历城市数组
创建option对象
将option对象加追加到select中
- 设置县区
获取已经选择的省份和城市下标
根据省份和城市下标遍历区县数组
创建option对象
将option对象加追加到select中
4.网页加载完成应该将省市县显示在第一个
当省份改变城市的区县一起改变
当城市改变区县改变
三级联动的js实现:// 当框框加载完成之后调用设置省份
window.onload = setProvince;// 获取省市县/区的select选择框对象
var province = document.getElementsByTagName("select")[0];
var city = document.getElementsByTagName("select")[1];
var county = document.getElementsByTagName("select")[2];// 设置省份
function setProvince() {// 遍历省份数组, provinceArr在city.js中for (var i = 0; i < provinceArr.length; i++){// 创建省份option选项var opt = document.createElement("option");opt.value = provinceArr[i]; // 设置value-提交给服务器用opt.innerHTML = provinceArr[i]; // 设置option文本显示内容province.appendChild(opt); // 追加省份到下拉框// 当省份发生变化更改城市province.onchange = function(){setCity(this.selectedIndex);};}// 省份加载完成,默认显示第一个省份的城市setCity(0);
}// 设置城市
function setCity(provincePos) {// 获取省份对象的城市,cityArr在city.js中var citys = cityArr[provincePos];city.length = 0; // 清空长度,重新从0开始赋值下拉框for (var i = 0; i < citys.length; i++){// 创建城市option选项var opt = document.createElement("option");opt.value = citys[i]; // 设置value-提交给服务器用opt.innerHTML = citys[i]; // 设置option文本显示内容city.appendChild(opt);city.onchange = function() {setCounty(provincePos, this.selectedIndex);}}// 默认显示城市的第一个县/区setCounty(provincePos, 0);
}// 设置县/区, 县/区是三位数组,需要传入哪个省份和城市
function setCounty(provincePos, cityPos) {// 获取县/区,countyArr在city.js中国var countys = countyArr[provincePos][cityPos];county.length = 0;for (var i = 0; i < countys.length; i++){// 创建县/区option选项var opt = document.createElement("option");opt.value = countys[i]; // 设置value-提交给服务器用opt.innerHTML = countys[i]; // 设置option文本显示内容county.appendChild(opt); // 追加到县/区选择框中}
}
数据回响实现联动:
/*
* 获取某个元素下标
* arr: 传入的数组
* obj: 需要获取下标的元素
* */
function getArrayIndex(arr, obj) {var i = arr.length;while (i--) {if (arr[i] === obj) {return i;}}return -1;
}// 设置城市
function getCity(provincePos, receiverCity) {// 获取省份对象的城市,cityArr在city.js中var citys = cityArr[provincePos];city.length = 0; // 清空长度,重新从0开始赋值下拉框for (var i = 0; i < citys.length; i++){// 创建城市option选项var opt = document.createElement("option");opt.value = citys[i]; // 设置value-提交给服务器用opt.innerHTML = citys[i]; // 设置option文本显示内容if (opt.value == receiverCity){opt.selected = true; // 让回响的数据设置为选中}city.appendChild(opt);city.onchange = function() {setCounty(provincePos, this.selectedIndex);}}// 默认显示城市的第一个县/区setCounty(provincePos, 0);
}// 设置县/区, 县/区是三位数组,需要传入哪个省份和城市
function getCounty(provincePos, cityPos, receiverDistrict) {// 获取县/区,countyArr在city.js中国var countys = countyArr[provincePos][cityPos];county.length = 0;for (var i = 0; i < countys.length; i++){// 创建县/区option选项var opt = document.createElement("option");opt.value = countys[i]; // 设置value-提交给服务器用opt.innerHTML = countys[i]; // 设置option文本显示内容if (opt.value == receiverDistrict){opt.selected = true; // 让回响的数据设置为选中}county.appendChild(opt); // 追加到县/区选择框中}
}
10.后台登录时验证码的实现?
运用Google的Kaptcha
(1)首先引入依赖
com.github.penggle kaptcha 2.3.2
(2)KaptchaConfig配置。
主要对图片边框、字体颜色、图片宽高、字体大小、验证码长度等进行设置。
package com.neuedu.controller.back;import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;import java.util.Properties;@Component
public class KaptchaConfig {@Beanpublic DefaultKaptcha getDefaultKaptcha(){com.google.code.kaptcha.impl.DefaultKaptcha defaultKaptcha = new com.google.code.kaptcha.impl.DefaultKaptcha();Properties properties = new Properties();//图片边框properties.put("kaptcha.border", "no");//字体颜色properties.put("kaptcha.textproducer.font.color", "black");//图片宽properties.put("kaptcha.image.width", "150");//图片高properties.put("kaptcha.image.height", "40");//字体大小properties.put("kaptcha.textproducer.font.size", "30");//session keyproperties.put("kaptcha.session.key", "verifyCode");//验证码长度properties.put("kaptcha.textproducer.char.space", "5");Config config = new Config(properties);defaultKaptcha.setConfig(config);return defaultKaptcha;}
}
(3)CommonController,生产验证码字符串并保存到session中,使用生成的验证码字符串返回一个BufferedImage对象并转换为byte写入到byte数组中;定义response输出类型为image/jpeg类型,使用response输出流输出图片的byte数组。
package com.neuedu.controller.back;import com.google.code.kaptcha.impl.DefaultKaptcha;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;@Controller
public class CommonController {@Autowiredprivate DefaultKaptcha captchaProducer;@GetMapping("/common/kaptcha")public void defaultKaptcha(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {byte[] captchaOutputStream = null;ByteArrayOutputStream imgOutputStream = new ByteArrayOutputStream();try {//生产验证码字符串并保存到session中String verifyCode = captchaProducer.createText();httpServletRequest.getSession().setAttribute("verifyCode", verifyCode);// 使用生成的验证码字符串返回一个BufferedImage对象并转为byte写入到byte数组中BufferedImage challenge = captchaProducer.createImage(verifyCode);ImageIO.write(challenge, "jpg", imgOutputStream);} catch (IllegalArgumentException e) {httpServletResponse.sendError(HttpServletResponse.SC_NOT_FOUND);return;}// 定义response输出类型为image/jpeg类型,使用response输出流输出图片的byte数组captchaOutputStream = imgOutputStream.toByteArray();httpServletResponse.setHeader("Cache-Control", "no-store");httpServletResponse.setHeader("Pragma", "no-cache");httpServletResponse.setDateHeader("Expires", 0);httpServletResponse.setContentType("image/jpeg");ServletOutputStream responseOutputStream = httpServletResponse.getOutputStream();responseOutputStream.write(captchaOutputStream);responseOutputStream.flush();responseOutputStream.close();}
}
11.模态框的实现?
SweetAlert
12.模糊搜索如何实现?排序如何实现?
13.项目部署
(1)购买阿里云服务器
(2)Xshell连接阿里云(Linux下应用Xshell通过SSH连接云服务器)
(3)开放端口
(4)配置线上环境
创建普通用户
安装jdk&tomcat&mysql
(5)线上部署
spring boot项目打包成jar包,运行jar包,通过java -jar xx.jar
在命令行中进行打包,首先删除掉项目中的target目录
mvn clean package -DskipTests //打包,跳过单元测试
等待打包成功,显示BUILD SUCCESS,在项目目录下生成一个target目录,找到xx.jar文件上传到Linux中,上传的位置,总是上传到Linux下所在的当前目录。
设置成一个后台进程,关闭Xshell后依然可以运行,执行命令nohup java -jar busines.jar &
将数据库部署到服务器上
进入Linux的mysql中,首先上传数据库文件
输入命令mysql -u root -p,输入密码。构建数据库。
连接支付宝的沙箱环境,进行网站支付,需要在支付宝开放平台的开发者中心的沙箱环境中修改回调地址。
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
