JavaSSM框架学完,手写一个汽车租赁系统,真NE!

适合人群

学完了SSM框架的相关知识,但是总感觉自己对于框架的使用和理解并不是很深刻,所以决定写一个项目来练习和提升自己对于框架的理解以及使用框架进行开发过程的理解

适合人群:

  1. 熟悉SSM框架,熟悉SSM框架开发流程
  2. 了解LayUI框架的基本知识
  3. 熟悉jQuery,jsp等技术

通过练习该项目,能够提升对于SSM框架的理解,了解项目的基本开发流程以及前后端数据的交互.

项目介绍

先看一下项目演示:

在这里插入图片描述

项目整体功能图

在这里插入图片描述

该项目是一个汽车租赁项目,登录成功后,能实现租车时的汽车出库和汽车入库,有客户管理,车辆管理,出租单管理,检查单管理等业务功能.也有客户管理,角色分配等系统功能,同时能实现对于客户,车辆,业绩的简单数据分析.

涉及的技术

  • Spring,SpirngMVC,MyBatis框架(SSM)
  • 前端LayUI框架,jsp,jQuery等技术
  • Quartz定时任务框架
  • log4j日志系统,druid数据源监控
  • echarts为数据分析提供技术支持
  • maven的使用
  • 简单的RBAC角色分配技术

数据库设计

一.业务表

1,客户表(bus_customers)

字段名 字段说明 类型 是否主键 备注
identity 身份证 varhcar
custname 姓名 Varchar
sex 性别 Int
address 地址 varchar
phone 电话 varchar
career 职位 varchar

2,车辆表(bus_cars)

字段名 字段说明 类型 是否主键 备注
carnumber 车牌号 varhcar
cartype 类型 varchar
color 颜色 varchar
price 购买价格 double
rentprice 出租价格 double
deposit 押金 double
isrenting 是否出租 int
description 描述 varchar
carimg 车辆图片 varchar

3,出租表(bus_rents)

字段名 字段说明 类型 是否主键 备注
rentid 出租单号 varhcar 后台使用时间生成
price 出租实际价格 double
begindate 开始时间 Datetime
returndate 还车时间 Datetime
rentflag 出租状态 int 0未归还1已归还
identity 客户身份证 varchar
carnumber 车牌号 varchar
opername 操作员 varchar 当前登陆人

4,还车表(bus_checks)

字段名 字段说明 类型 是否主键 备注
checkid 检查单号 varhcar 后台使用时间生成
checkdate 检查时间 datetime
checkdesc 描述 varchar
problem 存在问题 varchar
paymoney 赔付金额 double
opername 操作员 varchar 当前登陆人
rentid 出租单号 varchar

二,系统表(RBAC权限管理)

1.菜单表(sys_menus)

字段名 字段说明 类型 是否主键 备注
id ID Int
pid 父节点id Int
name 菜单名称 varchar
href 跳转地址 varchar
open 是否打开 Int 0不打1打开
parent 是否父节点 Int 0非父节点1父节点
target 打开方式 varchar
icon 节点图标 varchar
tabicon Tab图标 varchar img
available 是否可用 Int 0不可用1可用

2. 用户表(sys_users)

字段名 字段说明 类型 是否主键 备注
userid 用户编号 Int
loginname 登陆名 varchar
identity 身份证号 varchar
realname 真实名称 varchar
sex 性别 Int 0女1男
address 地址 varchar
phone 电话 varchar
pwd 密码 varchar
position 职位 varchar
type 用户类型 Int 1,超级管理员2,系统用户Where type<>1

3.角色表(sys_roles)

字段名 字段说明 类型 是否主键 备注
roleid 角色编号 Int
rolename 角色名称 varchar
roledesc 角色备注 varchar

4. 角色和菜单关系表(sys_role_menu)

字段名 字段说明 类型 是否主键 备注
rid 角色编号 Int 角色表的roleid外键
mid 菜单编号 Int 菜单表的id外键

5.用户和角色和关系表(sys_role_user)

字段名 字段说明 类型 是否主键 备注
uid 用户编号 Int 用户表的userid外键
rid 角色编号 Int 角色表的roleid外键

二,系统表(其它)

1.登陆日志表(sys_log_login)

字段名 字段说明 类型 是否主键 备注
id 日志ID Int
loginname 登陆名+真实姓名 varchar
loginip 登陆IP varchar
logintime 登陆时间 datetime

2. 系统公告表(sys_news)

字段名 字段说明 类型 是否主键 备注
id 编号 Int
title 标题 varchar
Content 内容 varchar
createtime 发布时间 datetime
opername 发布人 varchar

环境的搭建

  • 我使用的是IDEA的开发工具

个人感觉IDEA开发工具对于程序员比较友好,熟练的使用能够提高开发的效率

创建maven项目导入相关依赖的jar包创建对应的包

这部分比较基础,都是一些配置相关,详细的配置方法在我之前的博客文章中都有介绍,这里不赘述.

目录结构结合项目介绍

这里给出创建好的目录结构

