所需技術:spring、mybatis、druid、flyway、logback、nodejs、html、css3 ;
目標:建立一個業務框架,後端採用spring+mybatis,中間層採用node,前端html5,css3等;css
工程建成後目錄以下:html
一、建立maven工程,添加全部目標依賴;
二、建立spring目錄,建立spring基礎配置;
三、整合mybatis、durid、flyway;
四、整合logback工具;
五、添加測試類,測試經過,第一階段完成;前端
一、建立一個新的工程soyann,添加business模塊,目錄結構以下;html5
二、添加全部模塊所須要的依賴,補全pom.xmljava
<?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-applicationContest.xml,做爲spring配置的根文件。在添加其它模塊前,建立一個根配置,做爲各模塊的公共配置項;node
二、根配置的內容以下,後期隨着添加各個模塊,將會做相應的改動。mysql
<?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>
一、druid是阿里巴巴的數據庫鏈接池。flyway爲數據庫版本管理工具。經過整合mybatis、druid及flyway,能夠實現數據庫查詢後將數據持久化。接下來按順序一個個文件添加進來。
二、添加spring-flyway.xml文件,配置以下:css3
<?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這個目錄下讀取數據庫的腳本。git
三、添加jdbc.properties文件,配置以下:github
#數據庫驅動 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
這裏採用了數據庫鏈接密碼加密功能,怎樣生成鏈接加密下面再分解。
四、添加實體文件。在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文件,無須手寫容易出錯。運行命令,將生成的實體文件添加到對應目錄下:
五、添加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:事物傳播行爲 一、REQUIRED(默認值):在有transaction狀態下執行;如當前沒有transaction,則建立新的transaction 二、SUPPORTS:如當前有transaction,則在transaction狀態下執行;若是當前沒有transaction,在無transaction狀態下執行 三、MANDATORY:必須在有transaction狀態下執行,若是當前沒有transaction,則拋出異常IllegalTransactionStateException 四、REQUIRES_NEW:建立新的transaction並執行;若是當前已有transaction,則將當前transaction掛起 五、NOT_SUPPORTED:在無transaction狀態下執行;若是當前已有transaction,則將當前transaction掛起 六、NEVER:在無transaction狀態下執行;若是當前已有transaction,則拋出異常IllegalTransactionStateException 七、NESTED 若是當前存在事務,則在嵌套事務內執行。若是當前沒有事務,則執行與 REQUIRED 相似的操做 read-only:讀寫或只讀事務,默認false(讀寫) isolation:可選的事務隔離級別設置 一、DEFAULT: 這是一個PlatfromTransactionManager默認的隔離級別,使用數據庫默認的事務隔離級別.另外四個與JDBC的隔離級別相對應 二、READ_COMMITTED: 保證一個事務修改的數據提交後才能被另一個事務讀取。另一個事務不能讀取該事務未提交的數據 三、READ_UNCOMMITTED: 這是事務最低的隔離級別,它充許令外一個事務能夠看到這個事務未提交的數據 四、REPEATABLE_READ: 這種事務隔離級別能夠防止髒讀,不可重複讀。可是可能出現幻像讀 五、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不能相互調用,且往下。
六、更新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>
七、添加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>
八、在IDEA工具中引入spring及web文件
一、在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>
二、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框架整合基本完成,下面就來測試下這個框架吧。
一、resource/db/migration添加數據庫腳本;這裏我用了別人建立好的,再也不貼代碼;
二、在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(); } }
三、在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("任務執行結束"); } }
添加代碼後,執行代碼,查看控制檯輸出結果。
輸出結果正確,證實本框架已經初步整合。本文到這裏結束
參考資料:傳送門