本項目是一個整合 SpringMVC+Spring+MyBatis(SSM) 框架的 Demo。提供視頻部署教程
擁有高效率便捷開發(fā)模式,使開發(fā)人員更專注于業(yè)務(wù),達(dá)到面向業(yè)務(wù)開發(fā)。
項目使用 Maven 構(gòu)建,便于項目管理,支持 Oracle、MySql 等主流數(shù)據(jù)庫。
前端展示界面采用基于 Boostrap 實現(xiàn)的響應(yīng)式布局,并集成了一系列的動畫效果插件,整體界面簡潔、美觀大方并可優(yōu)雅的與后臺完成交互操作。
項目封裝了一系列常用方法、部署運(yùn)行簡單,便于個人或企業(yè)進(jìn)行高效開發(fā)。
項目已提交至Github請前往https://github.com/micyo202/yan-demo查看詳情。
-
附:為了方便大家更好的學(xué)習(xí),特別提供了該項目的部署教程視頻,請前往http://v.youku.com/v_show/id_XMzI2MDg4Njk4NA==.html?spm=a2h3j.8428770.3416059.1進(jìn)行觀看,更多詳細(xì)配置說明還請參考本文檔中 ------ 六、配置說明(Properties)
一、項目開發(fā)環(huán)境&工具(Environment&Tools)
- MacOS Sierra / Windows 7
- MySql 5.7
- JDK 1.8
- CentOS 7
- IntelliJ IDEA 2017.2.5 / Eclipse 4.6.1
- Navicat Premium 11.1.12
- Maven 3.3.9
- Jetty 9.4.6.v20170531 / Tomcat 9.0
二、Maven配置(pom.xml)
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.yan</groupId>
<artifactId>yan_demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>yan_demo</name>
<description>基于 SpringMVC+Spring+Mybatis 開發(fā)的 Yan Frame Demo.</description>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.framework.version>4.3.11.RELEASE</spring.framework.version>
<aspectj.version>1.8.10</aspectj.version>
<shiro.version>1.4.0</shiro.version>
<jackson.version>2.9.1</jackson.version>
<logback.version>1.2.3</logback.version>
</properties>
<dependencies>
<!-- 添加 junit 依賴包 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- 添加 commons 依賴包 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.6</version>
</dependency>
<!-- 添加 spring 依賴包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.framework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.framework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.framework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.framework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.framework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.framework.version}</version>
<scope>test</scope>
</dependency>
<!-- 添加 aspectJ 依賴包 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
<!-- 添加 shiro 依賴包 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-quartz</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>${shiro.version}</version>
</dependency>
<!-- 添加 mybatis 依賴包 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
<!-- 添加 mybatis 分頁插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.1</version>
</dependency>
<!-- 添加 druid 依賴包 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.3</version>
</dependency>
<!-- 添加 mysql 驅(qū)動 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.44</version>
</dependency>
<!-- 添加 jackson 依賴包 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<!-- 添加 servlet 依賴包 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<!-- 添加 jstl 依賴包 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- 添加 log 依賴包 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
<!-- 添加 dom4j 依賴包(用于解析 xml)-->
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 添加 jetty 插件(命令運(yùn)行方式:進(jìn)入工程目錄執(zhí)行:mvn jetty:run 啟動服務(wù)) -->
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.4.6.v20170531</version>
<configuration>
<!-- 指定監(jiān)控的掃描時間間隔,0為關(guān)閉jetty自身的熱部署 -->
<scanIntervalSeconds>0</scanIntervalSeconds>
<webAppConfig>
<contextPath>/yan_demo</contextPath>
</webAppConfig>
<httpConnector>
<port>8888</port>
</httpConnector>
</configuration>
</plugin>
<!-- 添加 mybatis-generator 插件(命令運(yùn)行方式:進(jìn)入工程目錄執(zhí)行:mvn mybatis-generator:generate 生成代碼) -->
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.5</version>
</plugin>
</plugins>
</build>
</project>
三、項目結(jié)構(gòu)(Construction)
- com.yan.common:通用功能模塊(包含:用戶登錄、菜單、后臺管理等...)
- com.yan.core:框架核心模塊(包括基礎(chǔ)的控制器、過濾器、攔截器、類加載器、注入器、注解、以及框架封裝的核心方法部分)
- com.yan.demo:業(yè)務(wù)模塊(根據(jù)實際項目名稱換掉demo名稱,所有業(yè)務(wù)模塊均在該路徑下)
- com.yan.**.controller:控制器路徑,存放自己編寫業(yè)務(wù)處理的控制器(繼承BaseController)
- com.yan.**.mapper:持久層映射接口類路徑(mbg生成mybatis對應(yīng)的Mapper映射接口類)
- com.yan.**.model:模型類路徑(mbg生成的模型以及自定義模型)
- com.yan.junit:單元測試模塊(便于撰寫單元測試代碼)
- resources/database:數(shù)據(jù)庫sql文件(數(shù)據(jù)庫表結(jié)構(gòu)的*.sql文件,包含Yan Frame框架所需的基本系統(tǒng)數(shù)據(jù)表,如:用戶表、權(quán)限表、菜單表等...)
- resources/mybatis:mapper映射文件(所有mybatis的sql模板*.xml文件)
- resources/properties:配置文件(如:系統(tǒng)基本配置、數(shù)據(jù)庫配置、日志配置、MyBatis generator配置)
- resources/spring:spring的配置文件(命名規(guī)范:spring-*.xml)
- webapp/common:公共路徑(前臺框架的通用*.jsp頭文件,頁面僅需引入這里面對應(yīng)的jsp即可)
- webapp/resources:靜態(tài)資源路徑(包含了js、css、images、doc、plugins等)
- webapp/views:視圖路徑(所有業(yè)務(wù)功能的*.jsp頁面)
四、常用方法(Methods)
方法均在繼承于BaseController的類中使用this.metodName;進(jìn)行調(diào)用(其中methodName代表需要調(diào)用的方法名稱)
| 方法名 | 參數(shù) | 返回值 | 描述 |
|---|---|---|---|
| getSession | 無 | HttpSession 服務(wù)器會話 | 獲取服務(wù)器會話 session 對象 |
| setSession | session 服務(wù)器會話 | 無 | 設(shè)置服務(wù)器會話 session 對象 |
| getRequest | 無 | HttpServletRequest 用戶請求 | 獲取用戶請求 request 對象 |
| setRequest | request 用戶請求 | 無 | 設(shè)置用戶請求 request 對象 |
| getResponse | 無 | HttpServletResponse 服務(wù)器響應(yīng)結(jié)果 | 獲取服務(wù)器響應(yīng)結(jié)果 response 對象 |
| setResponse | response 服務(wù)器響應(yīng)結(jié)果 | 無 | 設(shè)置服務(wù)器響應(yīng)結(jié)果 response 對象 |
| getSessionUser | 無 | TbSysUser 用戶對象 | 獲取登錄成功后 session 中的存儲的用戶信息 |
| getMapper | type 生成的 Mapper 接口對象類型 | T 泛型,傳入?yún)?shù)對象的類型Mapper | 獲取 mapper 對象 |
| getMapper | 無 | DelegateMapper 通用 mapper,查看自定義 sqlMap 的代理 mapper 對象 | 獲取 delegateMapper 對象 |
| setDataSource | dataSource 數(shù)據(jù)源名稱(必須是spring配置中包含的名稱) | 無 | 動態(tài)切換數(shù)據(jù)源方法,設(shè)置數(shù)據(jù)源名稱 |
| clearDataSource | 無 | 無 | 清除數(shù)據(jù)源,在切換完數(shù)據(jù)源后,進(jìn)行清理,將數(shù)據(jù)源還原為默認(rèn)數(shù)據(jù)源 |
| offsetPage | offset 起始數(shù)量;limit 限制條數(shù) | 無 | 分頁查詢范圍,參數(shù)均由 bootstrapTable 分頁插件進(jìn)行傳入,無需人工控制,只需調(diào)用方法即可 |
| resultPage | list 查詢到的分頁結(jié)果,為 Page 對象 | PageModel<T> 自定義的分頁模型,T 為查詢的對象 | 分頁結(jié)果集對象 |
| resultMsg | status 狀態(tài)值(可根據(jù)需求任意設(shè)置,無強(qiáng)制標(biāo)準(zhǔn));msg 消息內(nèi)容;res 返回的對象 | MsgModel 自定義消息模型 | 消息返回對象 |
| fileUpLoad | request 上傳方法中傳遞的 request 對象,并非父類中的 request 對象 | List<String> 上傳文件成功后的新文件名稱,以集合形式返回 | 文件上傳方法,支持多個文件上傳 |
| fileDownLoad | fileName 需要下載的文件名稱 | ResponseEntity<byte[]> 下載的文件,在瀏覽器會進(jìn)行下載 | 文件下載方法 |
| isNull | obj 需要進(jìn)行判斷的對象 | boolean 為null或空返回 true,否則返回 false | 判斷對象是否為null,或空 |
| obj2Str | obj 需要轉(zhuǎn)換的對象 | String 對象的值(為null則返回"") | 對象轉(zhuǎn)換為 String,通常用于獲取 Map 集合中的對象時使用 |
| getUUID | 無 | String 32位主鍵字符串 | 生成 uuid 主鍵,長度為32位,且為大寫模式 |
| base64Encoder | str 需要進(jìn)行編碼的字符串 | String 進(jìn)行編碼后的結(jié)果字符串 | 對字符串進(jìn)行 base64 編碼 |
| base64Decoder | str 已進(jìn)行 base64 編碼的編碼字符串 | String 解碼后的原字符串 | 對字符串進(jìn)行 base64 解碼 |
| md5 | str 需要進(jìn)行 md5 加密的字符串 | String 加密后的結(jié)果 | 對字符串進(jìn)行 md5 加密算法 |
| currentDate | pattern 獲取系統(tǒng)時間的格式,如:yyyy-MM-dd HH:mm:ss | String 返回格式化后的當(dāng)前時間 | 獲取系統(tǒng)當(dāng)前時間 |
| timeStamp2Date | timestamp 需要進(jìn)行轉(zhuǎn)換的時間戳;pattern 轉(zhuǎn)換后的格式 | String 格式化后的日期 | 時間戳轉(zhuǎn)換成日期 |
| date2TimeStamp | dateStr 需要進(jìn)行轉(zhuǎn)換的日期字符串;pattern 日期的格式 | String 轉(zhuǎn)換后的時間戳 | 日期轉(zhuǎn)換為時間戳 |
| readFromFile | filePath 文件路徑(絕對路徑) | String 讀取的文件內(nèi)容 | 從指定文件中讀取文件內(nèi)容 |
| writeToFile | content 需要寫入文件中的內(nèi)容 | filePath 文件路徑(絕對路徑) | 將內(nèi)容寫入到指定文件中(寫入會覆蓋文件原有內(nèi)容,建議先讀取,再寫入,將讀取的內(nèi)容與需要寫入的內(nèi)容并在一起進(jìn)行寫入) |
| generatePath | path 文件夾路徑(絕對路徑) | 無 | 生成指定路徑文件夾,先進(jìn)行判斷文件夾是否存在,若不存在則創(chuàng)建對應(yīng)目錄的文件夾,若存在則不進(jìn)行任何操作 |
| generateFile | path 文件路徑(絕對路徑) | 無 | 生成指定路徑的文件,先進(jìn)行判斷文件是否存在,若不存在則進(jìn)行創(chuàng)建文件,若存在則不進(jìn)行任何操作 |
| propertiesValue | key 資源文件中的 key 值 | String 讀取到的 key 對應(yīng)的 value 值 | 讀取 properties 文件中的值,讀取 classpath 下 /properties/config.properties 配置文件 |
| propertiesValue | resource 資源文件路徑(對應(yīng) classpath 中的路徑);key 資源文件中的 key 值 | String 讀取到的 key 對應(yīng)的 value 值 | 讀取指定路徑 properties 文件中的值,會從 classpath 路徑下進(jìn)行查找資源文件 |
五、示例代碼(Codes)
創(chuàng)建一個繼承與BaseController的控制器
@Controller
public class XxxController extends BaseController {
...
}
獲取日志日志記錄Logger對象
// 使用注解獲取
@LogInject
private static Logger log;
// 使用工廠方法獲取
private static Logger log = LoggerFactory.getLogger(XxxController.class);
獲取mapper對象
// 注解方式獲取delegateMapper
@MapperInject
private DelegateMapper delegateMapper;
// 注解方式獲取對象對應(yīng)的mapper
@MapperInject(XxxMapper.class)
private XxxMapper mapper;
// 獲取delegateMapper
this.getMapper();
// 獲取對象對應(yīng)的mapper
this.getMapper(XxxMapper.class);
動態(tài)切換數(shù)據(jù)源
// 注解切換數(shù)據(jù)源,默認(rèn)切換擴(kuò)展數(shù)據(jù)源
@DynamicDataSource
public String init(){
...
}
// 注解切換數(shù)據(jù)源,傳入ENUM類型的數(shù)據(jù)源名稱
@DynamicDataSource(DataSourceName.EXTEND)
public String init(){
...
}
// 調(diào)用父類方法執(zhí)行切換數(shù)據(jù)源(參數(shù)名稱建議使用框架中已經(jīng)定義好的,DataSourceName.DEFAULT/EXTEND.getName())
this.setDataSource("extendDataSource");
...
this.clearDataSource();
分頁查詢后臺代碼
@RequestMapping("/list")
@ResponseBody
public PageModel<Xxx> list(int offset, int limit) {
// 調(diào)用父類方法傳入分頁參數(shù)
this.offsetPage(offset, limit);
List<Xxx> list = mapper.selectByExample(null); // 調(diào)用查詢方法
return this.resultPage(list);
}
分頁查詢前臺代碼
<table id="table"><table>
$('#table').bsTable({
url: '${pageContext.request.contextPath}/xxx/list',
idField: 'id',
columns: [
{field: 'state', checkbox: true},
{field: 'id', title: 'id', align: 'center'},
...
]
});
文件上傳
@RequestMapping("/upload")
public String upload(HttpServletRequest request) {
// 調(diào)用父類的上傳方法,在jsp中必須指定form為enctype="multipart/form-data"
List<String> fileNames = this.fileUpLoad(request);
return "success";
}
文件下載(在jsp頁面使用通用的下載方法,使用restful風(fēng)格)
<a href="${pageContext.request.contextPath}/文件名稱/download">文件下載</a>
自定義文件下載后臺方法
@RequestMapping("/download")
public ResponseEntity<byte[]> download(String fileName) {
// 調(diào)用父類文件下載方法
return this.fileDownLoad(fileName);
}
常用DelegateMapper及對象Mapper方法
// 使用自定義sql模板查詢單個對象
Demo demo = delegateMapper.selectOne(statement);
Demo demo = delegateMapper.selectOne(statement, parameter);
// 使用自定義sql模板查詢對象集合
List<Demo> list = delegateMapper.selectList(statement);
List<Demo> list = delegateMapper.selectList(statement, parameter);
// 使用自定義sql模板有范圍的查詢,(每次返回指定的對象條數(shù)集合)
List<Demo> list = delegateMapper.selectList(statement, parameter, rowBounds);
// 使用自定義sql模板進(jìn)行分頁查詢
PageModel<Demo> page = delegateMapper.selectPagination(statement, offset, limit);
PageModel<Demo> page = delegateMapper.selectPagination(statement, parameter, offset, limit);
// 使用自定義sql模板保存
int res = delegateMapper.insert(statement);
int res = delegateMapper.insert(statement, parameter);
// 使用自定義sql模板修改
int res = delegateMapper.update(statement);
int res = delegateMapper.update(statement, parameter);
// 使用自定義sql模板刪除
int res = delegateMapper.delete(statement);
int res = delegateMapper.delete(statement, parameter);
// 使用對象方法根據(jù)主鍵查詢
Demo demo = mapper.selectByPrimaryKey(id);
// 使用對象方法根據(jù)criteria查詢
List<Demo> list = mapper.selectByExample(example);
// 使用對象方法根據(jù)criteria分頁查詢
this.offsetPage(offset, limit);
List<Demo> list = mapper.selectByExample(example);
this.resultPage(list); // 返回的結(jié)果集
// 使用對象方法添加
int res = mapper.insert(record);
int res = mapper.insertSelective(record);
// 使用對象方法根據(jù)主鍵修改
int res = mapper.updateByPrimaryKey(record);
int res = mapper.updateByPrimaryKeySelective(record);
// 使用對象方法根據(jù)criteria修改
int res = mapper.updateByExample(record, example);
int res = mapper.updateByExampleSelective(record, example);
// 使用對象方法根據(jù)主鍵刪除
int res = mapper.deleteByPrimaryKey(productCode);
// 使用對象方法刪除根據(jù)criteria刪除
int res = mapper.deleteByExample(example);
更多方法使用請參考項目中API文檔或demo模塊下的代碼
六、效果預(yù)覽(Preview)

login

web

mobile