一:订餐系统项目说明:
1.1 项目要求
该项目由java+mysql+mybatis完成的订餐系统,作为一个java小型综合项目,包含了java初级阶段和mybatis阶段大部分功能。该项目为cs架构,主要整合java+mysql+mybatis技术应用,后期则修改为B/S架构项目。项目功能不断修改和完善。
技术栈:
java+mysql+mybatis完成订餐系统项目,
mysql:使用索引和分页
mybatis:使用自带的二级缓存
1.2 实现功能
运行系统显示:
用户名:
密码:
如果输错用户名密码显示:需要注册吗(y/n): n:直接byebye
输入y
请输入用户名:
请输入密码:
OK注册成功
用户名:
密码:
登录成功 (直接显示menu)
---------------------------menu-------------------------------
1:我要下单 2:签收 3:订单管理 4:退出
选择输入:1
---------------------------menu-------------------------------
------------------------------1 ----------------------------
输入页码翻页
页码:1 2 3 4…
菜品ID 菜品名称 销售量 库存量 单价
1 地瓜 200份 80份 20元
2 稀饭 210份 80份 20元
3 米饭 300份 70份 10元
页码:1 2 3 4…
点餐按0
------------------------------1 ----------------------------
请输入菜品ID:1
请输入订购份数:2
继续选购(Y/N): y // 这里要记住当前在第几页,继续选购仍要返回原来的页码,仍要显示 1 部分
输入N:
您于2022-4-5 12:12:12分订购了
菜品ID 菜品名称 分数 单价 价格
1 地瓜 2份 20元 40元
2 稀饭 1份 20元 20元
共计:60元
返回菜单输入1(回到menu部分);退出输入0
请输入:0
以安排小哥配送!如果没有订单 直接显示bye bye.退出系统
2:签收
您的订单:
菜品ID 菜品名称 分数 单价 价格 状态 交易 日期
1 地瓜 2份 20元 40元 未签收 2022-4-1
2 稀饭 1份 20元 20元 未签收 2022-2-1
共计60元:
签收输入菜品ID,多个用逗号隔开:1,2 … 退出选择: 0 ----》退出后回到主菜单menu部分
签收成功!
(上面就按说明写,不用考虑其余的扩展需求,注意要修改状态 和交易日期)
3:订单管理
您的订单:
菜品ID 菜品名称 分数 单价 价格 状态 操作 交易 日期
1 地瓜 2份 20元 40元 已签收 交易关闭 2022-5-1
2 稀饭 1份 20元 20元 未签收 删除 2022-2-1
选择操作菜品ID:
2
删除点(y) 签收点(n) —> 注意 已签收不能操作
y
操作完成
4:退出
byebye
为防止上面文字跑版截图如下:
二:系统框架
2.1 导入jar包
2.2 项目结构
log4j.properties主要用于开发时,打印SQL语句,项目没有做日志
三:mysql数据库设计说明
3.1 用户表
3.2 产品表
3.3 订单表
3.4 订单项表
四:mybatis 基础搭建
4.1 资源文件
4.1.1 db.properties
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://192.168.1.3:3306/meituan?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&useSSL=false
username=root
password=123
4.1.2 mabatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="org/jnx/resoures/db.properties"/>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper class="org.jnx.mapper.UserMapper"/>
</mappers>
</configuration>
4.1.3 MyBatisUtil
package org.jnx.util;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
public class MyBatisUtil {
public static SqlSessionFactory factory;
static{
InputStream is = null;
try {
is = Resources.getResourceAsStream("org/jnx/resoures/mabatis-config.xml");
factory = new SqlSessionFactoryBuilder().build(is);
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSession openSession(){
return factory.openSession(false);
}
public static void closeSession(SqlSession session){
if (session != null){
session.close();
}
}
}
五: 自定义异常类
5.1 自定义异常类
public class CopeException extends RuntimeException{
private ErrorEnum err;
public CopeException(ErrorEnum err){
super("异常code:"+err.getCode()+",异常原因:"+err.getErrMsg());
}
}
5.2 错误枚举
package org.jnx.exp;
public enum ErrorEnum {
NULLUSER(1,"用户名或密码不存在"),
DELERROR(2,"已签收订单不能撤销"),
REGISTERR(3,"用户名重复,请更换用户名"),
REGISTERR2(4,"网络阻塞,好像除了点小问题"),
INPUTILLEGAL(5,"输入不合法"),
UNKONERROR(6,"发生未知错误");
private Integer code;
private String errMsg;
ErrorEnum(Integer code, String errMsg){
this.code=code;
this.errMsg=errMsg;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getErrMsg() {
return errMsg;
}
public void setErrMsg(String errMsg) {
this.errMsg = errMsg;
}
}
六:管理类
所有操作都是通过该类,相当于一个中央控制器,类似于前台,在web开发环境中类似于 servlet的 action和spring的controller;该类将在后面不断扩充
package org.jnx;
import org.jnx.pojo.User;
import org.jnx.service.UserService;
import org.jnx.util.SecurityUtils;
import java.util.Scanner;
import static org.jnx.util.SecurityUtils.checkIsLogin;
public class SysManager {
// 记录已登录用户
public static User LOGINEDUSER=new User();
public static Scanner sc=new Scanner(System.in);
public void menu(){
// 检查用户是否登录,如果没有登录进入登录界面
if(!checkIsLogin()){
copelogin();
/*这里为什么返回return:
如果没有return:第一次没有登录,系统将会跳到注册或登录界面,此时第一次运行还没结束,执行完注册或登录后,
则会向下运行显示菜单代码,当执行完 显示菜单代码后,返回第一次运行状态,执行显示菜单页面。
简而言之,一旦第一次没有登录,显示菜单代码 将会运行2次*/
return;
}
// 显示菜单
if(checkIsLogin()){
System.out.println("这里是菜单");
}
}
// 未登录情况的处理
private void copelogin(){
UserService userService=new UserService();
System.out.println("1:注册;2:登录");
if (sc.nextInt() == 1) {
userService.regist();
}
try {
LOGINEDUSER = userService.login();
} catch (Exception e) {
System.out.println("需要注册吗(y/n): ");
if(!"y".equals(sc.next())){
System.out.println("bye bye!");
System.exit(0);
}
userService.regist();
LOGINEDUSER = userService.login();
}
menu();
}
public static void main(String[] args) {
new SysManager().menu();
}
}
七: 菜单模块
登录模块
7.1:登录模块结构图
执行任何操作都需要先检查是否登录,没有登录先注册或返回登录
7.2:pojo类
package org.jnx.pojo;
import java.io.Serializable;
/**
* user对象的pojo类
* */
public class User implements Serializable {
private Integer id;
private String username;
private String password;
private boolean isLogin;
public boolean isLogin() {
return isLogin;
}
public void setLogin(boolean login) {
isLogin = login;
}
public User(String username, String password) {
this.username = username;
this.password = password;
}
public User() {
}
public User(Integer id, String username, String password) {
this.id = id;
this.username = username;
this.password = password;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
7.3: UserMapper
package org.jnx.mapper;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import org.jnx.pojo.User;
import java.io.Serializable;
public interface UserMapper {
/**
* 用户登录
* */
@Select("select * from users where username=#{username}")
User queyByUserName(User user);
/**
* 在用户注册之前执行,查询是否有相同的用户名,系统不允许有相同的用户名存在
* @param username 根据用户名查询是否存在相同用户名
* */
@Select("select * from users where username=#{username}")
User queryUser(String username);
/**
* 用户注册
* */
@Insert("insert into users (username,password) values(#{username},#{password})")
int regist(User user);
}
7.4: UserService类
package org.jnx.service;
import org.apache.ibatis.session.SqlSession;
import org.jnx.exp.CopeException;
import org.jnx.exp.ErrorEnum;
import org.jnx.mapper.UserMapper;
import org.jnx.pojo.User;
import org.jnx.util.MyBatisUtil;
import java.util.Scanner;
/**
* 该类用于用户相关操作的业务实现
* */
public class UserService {
Scanner sc=new Scanner(System.in);
/**
* 用户登录代码,该方法是,查询用户是否曾经注册过该系统
* @return User 返回登录成功的User对象
* */
public User login() {
User userLogin = new User();
SqlSession sqlSession = MyBatisUtil.openSession();
System.out.println("---------------欢迎登录订餐系统---------------");
System.out.println("请输入用户名:");
userLogin.setUsername(sc.next());
System.out.println("请输入密码:");
userLogin.setPassword(sc.next());
try {
userLogin = sqlSession.getMapper(UserMapper.class).queyByUserName(userLogin);
} catch (Exception e) {
throw new CopeException(ErrorEnum.UNKONERROR);
} finally {
MyBatisUtil.closeSession(sqlSession);
}
if(userLogin==null){
// 如果返回为空,则说明用户没有登录,开发中一般需要1:记录到日志中,2:抛出异常。
// 在此我们只抛出自定义异常(日志后面再学)
throw new CopeException(ErrorEnum.NULLUSER);
}
userLogin.setLogin(true);
System.out.println("OK注册成功");
return userLogin;
}
/**
* 在用户注册之前执行,查询是否有相同的用户名,系统不允许有相同的用户名存在
* 1: 先检查输入是否匹配
* 2: 检查是否有重复用户名
* 3: 检查是否注册成功
* */
public void regist(){
SqlSession sqlSession = MyBatisUtil.openSession();
User user=new User();
//先检查输入是否匹配
try {
System.out.println("请输入用户名:");
user.setUsername(sc.next());
System.out.println("请输入密码:");
user.setPassword(sc.next());
}catch (Exception e){
// 提前先记住,这里要先记录日志(后期再学日志),再抛出异常,没这习惯将来进入大厂要扣工资
throw new CopeException(ErrorEnum.INPUTILLEGAL);
}
// 2 检查是否有重复用户名
try {
User login = sqlSession.getMapper(UserMapper.class).queryUser(user.getUsername());
if(login!=null){
throw new CopeException(ErrorEnum.REGISTERR);
}
// 检查是否注册成功
int regist = sqlSession.getMapper(UserMapper.class).regist(user);
if(regist!=1){
// sqlSession.rollback(); 这里发生错误无需回滚,因为单一操作增加失败不会产生脏数据
// 抛出异常后,也不会再执行下面的commit提交代码
throw new CopeException(ErrorEnum.REGISTERR2);
}
sqlSession.commit();
} finally {
MyBatisUtil.closeSession(sqlSession);
}
}
}
7.5: SecurityUtil
package org.jnx.util;
import org.jnx.pojo.User;
import org.jnx.service.UserService;
import java.util.Scanner;
import static org.jnx.SysManager.LOGINEDUSER;
import static org.jnx.SysManager.sc;
public class SecurityUtils {
// 检查是否登录 返回bool值 true登录 false 未登录
public static boolean checkIsLogin(){
return LOGINEDUSER.isLogin();
}
}