项目总体要求>>>
1. 分层设计
2. 使用单例模式封装数据类
3. Dao层不可出现于用户交互的代码,如输入或者输入等
4. 在合适的地方使用try...catch...进行异常处理
[★] 5. 在合适的地方使用 log4j 记录日志:记录在文件中
6. 用户输入信息必须进行合理性验证
7. 进行增删改操作的最后,必须有确认步骤
8. 输出中不能有null、false、true等专业词汇
9. 程序不能出异常,不能非法退出
IDEA 控制台菜单界面参考>>>
1. 登陆
2. 注册(用户名不能重复)
3. 最新二手车信息
4. 搜索车辆
[★] 5. 对比车辆
[★] 6. 我的收藏
7. 后台管理
8. 退出系统
项目具体要求>>>
一、登录注册
1) 选择登陆:要求输入用户名密码和验证码;输入错误时要给出相应的提示信息
2) 选择注册:要求输入用户名,密码,确认密码,邮箱,手机号,注册日期;
如果用户名或邮箱或手机号已被使用,则该用户注册失败,也应给与相应的提示信息;
邮箱、手机号皆需验证规则
二、最新二手车信息
3) 选择最新二手车信息:要求显示最新发布的10辆二手车的信息内容:
包含车辆的品牌,车型,里程数,价格等
呈现的内容如下(参考):
品牌 车型 里程数 价格 发布时间
1.大众 朗逸 54000 75000 2014-7-5
2.
...
10.
4) 以上看到的10辆车的信息可以进行选择后显示车辆的详细信息:
包含之前呈现的信息以及排量,上牌的时间,离合器类型等
同时在下方呈现菜单(参考):
1. 收藏(必须登陆后才能进行收藏)
2. 加入对比
3. 购买(只能在登陆后才能看到该菜单项)
4. 返回主菜单
5) 选择收藏:将该车辆收藏至登陆人的"我的收藏";
当用户选择主菜单中的"我的收藏"选项时,可以查看登陆人收藏的所有车辆信息;
每个人最多只能收藏10辆车;在收藏第11辆车的时将第01辆车移除收藏列表
6) 选择加入对比:可以将车辆加入对比列表,对比列表最多只能存储4辆车的信息;
若车辆已满,则给出提示信息,同时可选择是否将页面跳转至"对比车辆"菜单项
7) 选择购买:支付登陆人的金额,若金额不够,则购买失败,否则交易成功,打印凭条
三、搜索车辆
8) 选择搜索车辆:进入如下菜单:
1. 根据品牌搜索
2. 根据价格搜索
3. 根据上牌日期搜索
9) 选择根据品牌搜索:要求呈现当前二手车系统的所有品牌信息,显示如下:
1. 大众
2. 福特
3. 斯柯达
...
10) 选择品牌后,要求呈现该品牌所对应的所有车型,如选择了上面的1后,显示如下:
1. 桑塔纳
2. 朗逸
3. 速腾
4. 帕萨特
...
11) 选择车型后查看该车辆的详细信息,显示对应品牌车型所发布的所有二手车的信息;
信息呈现的内容同 3),可以对车辆进行选择,该功能同 4)
12) 选择根据价格搜索:呈现如下菜单:
1. 5万以下
2. 5-10万
3. 10-15万
4. 15万以上
13) 选择任意项搜索出对应价格范围的车辆信息,
信息呈现内容同 3),可以对车辆进行选择,该功能同 4)
14) 选择根据上牌日期搜索:输入起始年份和月份以及结束的年份和月份,
可以显示对应时间范围中的所有二手车信息,
内容呈现同 3),可以对车辆进行选择,该功能同 4)
四、对比车辆
15) 选择对比车辆:呈现如下菜单:
1. 查看对比信息
2. 删除对比车辆
3. 返回上一级菜单
16) 选择查看对比信息:可以将之前加入对比的车辆信息进行对比(如果只有一辆车则无法参与对比);
对比信息如下:
品牌 雪佛兰 大众
车型 科鲁兹 朗逸
价格 65000 75000
排量 1.6 1.6
里程数 32000 23000
离合器 自动挡 手自一体
上牌时间 ... ...
返回上一个菜单
17) 选择删除对比车辆:需要先显示对比列表中的车辆品牌和车型;
选择要删除的车辆,进行删除(删除操作时要给出提示信息)
五、我的收藏
18) 选择我的收藏,可以查看收藏的车辆信息;
内容呈现同 3),可以选择查看收藏车辆的详细信息,该功能同 4)
六、后台管理
19) 选择后台管理:呈现如下菜单:
1. 品牌管理
2. 车型管理
3. 发布车辆信息
20) 选择品牌管理:添加品牌信息
21) 选择车型管理:首先呈现所有的品牌信息,选择品牌后呈现如下菜单:
1. 添加车型
2. 删除车型
22) 选择添加车型:输入车型名称并将该车型添加至对应的品牌中
23) 选择删除车型:显示当前品牌下所有的对应的车型;
选择车型后可以删除该车型(该车型对应的二手车都应删除);
收藏夹,对比列表中的该车型的车都应该被删除
24) 选择发布车辆信息:要求输入车辆的详细信息(要求品牌和车型是通过选择获取的,
其余直接键盘输入获取)同时自动根据当前系统时间记录发布车辆的时间
【项目整体思路】
1、首先是util层(工具层),有两个类(CommonUtil、RandomFourNumUtils)
- RandomFourNumUtils:生成一个String类型的四位随机数
- CommonUtil:dateStrIsValid:检查日期字符串是否合法,用Try-Catch抛出异常
2、其次是main层,有两个类(Main、easycheck)
- easycheck:系统使用说明与项目要求(方便对照)
- Main:主菜单(Switch实现)
3、然后是entity层(实体层),有五个类
- Admin:实现对象序列化(设置用户名与密码)
- Brand:同上(设置品牌名称与编号)
- Car:同上(设置汽车各类参数)
- CarType:同上(设置车型编号与名称)
- User:同上(设置用户相关信息)
4、接着是Dao层(数据存取对象层),有三个类
- UserDao:使用单例模式封装数据类
- saveUser: 保存用户信息
- findUserByNameAndPassword:根据账号和密码查询用户
- FileDB:文件操作类
- saveObjToFile:将对象保存到文件中,如果本地不存在数据就创建一个文件,用Try-Catch抛出异常
- getObjFromFile:从文件中读出对象,并且返回文件中存储的序列化对象
- 如果本地不存在数据,就创建一个文件用Try-Catch抛出异常
- DataAccessDao:数据访问类,通过I/O流对文件的操作,实现数据的增删改查
- buy:买车
- saveCarType:添加车型
- queryRecentTenCars:查询最新10条发布车辆信息
- saveBrand:添加品牌,用isExistsBrand判断是否可以添加品牌
5、最后是service层,有四个类
- 1)首先是CarService类:
- 可以根据车型、品牌、价格、挂牌日期,筛选出符合条件的车并显示,相应的可以根据情况收藏车或购买,购买的话打印账单
- 2)其次是RegisterService类:
- 注册类,检查输入,用户是否已经存在,输入邮箱手机号等,均成功则注册完成
- 在这里默认用户存款10W
- 3)然后是LoginService类:
- 登陆类,与注册类大致相同,其中要防止多人多次登陆,登陆后更改功能1
- 4)最后是BakendService类:
- 后台服务,用伪管理员密码控制登陆,进入后可以对车辆类作出增删,也可以对相应已经登陆的用户增加余额
【部分源码】
MAIN
package main;
import entity.User;
import service.BakendService;
import service.CarService;
import service.LoginService;
import service.RegisterService;
import java.util.Scanner;
public class Main {
public static boolean isLogin=false;
public static User user;
public static void main(String[] args) {
boolean isFirst=true;
LoginService loginService = new LoginService();
RegisterService registerService = new RegisterService();
CarService carService = new CarService();
BakendService bakendService = new BakendService();
System.out.println("****** 主菜单 ******");
System.out.println("1: 登录");
System.out.println("2: 注册");
System.out.println("3: 最新二手车信息");
System.out.println("4: 搜索车辆");
System.out.println("6: 我的收藏");
System.out.println("7: 后台管理");
System.out.println("8: 退出系统.");
System.out.print("请输入功能前对应的数字:");
while (true) {
if(!isFirst) {
System.out.println("请输入功能前对应的数字继续...");
}
isFirst=false;
Scanner sc = new Scanner(System.in);
String choice = sc.nextLine();
// 选择
switch (choice) {
case "1":
loginService.login();
break;
case "2":
registerService.register();
break;
case "3":
carService.queryTenCars();
break;
case "4":
carService.searchCar();
break;
case "6":
carService.queryAllMyLike();
break;
case "7":
bakendService.showBakendManage();
break;
case "8":
System.exit(1);
break;
default:
System.out.println("输入的数字错误");
break;
}
}
}
}
USER DAO
package dao;
import entity.User;
import java.util.ArrayList;
import java.util.List;
public class UserDao {
private static UserDao instance;
private String userFile = "user.txt";
//单例模式
public static UserDao getInstance(){
if(instance==null){
synchronized (UserDao.class){
if(instance==null){
instance = new UserDao();
}
}
}
return instance;
}
/**
* 保存用户信息
* @param user
*/
public void saveUser(User user){
FileDB<List<User>> fileDB = new FileDB<>(userFile);
List<User> userList = fileDB.getObjFromFile();
if(userList ==null) {
userList = new ArrayList<>();
}
userList.add(user);
fileDB.saveObjToFile(userList);
}
/**
* 根据账号和密码查询用户
* @param userName
* @param password
* @return
*/
public User findUserByNameAndPassword(String userName,String password){
FileDB<List<User>> fileDB = new FileDB<>(userFile);
List<User> userList = fileDB.getObjFromFile();
if(userList!=null) {
for (int i = 0; i < userList.size(); i++) {
if (userList.get(i).getUserName().equals(userName)&&userList.get(i).getPassword().equals(password)) {
return userList.get(i);
}
}
}
return null;
}
/**
* 检查用户名是否村子
* @param userName
* @return
*/
public boolean checkUserNameExists(String userName){
FileDB<List<User>> fileDB = new FileDB<>(userFile);
List<User> userList = fileDB.getObjFromFile();
if(userList!=null) {
for (int i = 0; i < userList.size(); i++) {
if (userList.get(i).getUserName().equals(userName)) {
return true;
}
}
}
return false;
}
/**
* 检查邮箱是否存在
* @param email
* @return
*/
public boolean checkEmailExists(String email){
FileDB<List<User>> fileDB = new FileDB<>(userFile);
List<User> userList = fileDB.getObjFromFile();
if(userList!=null) {
for (int i = 0; i < userList.size(); i++) {
if (userList.get(i).getEmail().equals(email)) {
return true;
}
}
}
return false;
}
/**
* 检查手机号是否存在
* @param phone
* @return
*/
public boolean checkPhoneExists(String phone){
FileDB<List<User>> fileDB = new FileDB<>(userFile);
List<User> userList = fileDB.getObjFromFile();
if(userList!=null) {
for (int i = 0; i < userList.size(); i++) {
if (userList.get(i).getPhone().equals(phone)) {
return true;
}
}
}
return false;
}
}
ADMIN
package entity;
import java.io.Serializable;
public class Admin implements Serializable {
private String name;//用户名
private String password;//密码
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
LoginService
package service;
import dao.UserDao;
import entity.User;
import main.Main;
import java.util.Scanner;
/**类名:登录类
* 作用:处理登录业务逻辑
*/
public class LoginService {
/**
* 检查用户名格式
* @param userName
* @return
*/
public boolean checkUserName(String userName){
if(userName!=null&&userName.trim().length()>=3&&userName.trim().length()<=10){
return true;
}else{
return false;
}
}
public void login() {
UserDao userDao = UserDao.getInstance();
// 键盘录入信息
System.out.println("登录");
System.out.println("------------------------");
System.out.println("请输入用户名与密码");
System.out.println("用户名长度限制3~10字符");
System.out.println("密码长度限制6~32字符");
System.out.println("------------------------");
Scanner sc = new Scanner(System.in);
String userName="";
String password="";
while (true) {
System.out.println("请输入用户名");
boolean flag = false;
userName = sc.nextLine();
// 判断用户名是否合规
flag=checkUserName(userName);
if (flag == false) {
System.out.println("用户名长度错误!");
} else {
System.out.println("请输入密码");
password = sc.nextLine();
User user = userDao.findUserByNameAndPassword(userName,password);
if(user!=null){
System.out.println("登录成功");
Main.isLogin=true;
Main.user = user;
break;
}else {
System.out.println("用户名密码校验失败,请重新输入用户名、密码");
}
}
}
}
}
RandomFourNumUtils
package util;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class RandomFourNumUtils {
/**
* 生成一个四位数,包括字母
* @return
*/
public static String getRandomFourNum() {
String[] beforeShuffle = new String[] { "2", "3", "4", "5", "6", "7",
"8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J",
"K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
"W", "X", "Y", "Z" };
List list = Arrays.asList(beforeShuffle);
Collections.shuffle(list);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < list.size(); i++) {
sb.append(list.get(i));
}
String afterShuffle = sb.toString();
String result = afterShuffle.substring(5, 9);
return result;
}
}