SSM框架簡介及整合教程


1.Spring

Spring 框架是 Java 應用最廣的框架,它的成功來源於理念,而不是技術本身,它的理念包括 IoC (控制反轉)A面向切面編程)。Spring框架是個輕量級的Java EE框架,所謂輕量級,是指不依賴於容器就能運行的。簡單來說,Spring是一個輕量級的控制反轉(IoC)和面向切面(AOP)的容器框架。

2.Spring MVC

作用於web層,相當於controller,與struts中的action一樣,都是用來處理用戶請求的。同時,相比於struts2來說,更加細粒度,它是基於方法層面的,而struts是基於類層面的。Spring MVC 分離了控制器、模型對象、分派器以及處理程序對象的角色,這種分離讓它們更容易進行定制。

Struts2 與 SpringMVC 的對比:

3.MyBatis

MyBatis 本是apache的一個開源項目iBatis, 2010年這個項目由apache software foundation 遷移到了google code,並且改名為MyBatis 。MyBatis 是一款優秀的持久層框架,它支持定制化 SQL、存儲過程以及高級映射。MyBatis 避免了幾乎所有的 JDBC 代碼和手動設置參數以及獲取結果集。MyBatis 可以使用簡單的 XML 或注解來配置和映射原生信息,將接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java對象)映射成數據庫中的記錄。

Hibernate 和 MyBatis 的對比:

  • Hibernate功能強大,數據庫無關性好,O/R映射能力強,如果你對Hibernate相當精通,而且對Hibernate進行了適當的封裝,那么你的項目整個持久層代碼會相當簡單,需要寫的代碼很少,開發速度很快,非常爽。
  • Hibernate的缺點就是學習門檻不低,要精通門檻更高,而且怎么設計O/R映射,在性能和對象模型之間如何權衡取得平衡,以及怎樣用好Hibernate方面需要你的經驗和能力都很強才行。
  • MyBatis入門簡單,即學即用,提供了數據庫查詢的自動對象綁定功能,而且延續了很好的SQL使用經驗,對於沒有那么高的對象模型要求的項目來說,相當完美。
  • MyBatis的缺點就是框架還是比較簡陋,功能尚有缺失,雖然簡化了數據綁定代碼,但是整個底層數據庫查詢實際還是要自己寫的,工作量也比較大,而且不太容易適應快速數據庫修改。

4.SSM框架整合

本項目將以購物為背景,主要包括商品信息及庫存【因為想順便學習一下事務的處理】、訂單信息。下面將從數據庫創建、項目結構說明、配置文件、業務代碼等方面進行一步步說明。

4.1 數據庫創建

1. 商品表

初始化表數據

2. 訂單表

