我的產品開發之旅 - SSM框架升級API平台(Spring + SpringMVC + MyBatis)
1、大眾框架,Spring、SpringMVC、MyBatis屬於熱門框架,新招聘來的開發人員大多有一些這方面技術積累,減低人員流動再適應的影響。
2、易用性,註解等功能提高開發效率,靈活。
3、性能優秀。
基本概念(個人理解,如有其他高見,請留言指教)
Spring
Spring兩個核心概念,IOC 和 AOP。
首先說說IoC(Inversion of Control,控制反轉),這個玩意從字面上確實比較懵逼,咱們可以這樣去理解,之前我們要獲得一個對象,那麼得new一個,這個對象是由new它的對象去控制其生命周期的,但是使用了Spring後,所有的對象都交給Spring去控制了,我們要用的時候,直接用就好,所有的對象都交給Spring去控制。所以對於某個具體的對象而言,以前是它自己來控制其new出來的對象,現在是所有的對象都由spring來控制,這個就是我理解的控制反轉。
AOP這個就是面向切面編程,可以為某一類對象 進行監督和控制(也就是 在調用這類對象的具體方法的前後去調用你指定的 模塊)從而達到對一個模塊擴充的功能。這些都是通過 配置類達到的。
Spring的實現離不開反射原理,通過xml配置文件反射初始化相應的對象。
更通俗一點,Spring就是個容器框架,你把需要它幫你管理的對象在xml配置文件里告訴它,之後你需要用到這些對象的時候直接使用Spring提供的方法用就可以了,把大部門精力都花在你的業務上吧。
SpringMVC
SpringMVC是一個基於Spring的MVC框架,需要有Spring的支撐才能跑得起來。
MyBatis
先來段官方的:MyBatis 是支持定製化 SQL、存儲過程以及高級映射的優秀的持久層框架。MyBatis 避免了幾乎所有的 JDBC 代碼和手動設置參數以及獲取結果集。MyBatis 可以對配置和原生Map使用簡單的 XML 或註解,將介面和 Java 的 POJOs(Plain Old Java Objects,普通的 Java對象)映射成資料庫中的記錄。
MyBatis的前身是iBatis,本是apache的一個開源項目,3.0之後改名為MyBatis,它的作用在於代替項目中daoImpl層,將sql語句寫在配置的xml文件中,不必對結果集做轉換處理,MyBatis可以自定義返回類型,可以動態改變sql語句,因其存放於xml文件中。MyBatis的強大之處遠不止這裡,想跟深入了解可以自行查閱資料。
Spring 和 MyBatis簡直是絕配!利用的Spring,僅需簡單配置一下,就可以直接將MyBatis配置好的對象存放於其容器中,然後可以直接用註解的方式來調用就可以了,省去了MyBatis常規調用時候的繁瑣。好了,開工吧!
如何創建一個SpringMCV項目,請看我的上一篇文章
我的產品開發之旅(5) - 使用Spring MVC搭建API平台
按照這篇網址搭建好SpringMCV項目後,將 mvc-dispatcher-servlet.xml 配置文件挪動到resources中去,這樣項目結構比較規範一些,現在我們的項目目錄結構應該是這樣的。
開始將MyBatis整合到SpringMCV項目中
0、從0開始,將相應的第三方框架包添加到項目中,本次僅貼出新增的包。
<!-- mybatis核心包 -->n<dependency>n <groupId>org.mybatis</groupId>n <artifactId>mybatis</artifactId>n <version>3.4.1</version>n</dependency>nn<!-- mysql驅動包 -->n<dependency>n <groupId>mysql</groupId>n <artifactId>mysql-connector-java</artifactId>n <version>5.1.38</version>n</dependency>nn<!-- mybatis-spring包 -->n<dependency>n <groupId>org.mybatis</groupId>n <artifactId>mybatis-spring</artifactId>n <version>1.3.0</version>n</dependency>nn<!-- mybatis自動生成包 -->n<dependency>n <groupId>tk.mybatis</groupId>n <artifactId>mapper</artifactId>n <version>3.3.9</version>n</dependency>nn<!-- mybatis generator 自動生成sql -->n<dependency>n <groupId>org.mybatis.generator</groupId>n <artifactId>mybatis-generator-core</artifactId>n <version>1.3.2</version>n</dependency>nnn<!-- 資料庫連接池 -->n<dependency>n <groupId>c3p0</groupId>n <artifactId>c3p0</artifactId>n <version>0.9.1.2</version>n</dependency>nnn<!-- 單元測試 -->n<dependency>n <groupId>junit</groupId>n <artifactId>junit</artifactId>n <version>4.11</version>n</dependency>n
1、創建 jdbc.properties 配置文件,用於存儲資料庫相關連接信息。
driver=org.gjt.mm.mysql.Drivernurl=jdbc:mysql://120.***.9.171:3306/zhiwu?useUnicode=true&characterEncoding=UTF-8nusername=hehehenpassword=heiheiheinn#定義初始連接數nmaxPoolSize=30n#定義最小空閑nminPoolSize=10n#關閉連接後不自動commitnautoCommitOnClose=falsen#當獲取連接失敗重試次數nacquireRetryAttempts=2n#獲取連接超時時間ncheckoutTimeout=10000n
2、創建 log4j.properties 配置文件,用於存儲log4j日誌框架需要的配置信息。
log4j.rootLogger=INFO,Console,Filen#定義日誌輸出目的地為控制台nlog4j.appender.Console=org.apache.log4j.ConsoleAppendernlog4j.appender.Console.Target=System.outn#可以靈活地指定日誌輸出格式,下面一行是指定具體的格式nlog4j.appender.Console.layout = org.apache.log4j.PatternLayoutnlog4j.appender.Console.layout.ConversionPattern=[%c] - %m%nnn#文件大小到達指定尺寸的時候產生一個新的文件nlog4j.appender.File = org.apache.log4j.RollingFileAppendern#指定輸出目錄nlog4j.appender.File.File = logs/ssm.logn#定義文件最大大小nlog4j.appender.File.MaxFileSize = 10MBn# 輸出所以日誌,如果換成DEBUG表示輸出DEBUG以上級別日誌nlog4j.appender.File.Threshold = ALLnlog4j.appender.File.layout = org.apache.log4j.PatternLayoutnlog4j.appender.File.layout.ConversionPattern =[%p] [%d{yyyy-MM-dd HH:mm:ss}][%c]%m%nn
3、創建 mybatis-config.xml 配置文件,用於存儲MyBatis的全局屬性。
<?xml version="1.0" encoding="utf-8"?>n<!DOCTYPE configurationn PUBLIC "-//mybatis.org//DTD Config 3.0//EN"n "http://mybatis.org/dtd/mybatis-3-config.dtd">nn<configuration>nn <!-- 配置全局屬性 -->n <settings>n <!-- 使用jdbc的getGeneratedKeys獲取資料庫自增主鍵值 -->n <setting name="useGeneratedKeys" value="true" />nn <!-- 使用列別名替換列名 默認:true -->n <setting name="useColumnLabel" value="true" />nn <!-- 開啟駝峰命名轉換:Table{create_time} -> Entity{createTime} -->n <setting name="mapUnderscoreToCamelCase" value="true" />n </settings>nn</configuration>n
4、重點來了,創建 mybatis-spring.xml 配置文件,這是Spring項目和MyBatis項目整合的關鍵所在。作用都有代碼注釋,直接看代碼就好。
<?xml version="1.0" encoding="UTF-8"?>n<beans xmlns="http://www.springframework.org/schema/beans"n xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"n xmlns:context = "http://www.springframework.org/schema/context"n xmlns:tx="http://www.springframework.org/schema/tx"n xsi:schemaLocation="http://www.springframework.org/schema/beansn http://www.springframework.org/schema/beans/spring-beans.xsdn http://www.springframework.org/schema/contextn http://www.springframework.org/schema/context/spring-context.xsdn http://www.springframework.org/schema/txn http://www.springframework.org/schema/tx/spring-tx.xsd">nnn <!-- 配置mybatis相關 -->n <!-- 引入配置文件 -->n <bean id="propertyConfigurer"n class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">n <property name="location" value="classpath:jdbc.properties" />n </bean>nn <!-- 2.資料庫連接池 -->n <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">nn <property name="driverClass" value="${driver}" />n <property name="jdbcUrl" value="${url}" />n <property name="user" value="${username}" />n <property name="password" value="${password}" />nnn <!-- c3p0連接池的私有屬性 -->n <property name="maxPoolSize" value="${maxPoolSize}" />n <property name="minPoolSize" value="${minPoolSize}" />n <!-- 關閉連接後不自動commit -->n <property name="autoCommitOnClose" value="${autoCommitOnClose}" />n <!-- 獲取連接超時時間 -->n <property name="checkoutTimeout" value="${checkoutTimeout}" />n <!-- 當獲取連接失敗重試次數 -->n <property name="acquireRetryAttempts" value="${acquireRetryAttempts}" />nn </bean>nn <!-- 3.配置SqlSessionFactory對象 -->n <!-- spring和MyBatis完美整合,不需要mybatis的配置映射文件 -->n <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">n <!-- 注入資料庫連接池 -->n <property name="dataSource" ref="dataSource" />n <!-- 配置MyBaties全局配置文件:mybatis-config.xml -->n <property name="configLocation" value="classpath:mybatis-config.xml" />n <!-- 掃描entity包 使用別名 -->n <property name="typeAliasesPackage" value="com.zhiwu.model" />n <!-- 掃描sql配置文件mapper中的xml文件 -->n <property name="mapperLocations" value="classpath:mapper/*.xml" />n </bean>nn <!-- DAO介面所在包名,Spring會自動查找其下的類 -->n <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">n <property name="basePackage" value="com.zhiwu.dao" />n <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>n </bean>nn <!-- (事務管理)transaction manager, use JtaTransactionManager for global tx -->n <bean id="transactionManager"n class="org.springframework.jdbc.datasource.DataSourceTransactionManager">n <property name="dataSource" ref="dataSource" />n </bean>nn <!-- 配置基於註解的聲明式事務 -->n <tx:annotation-driven transaction-manager="transactionManager"/>nn</beans>n
5、Spring配置MVC框架用到的配置文件mvc-dispatcher-servlet.xml 也在這裡貼出來吧。這是創建SpringMVC項目時候就已經創建了的。
<?xml version="1.0" encoding="UTF-8"?>n<beans xmlns="http://www.springframework.org/schema/beans"n xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"n xmlns:context = "http://www.springframework.org/schema/context"n xmlns:mvc="http://www.springframework.org/schema/mvc"n xmlns:tx="http://www.springframework.org/schema/tx"n xsi:schemaLocation="http://www.springframework.org/schema/beansn http://www.springframework.org/schema/beans/spring-beans.xsdn http://www.springframework.org/schema/contextn http://www.springframework.org/schema/context/spring-context.xsdn http://www.springframework.org/schema/mvcn http://www.springframework.org/schema/mvc/spring-mvc.xsdn http://www.springframework.org/schema/txn http://www.springframework.org/schema/tx/spring-tx.xsd">nn <!--掃描包中所有的註解-->n <context:component-scan base-package="com.zhiwu"/>nn <!-- 靜態資源(js、image等)的訪問 -->n <mvc:default-servlet-handler/>nn <!-- 開啟註解,並解決@ResponseBody 的實現類其默認的編碼是 iso-8859-1的問題 -->n <mvc:annotation-driven>n <mvc:message-converters>n <!-- default StringHttpMessageConverter, solve encoding problem -->n <bean class="org.springframework.http.converter.StringHttpMessageConverter">n <constructor-arg value="UTF-8" />n <property name="writeAcceptCharset" value="false" />n </bean>n </mvc:message-converters>n </mvc:annotation-driven>nn <!--ViewResolver 視圖解析器-->n <!--用於支持Servlet、JSP視圖解析-->n <bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">n <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>n <property name="prefix" value="/WEB-INF/pages/"/>n <property name="suffix" value=".jsp"/>n </bean>nnn</beans>n
<context:component-scan base-package="com.zhiwu"/>n
這句代碼是配置Spring的關鍵所在,它表示將掃描包中所有的註解,這是Spring2.5之後出來的新功能(沒記錯的話),有了它,就不用在配置文件中一個個的配置需要放到容器中的對象了。當然,如果你覺得這樣掃描整個項目粒度太大,那麼 <context:component-scan> 也提供了相應的方法讓你配置,詳細配置方法網上很多。
<context:component-scan>使用說明 - 菜鳥博客 - 博客頻道 - CSDN.NET
5.1 、配置web.xml引用剛才創建的兩個Spring配置文件
<!DOCTYPE web-app PUBLICn "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"n "http://java.sun.com/dtd/web-app_2_3.dtd" >nn<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"n xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"n xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"n version="3.1">nn <display-name>Archetype Created Web Application</display-name>nnn <!-- 創建一個servlet,命名為mvc-dispatcher -->n <servlet>n <servlet-name>mvc-dispatcher</servlet-name>n <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>nn <!-- 指定Spring配置文件的位置,否則會根據servlet-name+「-servlet.xml」自動匹配Spring配置文件 -->n <init-param>n <param-name>contextConfigLocation</param-name>n <param-value>n classpath:mvc-dispatcher-servlet.xml,n classpath:mybatis-spring.xmln </param-value>n </init-param>nn <load-on-startup>1</load-on-startup>n </servlet>nnn <!-- 配置這個mvc-dispatcher的攔截請求,url-pattern為 / ,說明攔截所有請求 -->n <servlet-mapping>n <servlet-name>mvc-dispatcher</servlet-name>n <url-pattern>/</url-pattern>n </servlet-mapping>nnn <!-- 為了能夠處理中文的post請求,再配置一個encodingFilter過濾器,將數據轉換成utf-8編碼,以避免post請求中文出現亂碼情況 -->n <filter>n <filter-name>encodingFilter</filter-name>n <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>nn <init-param>n <param-name>encoding</param-name>n <param-value>UTF-8</param-value>n </init-param>nn <init-param>n <param-name>forceEncoding</param-name>n <param-value>true</param-value>n </init-param>n </filter>nn <!-- 過濾器攔截所有請求 -->n <filter-mapping>n <filter-name>encodingFilter</filter-name>n <url-pattern>/*</url-pattern>n </filter-mapping>nnn</web-app>n
引用Spring配置文件的重點在於這段代碼,<param-value>是引用的文件路徑集合,多個配置文件用 「 , 」 分隔。
<!-- 指定Spring配置文件的位置,否則會根據servlet-name+「-servlet.xml」自動匹配Spring配置文件 -->n <init-param>n <param-name>contextConfigLocation</param-name>n <param-value>n classpath:mvc-dispatcher-servlet.xml,n classpath:mybatis-spring.xmln </param-value>n </init-param>n
6、在resources文件夾下新建一個mapper文件夾。
以上操作全部完成後,項目的目錄結構應該是這樣的。
7、我們在項目的dao文件夾下創建一個IMyTestDao介面類。(註:SortModel 實體類在上一章中已經創建,這裡就不貼出來了)
package com.zhiwu.dao;nnimport com.zhiwu.model.SortModel;nnimport java.util.List;nn/**n * Created by 韋慶明 on 2016/12/13.n * 測試MyBatis介面類n */npublic interface IMyTestDao {nn SortModel selectSort(int id);nn List<SortModel> allSort();nn <T> List<SortModel> querySort(T model);n}n
按之前的項目結構,需要創建一個對應了Impl類來具體實現這個介面類的資料庫操作,現在使用了MyBatis後,不需要創建Impl實現類了,我們在第 6 步的時候 ,創建了mapper文件夾,在此文件夾中為每一個dao介面創建項對應的 mapper.xml 資料庫操作配置文件,在 xml 文件裡面寫相應業務的 sql 語句。
8、創建名為 MyTest.xml (XML映射文件)
<?xml version="1.0" encoding="utf-8"?>n<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"n "http://mybatis.org/dtd/mybatis-3-mapper.dtd">n<mapper namespace="com.zhiwu.dao.IMyTestDao">n <select id="selectSort" parameterType="java.lang.Integer" resultMap="sortMap">n SELECT id,sortName,sortImgUrl FROM Sort WHERE 1 = 1n AND id = #{id}n </select>nn <select id="allSort" resultMap="sortMap">n SELECT id,sortName,sortImgUrl FROM Sortn </select>nn <select id="querySort" parameterType="SortModel" resultMap="sortMap">n SELECT id,sortName,sortImgUrl FROM Sort WHERE 1 = 1n <if test="id > 0">n AND id = #{id}n </if>n </select>nn <resultMap type="com.zhiwu.model.SortModel" id="sortMap">n <id column="id" property="id"/>n <result column="sortName" property="sortName"/>n <result column="sortImgUrl" property="sortImgUrl"/>n </resultMap>n</mapper> n
Mapper XML 基本介紹(XML映射文件)
1、指定dao介面位置,必須是完整的路徑,如下:
<mapper namespace="com.zhiwu.dao.IMyTestDao">n
2、增、刪、查、改四種配置
僅介紹常用配置屬性,如想要了解更多,請前往:mybatis - MyBatis 3
常用屬性:
id:這個id必須對應著dao介面類中的方法/函數名稱,並且在一個xml文件中不能重複。
parameterType:傳入的參數類型(int,String等),也可以填寫實體類的名稱,非必傳。
sql語句參數定義: #{idx}
查詢 <select> 標籤
resultType:指定的返回類型,可以是對應的實體類。
resultMap:自定義返回數據結構,稍後會有介紹,resultType和resultMap不可同時出現。
<select id="selectSort" parameterType="java.lang.Integer" resultMap="sortMap">n SELECT id,sortName,sortImgUrl FROM Sort WHERE 1 = 1n AND id = #{id}n</select>n
resultMap自定義返回數據結構參數說明
type:實體類的路徑
id:自定義,不能重複,用於被調用
column:資料庫欄位名稱
property:實體類參數名稱
<resultMap type="com.zhiwu.model.SortModel" id="sortMap">n <id column="id" property="id"/>n <result column="sortName" property="sortName"/>n <result column="sortImgUrl" property="sortImgUrl"/>n </resultMap>n
插入 <insert> 標籤
useGeneratedKeys:(僅對 insert 和 update 有用),獲取自增的主鍵。
keyProperty:(僅對 insert 和 update 有用),將useGeneratedKeys獲取到的主鍵賦值到對應的欄位中,keyProperty = 欄位名。
<insert id="insertAuthor" parameterType="Author" useGeneratedKeys="true"n keyProperty="id">n insert into Author (username,password,email,bio)n values (#{username},#{password},#{email},#{bio})n</insert>n
修改 <update> 標籤
<update id="updateAuthor" parameterType="Author">n update Author setn username = #{username},n password = #{password},n email = #{email},n bio = #{bio}n where id = #{id}n</update>n
刪除 <delete> 標籤
<delete id="deleteAuthor">n delete from Author where id = #{id}n</delete>n
現在XML文件配置好了,因為有了Spring這個強大的容器框架,所以我們引用非常的簡單。
創建業務邏輯層相應類
Service介面類:IMyTestService
package com.zhiwu.service;nnimport com.zhiwu.model.SortModel;nn/**n * Created by 韋慶明 on 2016/12/14.n * 測試MyBatis業務邏輯介面類n */nnpublic interface IMyTestService {nn Object selectSort(int id);n}n
Impl實現類:IMyTestService
package com.zhiwu.serviceImpl;nnimport com.zhiwu.dao.IMyTestDao;nimport com.zhiwu.model.SortModel;nimport com.zhiwu.service.IMyTestService;nimport org.springframework.beans.factory.annotation.Autowired;nimport org.springframework.stereotype.Service;nnimport java.util.List;nn/**n * Created by 韋慶明 on 2016/12/14.n * 測試MyBatis業務邏輯實現類n * 注入到Spring容器中 :@Service("myTestImpl")n */nn@Service("myTestImpl")npublic class MyTestImpl implements IMyTestService {nn //使用@Autowired注釋獲取相應的對象n @Autowired(required = false)nprivate IMyTestDao myTestdao;nn public Object selectSort(int id) {nn SortModel model = null;n List<SortModel> list = null;n List<SortModel> listb = null;n try {n n //根據ID獲取Sort表的數據n model = myTestdao.selectSort(id);n n //獲取Sort表所有的數據n list = myTestdao.allSort();n n //根據多條件條件獲取Sort表的數據n SortModel qmodel = new SortModel();n qmodel.setId(1);n listb = myTestdao.querySort(qmodel);nn }catch (Exception e)n {n e.printStackTrace();n }nn //返回Sort表所有的數據,並轉換成json字元串n return JsonUtils.getUtils().toJson(list);n}n
Spring常用註解/注釋介紹:
Spring有四種註解類型:
- @Component – 指示自動掃描組件。
- @Repository – 表示在持久層DAO組件。
- @Service – 表示在業務層服務組件。
- @Controller – 表示在表示層控制器組件。
其實@Repository、@Service 、@Controller 三種類型都會被註解成@Component,但是為了保證框架的層次清晰,不推薦全部使用@Component,而是每一層都使用對應的註解,這樣會讓項目更加層次分明,易讀性高。
@Autowired 注釋:它可以對類成員變數、方法及構造函數進行標註,完成自動裝配的工作。
@Resource 注釋:作用相當於 @Autowired,只不過 @Autowired 按 byType 自動注入,面@Resource 默認按 byName 自動注入罷了,目前比較推薦使用@Resource。
創建介面控制層相應類
package com.zhiwu.controller;nnimport com.zhiwu.service.IMyTestService;nimport com.zhiwu.serviceImpl.MyTestImpl;nimport org.springframework.beans.factory.annotation.Autowired;nimport org.springframework.stereotype.Controller;nimport org.springframework.web.bind.annotation.*;nnimport javax.annotation.Resource;nn/**n * Created by 韋慶明 on 2016/12/14.n * @Controller 採用註解的方式,明確地定義該類為處理請求的Controller類n */nn@Controllern@RequestMapping("/1.0/zhiwu")npublic class MyTestController {nnn//使用@Resource注釋從Spring容器中獲取相應的對象n @Resource(name = "myTestImpl")nprivate IMyTestService myTestService;nn /* 註冊用戶 */n @RequestMapping(value = "/mytest.do",n method = RequestMethod.GET,n produces = "application/json; encoding=UTF-8;charset=UTF-8")n@ResponseBodyn public Object myTest(@RequestParam String data) {n Object result= myTestService.selectSort(1);n return result;n }nn}n
運行起來
如果你按照我寫的步驟一步步創建,那麼現在項目結構應該是這樣的至此,一個SSM框架的項目搭建完成。代碼我會抽時間更新到github上,到時候會在此貼上鏈接。
推薦閱讀:
※大的golang工程都是怎麼從0開始構建的,代碼又是怎麼組織的?
※攜程第四代架構探秘之運維基礎架構升級
※未來會出現96位計算機么?