所需技术:spring、mybatis、druid、flyway、logback、nodejs、html、css3 ;
目标:创建一个业务框架,后端采用spring+mybatis,中间层采用node,前端html5,css3等;
工程建成后目录如下:
整合步骤:
1、创建maven工程,添加所有目标依赖;
2、创建spring目录,创建spring基础配置;
3、整合mybatis、durid、flyway;
4、整合logback工具;
5、添加测试类,测试通过,第一阶段完成;
一、创建soyann工程,添加项目依赖(IDEA)
1、创建一个新的工程soyann,添加business模块,目录结构如下;
2、添加所有模块所需要的依赖,补全pom.xml
<?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>com.soyann</groupId>
<artifactId>Business</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>Business Maven Webapp</name>
<url>http://maven.apache.org</url>
<properties>
<jstl.version>1.2</jstl.version>
<junit.version>4.12</junit.version>
<druid.version>1.1.2</druid.version>
<mysql.version>5.1.39</mysql.version>
<slf4j.version>1.7.21</slf4j.version>
<taglibs.version>1.1.0</taglibs.version>
<mybatis.version>3.4.1</mybatis.version>
<logback.version>1.1.7</logback.version>
<flywaydb.version>4.2.0</flywaydb.version>
<fastjson.version>1.2.33</fastjson.version>
<spring.version>4.3.0.RELEASE</spring.version>
<pagehelper.version>5.0.3</pagehelper.version>
<commons-lang3.version>3.4</commons-lang3.version>
<commons-logging.version>1.2</commons-logging.version>
<mybatis-spring.version>1.3.0</mybatis-spring.version>
<mybatis-ehcache.version>1.0.3</mybatis-ehcache.version>
<aspectj.version>1.8.6</aspectj.version>
<asm.version>3.3.1</asm.version>
<hamcrest.version>1.3</hamcrest.version>
<aopalliance.version>1.0</aopalliance.version>
</properties>
<dependencies>
<!-- junit 单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
<!--logback 日志 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>${commons-logging.version}</version>
</dependency>
<!-- logback和spring集成依赖包 -->
<dependency>
<groupId>org.logback-extensions</groupId>
<artifactId>logback-ext-spring</artifactId>
<version>0.1.4</version>
</dependency>
<!-- apache工具包 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons-lang3.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.4.2</version>
</dependency>
<!-- spring核心包 start -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-oxm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- spring核心包 end -->
<!-- aop代理 -->
<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>
<dependency>
<groupId>asm</groupId>
<artifactId>asm</artifactId>
<version>${asm.version}</version>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
<version>${hamcrest.version}</version>
</dependency>
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>${aopalliance.version}</version>
</dependency>
<!-- mybatis核心包 start -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>${mybatis-spring.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
<!-- mybatis-generator 依赖 -->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.5</version>
<type>jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mybatis.caches</groupId>
<artifactId>mybatis-ehcache</artifactId>
<version>${mybatis-ehcache.version}</version>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>${pagehelper.version}</version>
</dependency>
<!-- mybatis end -->
<!-- 数据库管理工具 -->
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
<version>${flywaydb.version}</version>
</dependency>
<!-- mysql 数据库连接 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!--阿里巴巴数据连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
<!--阿里巴巴json处理 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<!-- JSTL 标签支持 -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>${jstl.version}</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>${taglibs.version}</version>
</dependency>
</dependencies>
<build>
<finalName>Business</finalName>
<plugins>
<!-- mybatis-generator代码生成 -->
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.5</version>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
</dependencies>
<configuration>
<verbose>true</verbose>
<overwrite>true</overwrite>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
二、创建spring配置项
1、创建spring-applicationContest.xml,作为spring配置的根文件。在添加其它模块前,创建一个根配置,作为各模块的公共配置项;
2、根配置的内容如下,后期随着添加各个模块,将会作相应的改动。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.1.xsd ">
<!-- 配置要扫描的包 ,有多个可以用';'号隔开,也可写多个context:component-scan -->
<context:component-scan base-package="com.soyann.business" />
<!-- spring 启用aop -->
<aop:aspectj-autoproxy proxy-target-class="true" />
<!-- 激活各种对于bean类的注解标注 -->
<context:annotation-config />
</beans>
三、整合mybatis,druid,flyway工具
1、druid是阿里巴巴的数据库连接池。flyway为数据库版本管理工具。通过整合mybatis、druid及flyway,可以实现数据库查询后将数据持久化。接下来按顺序一个个文件添加进来。
2、添加spring-flyway.xml文件,配置如下:
<?xml version="1.0" encoding="utf-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd"
default-lazy-init="false">
<!-- flyway配置 -->
<bean id="flyway" class="org.flywaydb.core.Flyway" init-method="migrate">
<!-- 指向spring-mybatis.xml中的dataSource配置 -->
<property name="dataSource" ref="dataSource" />
<property name="encoding" value="UTF-8" />
<property name="table" value="TB_SCHEMA_VERSION" />
<property name="locations" value="db/migration" />
<property name="baselineOnMigrate" value="true" />
<property name="baselineVersion">
<bean class="org.flywaydb.core.api.MigrationVersion"
factory-method="fromVersion">
<constructor-arg value="0" />
</bean>
</property>
</bean>
</beans>
这里需要注意的是,<property name="dataSource" ref="dataSource" />中描述的dataSource是指spring-mybatis.xml中描述的dataSource。<property name="locations" value="db/migration" />中,描述了你数据库脚本的版本目录,工具从db/migration这个目录下读取数据库的脚本。
3、添加jdbc.properties文件,配置如下:
#数据库驱动
jdbc.driver=com.mysql.jdbc.Driver
#数据库连接url
jdbc.url=jdbc:mysql://127.0.0.1:3306/soyann?relaxAutoCommit=true&useUnicode=true&characterEncoding=UTF-8&characterSetResults=UTF-8&zeroDateTimeBehavior=convertToNull&autoReconnect=true&failOverReadOnly=false
#数据库连接用户名
jdbc.username=root
#数据库连接密码
jdbc.password=AXUE+dhMhCrtVF1usq8EB7bv4kBhkv6n81KtiG9HRnPEoQjWsPax84mMFAQONb3ireEifDcFFxdRnrZYomc3pA==
#配置数据库密码是否需要解密,这里需要注意druid 1.0.16版本及以上的解密时需要同时配置publicKey,配置方式如下
druid.connectionProperties=config.decrypt=true;config.decrypt.key=MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALBt81XVN/W8vchTvUPwUD6NLk9LpwRRhY/+TQvkvM1hZIpzX1+SB1JLjcWcIwu4AkELau0pyjJ4LfC0LoOA/q0CAwEAAQ==
#配置初始化大小、最小、最大
druid.initialSize=10
#最小连接池数量
druid.minIdle=10
#最大连接池数量
druid.maxActive=50
#获取连接时最大等待时间,单位毫秒
druid.maxWait=5000
#配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒,有两个含义:1) Destroy线程会检测连接的间隔时间,如果连接空闲时间大于等于minEvictableIdleTimeMillis则关闭物理连接;2) testWhileIdle的判断依据
druid.timeBetweenEvictionRunsMillis=60000
#配置一个连接在池中最小生存的时间,单位是毫秒
druid.minEvictableIdleTimeMillis=300000
#验证语句
druid.validationQuery=SELECT 'x'
#检测连接是否有效的超时时间,单位:秒。底层调用jdbc Statement对象的void setQueryTimeout(int seconds)方法
druid.validationQueryTimeout=5
#申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能
druid.testOnBorrow=false
#归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能
druid.testOnReturn=false
#建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效
druid.testWhileIdle=true
#打开PSCache,并且指定每个连接上PSCache的大小,如果用Oracle,则把poolPreparedStatements配置为true,mysql可以配置为false。分库分表较多的数据库,建议配置为false
druid.poolPreparedStatements=false
druid.maxPoolPreparedStatementPerConnectionSize=100
#定期把监控数据输出到日志中
druid.timeBetweenLogStatsMillis=300000
#配置监控统计拦截的filters
druid.filters=config,stat,slf4j
#使用全局监控
druid.useGlobalDataSourceStat=true
#对于长时间不使用的连接强制关闭,禁用此配置,设置为false
druid.removeAbandoned=false
#超过30分钟开始关闭空闲连接
druid.removeAbandonedTimeout=1800
#将当前关闭动作记录到日志
druid.logAbandoned=true
这里采用了数据库连接密码加密功能,怎样生成连接加密下面再分解。
4、添加实体文件。在Resource根目录下,添加generatorConfig.xml配置,自动生成实体文件,内容如下:
<?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="D:\mysql-connector-java-5.1.39.jar" /> -->
<!-- MyBatis3 - The "by example" methods in these generated objects support virtually unlimited dynamic where clauses.
MyBatis3Simple -The mappers generated with this target runtime are very basic CRUD operations only with no "by example" methods and very little dynamic SQL -->
<context id="soyann" targetRuntime="MyBatis3">
<property name="javaFileEncoding" value="UTF-8"/>
<!--生成注释 -->
<commentGenerator>
<property name="suppressAllComments" value="false"/>
<property name="suppressDate" value="false"/>
<property name="addRemarkComments" value="true"/>
</commentGenerator>
<!--
<jdbcConnection driverClass="oracle.jdbc.driver.OracleDriver"
connectionURL="jdbc:oracle:thin:@远程ip地址或localhost:1521:orcl" userId="用户名"
password="密码">
针对oracle数据库
<property name="remarksReporting" value="true"></property>
</jdbcConnection>
-->
<!--数据库连接 -->
<jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/soyann"
userId="root" password="123456">
<!-- 针对mysql数据库 -->
<property name="useInformationSchema" value="true"></property>
</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="com.soyann.general.model"
targetProject="MAVEN">
<property name="enableSubPackages" value="true"/>
<property name="trimStrings" value="true"/>
</javaModelGenerator>
<!-- 生成的SQL映射文件包名和位置,这里配置将生成的SQL映射文件放在com.soyann.general.mapper这个包下 -->
<sqlMapGenerator targetPackage="com.soyann.general.mapper"
targetProject="MAVEN">
<property name="enableSubPackages" value="true"/>
</sqlMapGenerator>
<!--生成Dao文件 可以配置 type="XMLMAPPER"生成xml的dao实现 context id="DB2Tables" 修改targetRuntime="MyBatis3" -->
<javaClientGenerator type="XMLMAPPER"
targetPackage="com.soyann.general.dao" targetProject="MAVEN">
<property name="enableSubPackages" value="true"/>
</javaClientGenerator>
<!--要生成那些表(更改tableName和domainObjectName就可以),对应数据库表 mysql可以加入主键自增 字段命名 忽略某字段等 -->
<table tableName="tb_user" domainObjectName="UserEntity" enableCountByExample="false"
enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false"
selectByExampleQueryId="false"/>
</context>
</generatorConfiguration>
<!-- mybatis-generator:generate 执行命令-->
接下来在idea中添加启动命令:
添加此配置的作用是自动生成数据表实体跟mapper文件,无须手写容易出错。运行命令,将生成的实体文件添加到对应目录下:
5、添加spring-mybatis.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.1.xsd ">
<bean id="stat-filter" class="com.alibaba.druid.filter.stat.StatFilter">
<property name="slowSqlMillis" value="30000"/>
<property name="logSlowSql" value="true"/>
<property name="mergeSql" value="true"/>
<property name="dbType" value="mysql"/>
</bean>
<bean id="wall-filter" class="com.alibaba.druid.wall.WallFilter">
<property name="dbType" value="mysql"/>
<property name="config" ref="wallConfig"></property>
</bean>
<!--
数据库类型 目录
mysql META-INF/druid/wall/mysql
oracle META-INF/druid/wall/oracle
sqlserver META-INF/druid/wall/sqlserver
postgres META-INF/druid/wall/postgres
-->
<bean id="wallConfig" class="com.alibaba.druid.wall.WallConfig">
<property name="dir" value="META-INF/druid/wall/mysql"></property>
<property name="multiStatementAllow" value="true"/>
</bean>
<!-- 配置数据源,使用 druid -->
<bean id="dataSource" name="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close">
<!-- 基本属性 url、user、password -->
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<!-- 配置初始化大小、最小、最大 -->
<property name="initialSize" value="${druid.initialSize}"/>
<property name="minIdle" value="${druid.minIdle}"/>
<property name="maxActive" value="${druid.maxActive}"/>
<!-- 配置获取连接等待超时的时间 -->
<property name="maxWait" value="${druid.maxWait}"/>
<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
<property name="timeBetweenEvictionRunsMillis" value="${druid.timeBetweenEvictionRunsMillis}"/>
<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
<property name="minEvictableIdleTimeMillis" value="${druid.minEvictableIdleTimeMillis}"/>
<!-- 验证语句、申请、归还是验证、申请连接的时候检测 -->
<property name="validationQuery" value="${druid.validationQuery}"/>
<property name="validationQueryTimeout" value="${druid.validationQueryTimeout}"/>
<property name="testWhileIdle" value="${druid.testWhileIdle}"/>
<property name="testOnBorrow" value="${druid.testOnBorrow}"/>
<property name="testOnReturn" value="${druid.testOnReturn}"/>
<!-- 打开PSCache,并且指定每个连接上PSCache的大小 -->
<property name="poolPreparedStatements" value="${druid.poolPreparedStatements}"/>
<property name="maxPoolPreparedStatementPerConnectionSize"
value="${druid.maxPoolPreparedStatementPerConnectionSize}"/>
<!-- 配置removeAbandoned功能 -->
<property name="removeAbandoned" value="${druid.removeAbandoned}"/>
<!-- 如果连接超过该时间,连接会被强制关闭 -->
<property name="removeAbandonedTimeout" value="${druid.removeAbandonedTimeout}"/>
<!-- 关闭abanded连接时输出错误日志 -->
<property name="logAbandoned" value="${druid.logAbandoned}"/>
<property name="connectionProperties" value="${druid.connectionProperties}"/>
<property name="useGlobalDataSourceStat" value="${druid.useGlobalDataSourceStat}"/>
<!-- 配置监控统计拦截的filters -->
<property name="filters" value="${druid.filters}"/>
<property name="proxyFilters">
<list>
<ref bean="stat-filter"/>
<!-- druid防火墙认为flyway自动创建表的ddl语句有sql注入问题,如果要自动创建,可以先注释掉下面的<ref bean="wall-filter"/>引用配置,启动程序,等表创建好了后再去掉注释即可 -->
<ref bean="wall-filter"/>
</list>
</property>
</bean>
<!-- 使用sqlSessionFactoryBean工厂产生SqlSession对象,方便后期注入Dao -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean" depends-on="flyway">
<property name="dataSource" ref="dataSource"/>
<!-- mybatis 设置 -->
<property name="configLocation" value="classpath:mybatis/mybatis-config.xml"/>
<!--自动扫描mapping.xml文件,匹配Mapper映射文件 -->
<property name="mapperLocations" value="classpath:mybatis/mapper/sqlmap-mapping-*.xml"/>
<!-- 这里通配符写法有问题,改为使用在javabean加上注解@Alias来自定义别名 -->
<!-- <property name="typeAliasesPackage" value="com.soyann.**.model" /> -->
</bean>
<!-- 通过扫描的模式,不需要配置SqlSessionFactory 或 SqlSessionTemplate,MapperScannerConfigurer
将会创建 MapperFactoryBean,之后自动装配; 但是,如果你使用了一个以上的 DataSource ,那么自动装配可能会失效 。
这种情况下,你可以使用 sqlSessionFactoryBeanName 或 sqlSessionTemplateBeanName 属性来设置正确的 bean
名 称来使用; 注意 bean 的名称是必须的,而不是 bean 的引用,因此,value 属性在这里替代通常的 ref;
扫描目录在com.soyann.*.mapper目录下,所有的mapper都继承SqlMapper接口,这样一个bean就可以了 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.soyann.business.*.mapper"/>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>
<!--配置事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 事物管理方式一:基于xml配置方式 -->
<!-- propagation:事物传播行为
1、REQUIRED(默认值):在有transaction状态下执行;如当前没有transaction,则创建新的transaction
2、SUPPORTS:如当前有transaction,则在transaction状态下执行;如果当前没有transaction,在无transaction状态下执行
3、MANDATORY:必须在有transaction状态下执行,如果当前没有transaction,则抛出异常IllegalTransactionStateException
4、REQUIRES_NEW:创建新的transaction并执行;如果当前已有transaction,则将当前transaction挂起
5、NOT_SUPPORTED:在无transaction状态下执行;如果当前已有transaction,则将当前transaction挂起
6、NEVER:在无transaction状态下执行;如果当前已有transaction,则抛出异常IllegalTransactionStateException
7、NESTED 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与 REQUIRED 类似的操作
read-only:读写或只读事务,默认false(读写)
isolation:可选的事务隔离级别设置
1、DEFAULT: 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别.另外四个与JDBC的隔离级别相对应
2、READ_COMMITTED: 保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据
3、READ_UNCOMMITTED: 这是事务最低的隔离级别,它充许令外一个事务可以看到这个事务未提交的数据
4、REPEATABLE_READ: 这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读
5、SERIALIZABLE 这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读外,还避免了幻像读
rollback-for:导致事务回滚的异常类数组,Class对象数组,必须继承自Throwable,一般我们都继承RuntimeException
timeout:事务超时时间设置 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="append*" propagation="REQUIRED" />
<tx:method name="insert*" propagation="REQUIRED" />
<tx:method name="save*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="modify*" propagation="REQUIRED" />
<tx:method name="edit*" propagation="REQUIRED" />
<tx:method name="delete*" propagation="REQUIRED" />
<tx:method name="remove*" propagation="REQUIRED" />
<tx:method name="repair" propagation="REQUIRED" />
<tx:method name="delAndRepair" propagation="REQUIRED" />
<tx:method name="get*" propagation="SUPPORTS" />
<tx:method name="find*" propagation="SUPPORTS" />
<tx:method name="load*" propagation="SUPPORTS" />
<tx:method name="search*" propagation="SUPPORTS" />
<tx:method name="datagrid*" propagation="SUPPORTS" />
<tx:method name="*" propagation="SUPPORTS" />
</tx:attributes>
</tx:advice>
<aop:config expose-proxy="true" proxy-target-class="true">
<!-- 配置哪些类的方法进行事务管理:定义在service包或者子包里的任意方法的执行 -->
<aop:pointcut id="transactionPointcut"
expression="execution(* com.soyann.business.*.service..*.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="transactionPointcut" order="0"/>
</aop:config>
<!--配置druid spring jdbc监控-->
<bean id="druid-stat-interceptor"
class="com.alibaba.druid.support.spring.stat.DruidStatInterceptor">
</bean>
<bean id="druid-stat-pointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut"
scope="prototype">
<property name="patterns">
<list>
<value>com.soyann.business.*.service.*</value>
<value>com.soyann.business.*.mapper.*</value>
</list>
</property>
</bean>
</beans>
添加文件后,发现还有点问题,spring-flyway.xml及spring-mybatis.xml不能相互调用,且往下。
6、更新spring-applicationContext.xml文件,引用spring-flyway.xml、spring-mybatis.xml、jdbc.properties配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.1.xsd ">
<!-- 配置要扫描的包 ,有多个可以用';'号隔开,也可写多个context:component-scan -->
<context:component-scan base-package="com.soyann.business.*.mapper" />
<context:component-scan base-package="com.soyann.business.*.service" />
<!-- spring 启用aop -->
<aop:aspectj-autoproxy proxy-target-class="true" />
<!-- 激活各种对于bean类的注解标注 -->
<context:annotation-config />
<!-- 引入属性文件:方式二 -->
<bean id="configProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE"/>
<property name="ignoreResourceNotFound" value="true" />
<property name="locations">
<list>
<value>classpath:jdbc.properties</value>
<!--<value>classpath:redis.properties</value>
<value>classpath:webside.properties</value>-->
</list>
</property>
</bean>
<!-- 引入模块配置文件 -->
<import resource="spring-mybatis.xml" />
<import resource="spring-flyway.xml" />
</beans>
7、添加web.xml文件,配置数据库连接池等内容:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<!-- RequestContextListener -->
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<!-- 指定Web根目录 -->
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>Business.root</param-value>
</context-param>
<!-- 阿里巴巴druid连接池 启用 Web 监控统计功能 start-->
<filter>
<filter-name>DruidWebStatFilter</filter-name>
<filter-class>com.alibaba.druid.support.http.WebStatFilter</filter-class>
<init-param>
<param-name>exclusions</param-name>
<param-value>*. js ,*. gif ,*. jpg ,*. png ,*. css ,*. ico ,/ druid /*</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>DruidWebStatFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>DruidStatView</servlet-name>
<servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DruidStatView</servlet-name>
<url-pattern>/druid/*</url-pattern>
</servlet-mapping>
<!-- 连接池 启用 Web 监控统计功能 end-->
</web-app>
8、在IDEA工具中引入spring及web文件
四、整合logback工具
1、在resource目录下添加logback.xml,内容如下;
<?xml version="1.0" encoding="UTF-8"?>
<!-- 从高到地低 OFF 、 FATAL 、 ERROR 、 WARN 、 INFO 、 DEBUG 、 TRACE 、 ALL -->
<!-- 日志输出规则 根据当前ROOT 级别,日志输出时,级别高于root默认的级别时 会输出 -->
<!-- 以下 每个配置的 filter 是过滤掉输出文件里面,会出现高级别文件,依然出现低级别的日志信息,通过filter 过滤只记录本级别的日志-->
<!--属性描述 scan:性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true scanPeriod:设置监测配置文件是否有修改的时间间隔。-->
<!--如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。-->
<!--debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。-->
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener"/>
<!--定义日志文件输入位置-->
<property name="FILE_DIR" value="/logs"/>
<property name="FILE_NAME" value="soyann"/>
<!-- 日志最大的历史 30天 -->
<property name="maxHistory" value="30"/>
<!-- Console 控制台级别输出日志 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoder 默认配置为PatternLayoutEncoder 对日志进行格式化-->
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{0} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- ERROR级别日志 -->
<!-- 滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件 RollingFileAppender-->
<appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 过滤器,只记录WARN级别的日志 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<!-- 最常用的滚动策略,它根据时间来制定滚动策略.既负责滚动也负责出发滚动 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志输出位置 可相对、和绝对路径 -->
<fileNamePattern>${FILE_DIR}/%d{yyyy-MM-dd}/${FILE_NAME}_error.log</fileNamePattern>
<!-- 可选节点,控制保留的归档文件的最大数量,超出数量就删除旧文件假设设置每个月滚动,且<maxHistory>是6,
则只保存最近6个月的文件,删除之前的旧文件。注意,删除旧文件是,那些为了归档而创建的目录也会被删除-->
<maxHistory>${maxHistory}</maxHistory>
</rollingPolicy>
<!-- 按照固定窗口模式生成日志文件,当文件大于20MB时,生成新的日志文件。窗口大小是1到3,当保存了3个归档文件后,将覆盖最早的日志。
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<fileNamePattern>${log_dir}/%d{yyyy-MM-dd}/.log.zip</fileNamePattern>
<minIndex>1</minIndex>
<maxIndex>3</maxIndex>
</rollingPolicy> -->
<!-- 查看当前活动文件的大小,如果超过指定大小会告知RollingFileAppender 触发当前活动文件滚动
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<maxFileSize>5MB</maxFileSize>
</triggeringPolicy> -->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>
</encoder>
</appender>
<!-- WARN级别日志 appender -->
<appender name="WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 过滤器,只记录WARN级别的日志 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>WARN</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 按天回滚 daily -->
<fileNamePattern>${FILE_DIR}/%d{yyyy-MM-dd}/${FILE_NAME}_warn-log.log
</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>${maxHistory}</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>
</encoder>
</appender>
<!-- INFO级别日志 appender -->
<appender name="INFOAPPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>${FILE_DIR}/${FILE_NAME}.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 按天来滚动,如果需要按小时来滚动,则设置为{yyyyMMddHH},如果要启用压缩,需要将fileNamePattern的后缀名设置为压缩格式.zip或.gz,如:${FILE_DIR}/${FILE_NAME}.%d{yyyyMMddHH}.zip -->
<fileNamePattern>${FILE_DIR}/${FILE_NAME}.%d{yyyyMMdd}.%i.log</fileNamePattern>
<maxFileSize>50MB</maxFileSize>
<!-- 如果按天来回滚,则最大保存时间为30天,30天之前的都将被清理掉 -->
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%d{HH:mm:ss} [%thread] %-5level %logger{0} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
<!-- 临界过滤,过滤掉 TRACE 和 DEBUG 级别的日志 -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level><!-- 只打印info及以上级别日志 -->
</filter>
</appender>
<!-- DEBUG级别日志 appender -->
<appender name="DEBUGAPPENDER"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>${FILE_DIR}/${FILE_NAME}_debug.log</File>
<rollingPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 按天来滚动,如果需要按小时来滚动,则设置为{yyyyMMddHH},如果要启用压缩,需要将fileNamePattern的后缀名设置为压缩格式.zip或.gz,如:${FILE_DIR}/${FILE_NAME}.%d{yyyyMMddHH}.zip -->
<fileNamePattern>${FILE_DIR}/${FILE_NAME}_debug.%d{yyyyMMdd}.%i.log</fileNamePattern>
<maxFileSize>50MB</maxFileSize>
<!-- 如果按天来回滚,则最大保存时间为30天,30天之前的都将被清理掉 -->
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%d{HH:mm:ss} [%thread] %-5level %logger{0} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter"><!-- 只打印debug日志 -->
<level>DEBUG</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 异步输出,这里可以根据具体需求再调整,或者不用异步输出 -->
<appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
<!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
<discardingThreshold>0</discardingThreshold>
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
<queueSize>512</queueSize>
<!-- 5秒,单位毫秒,默认是1秒 -->
<maxFlushTime>5000</maxFlushTime>
<!-- 添加附加的appender,最多只能添加一个 -->
<appender-ref ref="DEBUGAPPENDER"/>
</appender>
<!-- TRACE级别日志 appender -->
<appender name="TRACE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 过滤器,只记录ERROR级别的日志 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>TRACE</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 按天回滚 daily -->
<fileNamePattern>${FILE_DIR}/%d{yyyy-MM-dd}/${FILE_NAME}_trace-log.log
</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>${maxHistory}</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>
</encoder>
</appender>
<logger name="com.soyann" level="INFO" additivity="false">
<appender-ref ref="INFOAPPENDER"/>
</logger>
<logger name="com.soyann" level="DEBUG" additivity="false">
<appender-ref ref="ASYNC"/>
</logger>
<logger name="dao" level="DEBUG" additivity="false">
<appender-ref ref="STDOUT"/>
<appender-ref ref="INFOAPPENDER"/>
</logger>
<!-- 所有的日志级别:OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL ,建议只使用四个级别,优先级从高到低分别是 ERROR、WARN、INFO、DEBUG-->
<!-- root级别 DEBUG -->
<root level="DEBUG">
<!-- 控制台输出 -->
<appender-ref ref="STDOUT" />
<!-- 文件输出 -->
<appender-ref ref="ERROR" />
<appender-ref ref="INFO" />
<appender-ref ref="WARN" />
<appender-ref ref="DEBUG" />
<appender-ref ref="TRACE" />
</root>
</configuration>
2、web.xml中注册logback:
<!--logback日志配置 start-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/spring-applicationContext.xml</param-value>
</context-param>
<context-param>
<param-name>logbackConfigLocation</param-name>
<param-value>classpath:logback.xml</param-value>
</context-param>
<listener>
<listener-class>ch.qos.logback.ext.spring.web.LogbackConfigListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--logback日志配置 end-->
到这里,spring+mybatis框架整合基本完成,下面就来测试下这个框架吧。
五、框架测试
1、resource/db/migration添加数据库脚本;这里我用了别人创建好的,不再贴代码;
2、在service目录下添加一个接口及实现类,代码如下:
IUserService.java
package com.soyann.business.user.service;
import com.soyann.business.user.model.UserEntity;
import java.util.List;
/**
* @ProjectName: soyann
* @FileName: com.soyann.business.user.service
* @Description: (do what)
* @Copyright: Copyright(C) 2016-2017 All rights Reserved
* @Company: ShenZhen Information Technology Co.,LTD.
* @Author: dell657 neil
* @Version V1.0
* @Date: 2017/10/28
* <p>
* Modification History:
* Date Author Version Discription
* -----------------------------------------------------------------------------------
* 2017/10/28 neil 1.0 1.0
* Why & What is modified: <修改原因描述>
*/
public interface IUserService {
UserEntity getUserById(int userId);
List<UserEntity> getAllUser();
}
UserServiceImpl.java
package com.soyann.business.user.service.impl;
import com.soyann.business.user.mapper.UserMapper;
import com.soyann.business.user.model.UserEntity;
import com.soyann.business.user.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
/**
* @ProjectName: soyann
* @FileName: com.soyann.business.user.service.impl
* @Description: (do what)
* @Copyright: Copyright(C) 2016-2017 All rights Reserved
* @Company: ShenZhen Information Technology Co.,LTD.
* @Author: dell657 neil
* @Version V1.0
* @Date: 2017/10/28
* <p>
* Modification History:
* Date Author Version Discription
* -----------------------------------------------------------------------------------
* 2017/10/28 neil 1.0 1.0
* Why & What is modified: <修改原因描述>
*/
@Service("userService")
public class UserServiceImpl implements IUserService {
@Autowired(required=false)
private UserMapper userMapper;
@Override
public UserEntity getUserById(int userId) {
return userMapper.selectByPrimaryKey(userId);
}
@Override
public List<UserEntity> getAllUser() {
return userMapper.getAllUser();
}
}
3、在test目录下添加测试类TestMyBatis.java,代码如下:
package com.soyann.business.mybatis;
import com.alibaba.fastjson.JSON;
import com.soyann.business.user.model.UserEntity;
import com.soyann.business.user.service.IUserService;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.List;
/**
* @ProjectName: soyann
* @FileName: com.soyann.business.mybatis
* @Description: (do what)
* @Copyright: Copyright(C) 2016-2017 All rights Reserved
* @Company: ShenZhen Information Technology Co.,LTD.
* @Author: neil
* @Version V1.0
* @Date: 2017/10/28
* <p>
* Modification History:
* Date Author Version Discription
* -----------------------------------------------------------------------------------
* 2017/10/28 neil 1.0 1.0
* Why & What is modified: <修改原因描述>
*/
//表示继承了SpringJUnit4ClassRunner类
/*@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:spring/spring-applicationContext.xml"})*/
public class TestMyBatis {
private static Logger logger = LoggerFactory.getLogger(TestMyBatis.class);
@Resource
private IUserService userService = null;
@Before
public void before() {
//使用"spring.xml"和"spring-mybatis.xml"这两个配置文件创建Spring上下文
ApplicationContext ac = new ClassPathXmlApplicationContext(new String[]{"spring/spring-applicationContext.xml", "spring/spring-mybatis.xml"});
//从Spring容器中根据bean的id取出我们要使用的userService对象
userService = (IUserService) ac.getBean("userService");
}
@Test
public void test1() {
logger.info("任务开始执行...");
UserEntity userEntity = userService.getUserById(4);
// System.out.println(user.getUserName());
// logger.info("值:"+user.getUserName());
//System.out.println(JSON.toJSONString(userEntity));
logger.info(JSON.toJSONString(userEntity));
logger.info("任务执行结束");
logger.error("任务执行结束");
logger.debug("任务执行结束");
}
}
添加代码后,执行代码,查看控制台输出结果。
输出结果正确,证明本框架已经初步整合。本文到这里结束
参考资料:传送门
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。