image-20200714155711472

  • 将项目的包分为三个:分别是bus对应业务相关的包,sys对应系统功能相关,task对应数据分析相关.

合理的分包,程序不仅可读性强,开发也更高效

配置好开发环境:

  1. 创建项目

  2. 导入依赖

  3. 创建druid.properties

  4. 创建log4j.properties

  5. 创建spring-dao.xml

  6. 创建spring-service.xml

  7. 创建spring-context.xml

  8. 创建spring-mvc.xml

  9. 修改web.xml

  10. 创建file.properties

    文件上传下载的配置文件

    #file upload path config
    path=G:/upload/
    
  11. 创建AppListener

    过滤器

    package per.leiyu.sys.listener;
    
    import javax.servlet.ServletContext;
    import javax.servlet.ServletContextEvent;
    import javax.servlet.ServletContextListener;
    import javax.servlet.annotation.WebListener;
    
    @WebListener
    public class AppListener implements ServletContextListener{
    
    	@Override
    	public void contextDestroyed(ServletContextEvent arg0) {
    		
    	}
    
    	@Override
    	public void contextInitialized(ServletContextEvent arg0) {
    		//取到ServletContext
    		ServletContext context=arg0.getServletContext();
    		context.setAttribute("leiyujia", context.getContextPath());
    		System.err.println("---------Servlet容器创建成功 leiyujia被放到ServletContext作用域-------");
    	}
    
    }
    
    
  12. 创建RandomUtils

    产生随机数的工具类

    package per.leiyu.sys.utils;
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.Random;
    import java.util.UUID;
    
    /**
     * 随机工具类
     * @author leiyu
     */
    public class RandomUtils {
    
    	private static SimpleDateFormat sdf1=new SimpleDateFormat("yyyy-MM-dd");
    	private static SimpleDateFormat sdf2=new SimpleDateFormat("yyyyMMddHHmmssSSS");
    	private static SimpleDateFormat sdf3=new SimpleDateFormat("yyyyMMdd_HHmmss_SSS");
    	private static Random random=new Random();
    	
    	/**
    	 * 得到当前日期
    	 */
    	public static String getCurrentDateForString() {
    		return sdf1.format(new Date());
    	}
    
    	/**
    	 * 生成文件名使用时间+4位随机数
    	 * @param fileName 文件名称
    	 */
    	public static String createFileNameUseTime(String fileName) {
    		String fileSuffix=fileName.substring(fileName.lastIndexOf("."),fileName.length());
    		String time=sdf2.format(new Date());
    		Integer num=random.nextInt(9000)+1000;
    		return time+num+fileSuffix;
    	}
    
    	/**
    	 * 生成文件名使用时间+4位随机数
    	 * @param fileName 文件名称
    	 * @param suffix  临时文件的后缀
    	 */
    	public static String createFileNameUseTime(String fileName,String suffix) {
    		String fileSuffix=fileName.substring(fileName.lastIndexOf("."),fileName.length());
    		String time=sdf2.format(new Date());
    		Integer num=random.nextInt(9000)+1000;
    		return time+num+fileSuffix+suffix;
    	}
    	
    	/**
    	 * 生成文件名使用UUID
    	 * @param fileName 文件名称
    	 */
    	public static String createFileNameUseUUID(String fileName) {
    		String fileSuffix=fileName.substring(fileName.lastIndexOf("."),fileName.length());
    		return UUID.randomUUID().toString().replace("-", "").toUpperCase()+fileSuffix;
    	}
    
    	/**
    	 * 根据时间+五位随机数生成字符串
    	 * @param preffx
    	 * @return
    	 */
        public static String createRandomStringUseTime(String preffx) {
        	return preffx+"_"+sdf3.format(new Date())+"_"+(random.nextInt(90000)+10000);
        }
    }
    
    
  13. 创建WebUtils

    Web的工具类:

    1. 得到当前线程的请求对象
    2. 得到当前线程的响应对象
    3. 得到session对象
    4. 得到servletContext对象
    package per.leiyu.sys.utils;
    
    import org.springframework.web.context.request.RequestContextHolder;
    import org.springframework.web.context.request.ServletRequestAttributes;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    
    /**
     * web的工具类
     * @author leiyu
     */
    public class WebUtils {
    	
    	public static ServletRequestAttributes getServletRequestAttributes() {
    		return (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
    	}
    
    	/**
    	 * 得到当前线程的请求对象
    	 * @return
    	 */
    	public static HttpServletRequest getHttpServletRequest() {
    		return getServletRequestAttributes().getRequest();
    	}
    
    	/**
    	 * 得到当前线程的响应对象
    	 */
    	public static HttpServletResponse getHttpServletResponse() {
    		return getServletRequestAttributes().getResponse();
    	}
    	
    	/**
    	 * 得到session对象
    	 */
    	public static HttpSession getHttpSession() {
    		return getHttpServletRequest().getSession();
    	}
    	
    	/**
    	 * 得到servletContext对象
    	 */
    	public static String getServletContext() {
    		return getHttpServletRequest().getServletPath();
    	}
    }
    
    
  14. 创建AppFileUtils

    文件上传下载的工具类

    package per.leiyu.sys.utils;
    
    import org.apache.commons.io.FileUtils;
    import org.springframework.http.HttpHeaders;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.MediaType;
    import org.springframework.http.ResponseEntity;
    
    import javax.servlet.http.HttpServletResponse;
    import java.io.File;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.PrintWriter;
    import java.net.URLEncoder;
    import java.util.Properties;
    
    /**
     * 文件上传工具类
     * @author leiyu
     */
    public class AppFileUtils {
    	
    	/**
    	 * 得到文件上传的路径
    	 */
    	public static String PATH="G:/upload/";
    	static {
    		InputStream stream = AppFileUtils.class.getClassLoader().getResourceAsStream("file.properties");
    		Properties properties=new Properties();
    		try {
    			properties.load(stream);
    			PATH=properties.getProperty("path");
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    	}
    
    	/**
    	 * 文件下载
    	 * @param response
    	 * @param path
    	 * @param oldName
    	 * @return
    	 */
    	public static  ResponseEntity<Object> downloadFile(HttpServletResponse response, String path, String oldName) {
    		//4.使用绝对路径+相对路径去找到文件对象
    		File file=new File(AppFileUtils.PATH,path);
    		//5.判断文件是否存在
    		if(file.exists()) {
    			try {
    				try {
    					//如果名字有中文 要处理编码
    					oldName=URLEncoder.encode(oldName,"UTF-8");
    				} catch (Exception e) {
    					e.printStackTrace();
    				}
    				//把file转成一个bytes
    				byte[] bytes=FileUtils.readFileToByteArray(file);
    				HttpHeaders header=new HttpHeaders();
    				//封装响应内容类型(APPLICATION_OCTET_STREAM 响应的内容不限定)
    				header.setContentType(MediaType.APPLICATION_OCTET_STREAM);
    				//设置下载的文件的名称
    				header.setContentDispositionFormData("attachment",oldName);
    				//创建ResponseEntity对象
    				ResponseEntity<Object> entity = new ResponseEntity<Object>(bytes,header,HttpStatus.CREATED);
    				return entity;
    			} catch (Exception e) {
    				e.printStackTrace();
    			}
    			return null;
    		}else {
    			PrintWriter out;
    			try {
    				out = response.getWriter();
    				out.write("文件不存在");
    				out.flush();
    				out.close();
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    			return null;
    		}
    	}
    
    	/**
    	 * 根据相对路径删除硬盘上文件
    	 * @param path
    	 */
    	public static void deleteFileUsePath(String path) {
    		String realPath=PATH+path;
    		//根据文件
    		File file=new File(realPath);
    		if(file.exists()) {
    			file.delete();
    		}
    	}
    
    	/**
    	 * 更改文件名
    	 * @param carimg
    	 * @param suffix
    	 */
        public static String updateFileName(String carimg,String suffix) {
    		//找到文件
    		try{
    			File file = new File(PATH,carimg);
    			if (file.exists()){
    				file.renameTo(new File(PATH,carimg.replace(suffix,"")));
    				return carimg.replace(suffix,"");
    			}
    		}catch (Exception e){
    			e.printStackTrace();
    		}
    		return null;
    	}
    
    	/**
    	 * 根据路径删除图片
    	 * @param carimg
    	 */
    	public static void removeFileByPath(String carimg) {
    		//找到文件
    		try{
    			File file = new File(PATH,carimg);
    			if (file.exists()){
    				file.delete();
    			}
    		}catch (Exception e){
    			e.printStackTrace();
    		}
    	}
    }
    
    

这篇博客主要是数据库环境和java开发环境的搭建

下一篇博客开始详细开发流程的详细介绍.

你问为什么不把开发流程和项目环境搭建放在一起?

54918411_1502106113102

先理解SSM最基础的技术(当时我环境搭建也是搞了很久才搞明白(尤其是maven的依赖),可能是因为笨吧)

我是雷雨,一个普本科的学生,主要专注于Java后端和大数据开发

如果这篇文章有帮助到你,希望你给我一个大大的赞
如果有什么问题,希望你能留言和我一起研究,学习靠自觉,分享靠自愿

转载注明出处
https://blog.csdn.net/qq_40742223

PATH,carimg);
if (file.exists()){
file.delete();
}
}catch (Exception e){
e.printStackTrace();
}
}
}

```

不知不觉1w多字了,这篇博客主要是数据库环境和java开发环境的搭建.

下一篇博客开始详细开发流程的详细介绍.

你问为什么不把开发流程和项目环境搭建放在一起?
在这里插入图片描述
先理解SSM最基础的技术(当时我环境搭建也是搞了很久才搞明白(尤其是maven的依赖),可能是因为笨吧)

我是雷雨,一个普本科的学生,主要专注于Java后端和大数据开发

如果这篇文章有帮助到你,希望你给我一个的赞
如果有什么问题,希望你能评论区和我一起研究.

如果您要转载请转载注明出处
https://blog.csdn.net/qq_40742223

猜你喜欢

转载自blog.csdn.net/qq_40742223/article/details/107340680