使用Maven构建 基于SpringMVC+Spring+Myb
2017-09-20 本文已影响2219人
槿灬
本项目是一个整合 SpringMVC+Spring+MyBatis(SSM) 框架的 Demo。提供视频部署教程
拥有高效率便捷开发模式,使开发人员更专注于业务,达到面向业务开发。
项目使用 Maven 构建,便于项目管理,支持 Oracle、MySql 等主流数据库。
前端展示界面采用基于 Boostrap 实现的响应式布局,并集成了一系列的动画效果插件,整体界面简洁、美观大方并可优雅的与后台完成交互操作。
项目封装了一系列常用方法、部署运行简单,便于个人或企业进行高效开发。
项目已提交至Github请前往https://github.com/micyo202/yan-demo查看详情。
-
附:为了方便大家更好的学习,特别提供了该项目的部署教程视频,请前往http://v.youku.com/v_show/id_XMzI2MDg4Njk4NA==.html?spm=a2h3j.8428770.3416059.1进行观看,更多详细配置说明还请参考本文档中 ------ 六、配置说明(Properties)
一、项目开发环境&工具(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 开发的 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 驱动 -->
<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 插件(命令运行方式:进入工程目录执行:mvn jetty:run 启动服务) -->
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.4.6.v20170531</version>
<configuration>
<!-- 指定监控的扫描时间间隔,0为关闭jetty自身的热部署 -->
<scanIntervalSeconds>0</scanIntervalSeconds>
<webAppConfig>
<contextPath>/yan_demo</contextPath>
</webAppConfig>
<httpConnector>
<port>8888</port>
</httpConnector>
</configuration>
</plugin>
<!-- 添加 mybatis-generator 插件(命令运行方式:进入工程目录执行: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>
三、项目结构(Construction)
- com.yan.common:通用功能模块(包含:用户登录、菜单、后台管理等...)
- com.yan.core:框架核心模块(包括基础的控制器、过滤器、拦截器、类加载器、注入器、注解、以及框架封装的核心方法部分)
- com.yan.demo:业务模块(根据实际项目名称换掉demo名称,所有业务模块均在该路径下)
- com.yan.**.controller:控制器路径,存放自己编写业务处理的控制器(继承BaseController)
- com.yan.**.mapper:持久层映射接口类路径(mbg生成mybatis对应的Mapper映射接口类)
- com.yan.**.model:模型类路径(mbg生成的模型以及自定义模型)
- com.yan.junit:单元测试模块(便于撰写单元测试代码)
- resources/database:数据库sql文件(数据库表结构的*.sql文件,包含Yan Frame框架所需的基本系统数据表,如:用户表、权限表、菜单表等...)
- resources/mybatis:mapper映射文件(所有mybatis的sql模板*.xml文件)
- resources/properties:配置文件(如:系统基本配置、数据库配置、日志配置、MyBatis generator配置)
- resources/spring:spring的配置文件(命名规范:spring-*.xml)
- webapp/common:公共路径(前台框架的通用*.jsp头文件,页面仅需引入这里面对应的jsp即可)
- webapp/resources:静态资源路径(包含了js、css、images、doc、plugins等)
- webapp/views:视图路径(所有业务功能的*.jsp页面)
四、常用方法(Methods)
方法均在继承于BaseController的类中使用this.metodName;进行调用(其中methodName代表需要调用的方法名称)
方法名 | 参数 | 返回值 | 描述 |
---|---|---|---|
getSession | 无 | HttpSession 服务器会话 | 获取服务器会话 session 对象 |
setSession | session 服务器会话 | 无 | 设置服务器会话 session 对象 |
getRequest | 无 | HttpServletRequest 用户请求 | 获取用户请求 request 对象 |
setRequest | request 用户请求 | 无 | 设置用户请求 request 对象 |
getResponse | 无 | HttpServletResponse 服务器响应结果 | 获取服务器响应结果 response 对象 |
setResponse | response 服务器响应结果 | 无 | 设置服务器响应结果 response 对象 |
getSessionUser | 无 | TbSysUser 用户对象 | 获取登录成功后 session 中的存储的用户信息 |
getMapper | type 生成的 Mapper 接口对象类型 | T 泛型,传入参数对象的类型Mapper | 获取 mapper 对象 |
getMapper | 无 | DelegateMapper 通用 mapper,查看自定义 sqlMap 的代理 mapper 对象 | 获取 delegateMapper 对象 |
setDataSource | dataSource 数据源名称(必须是spring配置中包含的名称) | 无 | 动态切换数据源方法,设置数据源名称 |
clearDataSource | 无 | 无 | 清除数据源,在切换完数据源后,进行清理,将数据源还原为默认数据源 |
offsetPage | offset 起始数量;limit 限制条数 | 无 | 分页查询范围,参数均由 bootstrapTable 分页插件进行传入,无需人工控制,只需调用方法即可 |
resultPage | list 查询到的分页结果,为 Page 对象 | PageModel<T> 自定义的分页模型,T 为查询的对象 | 分页结果集对象 |
resultMsg | status 状态值(可根据需求任意设置,无强制标准);msg 消息内容;res 返回的对象 | MsgModel 自定义消息模型 | 消息返回对象 |
fileUpLoad | request 上传方法中传递的 request 对象,并非父类中的 request 对象 | List<String> 上传文件成功后的新文件名称,以集合形式返回 | 文件上传方法,支持多个文件上传 |
fileDownLoad | fileName 需要下载的文件名称 | ResponseEntity<byte[]> 下载的文件,在浏览器会进行下载 | 文件下载方法 |
isNull | obj 需要进行判断的对象 | boolean 为null或空返回 true,否则返回 false | 判断对象是否为null,或空 |
obj2Str | obj 需要转换的对象 | String 对象的值(为null则返回"") | 对象转换为 String,通常用于获取 Map 集合中的对象时使用 |
getUUID | 无 | String 32位主键字符串 | 生成 uuid 主键,长度为32位,且为大写模式 |
base64Encoder | str 需要进行编码的字符串 | String 进行编码后的结果字符串 | 对字符串进行 base64 编码 |
base64Decoder | str 已进行 base64 编码的编码字符串 | String 解码后的原字符串 | 对字符串进行 base64 解码 |
md5 | str 需要进行 md5 加密的字符串 | String 加密后的结果 | 对字符串进行 md5 加密算法 |
currentDate | pattern 获取系统时间的格式,如:yyyy-MM-dd HH:mm:ss | String 返回格式化后的当前时间 | 获取系统当前时间 |
timeStamp2Date | timestamp 需要进行转换的时间戳;pattern 转换后的格式 | String 格式化后的日期 | 时间戳转换成日期 |
date2TimeStamp | dateStr 需要进行转换的日期字符串;pattern 日期的格式 | String 转换后的时间戳 | 日期转换为时间戳 |
readFromFile | filePath 文件路径(绝对路径) | String 读取的文件内容 | 从指定文件中读取文件内容 |
writeToFile | content 需要写入文件中的内容 | filePath 文件路径(绝对路径) | 将内容写入到指定文件中(写入会覆盖文件原有内容,建议先读取,再写入,将读取的内容与需要写入的内容并在一起进行写入) |
generatePath | path 文件夹路径(绝对路径) | 无 | 生成指定路径文件夹,先进行判断文件夹是否存在,若不存在则创建对应目录的文件夹,若存在则不进行任何操作 |
generateFile | path 文件路径(绝对路径) | 无 | 生成指定路径的文件,先进行判断文件是否存在,若不存在则进行创建文件,若存在则不进行任何操作 |
propertiesValue | key 资源文件中的 key 值 | String 读取到的 key 对应的 value 值 | 读取 properties 文件中的值,读取 classpath 下 /properties/config.properties 配置文件 |
propertiesValue | resource 资源文件路径(对应 classpath 中的路径);key 资源文件中的 key 值 | String 读取到的 key 对应的 value 值 | 读取指定路径 properties 文件中的值,会从 classpath 路径下进行查找资源文件 |
五、示例代码(Codes)
创建一个继承与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;
// 注解方式获取对象对应的mapper
@MapperInject(XxxMapper.class)
private XxxMapper mapper;
// 获取delegateMapper
this.getMapper();
// 获取对象对应的mapper
this.getMapper(XxxMapper.class);
动态切换数据源
// 注解切换数据源,默认切换扩展数据源
@DynamicDataSource
public String init(){
...
}
// 注解切换数据源,传入ENUM类型的数据源名称
@DynamicDataSource(DataSourceName.EXTEND)
public String init(){
...
}
// 调用父类方法执行切换数据源(参数名称建议使用框架中已经定义好的,DataSourceName.DEFAULT/EXTEND.getName())
this.setDataSource("extendDataSource");
...
this.clearDataSource();
分页查询后台代码
@RequestMapping("/list")
@ResponseBody
public PageModel<Xxx> list(int offset, int limit) {
// 调用父类方法传入分页参数
this.offsetPage(offset, limit);
List<Xxx> list = mapper.selectByExample(null); // 调用查询方法
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) {
// 调用父类的上传方法,在jsp中必须指定form为enctype="multipart/form-data"
List<String> fileNames = this.fileUpLoad(request);
return "success";
}
文件下载(在jsp页面使用通用的下载方法,使用restful风格)
<a href="${pageContext.request.contextPath}/文件名称/download">文件下载</a>
自定义文件下载后台方法
@RequestMapping("/download")
public ResponseEntity<byte[]> download(String fileName) {
// 调用父类文件下载方法
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模板有范围的查询,(每次返回指定的对象条数集合)
List<Demo> list = delegateMapper.selectList(statement, parameter, rowBounds);
// 使用自定义sql模板进行分页查询
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);
// 使用对象方法根据主键查询
Demo demo = mapper.selectByPrimaryKey(id);
// 使用对象方法根据criteria查询
List<Demo> list = mapper.selectByExample(example);
// 使用对象方法根据criteria分页查询
this.offsetPage(offset, limit);
List<Demo> list = mapper.selectByExample(example);
this.resultPage(list); // 返回的结果集
// 使用对象方法添加
int res = mapper.insert(record);
int res = mapper.insertSelective(record);
// 使用对象方法根据主键修改
int res = mapper.updateByPrimaryKey(record);
int res = mapper.updateByPrimaryKeySelective(record);
// 使用对象方法根据criteria修改
int res = mapper.updateByExample(record, example);
int res = mapper.updateByExampleSelective(record, example);
// 使用对象方法根据主键删除
int res = mapper.deleteByPrimaryKey(productCode);
// 使用对象方法删除根据criteria删除
int res = mapper.deleteByExample(example);
更多方法使用请参考项目中API文档或demo模块下的代码
六、效果预览(Preview)
loginweb
mobile