1.包含源程序,数据库脚本。代码和数据库脚本都有详细注释。
2.课题设计仅供参考学习使用,可以在此基础上进行扩展完善
开发环境:
代码已经上传github,下载地址:https://github.com/21503882/airplane-ticket
Eclipse ,MYSQL,JDK1.8,Tomcat 7
涉及技术点:
MVC模式、SpringMvc、Mybatis、Spring、bootstrap、HTML、JavaScript、CSS、JQUERY、log4j、Ajax、maven等
系统采用Mybatis框架实现ORM对象关系映射,前台JSP实现,后台springMvc映射,使用Spring框架进行整合。适合学习J2EE的一段时间的熟手,代码思路清晰,注解详细,数据库用的是mysql5.1,服务器用的tomcat7,JDK版本1.8. 编程软件Eclispe J2EE版本。是典型MVC架构,并且前后台分离
主要功能界面:
下图分别为:
新会员注册——登录——预定飞机票——查看预定信息
会员中心:
后台管理员登录:
4.1.1系统功能模块的划分
根据航空公司的需要,系统应当包含基本的功能有:用户注册、用户登录和管理员登录,航班查看等。用户则划分为基本乘客和管理员两大类,管理员还兼具有管理职能。功能模块图如下:
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.StringWriter;
import java.nio.charset.Charset;
import java.sql.*;
import java.util.*;
import java.util.regex.Pattern;
/**
* mybatisgen generate core.
*
* @author bleedfly.
*/
public class MyBatisGenCore {
private static String dbLocation = "db.config";
/**
* 根据表名获取字段信息
*
* @param cn
* @param table
* @return
* @throws Exception
*/
public static List<Map<String, String>> getColInfoList(Connection cn, String table) throws Exception {
String sql = "select * from " + table + " where 1>2";
Statement stmt = null;
ResultSet rs = null;
try {
// 获取数据库元数据信息
DatabaseMetaData dbmd = cn.getMetaData();
ResultSet primaryKeys = dbmd.getPrimaryKeys(null, null, table);
String pks =getstrPimaryKeys(primaryKeys);
stmt = cn.createStatement();
rs = stmt.executeQuery(sql);
// 获取结果集元数据信息
ResultSetMetaData rsmd = rs.getMetaData();
int num = rsmd.getColumnCount();
Map<String, String> map;
List<Map<String, String>> list = new ArrayList<Map<String, String>>();
for (int i = 1; i <= num; i++) {
map = new HashMap<String, String>();
map.put(MyBatisGenConst.RSMD_COLUMN_NAME, rsmd.getColumnName(i));
map.put(MyBatisGenConst.RSMD_COLUMN_CLASS_NAME, rsmd.getColumnClassName(i));
map.put(MyBatisGenConst.RSMD_COLUMN_TYPE_NAME, rsmd.getColumnTypeName(i));
map.put(MyBatisGenConst.RSMD_COLUMN_PRECISION, rsmd.getPrecision(i) + "");
map.put(MyBatisGenConst.RSMD_COLUMN_SCALE, rsmd.getScale(i) + "");
list.add(map);
}
//主键串放入list
map = new HashedMap();
map.put(MyBatisGenConst.RSMD_COLUMN_PRIMARY_KEY,pks);
list.add(map);
return list;
} catch (Exception e) {
throw new Exception(e + ",table=" + table, e);
} finally {
try {
stmt.close();
} catch (Exception e2) {
e2.printStackTrace();
}
try {
rs.close();
} catch (Exception e2) {
e2.printStackTrace();
}
}
}
/**
* 获取列信息。
*
* @param table
* @return
* @throws Exception
*/
public static List<Map<String, String>> getColInfoList(String table) throws Exception {
Connection cn = getConnection();
try {
return getColInfoList(cn, table);
} finally {
try {
cn.close();
} catch (Exception e2) {
e2.printStackTrace();
}
}
}
/**
* 获取参数列表
*
* @param colInfoList
* @return
* @throws Exception
*/
public static List<Map<String, String>> makeParamList(List<Map<String, String>> colInfoList) throws Exception {
List<Map<String, String>> list = new ArrayList<Map<String, String>>();
Map<String, String> map;
int num = colInfoList.size();
Map<String, String> mapNew;
for (int i = 0; i < num; i++) {
map = colInfoList.get(i);
mapNew = new HashMap<String, String>();
String columnName = map.get(MyBatisGenConst.RSMD_COLUMN_NAME);
String columnClassName = map.get(MyBatisGenConst.RSMD_COLUMN_CLASS_NAME);
String columnTypeName = map.get(MyBatisGenConst.RSMD_COLUMN_TYPE_NAME);
String scaleStr = map.get(MyBatisGenConst.RSMD_COLUMN_SCALE);
int scale = NumberUtils.toInt(scaleStr);
String precisionStr = map.get(MyBatisGenConst.RSMD_COLUMN_PRECISION);
int precision = NumberUtils.toInt(precisionStr);
// mysql中的数据类型与java数据类型映射转换
String javaType = getJavaType(columnClassName, columnTypeName, scale, precision);
String jdbcType = getJdbcType(columnClassName, columnTypeName);
// 将有"_"的列名转换成java中的驼峰命名规则
String propName = getPropName(columnName);
// 生成java实体类中属性对应的getter和setter方法名
String setMethod = getSetMethod(propName);
String getMethod = getGetMethod(propName);
mapNew.put(MyBatisGenConst.VP_COLUMN_NAME, columnName.toLowerCase());
mapNew.put(MyBatisGenConst.VP_PROP_NAME, propName);
mapNew.put(MyBatisGenConst.VP_JAVA_TYPE, javaType);
mapNew.put(MyBatisGenConst.VP_JDBC_TYPE, jdbcType);
mapNew.put(MyBatisGenConst.VP_GET_METHOD, getMethod);
mapNew.put(MyBatisGenConst.VP_SET_METHOD, setMethod);
list.add(mapNew);
}
return list;
}
/**
* 获取字段的java类型
*
* @param columnClassName 字段类名
* @param columnTypeName 字段类型名称
* @param scale 精度 小数位数
* @return
*/
public static String getJavaType(String columnClassName, String columnTypeName, int scale, int precision) {
if (columnClassName.equals("java.sql.Timestamp")) {
return "Date";
}
if (columnClassName.equals("java.lang.String")) {
return "String";
}
if (columnTypeName.equals("DECIMAL") && scale < 1) {
return "Long";
}
if (columnTypeName.equals("DECIMAL") && scale > 0) {
return "java.math.BigDecimal";
}
if (columnTypeName.startsWith("BIGINT")) {
return "Long";
}
if (columnTypeName.startsWith("INT")) {
return "Integer";
}
if (columnTypeName.startsWith("TINYINT") && precision == 1) {
return "Boolean";
}
if (columnTypeName.startsWith("TINYINT") && precision != 1) {
return "Integer";
}
if (columnTypeName.startsWith("SMALLINT")) {
return "Integer";
}
return columnClassName;
}
/**
* 获取jdbc类型
*
* @param columnClassName 字段类名
* @param columnTypeName 字段类型名称
* @return
*/
public static String getJdbcType(String columnClassName, String columnTypeName) {
System.out.println(columnClassName+","+columnTypeName);
if (columnClassName.equals("java.lang.String")) {
return "VARCHAR";
}
if (columnClassName.startsWith("java.sql.")) {
return "TIMESTAMP";
}
if (columnTypeName.startsWith("NUMBER")) {
return "DECIMAL";
}
if (columnTypeName.startsWith("INT")) {
return "INTEGER";
}
return columnTypeName;
}
/**
* 根据表名获取java类型
*
* @param tableName 表名
* @return
*/
public static String getClassName(String tableName) {
String t = tableName.toLowerCase();
t = t.replace(MyBatisGenConst.TABLE_PREFIX, "");
String[] arr = t.split("_");
int num = arr.length;
StringBuilder s = new StringBuilder();
for (int i = 0; i < num; i++) {
s.append(StringUtils.capitalize(arr[i]));
}
return s.toString();
}
/**
* 根据字段名获取java数据对象属性名
*
* @param columnName 字段名
* @return
*/
public static String getPropName(String columnName) {
String t = columnName.toLowerCase();
String[] arr = t.split("_");
int num = arr.length;
StringBuilder s = new StringBuilder();
for (int i = 0; i < num; i++) {
if (i > 0) {
s.append(StringUtils.capitalize(arr[i]));// 首字母大写
} else {
s.append(arr[i]);
}
}
return s.toString();
}
public static String getSetMethod(String propName) {
return "set" + StringUtils.capitalize(propName);
}
public static String getGetMethod(String propName) {
return "get" + StringUtils.capitalize(propName);
}
public static String getColsStr(List<Map<String, String>> list) {
int num = list.size();
Map<String, String> map;
String colName;
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < num; i++) {
map = list.get(i);
colName = map.get(MyBatisGenConst.VP_COLUMN_NAME);
if (i > 0) {
stringBuilder.append(",");
}
stringBuilder.append(colName);
}
return stringBuilder.toString();
}
public static String getstrPimaryKeys(ResultSet primaryKeys) throws SQLException {
StringBuffer sb = new StringBuffer();
String pks;
while (primaryKeys.next()) {
sb.append(primaryKeys.getString(MyBatisGenConst.COLUMN_NAME)).append(",");
}
pks = sb.toString();
return StringUtils.isBlank(pks)?"":pks.substring(0,pks.length()-1);
}
/**
* velocity模板合并
*
* @param template 模板字符串 如 hello,${name}
* @param paramMap 参数
* @return
* @throws Exception
*/
public static String merge(String template, Map<String, Object> paramMap) throws Exception {
VelocityContext vc = new VelocityContext(paramMap);
StringWriter writer = new StringWriter();
Velocity.evaluate(vc, writer, "mybatis_code_gen", template);
return writer.getBuffer().toString();
}
/**
* 获取sqlmap 参数列表 去掉 主键 GMT_CREATE GMT_MODIFIED 字段
*
* @param paramList
* @param pks
* @return
* @throws Exception
*/
public static List<Map<String, String>> getSqlmapParamList(List<Map<String, String>> paramList, String pks) throws Exception {
List<Map<String, String>> list = new ArrayList<Map<String, String>>();
Map<String, String> tmp;
Map<String, String> map;
int num = paramList.size();
for (int i = 0; i < num; i++) {
tmp = paramList.get(i);
String columnName = tmp.get(MyBatisGenConst.VP_COLUMN_NAME);
if (columnName.equalsIgnoreCase(pks)) {
continue;
}
if (columnName.equalsIgnoreCase("GMT_CREATE")) {
continue;
}
if (columnName.equalsIgnoreCase("GMT_MODIFIED")) {
continue;
}
map = new HashMap<String, String>();
map.putAll(tmp);
list.add(map);
}
return list;
}
/**
* 根据表名生成java数据对象类文件和sqlmap文件
*
* @param table 表名
* @throws Exception
*/
public static void gen(String table) throws Exception {
//TODO 拿出pkList
// 先获取表结构信息,其中包含每个列的基本信息:如列名,类型,精度等信息,以map数据结构保存
List<Map<String, String>> colInfoList = getColInfoList(table);
// 拿到主键
String pks = colInfoList.remove(colInfoList.size() - 1).get(MyBatisGenConst.RSMD_COLUMN_PRIMARY_KEY);
// 将属性信息转换成java数据结构规则的形式
List<Map<String, String>> paramList = makeParamList(colInfoList);
boolean isSharding = Pattern.compile(MyBatisGenConst.SHARDING_SUFFIX_REG).matcher(table).find();
if (isSharding) {
// 去掉分库分表后面的表后缀,如_0001
table = table.replaceAll(MyBatisGenConst.SHARDING_SUFFIX_REG, "");
}
// 将"_"的表名转换成java中对应的实体类类型(首字母大写,驼峰命名)
String className = getClassName(table);
String doTemplate = FileUtils.readFileToString(new File(MyBatisGenConst.DO_TEMPLATE), Charset.forName("UTF-8"));
String queryTemplate = FileUtils.readFileToString(new File(MyBatisGenConst.QUERY_TEMPLATE), Charset.forName("UTF-8"));
String sqlmapTemplate = FileUtils.readFileToString(new File(MyBatisGenConst.SQLMAP_TEMPLATE), Charset.forName("UTF-8"));
String mapperTemplate = FileUtils.readFileToString(new File(MyBatisGenConst.MAPPER_TEMPLATE), Charset.forName("UTF-8"));
String managerTemplate = FileUtils.readFileToString(new File(MyBatisGenConst.MANAGER_TEMPLATE), Charset.forName("UTF-8"));
String managerImplTemplate = FileUtils.readFileToString(new File(MyBatisGenConst.MANAGER_IMPL_TEMPLATE), Charset.forName("UTF-8"));
String sqlmapExtTemplate = FileUtils.readFileToString(new File(MyBatisGenConst.SQLMAP_EXT_TEMPLATE), Charset.forName("UTF-8"));
String mapperExtTemplate = FileUtils.readFileToString(new File(MyBatisGenConst.MAPPER_EXT_TEMPLATE), Charset.forName("UTF-8"));
Map<String, Object> param = new HashMap<String, Object>();
param.put(MyBatisGenConst.VP_MAIN_PACKAGE, MyBatisGenConst.MAIN_PACKAGE);
param.put(MyBatisGenConst.VP_DO_PACKAGE, MyBatisGenConst.DO_PACKAGE);
param.put(MyBatisGenConst.VP_QUERY_PACKAGE, MyBatisGenConst.QUERY_PACKAGE);
param.put(MyBatisGenConst.VP_MAPPER_PACKAGE, MyBatisGenConst.MAPPER_PACKAGE);
param.put(MyBatisGenConst.VP_MANAGER_PACKAGE, MyBatisGenConst.MANAGER_PACKAGE);
param.put(MyBatisGenConst.VP_MANAGER_IMPL_PACKAGE, MyBatisGenConst.MANAGER_IMPL_PACKAGE);
param.put(MyBatisGenConst.VP_MAPPER_EXT_PACKAGE, MyBatisGenConst.MAPPER_EXT_PACKAGE);
param.put(MyBatisGenConst.VP_CLASS_NAME, className);
param.put(MyBatisGenConst.VP_MAPPER_PROPERTY_NAME, className.substring(0,1).toLowerCase()+className.substring(1)+MyBatisGenConst.MAPPER_EXT_SUFFIX);
param.put(MyBatisGenConst.VP_LIST, paramList);
param.put(MyBatisGenConst.VP_QUERY_PREFIX, MyBatisGenConst.QUERY_PREFIX);
param.put(MyBatisGenConst.VP_DO_SUFFIX, MyBatisGenConst.DO_SUFFIX);
param.put(MyBatisGenConst.VP_MAPPER_SUFFIX, MyBatisGenConst.MAPPER_SUFFIX);
param.put(MyBatisGenConst.VP_MANAGER_SUFFIX, MyBatisGenConst.MANAGER_SUFFIX);
param.put(MyBatisGenConst.VP_MANAGER_IMPL_SUFFIX, MyBatisGenConst.MANAGER_IMPL_SUFFIX);
param.put(MyBatisGenConst.VP_MAPPER_EXT_SUFFIX, MyBatisGenConst.MAPPER_EXT_SUFFIX);
String vpTableName = table.toLowerCase();
if (isSharding) {
vpTableName += "_$tabNum$";
}
param.put(MyBatisGenConst.VP_TABLE_NAME, vpTableName);
param.put(MyBatisGenConst.VP_SERIAL_VERSION_UID, "" + (long) (Math.random() * 1000000000000000000L));
param.put(MyBatisGenConst.VP_SERIAL_VERSION_UID2, "" + (long) (Math.random() * 1000000000000000000L));
// param的信息量好大~
String doResult = merge(doTemplate, param);
// 获取字段名不包含 id gmt_create gmt_modified TODO 去掉主键
List<Map<String, String>> sqlmapParamList = getSqlmapParamList(paramList,pks);
param.put(MyBatisGenConst.VP_LIST, sqlmapParamList);
String colsWithoutCommColumns = getColsStr(sqlmapParamList);
param.put(MyBatisGenConst.VP_COLS_WITHOUT_COMMON_COLUMNS, colsWithoutCommColumns);
String cols = pks+"," + MyBatisGenConst.COMMON_COLUMN_STR + colsWithoutCommColumns;
param.put(MyBatisGenConst.VP_COLS, cols);
//TODO 这样只支持 单个主键
param.put(MyBatisGenConst.VP_PRIMARY_KEY, pks);
param.put(MyBatisGenConst.VP_PROP_PRIMARY_KEY,getPropName(pks));
//TODO param添加主键
String sqlmapResult = merge(sqlmapTemplate, param);
String mapperResult = merge(mapperTemplate, param);
String managerResult = merge(managerTemplate, param);
String managerImplResult = merge(managerImplTemplate, param);
String queryResult = merge(queryTemplate, param);
String mapperExtResult = merge(mapperExtTemplate, param);
String sqlmapExtResult = merge(sqlmapExtTemplate, param);
String doOutFilePath = MyBatisGenConst.MAPPER_DO_DIR + "/" + className + MyBatisGenConst.DO_SUFFIX + ".java";
String queryOutFilePath = MyBatisGenConst.MAPPER_QUERY_DIR + "/" + className + MyBatisGenConst.QUERY_PREFIX + ".java";
String sqlmapOutFilePath = MyBatisGenConst.MAPPER_XML_DIR + "/" + className + MyBatisGenConst.MAPPER_SUFFIX + ".xml";
String mapperOutFilePath = MyBatisGenConst.MAPPER_JAVA_DIR + "/" + className + MyBatisGenConst.MAPPER_SUFFIX + ".java";
String managerOutFilePath = MyBatisGenConst.MANAGER_JAVA_DIR + "/" + className + MyBatisGenConst.MANAGER_SUFFIX + ".java";
String managerImplOutFilePath = MyBatisGenConst.MANAGER_IMPL_JAVA_DIR + "/" + className + MyBatisGenConst.MANAGER_IMPL_SUFFIX + ".java";
String sqlmapExtOutFilePath = MyBatisGenConst.MAPPER_EXT_XML_DIR + "/" + className + MyBatisGenConst.MAPPER_EXT_SUFFIX + ".xml";
String mapperExtOutFilePath = MyBatisGenConst.MAPPER_EXT_JAVA_DIR + "/" + className + MyBatisGenConst.MAPPER_EXT_SUFFIX + ".java";
boolean success = new File(MyBatisGenConst.MAPPER_DO_DIR).mkdirs();
if (!success) {
System.out.println(String.format("mkdir %s error", MyBatisGenConst.MAPPER_DO_DIR));
}
success = new File(MyBatisGenConst.MAPPER_QUERY_DIR).mkdirs();
if (!success) {
System.out.println(String.format("mkdir %s error", MyBatisGenConst.MAPPER_QUERY_DIR));
}
success = new File(MyBatisGenConst.MANAGER_JAVA_DIR).mkdirs();
if (!success) {
System.out.println(String.format("mkdir %s error", MyBatisGenConst.MANAGER_JAVA_DIR));
}
success = new File(MyBatisGenConst.MANAGER_IMPL_JAVA_DIR).mkdirs();
if (!success) {
System.out.println(String.format("mkdir %s error", MyBatisGenConst.MANAGER_IMPL_JAVA_DIR));
}
success = new File(MyBatisGenConst.MAPPER_XML_DIR).mkdirs();
if (!success) {
System.out.println(String.format("mkdir %s error", MyBatisGenConst.MAPPER_XML_DIR));
}
success = new File(MyBatisGenConst.MAPPER_JAVA_DIR).mkdirs();
if (!success) {
System.out.println(String.format("mkdir %s error", MyBatisGenConst.MAPPER_JAVA_DIR));
}
success = new File(MyBatisGenConst.MAPPER_EXT_XML_DIR).mkdirs();
if (!success) {
System.out.println(String.format("mkdir %s error", MyBatisGenConst.MAPPER_EXT_XML_DIR));
}
success = new File(MyBatisGenConst.MAPPER_EXT_JAVA_DIR).mkdirs();
if (!success) {
System.out.println(String.format("mkdir %s error", MyBatisGenConst.MAPPER_EXT_JAVA_DIR));
}
File sqlmapOutFile = new File(sqlmapOutFilePath);
if (!sqlmapOutFile.exists()) {
success = sqlmapOutFile.createNewFile();
if (!success) {
System.out.println(String.format("createNewFile %s error", sqlmapOutFilePath));
}
}
File doOutFile = new File(doOutFilePath);
if (!doOutFile.exists()) {
success = doOutFile.createNewFile();
if (!success) {
System.out.println(String.format("createNewFile %s error", doOutFilePath));
}
}
File mapperOutFile = new File(mapperOutFilePath);
if (!mapperOutFile.exists()) {
success = mapperOutFile.createNewFile();
if (!success) {
System.out.println(String.format("createNewFile %s error", mapperOutFilePath));
}
}
File queryOutFile = new File(queryOutFilePath);
if (!queryOutFile.exists()) {
success = queryOutFile.createNewFile();
if (!success) {
System.out.println(String.format("createNewFile %s error", queryOutFilePath));
}
}
FileUtils.writeStringToFile(sqlmapOutFile, sqlmapResult, Charset.forName("UTF-8"));
FileUtils.writeStringToFile(doOutFile, doResult, Charset.forName("UTF-8"));
FileUtils.writeStringToFile(queryOutFile, queryResult, Charset.forName("UTF-8"));
FileUtils.writeStringToFile(mapperOutFile, mapperResult, Charset.forName("UTF-8"));
File mapperExtOutFile = new File(mapperExtOutFilePath);
if (!mapperExtOutFile.exists()) {
try{
mapperExtOutFile.createNewFile();
}catch (IOException e){
System.out.print("create file error");
}
FileUtils.writeStringToFile(mapperExtOutFile, mapperExtResult, Charset.forName("UTF-8"));
}
File sqlmapExtOutFile = new File(sqlmapExtOutFilePath);
if (!sqlmapExtOutFile.exists()) {
boolean created = sqlmapExtOutFile.createNewFile();
if(created){
FileUtils.writeStringToFile(sqlmapExtOutFile, sqlmapExtResult, Charset.forName("UTF-8"));
}
}
File managerOutFile = new File(managerOutFilePath);
if (!managerOutFile.exists()) {
success = managerOutFile.createNewFile();
if (!success) {
System.out.println(String.format("createNewFile %s error", managerOutFilePath));
}else{
FileUtils.writeStringToFile(managerOutFile, managerResult, Charset.forName("UTF-8"));
}
}
File managerImplOutFile = new File(managerImplOutFilePath);
if (!managerImplOutFile.exists()) {
success = managerImplOutFile.createNewFile();
if (!success) {
System.out.println(String.format("createNewFile %s error", managerImplOutFilePath));
}else{
FileUtils.writeStringToFile(managerImplOutFile, managerImplResult, Charset.forName("UTF-8"));
}
}
}
/**
* 获取数据库连接
*
* @return
* @throws ClassNotFoundException
* @throws SQLException
* @throws FileNotFoundException
* @throws IOException
*/
private static Connection getConnection() throws ClassNotFoundException, SQLException,
IOException {
Properties prop = new Properties();
prop.load(ClassLoader.getSystemResourceAsStream(dbLocation));
Class.forName(prop.getProperty("driver"));
String url = prop.getProperty("url");
String user = prop.getProperty("user");
String psw = prop.getProperty("pwd");
return DriverManager.getConnection(url, user, psw);
}
/**
* 批量生成java数据对象类文件和sqlmap文件
*
* @param tables 表 多个表用逗号分隔 table1,table2,table3
* @throws Exception
*/
public static void batchGen(List<String> tables, String location) throws Exception {
dbLocation = location;
System.out.println("table numbers: " + tables.size());
Connection cn = getConnection();
try {
for (String table : tables) {
MyBatisGenCore.gen(table.trim());
System.out.println(table.trim() + " done");
}
} finally {
try {
cn.close();
} catch (Exception e) {
}
}
}
}
代码已经上传github,下载地址:https://github.com/21503882/airplane-ticket