Spring Boot是最近幾年火起來的一個開源框架,經過使用特定方式的配置快速搭建應用開發項目(Spring原來強大並且噁心的xml配置,相信很多人配置過一次就不想搞第二次吧)。java
開發人員經過starter(啓動器)引入所需模塊,無需過度關注其中的依賴處理,Spring Boot會自動發現和組織其中的bean以及自動獲取相關配置。mysql
本示例項目介紹如何在Spring Boot項目中整合Mybatis模塊(使用阿里 druid數據源開源項目),另外在項目中log4j2替換Spring Boot默認日誌模塊、使用MyBatis Generator插件生成Mybatis相關代碼。git
建立一個普通的Maven webapp項目,很簡單,因此...過程略...github
在pom.xml文件中添加對應的依賴,需注意的是本人使用jetty替換tomcat容器、使用log4j2替換默認的logback,因此引入spring-boot-starter-web的時候排除累tomcat、logging的starter,不須要可自行調整。具體見如下代碼及註釋。web
在build標籤內增長mybatis-generator-maven-plugin插件,用於生成Mybatis的Model、mapper等文件,程序猿偷懶專用。spring
pom.xmlsql
<?xml version="1.0" encoding="UTF-8"?> <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>org.cent</groupId> <artifactId>springBootDemo</artifactId> <version>1.0-SNAPSHOT</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.4.0.RELEASE</version> </parent> <properties> <org.mybatis.spring.boot.version>1.1.1</org.mybatis.spring.boot.version> <org.aspectj.version>1.6.11</org.aspectj.version> <com.alibaba.druid.version>1.0.5</com.alibaba.druid.version> <mysql.connector.version>5.1.38</mysql.connector.version> <org.mybatis.generator.version>1.3.5</org.mybatis.generator.version> <org.spring.framework.orm.version>3.1.0.RELEASE</org.spring.framework.orm.version> <com.github.pagehelper.version>4.1.6</com.github.pagehelper.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <!-- 去除tomcat starter --> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> <!-- 去除logback starter --> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> <!-- 去除jdbc starter --> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </exclusion> </exclusions> </dependency> <!-- 使用jetty starter --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jetty</artifactId> </dependency> <!-- 使用actuator starter(監控和管理模塊) --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!-- 引入mybatis --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>${org.mybatis.spring.boot.version}</version> </dependency> <!-- mybatis分頁插件 --> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>${com.github.pagehelper.version}</version> </dependency> <!-- sql解析(mybatis分頁插件需依賴) --> <dependency> <groupId>com.github.jsqlparser</groupId> <artifactId>jsqlparser</artifactId> <version>0.9.6</version> </dependency> <!-- log4j2 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-log4j2</artifactId> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>${org.aspectj.version}</version> </dependency> <!-- mysql 驅動 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.connector.version}</version> </dependency> <!-- 數據庫鏈接池(阿里druid開源項目) --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>${com.alibaba.druid.version}</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <!-- mybatis代碼生成器 --> <plugin> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-maven-plugin</artifactId> <version>${org.mybatis.generator.version}</version> <configuration> <verbose>true</verbose> <overwrite>true</overwrite> </configuration> </plugin> </plugins> </build> </project>
jdbc.properties數據庫
demo.jdbc.url=jdbc:mysql://localhost:3306/spring_boot_demo demo.jdbc.username=root demo.jdbc.password=123456 demo.jdbc.initialSize=1 demo.jdbc.minIdle=1 demo.jdbc.maxActive=20 demo.jdbc.maxWait=60000 demo.jdbc.timeBetweenEvictionRunsMillis=60000
DataSourceProperties.classapache
package org.cent.springBootDemo.properties; import org.springframework.boot.context.properties.ConfigurationProperties; /** * 數據源配置類 * Created by cent on 2016/9/2. */ @ConfigurationProperties(locations = "classpath:jdbc.properties", prefix = "demo.jdbc") public class DataSourceProperties { private String url; private String username; private String password; private Integer initialSize; private Integer minIdle; private Integer maxActive; private Long maxWait; private Long timeBetweenEvictionRunsMillis; public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Integer getInitialSize() { return initialSize; } public void setInitialSize(Integer initialSize) { this.initialSize = initialSize; } public Integer getMinIdle() { return minIdle; } public void setMinIdle(Integer minIdle) { this.minIdle = minIdle; } public Integer getMaxActive() { return maxActive; } public void setMaxActive(Integer maxActive) { this.maxActive = maxActive; } public Long getMaxWait() { return maxWait; } public void setMaxWait(Long maxWait) { this.maxWait = maxWait; } public Long getTimeBetweenEvictionRunsMillis() { return timeBetweenEvictionRunsMillis; } public void setTimeBetweenEvictionRunsMillis(Long timeBetweenEvictionRunsMillis) { this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis; } }
MybatisConfig.classjson
package org.cent.springBootDemo.configs; import com.alibaba.druid.pool.DruidDataSource; import com.github.pagehelper.PageHelper; import org.apache.ibatis.logging.Log; import org.apache.ibatis.logging.LogFactory; import org.apache.ibatis.logging.log4j2.Log4j2Impl; import org.apache.ibatis.plugin.Interceptor; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.logging.log4j.Logger; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.SqlSessionTemplate; import org.mybatis.spring.mapper.MapperScannerConfigurer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.core.annotation.Order; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.core.io.support.ResourcePatternResolver; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.transaction.annotation.TransactionManagementConfigurer; import java.util.Properties; /** * Mybatis主配置 * Created by cent on 2016/9/20. */ @Configuration @EnableTransactionManagement//啓用事務控制 @AutoConfigureAfter(DatasourceConfig.class) @Import(DatasourceConfig.class)//設置爲在數據源以後初始化,防止數據源爲null致使啓動報錯 public class MybatisConfig implements TransactionManagementConfigurer { /** * 數據源對象 */ @Autowired private DruidDataSource dataSource; /** * 數據庫會話工廠bean * @return */ @Bean(name = "sqlSessionFactory") public SqlSessionFactory sqlSessionFactoryBean() { SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); bean.setDataSource(dataSource); bean.setTypeAliasesPackage("org.cent.springBootDemo.entity"); org.apache.ibatis.session.Configuration configuration=new org.apache.ibatis.session.Configuration(); configuration.setLogImpl(Log4j2Impl.class); bean.setConfiguration(configuration); //配置mybatis 分頁插件 PageHelper pageHelper=new PageHelper(); Properties properties = new Properties(); properties.setProperty("dialect","mysql"); properties.setProperty("params","pageNum=start;pageSize=limit;pageSizeZero=zero;reasonable=heli;count=contsql"); pageHelper.setProperties(properties); try { bean.setPlugins(new Interceptor[]{pageHelper}); return bean.getObject(); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } } /** * 數據庫會話模板bean * @param sqlSessionFactory * @return */ @Bean public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) { return new SqlSessionTemplate(sqlSessionFactory); } /** * 事務管理器配置 * @return */ @Bean @Override public PlatformTransactionManager annotationDrivenTransactionManager() { return new DataSourceTransactionManager(dataSource); } }
package org.cent.springBootDemo.configs; import org.mybatis.spring.mapper.MapperScannerConfigurer; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; /** * Mybatis Mapper掃描配置 * Created by cent on 2016/9/20. */ @Configuration @AutoConfigureAfter(MybatisConfig.class) public class MapperScannerConfiguierConfig { /** * Mybatis mapper掃描器 * @return */ @Bean public MapperScannerConfigurer mapperScannerConfigurer() { MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer(); mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory"); mapperScannerConfigurer.setBasePackage("org.cent.springBootDemo.mapper"); return mapperScannerConfigurer; } }
建立Spring Boot啓動入口Application類,這裏只有啓動的main方法,因此的配置都在其餘的config類配置。
package org.cent.springBootDemo.entrance; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; /** * Spring Boot啓動入口 * Created by cent on 2016/9/2. */ @EnableWebMvc @Configuration @SpringBootApplication(scanBasePackages = {"org.cent.springBootDemo"}) public class Application extends WebMvcConfigurerAdapter { public static void main(String[] args) throws Exception { SpringApplication.run(Application.class, args); } }
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> <generatorConfiguration> <!--數據庫驅動jar --> <classPathEntry location="C:\Users\user\.m2\repository\mysql\mysql-connector-java\5.1.38\mysql-connector-java-5.1.38.jar" /> <context id="DB2Tables" targetRuntime="MyBatis3"> <!--去除註釋 --> <commentGenerator> <property name="suppressAllComments" value="true" /> </commentGenerator> <!--數據庫鏈接 --> <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/spring_boot_demo" userId="root" password="123456"> </jdbcConnection> <!--默認false Java type resolver will always use java.math.BigDecimal if the database column is of type DECIMAL or NUMERIC. --> <javaTypeResolver > <property name="forceBigDecimals" value="false" /> </javaTypeResolver> <!--生成實體類 指定包名 以及生成的地址 (能夠自定義地址,可是路徑不存在不會自動建立 使用Maven生成在target目錄下,會自動建立) --> <javaModelGenerator targetPackage="org.cent.springBootDemo.entity" targetProject="src\main\java"> <property name="enableSubPackages" value="false" /> <property name="trimStrings" value="true" /> </javaModelGenerator> <!--生成SQLMAP文件 --> <sqlMapGenerator targetPackage="mapper" targetProject="src\main\resources"> <property name="enableSubPackages" value="false" /> </sqlMapGenerator> <!--生成Dao文件 能夠配置 type="XMLMAPPER"生成xml的dao實現 context id="DB2Tables" 修改targetRuntime="MyBatis3" --> <javaClientGenerator type="ANNOTATEDMAPPER" targetPackage="org.cent.springBootDemo.mapper" targetProject="src\main\java"> <property name="enableSubPackages" value="false" /> </javaClientGenerator> <!--對應數據庫表 mysql能夠加入主鍵自增 字段命名 忽略某字段等--> <table tableName="sys_user" domainObjectName="User" > </table> </context> </generatorConfiguration>
我用的是IDEA IntelliJ,使用Mybatis generator插件的方式以下圖,其餘開發工具相似。
UserService.class
package org.cent.springBootDemo.service; import com.github.pagehelper.PageInfo; import org.cent.springBootDemo.entity.User; /** * User服務接口 * Created by cent on 2016/9/20. */ public interface UserService { /** * 根據ID查找 * @return * @throws Exception */ public User queryById(Integer id) throws Exception; /** * 獲取分頁數據 * @param start * @param limit * @return * @throws Exception */ public PageInfo<User> selectPage(int start,int limit) throws Exception; }
UserServiceImpl.class
package org.cent.springBootDemo.service.impl; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import org.cent.springBootDemo.entity.User; import org.cent.springBootDemo.entity.UserExample; import org.cent.springBootDemo.mapper.UserMapper; import org.cent.springBootDemo.service.UserService; import org.mybatis.spring.SqlSessionTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Service; import javax.annotation.PostConstruct; import java.util.Map; /** * User服務接口實現類 * Created by cent on 2016/9/20. */ @Service public class UserServiceImpl implements UserService { @Autowired private SqlSessionTemplate sqlSessionTemplate; @Override public User queryById(Integer id) throws Exception { UserMapper userMapper = sqlSessionTemplate.getMapper(UserMapper.class); return userMapper.selectByPrimaryKey(id); } public PageInfo<User> selectPage(int start,int limit) throws Exception { UserMapper userMapper = sqlSessionTemplate.getMapper(UserMapper.class); PageHelper.startPage(start,limit); UserExample ue = new UserExample(); PageInfo<User> users = new PageInfo<User>(userMapper.selectByExample(ue)); return users; } }
定義UserController類。
UserController.class
package org.cent.springBootDemo.controller; import com.github.pagehelper.PageInfo; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.cent.springBootDemo.constants.PageConstants; import org.cent.springBootDemo.entity.User; import org.cent.springBootDemo.properties.DataSourceProperties; import org.cent.springBootDemo.service.UserService; import org.cent.springBootDemo.util.StringUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; import java.util.Map; /** * User Demo Controller * Created by cent on 2016/9/2. */ @RestController @RequestMapping(value="/user") public class UserController extends BaseController { Logger logger = LogManager.getLogger(getClass()); @Autowired private UserService userService; /** * 根據用戶ID獲取用戶信息 * @param id * @return */ @RequestMapping(value = "/{id}", method = RequestMethod.GET, produces = "application/json;charset=utf-8") @ResponseBody public User user(@PathVariable("id") Integer id) { try { User user = userService.queryById(id); return user; } catch (Exception e) { logger.error(e.getMessage(), e); return new User(); } } /** * 獲取用戶列表(分頁) * 請求參數:start-頁數、limit-每頁記錄數 * @param request * @return */ @RequestMapping(value = "", method = RequestMethod.GET, produces = "application/json;charset=utf-8") @ResponseBody public PageInfo<User> user(HttpServletRequest request) { try { Map<String, String> params = getRequestParams(request); Integer start = StringUtil.isBlank(params.get("start")) ? PageConstants.DEFAULT_START_PAGE : Integer.valueOf(params.get("start")); Integer limit = StringUtil.isBlank(params.get("limit")) ? PageConstants.DEFAULT_PAGE_LIMIT : Integer.valueOf(params.get("limit")); PageInfo<User> users = userService.selectPage(start, limit); return users; } catch (Exception e) { logger.error(e.getMessage(), e); return new PageInfo<User>(); } } }
log4j2.properties
appender.console.type = Console appender.console.name = STDOUT appender.console.target = SYSTEM_OUT appender.console.layout.type = PatternLayout appender.console.layout.pattern = %-d{yyyy-MM-dd HH:mm:ss} [ %p ] [ %c ] %m%n appender.rollingFileAppender.type = RollingFile appender.rollingFileAppender.name = rollingFile appender.rollingFileAppender.fileName = /spider/logs/all.log appender.rollingFileAppender.filePattern = /spider/logs/info_%d{yyyy-MM-dd}_%i.log appender.rollingFileAppender.layout.type = PatternLayout appender.rollingFileAppender.layout.pattern = %-d{yyyy-MM-dd HH:mm:ss} [ %p ] [ %c ] %m%n appender.rollingFileAppender.policies.type = Policies appender.rollingFileAppender.policies.time.type = TimeBasedTriggeringPolicy appender.rollingFileAppender.policies.time.interval = 1 appender.rollingFileAppender.policies.time.modulate = true appender.rollingFileAppender.policies.size.type = SizeBasedTriggeringPolicy appender.rollingFileAppender.policies.size.size=20M appender.rollingFileAppender.strategy.type = DefaultRolloverStrategy appender.rollingFileAppender.strategy.max = 100 appenders =console,rollingFileAppender #主logger rootLogger.level = info #rootLogger.appenderRefs = console,I,E rootLogger.appenderRefs =${appenders} rootLogger.appenderRef.console.ref = STDOUT rootLogger.appenderRef.rollingFileAppender.ref = rollingFile #輸出mybatis的SQL語句執行日誌 logger.sql.name=org.cent.springBootDemo.mapper logger.sql.level = debug logger.sql.additivity=false logger.sql.appenderRefs = console logger.sql.appenderRef.console.ref = STDOUT
application.properties
#使用log4j2的配置 logging.config=classpath:log4j2.properties
CREATE DATABASE `spring_boot_demo` /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci */; CREATE TABLE `sys_user` ( `ID` int(11) NOT NULL AUTO_INCREMENT, `USER_CODE` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL, `USER_NAME` varchar(128) COLLATE utf8_unicode_ci DEFAULT NULL, `REMARK` varchar(256) COLLATE utf8_unicode_ci DEFAULT NULL, `CREATE_TIME` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `UPDATE_TIME` timestamp NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`ID`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;