1
2
3
4
5
6
7
8
CREATE TABLE `orderinfo` (
`order_id` varchar( 20 ) NOT NULL COMMENT '訂單編號' ,
`goods_id` bigint( 18 ) NOT NULL COMMENT '商品ID' ,
`user_id` bigint( 10 ) NOT NULL COMMENT '用戶ID' ,
`order_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '下單時間' ,
  PRIMARY KEY (`order_id`),
  INDEX `idx_order_id` (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT= '訂單表'

OK,至此表結構及初始化數據構建完成,下面說下基於Mavan的項目結構。

4.2 項目結構說明

因為項目是使用maven來管理jar包的,先來貼一下,pom.xml的配置

pom.xml

為了避免學習小伙伴崇尚拿來主義【也就是去除了xmlns之類的東西】,這里只放項目依賴的jar包的dependencies;本案例將本着“需則用”的原則,避免在網上看到的各種亂七八糟的依賴都丟進來的情況,造成資源浪費和干擾閱讀。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
<dependencies>
       <!-- 單元測試 -->
       <dependency>
           <groupId>junit</groupId>
           <artifactId>junit</artifactId>
           <version> 4.11 </version>
       </dependency>
  
       <!-- 1 .日志 slf4j-->
       <dependency>
           <groupId>ch.qos.logback</groupId>
           <artifactId>logback-classic</artifactId>
           <version> 1.1 . 1 </version>
       </dependency>
  
       <!-- 2 .數據庫連接驅動 -->
       <dependency>
           <groupId>mysql</groupId>
           <artifactId>mysql-connector-java</artifactId>
           <version> 5.1 . 37 </version>
           <scope>runtime</scope>
       </dependency>
       <!-- 2 .數據庫連接池 -->
       <dependency>
           <groupId>c3p0</groupId>
           <artifactId>c3p0</artifactId>
           <version> 0.9 . 1.2 </version>
       </dependency>
  
       <!-- 3 .MyBatis 以及 spring-mybatis -->
       <dependency>
           <groupId>org.mybatis</groupId>
           <artifactId>mybatis</artifactId>
           <version> 3.3 . 0 </version>
       </dependency>
       <dependency>
           <groupId>org.mybatis</groupId>
           <artifactId>mybatis-spring</artifactId>
           <version> 1.2 . 3 </version>
       </dependency>
  
       <!-- 4 .Servlet 相關依賴 -->
       <dependency>
           <groupId>taglibs</groupId>
           <artifactId>standard</artifactId>
           <version> 1.1 . 2 </version>
       </dependency>
       <dependency>
           <groupId>jstl</groupId>
           <artifactId>jstl</artifactId>
           <version> 1.2 </version>
       </dependency>
       <dependency>
           <groupId>com.fasterxml.jackson.core</groupId>
           <artifactId>jackson-databind</artifactId>
           <version> 2.5 . 4 </version>
       </dependency>
       <dependency>
           <groupId>javax.servlet</groupId>
           <artifactId>javax.servlet-api</artifactId>
           <version> 3.1 . 0 </version>
       </dependency>
  
       <!-- 5 .Spring -->
  
       <!-- 5.1 Spring核心 :core bean context -->
       <dependency>
           <groupId>org.springframework</groupId>
           <artifactId>spring-core</artifactId>
           <version> 4.1 . 7 .RELEASE</version>
       </dependency>
       <dependency>
           <groupId>org.springframework</groupId>
           <artifactId>spring-beans</artifactId>
           <version> 4.1 . 7 .RELEASE</version>
       </dependency>
       <dependency>
           <groupId>org.springframework</groupId>
           <artifactId>spring-context</artifactId>
           <version> 4.1 . 7 .RELEASE</version>
       </dependency>
       <!-- 5.2 Spring jdbc依賴,事務依賴 -->
       <dependency>
           <groupId>org.springframework</groupId>
           <artifactId>spring-jdbc</artifactId>
           <version> 4.1 . 7 .RELEASE</version>
       </dependency>
       <dependency>
           <groupId>org.springframework</groupId>
           <artifactId>spring-tx</artifactId>
           <version> 4.1 . 7 .RELEASE</version>
       </dependency>
       <!-- 5.3 Spring web依賴>
       <dependency>
           <groupId>org.springframework</groupId>
           <artifactId>spring-web</artifactId>
           <version> 4.1 . 7 .RELEASE</version>
       </dependency>
       <dependency>
           <groupId>org.springframework</groupId>
           <artifactId>spring-webmvc</artifactId>
           <version> 4.1 . 7 .RELEASE</version>
       </dependency>
       <!-- 5.4 Spring test -->
       <dependency>
           <groupId>org.springframework</groupId>
           <artifactId>spring-test</artifactId>
           <version> 4.1 . 7 .RELEASE</version>
       </dependency>
  
       <!-- 6 .redis客戶端:Jedis【不使用的話可以直接去除】 -->
       <dependency>
           <groupId>redis.clients</groupId>
           <artifactId>jedis</artifactId>
           <version> 2.7 . 3 </version>
       </dependency>
       <dependency>
           <groupId>com.dyuproject.protostuff</groupId>
           <artifactId>protostuff-core</artifactId>
           <version> 1.0 . 8 </version>
       </dependency>
       <dependency>
           <groupId>com.dyuproject.protostuff</groupId>
           <artifactId>protostuff-runtime</artifactId>
           <version> 1.0 . 8 </version>
       </dependency>
  
       <!-- 7 .工具類 -->
       <dependency>
           <groupId>commons-collections</groupId>
           <artifactId>commons-collections</artifactId>
           <version> 3.2 </version>
       </dependency>
   </dependencies>

*項目結構圖

src/test/java:用於junit的測試類 src/main/java:
dao:數據庫處理
service:業務處理
enums:項目枚舉
mapper:dao中方法對應mybatis映射文件,Sql就在這里面
web:控制器,controller
entity:項目中的實體類,如:商品類和訂單類

4.3 配置文件

jdbc.properties

logback.xml

這里直接用的是控制台輸出,如果是生產環境,可以根據具體的需求進行配置。

mybatis-config

這里主要是MyBaties全局配置文件的配置,可以將一些類的別名、主鍵自增配置、駝峰命名規則配置等。

spring 相關配置文件

為了更加清晰的了解spring各個組件的作用,這里將數據源的配置、事務配置和視圖解析器的配置分開來。

spring-dao.xml

這里面主要就是spring配置整合mybatis的具體過程,具體包括:

  1. 引入數據庫配置文件
  2. 配置數據源【數據庫連接池】
  3. 配置SqlSessionFactory對象
  4. 配置掃描Dao接口包,動態實現Dao接口,注入到spring容器中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<!-- 1 .配置數據庫相關參數properties的屬性:${url} -->
<context:property-placeholder location= "classpath:jdbc.properties" />
  
<!-- 2 .數據庫連接池 -->
<bean id= "dataSource" class = "com.mchange.v2.c3p0.ComboPooledDataSource" >
    <!-- 配置連接池屬性 -->
    <property name= "driverClass" value= "${jdbc.driver}" />
    <property name= "jdbcUrl" value= "${jdbc.url}" />
    <property name= "user" value= "${jdbc.username}" />
    <property name= "password" value= "${jdbc.password}" />
  
    <!-- c3p0連接池的私有屬性 -->
    <property name= "maxPoolSize" value= "30" />
    <property name= "minPoolSize" value= "10" />
    <!-- 關閉連接后不自動commit -->
    <property name= "autoCommitOnClose" value= "false" />
    <!-- 獲取連接超時時間 -->
    <property name= "checkoutTimeout" value= "10000" />
    <!-- 當獲取連接失敗重試次數 -->
    <property name= "acquireRetryAttempts" value= "2" />
</bean>
  
<!-- 3 .配置SqlSessionFactory對象 -->
<bean id= "sqlSessionFactory" class = "org.mybatis.spring.SqlSessionFactoryBean" >
    <!-- 注入數據庫連接池 -->
    <property name= "dataSource" ref= "dataSource" />
    <!-- 配置MyBaties全局配置文件:mybatis-config.xml -->
    <property name= "configLocation" value= "classpath:mybatis-config.xml" />
    <!-- 掃描entity包 使用別名 -->
    <property name= "typeAliasesPackage" value= "com.glmapper.framerwork.entity" />
    <!-- 掃描sql配置文件:mapper需要的xml文件 -->
    <property name= "mapperLocations" value= "com.glmapper.framerwork.mapper/*.xml" />
</bean>
  
<!-- 4 .配置掃描Dao接口包,動態實現Dao接口,注入到spring容器中 -->
<bean class = "org.mybatis.spring.mapper.MapperScannerConfigurer" >
    <!-- 注入sqlSessionFactory -->
    <property name= "sqlSessionFactoryBeanName" value= "sqlSessionFactory" />
    <!-- 給出需要掃描Dao接口包 -->
    <property name= "basePackage" value= "com.glmapper.framerwork.dao" />
</bean>

spring-service

實際的開發過程中事務一般都是在service層進行操作。因此用一個單獨的spring-service.xml來進行事務的相關的配置

spring-web.xml

配置SpringMVC;需要說明一下,一般我們在實際的開發過程中,會配置json2map解析。這里沒有用到就不貼出來,讀者可以自行網上搜索一波。

web.xml

<!-- 編碼過濾器 -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<async-supported>true</async-supported>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Spring監聽器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 防止Spring內存溢出監聽器 -->
<listener>
<listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
</listener>
<!-- 配置DispatcherServlet -->
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 配置springMVC需要加載的配置文件
spring-dao.xml,spring-service.xml,spring-web.xml
Mybatis - > spring -> springmvc
-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/spring-*.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<!-- 默認匹配所有的請求 -->
<url-pattern>/</url-pattern>
</servlet-mapping>

至此,所有的配置文件結束,下面將進行具體的代碼環節

4.4 業務代碼

這里mapper中的xml文件就不貼了,自行腦補。。。。

實體類:包括商品和訂單

商品類

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/**
  * 商品信息類
  * @author glmapper
  *
  */
public class Goods {
     private long goodsId; // 商品ID
     private String goodsName; // 商品名稱
     private int number; // 商品庫存
  
     public long getGoodsId() {
         return goodsId;
     }
     public void setGoodsId( long goodsId) {
         this .goodsId = goodsId;
     }
     public String getGoodsName() {
         return goodsName;
     }
     public void setGoodsName(String goodsName) {
         this .goodsName = goodsName;
     }
     public int getNumber() {
         return number;
     }
     public void setNumber( int number) {
         this .number = number;
     }
}

訂單類

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/**
  * 訂單信息類
  * @author glmapper
  *
  */
public class OrderInfo {
     private String orderId; //訂單ID
     private long goodsId; //商品ID
     private long userId; //用戶ID
     private Date orderTime; //下單時間
     public String getOrderId() {
         return orderId;
     }
     public void setOrderId(String orderId) {
         this .orderId = orderId;
     }
     public long getGoodsId() {
         return goodsId;
     }
     public void setGoodsId( long goodsId) {
         this .goodsId = goodsId;
     }
     public long getUserId() {
         return userId;
     }
     public void setUserId( long userId) {
         this .userId = userId;
     }
     public Date getOrderTime() {
         return orderTime;
     }
     public void setOrderTime(Date orderTime) {
         this .orderTime = orderTime;
     }
}
  • 商品dao
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public interface GoodsDao {
  
     /**
      * 通過ID查詢單件商品信息
      *
      * @param id
      * @return
      */
     Goods queryById( long id);
  
     /**
      * 查詢所有商品信息
      *
      * @param offset 查詢起始位置
      * @param limit 查詢條數
      * @return
      */
     List<Goods> queryAll( @Param ( "offset" ) int offset, @Param ( "limit" ) int limit);
  
     /**
      * 減少商品庫存
      *
      * @param bookId
      * @return 如果影響行數等於>1,表示更新的記錄行數
      */
     int reduceNumber( long goodsId);
  
}
  • 訂單dao
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public interface OrderInfoDao {
  
   /**
    * 插入訂單記錄
    *
    * @param OrderInfo orderInfo
    * @return 插入的行數
    */
   int insertOrderInfo(OrderInfo orderInfo);
  
   /**
    * 通過主鍵查詢訂單記錄,返回訂單實體
    * @param orderId
    * @return
    */
   OrderInfo queryByOrderId(String orderId);
}
  • 下單服務接口orderService
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
@Service ( "orderService" )
public class OrderServiceImpl implements OrderService {
   //log生成器
   private Logger logger = LoggerFactory.getLogger(OrderServiceImpl. class );
  
   // 注入dao依賴【商品dao,訂單dao】
   @Autowired
   private GoodsDao goodsDao;
   @Autowired
   private OrderInfoDao orderInfoDao;
  
   @Override
   public Goods getById( long goodsId) {
       // TODO Auto-generated method stub
       return goodsDao.queryById(goodsId);
   }
  
   @Override
   public List<Goods> getList( int offset, int limit) {
       // TODO Auto-generated method stub
       return goodsDao.queryAll(offset, limit);
   }
  
   @Override
   @Transactional
   public OrderInfo buyGoods( long goodsId, long userId) {
       //扣減庫存,插入訂單 =一個事務  如果失敗則執行回滾
       try {
           // 減庫存
           int update = goodsDao.reduceNumber(goodsId);
           if (update <= 0 ) { // 庫存不足
               throw new NoNumberException( "no number" );
           } else {
               // 執行預約操作
               OrderInfo orderInfo= new OrderInfo();
               orderInfo.setGoodsId(goodsId);
               orderInfo.setUserId(userId);
               orderInfo.setOrderTime( new Date());
               String orderId=getRandomOrderId(goodsId);
               orderInfo.setOrderId(orderId);
               int insert = orderInfoDao.insertOrderInfo(orderInfo);
               if (insert <= 0 ) { // 重復預約
                   throw new RepeatAppointException( "repeat appoint" );
               } else { // 預約成功
                   return orderInfo;
               }
           }
       } catch (Exception e) {
           //這里可以豐富下具體的返回信息
           logger.error( "下單失敗" );
       }
       return null ;
   }
  
   private String getRandomOrderId( long goodsId) {
       SimpleDateFormat dateFormater = new SimpleDateFormat( "yyyyMMddhhmmss" );
       String prefix=dateFormater.format( new Date());
       String goodsIdStr=goodsId+ "" ;
       String temp= "" ;
       for ( int i = 0 ; i < 6 ; i++) {
           Random random= new Random(goodsIdStr.length()- 1 );
           temp+=goodsIdStr.charAt(random.nextInt());
       }
       return prefix+temp;
   }
}

OK,至此所有核心代碼及配置文件羅列完畢;【mapper中的xml和具體的controller就不貼了,相信大家對這個也不陌生。本文主要意圖在於梳理下自己學習中的一些點,SSM框架在實際的應用開發中還會有很多其他的開源技術結合進來,如:quartz,redis等。當前本文的列子就是一個空殼子,以備參考吧】


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM