基于javaweb+mysql的ssm+maven快递代拿系统(java+ssm+bootstrap+shiro+mysql+html)
运行环境
Java≥8、MySQL≥5.7、Tomcat≥8
开发工具
eclipse/idea/myeclipse/sts等均可配置运行
适用
课程设计,大作业,毕业设计,项目练习,学习演示等
功能说明
基于javaweb+mysql的SSM+Maven快递代拿系统(java+ssm+bootstrap+shiro+mysql+html)
使用技术
采用 Spring + SpringMVC + MyBatisPlus,连接池采用 Druid,安全框架使用 Shiro,前端采用 Bootstrap + layer 实现。
支付采用支付宝沙箱环境,支付APP下载链接,点击这里。
支付账号:uceskd4358 sandbox.com 登录密码、支付密码:111111
注意:
请务必使用以上链接下载沙箱支付宝
,也务必使用以上账号登录。不要使用真实支付宝APP和真实支付宝账号登录。
运行环境
-
集成开发环境:IntelliJ IDEA
-
项目构建工具:Maven - 数据库:MYSQL 5.7+ - JDK版本:1.8 - Tomcat版本:Tomcat8
(1)首先请创建数据库: shell CREATE DATABASE IF NOT EXISTS `express-ssm` /*!40100 DEFAULT CHARACTER SET utf8 */
(2)导入项目 sql 文件夹下的 express-ssm.sql
文件。 (3)编辑项目中 src/main/resources/cnf/mysql.properties
文件,修改数据库连接信息: jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/express-ssm?useUnicode=true&useSSL=false&characterEncoding=utf-8 jdbc.username=root # MYSQL 用户名 jdbc.password=root # MYSQL 密码
运行
项目运行时,在tomcat中配置项目运行路径为http://localhost:8080/ 注意:后面不要带项目名,否则会运行出错;
默认账户
注:以下为本项目默认存在的用户名密码,请将本仓库项目在本地运行后使用以下密码登录。
| 权限 | 用户名 | 密码 | | 管理员 | admin | 123 | | 配送员 | 李四 | 123 | | 用户名 | 小红 | 123 |
Map<String,String> params = getPayParams(request);
try {
// 验证订单
boolean flag = expressPaymentService.validAlipay(params);
if(flag) {
// 验证成功后,修改订单状态为已支付
String orderId = params.get("out_trade_no");
/*
* 订单状态(与官方统一)
* WAIT_BUYER_PAY:交易创建,等待买家付款;
* TRADE_CLOSED:未付款交易超时关闭,或支付完成后全额退款;
* TRADE_SUCCESS:交易支付成功;
* TRADE_FINISHED:交易结束,不可退款
*/
// 获取支付宝订单号
String tradeNo = params.get("trade_no");
// 更新状态
expressPaymentService.updateStatus(orderId, PaymentStatusEnum.TRADE_SUCCESS.getIndex(), tradeNo);
HttpSession session = request.getSession();
// 将支付信息写入session
session.setAttribute(SESSION_LATEST_PAYMENT, expressPaymentService.selectById(orderId));
// 支付成功后删除Express的session
session.removeAttribute(SESSION_LATEST_EXPRESS);
} else {
throw new Exception("支付宝支付验签失败");
}
} catch (Exception e) {
e.printStackTrace();
}
return "payment_result";
}
/**
* 服务器异步通知,获取支付宝POST过来反馈信息
* 该方法无返回值,静默处理
* 订单的状态已该方法为主,其他的状态修改方法为辅 *
* (1)程序执行完后必须打印输出“success”(不包含引号)。
* 如果商户反馈给支付宝的字符不是success这7个字符,支付宝服务器会不断重发通知,直到超过24小时22分钟。
* (2)程序执行完成后,该页面不能执行页面跳转。
* 如果执行页面跳转,支付宝会收不到success字符,会被支付宝服务器判定为该页面程序运行出现异常,而重发处理结果通知
* (3)cookies、session等在此页面会失效,即无法获取这些数据
* (4)该方式的调试与运行必须在服务器上,即互联网上能访问 *
*/
@PostMapping("/alipay/notify")
public void alipayNotify(HttpServletRequest request, HttpServletResponse response){
/*
默认只有TRADE_SUCCESS会触发通知,如果需要开通其他通知,请联系客服申请
触发条件名 触发条件描述 触发条件默认值
*/
@Controller
@RequestMapping("/payment")
public class PaymentController {
@Value("${session.latest_express}")
private String SESSION_LATEST_EXPRESS;
@Value("${session.latest_payment}")
private String SESSION_LATEST_PAYMENT;
@Autowired
private ExpressService expressService;
@Autowired
private ExpressPaymentService expressPaymentService;
@Autowired
private AliPaySetting aliPaySetting;
@Autowired
private AlipayClient alipayClient;
/**
* 从客户Cookie中取出最新的一条订单信息
*/
@GetMapping("/express")
@ResponseBody
public Msg getExpress(HttpSession session) {
Express express = (Express)session.getAttribute(SESSION_LATEST_EXPRESS);
if(express != null) {
return Msg.ok(null,express);
} else {
return Msg.error("订单好像丢失了,请重新下单...");
}
}
/**
* 线下支付方式
* @param money 支付金额
*/
@PostMapping("/insert")
public Msg insert(SysUser user) {
UUID uuid = UUID.randomUUID();
user.setId(uuid.toString());
user.setRoleId(1);
user.setStatus(0);
user.setPassword(PasswordUtils.entryptPassword("123456"));
//SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
user.setCreateDate(new Date());// new Date()为获取当前系统时间
user.setUpdateDate(new Date());
userService.insert(user);
return Msg.ok();
}
/**
* 获取用户信息
*/
@GetMapping("/{id}")
public Msg getById(@PathVariable String id) {
SysUser user = userService.selectById(id);
return Msg.ok(null,user);
}
/**
* 修改员工为在职
*/
@PostMapping("/active")
public Msg changeActive(String[] ids) {
changeUserStatus(ids, SysUserStatusEnum.ACTIVE.getIndex());
return Msg.ok();
}
/**
* 修改员工为冻结
*/
@PostMapping("/freeze")
public Msg changeFreeze(String[] ids) {
changeUserStatus(ids, SysUserStatusEnum.FREEZE.getIndex());
return Msg.ok();
}
}
/**
* 订单列表
* @param esw 筛选条件
*/
@GetMapping("/list")
public Map listExpress(Integer rows, Integer page, ExpressSelectWrapper esw, @RequestParam(defaultValue = "createDate") String order) {
// Get请求中文编码
try {
esw.setName(globalFunction.iso8859ToUtf8(esw.getName()));
esw.setStaffName(globalFunction.iso8859ToUtf8(esw.getStaffName()));
esw.setAddress(globalFunction.iso8859ToUtf8(esw.getAddress()));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
// 得到筛选条件
EntityWrapper<Express> expressWrapper = globalFunction.getExpressWrapper(esw);
Page<Express> selectPage = expressService.selectPage(new Page<>(page, rows, order, false), expressWrapper);
List<ExpressDto> list = globalFunction.express2dto(selectPage.getRecords());
Map<String,Object> map = new HashMap<>(16);
map.put("total", selectPage.getTotal());
map.put("rows", list);
return map;
}
/**
* 获取单个订单详情
*/
@GetMapping("/{id}")
public Msg getById(@PathVariable String id) {
Express express = expressService.selectById(id);
ExpressDto expressDto = globalFunction.express2dto(express);
return Msg.ok(null,expressDto);
}
/**
* 分配订单
* @param ids 订单数组
* @param staffId 派送员id
*/
@PostMapping("/assign")
public Msg assignExpress(String[] ids,String staffId) {
*/
@PostMapping("/confirm")
public Msg confirmExpress(ExpressPayment payment) {
String id = payment.getExpressId();
Express express = expressService.selectById(id);
express.setStatus(ExpressStatusEnum.COMPLTE.getIndex());
expressService.updateById(express);
expressPaymentService.updateById(payment);
return Msg.ok();
}
/**
* 异常订单
*/
@PostMapping("/error")
public Msg errorExpress(String[] ids, String text) {
for(String id : ids) {
Express express = expressService.selectById(id);
// 只有订单状态为TRANSPORT时才要确认
if(ExpressStatusEnum.TRANSPORT.getName().equals(ExpressStatusEnum.getName(express.getStatus()))) {
express.setStatus(ExpressStatusEnum.ERROR.getIndex());
express.setStaffRemark(text);
expressService.updateById(express);
}
}
return Msg.ok();
}
/**
* 删除订单
*/
@PostMapping("/delete")
public Msg deleteById(String[] ids) {
*/
@GetMapping("/list")
public Map listStaff(Integer rows, Integer page, SysUserSelectWrapper usw) {
// Get请求中文编码
try {
usw.setName(globalFunction.iso8859ToUtf8(usw.getName()));
usw.setAddress(globalFunction.iso8859ToUtf8(usw.getAddress()));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
// 得到筛选条件
EntityWrapper<SysUser> userWrapper = globalFunction.getSysUserWrapper(usw);
// 不显示admin角色
userWrapper.ne("role_id", RoleEnum.ADMIN.getIndex());
Page<SysUser> selectPage = userService.selectPage(new Page<>(page, rows), userWrapper);
List<SysUserDto> list = globalFunction.sysUser2dto(selectPage.getRecords());
Map<String,Object> map = new HashMap<>();
map.put("total", selectPage.getTotal());
map.put("rows", list);
return map;
}
/**
* 更新用户信息
*/
@PostMapping("")
public Msg update(SysUser user) {
userService.updateById(user);
return Msg.ok();
}
/**
* 新增用户信息
*/
@PostMapping("/insert")
public Msg insert(SysUser user) {
UUID uuid = UUID.randomUUID();
user.setId(uuid.toString());
user.setRoleId(1);
user.setStatus(0);
user.setPassword(PasswordUtils.entryptPassword("123456"));
//SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
user.setCreateDate(new Date());// new Date()为获取当前系统时间
user.setUpdateDate(new Date());
userService.insert(user);
return Msg.ok();
}
/**
* 获取用户信息
return map;
}
/**
* 删除反馈
*/
@PostMapping("/delete")
public Msg deleteById(String[] ids) {
for(String id : ids) {
feedbackService.deleteById(id);
}
return Msg.ok();
}
/**
* 处理反馈
*/
@PostMapping("")
public Msg handleFeedback(String id, String content) {
if(StringUtils.isBlank(id) || StringUtils.isBlank(content)) {
return Msg.error("参数错误");
}
Feedback feedback = feedbackService.selectById(id);
// 设置处理人为当前用户
feedback.setStaffId(globalFunction.getUserId());
feedback.setResult(content);
// 0代表未处理,1代表已处理;默认为0
feedback.setStatus(1);
feedbackService.updateById(feedback);
return Msg.ok();
}
}
*/
@GetMapping("/{id}")
public Msg getById(@PathVariable String id) {
SysUser user = userService.selectById(id);
return Msg.ok(null,user);
}
/**
* 修改员工为在职
*/
@PostMapping("/active")
public Msg changeActive(String[] ids) {
changeUserStatus(ids, SysUserStatusEnum.ACTIVE.getIndex());
return Msg.ok();
}
/**
* 修改员工为冻结
*/
@PostMapping("/freeze")
public Msg changeFreeze(String[] ids) {
changeUserStatus(ids, SysUserStatusEnum.FREEZE.getIndex());
return Msg.ok();
}
/**
* 修改员工为离职
*/
@PostMapping("/leave")
public Msg changeLeave(String[] ids) {
changeUserStatus(ids, SysUserStatusEnum.LEAVE.getIndex());
return Msg.ok();
}
}
/**
* 查询Controller
*/
@RestController
@RequestMapping("/search")
public class SearchController {
@Autowired
private ExpressService expressService;
@Autowired
private FeedbackService feedbackService;
@Autowired
private GlobalFunction globalFunction;
/**
* 订单查询
*/
@PostMapping("")
public Msg search(String id) {
// 订单号为纯数字,反馈号为数字+字母
if(StringUtils.isNumeric(id)) {
Express express = expressService.selectById(id);
if(express == null) {
return Msg.error("没有查到相关信息");
} else {
return Msg.ok("0", globalFunction.express2dto(express));
}
} else {
Feedback feedback = feedbackService.selectById(id);
if(feedback == null) {
return Msg.error("没有查到相关信息");
} else {
return Msg.ok("1", globalFunction.feedback2dto(feedback));
/**
* 线下支付方式
* @param money 支付金额
*/
@PostMapping("/offline")
@ResponseBody
public Msg paymentOffline(Double money, HttpSession session) {
Express express = (Express)session.getAttribute(SESSION_LATEST_EXPRESS);
if(express == null || money == null) {
return Msg.error("参数错误");
}
// 创建订单
String expressId = expressService.createExpress(express);
// 创建订单支付信息
ExpressPayment payment = expressPaymentService.createOfflinePayment(expressId, money);
// 将支付信息写入session
session.setAttribute(SESSION_LATEST_PAYMENT, payment);
// 支付成功后删除Express的session
session.removeAttribute(SESSION_LATEST_EXPRESS);
return Msg.ok(null,"/payment/result");
}
/**
* 支付宝支付方式
* @param money 支付金额
*/
@PostMapping("/alipay")
public void paymentAlipay(Double money, HttpSession session, HttpServletResponse response) throws IOException {
Express express = (Express)session.getAttribute(SESSION_LATEST_EXPRESS);
if(express == null || money == null) {
response.getWriter().write("参数错误,请重新下单");
}
// 金额保留两位
money = (double) (Math.round(money * 100)) / 100;
// 生成订单
private FeedbackService feedbackService;
@Autowired
private SysUserService userService;
@Autowired
private GlobalFunction globalFunction;
@Value("${session.latest_express}")
private String SESSION_LATEST_EXPRESS;
/**
* 验证验证码
*/
@PostMapping("/checkVerifyCode")
public Msg checkVerifyCode(String data, HttpServletRequest request) {
String validateCode;
try {
validateCode = ((String) request.getSession().getAttribute("validateCode")).toLowerCase();
} catch (NullPointerException e) {
return Msg.error("验证码初始化错误,请刷新页面重试");
}
String value = data.toLowerCase();
if(!validateCode.equals(value)) {
return Msg.error("验证码输入错误");
} else {
return Msg.ok();
}
}
/**
* 登陆
*/
@PostMapping("/login")
public Msg login(SysUser user) {
//Shiro实现登录
UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(), user.getPassword());
Subject subject = SecurityUtils.getSubject();
try {
//如果获取不到用户名就是登录失败,但登录失败的话,会直接抛出异常
subject.login(token);
} catch (Exception e) {
return Msg.error("用户名或密码错误");
}
*/
public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName,
String cookieValue) {
setCookie(request, response, cookieName, cookieValue, -1);
}
/**
* 设置Cookie的值 在指定时间内生效,但不编码
* @param cookieMaxage 过期时间
*/
public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName,
String cookieValue, int cookieMaxage) {
setCookie(request, response, cookieName, cookieValue, cookieMaxage, false);
}
/**
* 设置Cookie的值 不设置生效时间,编码
* @param isEncode 是否编码,编码格式为UTF-8
*/
public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName,
String cookieValue, boolean isEncode) {
setCookie(request, response, cookieName, cookieValue, -1, isEncode);
}
/**
* 设置Cookie的值 在指定时间内生效,编码
* @param cookieMaxage 过期时间
* @param isEncode 是否编码,编码格式为UTF-8
*/
public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName,
String cookieValue, int cookieMaxage, boolean isEncode) {
doSetCookie(request, response, cookieName, cookieValue, cookieMaxage, isEncode);
}
/**
* 设置Cookie的值 在指定时间内生效, 编码
* @param cookieMaxage 过期时间
* @param encodeString 编码格式
*/
public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName,
String cookieValue, int cookieMaxage, String encodeString) {
doSetCookie(request, response, cookieName, cookieValue, cookieMaxage, encodeString);
}
/**
* 确认订单
*/
@PostMapping("/confirm")
public Msg confirmExpress(ExpressPayment payment) {
String id = payment.getExpressId();
Express express = expressService.selectById(id);
express.setStatus(ExpressStatusEnum.COMPLTE.getIndex());
expressService.updateById(express);
expressPaymentService.updateById(payment);
return Msg.ok();
}
/**
* 异常订单
*/
@PostMapping("/error")
public Msg errorExpress(String[] ids, String text) {
for(String id : ids) {
Express express = expressService.selectById(id);
// 只有订单状态为TRANSPORT时才要确认
if(ExpressStatusEnum.TRANSPORT.getName().equals(ExpressStatusEnum.getName(express.getStatus()))) {
express.setStatus(ExpressStatusEnum.ERROR.getIndex());
express.setStaffRemark(text);
expressService.updateById(express);
}
}
return Msg.ok();
}
/**
* 删除订单
*/
@PostMapping("/delete")
public Msg deleteById(String[] ids) {
for(String id : ids) {
Express express = expressService.selectById(id);
if(express != null) {
// 设置删除标记为true
gd.drawLine(x, y, x + xl, y + yl);
}
// randomCode用于保存随机产生的验证码,以便用户登录后进行验证。
StringBuffer randomCode = new StringBuffer();
int red = 0, green = 0, blue = 0;
// 随机产生codeCount数字的验证码。
for (int i = 0; i < codeCount; i++) {
// 得到随机产生的验证码数字。
String strRand = String.valueOf(codeSequence[random.nextInt(36)]);
// 产生随机的颜色分量来构造颜色值,这样输出的每位数字的颜色值都将不同。
red = random.nextInt(255);
green = random.nextInt(255);
blue = random.nextInt(255);
// 用随机产生的颜色将验证码绘制到图像中。
//gd.setColor(new Color(red,green,blue));
gd.setColor(new Color(255,0,0));
gd.drawString(strRand, (i + 1) * codeX, codeY);
// 将产生的四个随机数组合在一起。
randomCode.append(strRand);
}
// 将四位数字的验证码保存到Session中。
HttpSession session = request.getSession();
session.setAttribute("validateCode", randomCode.toString());
// 禁止图像缓存。
response.setHeader("Pragma", "no-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
response.setContentType("image/jpeg");
// 将图像输出到Servlet输出流中。
ServletOutputStream sos = response.getOutputStream();
ImageIO.write(buffImg, "jpeg", sos);
sos.close();
}
}
//Shiro实现登录
UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(), user.getPassword());
Subject subject = SecurityUtils.getSubject();
try {
//如果获取不到用户名就是登录失败,但登录失败的话,会直接抛出异常
subject.login(token);
} catch (Exception e) {
return Msg.error("用户名或密码错误");
}
//所有用户均重定向对应的展示配送页面
if (subject.hasRole(RoleEnum.ADMIN.getName())) {
return Msg.ok(null,"/admin/express");
} else if (subject.hasRole(RoleEnum.STAFF.getName())) {
return Msg.ok(null,"/staff/home");
}
return Msg.error("授权失败");
}
/**
* 获取用户名
*/
@GetMapping("/username")
public Msg selfName() {
String username = (String)SecurityUtils.getSubject().getPrincipal();
return Msg.ok(null, username);
}
/**
* 登出
*/
@RequestMapping(value = "/logout")
public String logout() {
return "redirect:/logout";
}
/**
* 提交反馈
*/
@PostMapping("/feedback")
} else {
Feedback feedback = feedbackService.selectById(id);
if(feedback == null) {
return Msg.error("没有查到相关信息");
} else {
return Msg.ok("1", globalFunction.feedback2dto(feedback));
}
}
}
}
/**
* 密码Controller
*/
@RestController
@RequestMapping("/password")
public class PasswordController {
@Autowired
private SysUserService userService;
@Autowired
private GlobalFunction globalFunction;
/**
* 重置密码
*/
@PostMapping("/reset")
public Msg resetPassword(String oldPassword, String newPassword) {
SysUser user = globalFunction.getUser();
if(!PasswordUtils.validatePassword(oldPassword, user.getPassword())) {
return Msg.error("原始密码错误");
} else {
user.setPassword(PasswordUtils.entryptPassword(newPassword));
userService.updateById(user);
return Msg.ok();
/**
* 职员管理
*/
@RestController
@RequestMapping("/admin/staff")
public class StaffController {
@Autowired
private SysUserService userService;
@Autowired
private GlobalFunction globalFunction;
private void changeUserStatus(String[] ids, Integer status) {
for(String id : ids) {
SysUser user = userService.selectById(id);
user.setStatus(status);
userService.updateById(user);
}
}
/**
* 获取用户的状态列表
*/
@GetMapping("/status")
public Msg listStaffStatus() {
List<Map<String,Object>> result = new ArrayList<>();
for(SysUserStatusEnum enums :SysUserStatusEnum.values()) {
Map<String,Object> map = new HashMap<>();
map.put("id",enums.getIndex());
map.put("name",enums.getName());
result.add(map);
}
return Msg.ok(null,result);
}
/**
* 获取所有的职员名,用于分配订单