一、整合思路
SSM框架即SpringMVC + Spring + MyBati框架集,是一種輕量級的Web開源框架。它們各自在JAVA三層架構中負責的模塊如下圖所示:
其中,SpringMVC與Spring之間本就存在包含關系,所以它們之間並不需要整合,只需要在web.xml中配置使用即可。而SpringMVC並不和MyBatis直接交互,因此它們之間也不需要進行配置。只有Spring和MyBatis二者之間,我們需要用Spring來將MyBatis整合進來。
因此,我們只需要對web.xml和Spring的配置文件進行一些額外的配置即可。
下面,我們通過實現一個簡單的轉賬系統,來展示SSM框架的整合和使用。
二、SSM框架整合
首先新建一個JavaWeb項目,導入SpringMVC、Spring、MyBatis三個框架的jar包和它們之間整合所需要的jar包。
在src目錄下創建controller、dao、service、pojo四個包,分別用來存放控制層、持久層、業務層、普通java類的代碼。
配置web.xml,使項目加載SpringMVC和Spring。
1 <?xml version="1.0" encoding="UTF-8"?> 2 <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0"> 3 <display-name>SSM</display-name> 4 <welcome-file-list> 5 <welcome-file>index.html</welcome-file> 6 <welcome-file>index.htm</welcome-file> 7 <welcome-file>index.jsp</welcome-file> 8 <welcome-file>default.html</welcome-file> 9 <welcome-file>default.htm</welcome-file> 10 <welcome-file>default.jsp</welcome-file> 11 </welcome-file-list> 12 <!-- 配置服務器啟動時加載SpringMVC的調度器 --> 13 <servlet> 14 <servlet-name>SpringMVC</servlet-name> 15 <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 16 <load-on-startup>1</load-on-startup> 17 </servlet> 18 <!-- 配置由調度器處理的URL --> 19 <servlet-mapping> 20 <servlet-name>SpringMVC</servlet-name> 21 <url-pattern>/</url-pattern> 22 </servlet-mapping> 23 <!-- 配置監聽器啟動Spring --> 24 <listener> 25 <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 26 </listener> 27 <!-- 指定Spring配置文件路徑 --> 28 <context-param> 29 <param-name>contextConfigLocation</param-name> 30 <param-value>classpath:applicationContext.xml</param-value> 31 </context-param> 32 <!-- 配置過濾器避免中文亂碼 --> 33 <filter> 34 <filter-name>characterEncodingFilter</filter-name> 35 <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> 36 <init-param> 37 <param-name>encoding</param-name> 38 <param-value>UTF-8</param-value> 39 </init-param> 40 </filter> 41 <filter-mapping> 42 <filter-name>characterEncodingFilter</filter-name> 43 <url-pattern>/*</url-pattern> 44 </filter-mapping> 45 </web-app>
在WEB-INF中創建SpringMVC配置文件SpringMVC-servlet.xml(也可以將配置文件放到其他位置,但需要在web.xml中指明配置文件的路徑)和jsp文件夾,jsp文件夾用來存放jsp頁面。
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:context="http://www.springframework.org/schema/context" 5 xsi:schemaLocation=" 6 http://www.springframework.org/schema/beans 7 http://www.springframework.org/schema/beans/spring-beans.xsd 8 http://www.springframework.org/schema/context 9 http://www.springframework.org/schema/context/spring-context.xsd"> 10 <!-- 配置需要注解掃描的控制層包 --> 11 <context:component-scan base-package="controller" /> 12 <!-- 配置視圖解析器 --> 13 <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 14 <property name="prefix" value="/WEB-INF/jsp/"/> 15 <property name="suffix" value=".jsp"/> 16 </bean> 17 </beans>
在src目錄下創建Spring的配置文件applicationContext.xml(文件路徑在web.xml中指定),配置Spring並加載MyBatis。
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:context="http://www.springframework.org/schema/context" 5 xmlns:tx="http://www.springframework.org/schema/tx" 6 xsi:schemaLocation="http://www.springframework.org/schema/beans 7 https://www.springframework.org/schema/beans/spring-beans.xsd 8 http://www.springframework.org/schema/context 9 http://www.springframework.org/schema/context/spring-context.xsd 10 http://www.springframework.org/schema/tx 11 http://www.springframework.org/schema/tx/spring-tx.xsd"> 12 <!-- 配置需要注解掃描的業務層包 --> 13 <context:component-scan base-package="service"/> 14 <!-- 配置數據源 --> 15 <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 16 <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/> 17 <property name="url" value="jdbc:mysql://localhost:3306/user?serverTimezone=Asia/Shanghai"/> 18 <property name="username" value="root"/> 19 <property name="password" value="root"/> 20 </bean> 21 <!-- 配置MyBatis工廠 --> 22 <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> 23 <property name="dataSource" ref="dataSource"/> 24 <property name="configLocation" value="classpath:dao/mybatis-config.xml"/> 25 </bean> 26 <!-- 配置Spring掃描MyBatis的接口 --> 27 <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> 28 <property name="basePackage" value="dao"/> 29 <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/> 30 </bean> 31 <!-- 添加事務支持 --> 32 <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 33 <property name="dataSource" ref="dataSource"/> 34 </bean> 35 <!-- 開啟事務注解掃描 --> 36 <tx:annotation-driven transaction-manager="txManager"/> 37 </beans>
在dao包里創建MyBatis的配置文件mybatis-config.xml(文件路徑在Spring配置文件中指定),指明MyBatis映射文件的路徑。
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE configuration 3 PUBLIC "-//mybatis.org//DTD Config 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-config.dtd"> 5 <configuration> 6 <mappers> 7 <mapper resource="dao/UserMapper.xml"/> 8 </mappers> 9 </configuration>
在dao包中創建MyBatis的映射文件UserMapper.xml,用來后面實現轉賬系統時使用。
到了這里,SSM框架環境就已經搭建完成了,可以開始編寫代碼來實現轉賬系統了。整合后總的目錄結構如下所示:
三、轉賬系統實現
我們要實現的轉賬系統很簡單,該系統具體的操作流程就是“注冊——登錄——轉賬”,用戶注冊后,默認有100元的余額,然后就可以登陸系統,給指定的用戶轉賬。雖然系統簡單,但包含了SSM框架中最基礎的部分。
1、實現持久層
經過分析,我們要實現這樣的轉賬系統,首先需要一個記錄用戶信息的表,因此我們在數據庫中,創建一個user庫和一個user表,表定義如下:
1 CREATE TABLE `user` ( 2 `id` int(11) NOT NULL AUTO_INCREMENT, 3 `username` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, 4 `password` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, 5 `sum` int(11) NOT NULL DEFAULT 100, 6 PRIMARY KEY (`id`) USING BTREE 7 ) ENGINE = InnoDB AUTO_INCREMENT = 10 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
並插入幾條初始數據。
在pojo包中,創建一個跟user表字段對應的類User.java,便於我們傳遞數據。
1 package pojo; 2 3 public class User { 4 5 private int id; 6 7 private String username; 8 9 private String password; 10 11 private int sum; 12 13 public int getId() { 14 return id; 15 } 16 17 public void setId(int id) { 18 this.id = id; 19 } 20 21 public String getUsername() { 22 return username; 23 } 24 25 public void setUsername(String username) { 26 this.username = username; 27 } 28 29 public String getPassword() { 30 return password; 31 } 32 33 public void setPassword(String password) { 34 this.password = password; 35 } 36 37 public int getSum() { 38 return sum; 39 } 40 41 public void setSum(int sum) { 42 this.sum = sum; 43 } 44 45 @Override 46 public String toString() { 47 return "User [id=" + id + ", username=" + username + ", password=" + password + ", sum=" + sum + "]"; 48 } 49 50 }
在前面創建的MyBatis映射文件UserMapper.xml中,寫好需要的SQL語句。
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE mapper 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 5 <mapper namespace="dao.UserDao"> 6 <select id="selectUserByNameAndPass" resultType="pojo.User" parameterType="pojo.User"> 7 select * from user where username = #{username} and password = #{password} 8 </select> 9 <select id="selectUserByName" resultType="pojo.User" parameterType="pojo.User"> 10 select * from user where username = #{username} 11 </select> 12 <insert id="addUser" parameterType="pojo.User"> 13 insert into user (username,password) values (#{username},#{password}) 14 </insert> 15 <update id="updateSumByName" parameterType="pojo.User"> 16 update user set sum = #{sum} where username = #{username} 17 </update> 18 </mapper>
在dao包中創建UserDao.java接口,編寫MyBatis映射接口。
1 package dao; 2 3 import org.apache.ibatis.annotations.Mapper; 4 5 import pojo.User; 6 7 @Mapper 8 public interface UserDao { 9 10 public User selectUserByNameAndPass(User user); 11 12 public int addUser(User user); 13 14 public User selectUserByName(User user); 15 16 public int updateSumByName(User user); 17 }
到這里持久層就編寫完成了,此時的目錄結構如下:
2、實現業務層
經過分析,該系統需要實現的業務有三個,分別是“登錄”、“注冊”和“轉賬”。我們可以在service包下創建UserService.java類,用三個方法來實現這些業務。代碼如下:
1 package service; 2 3 import javax.servlet.http.HttpSession; 4 5 import org.springframework.beans.factory.annotation.Autowired; 6 import org.springframework.stereotype.Service; 7 import org.springframework.transaction.annotation.Transactional; 8 9 import dao.UserDao; 10 import pojo.User; 11 12 @Service 13 public class UserService { 14 15 @Autowired 16 private UserDao userDao; 17 18 @Autowired 19 private HttpSession httpSession; 20 21 public boolean login(User user) { 22 //驗證賬號密碼 23 user = userDao.selectUserByNameAndPass(user); 24 if (user == null) { 25 return false; 26 } 27 //設置Session 28 httpSession.invalidate(); 29 httpSession.setAttribute("username", user.getUsername()); 30 return true; 31 } 32 33 public boolean register(User user) { 34 //檢查用戶名是否重復 35 if (userDao.selectUserByName(user) != null) { 36 return false; 37 } 38 userDao.addUser(user); 39 return true; 40 } 41 42 @Transactional 43 public boolean transfer(User user_in) { 44 //檢查是否自己向自己轉賬 45 if (((String) httpSession.getAttribute("username")).equals(user_in.getUsername())) { 46 return false; 47 } 48 //檢查轉賬金額是否為正數 49 int transferSum = user_in.getSum(); 50 if (transferSum <= 0) { 51 return false; 52 } 53 //檢查轉賬目標用戶是否存在 54 user_in = userDao.selectUserByName(user_in); 55 if (user_in == null) { 56 return false; 57 } 58 //檢查用戶是否有足夠的余額進行轉賬 59 User user_out = new User(); 60 user_out.setUsername((String) httpSession.getAttribute("username")); 61 user_out = userDao.selectUserByName(user_out); 62 int remainSum = user_out.getSum() - transferSum; 63 if ( remainSum < 0) { 64 return false; 65 } 66 //開始轉賬 67 user_out.setSum(remainSum); 68 userDao.updateSumByName(user_out); 69 user_in.setSum(user_in.getSum() + transferSum); 70 userDao.updateSumByName(user_in); 71 return true; 72 } 73 }
三、實現控制層
跟業務層一樣,控制層也需要三個控制器來調用業務層。我們在controller包中創建UserController.java類,同樣需要編寫三個方法,代碼如下:
1 package controller; 2 3 import org.springframework.beans.factory.annotation.Autowired; 4 import org.springframework.stereotype.Controller; 5 import org.springframework.web.bind.annotation.RequestMapping; 6 7 import pojo.User; 8 import service.UserService; 9 10 @Controller 11 public class UserController { 12 13 @Autowired 14 private UserService userService; 15 16 @RequestMapping("/login") 17 public String login(User user) { 18 if(!userService.login(user)) { 19 return "LoginError"; 20 } 21 return "Transfer"; 22 } 23 24 @RequestMapping("/register") 25 public String register(User user) { 26 if(userService.register(user)) { 27 return "RegisterSuccess"; 28 } 29 return "RegisterError"; 30 } 31 32 @RequestMapping("/transfer") 33 public String transfer(User user) { 34 if (userService.transfer(user)) { 35 return "TransferSuccess"; 36 } 37 return "TransferError"; 38 } 39 }
4、實現視圖層
根據控制層中的定義,我們總共需要編寫七個jsp頁面,分別如下:
登錄注冊頁面login.jsp:
1 <%@ page language="java" contentType="text/html; charset=UTF-8" 2 pageEncoding="UTF-8"%> 3 <!DOCTYPE html> 4 <html> 5 <head> 6 <meta charset="UTF-8"> 7 <title>登錄</title> 8 </head> 9 <body> 10 <form action="${pageContext.request.contextPath}/login" method="post"> 11 <table> 12 <tr> 13 <td align="right">用戶名:</td> 14 <td><input type="text" name="username"/></td> 15 </tr> 16 <tr> 17 <td align="right">密碼:</td> 18 <td><input type="password" name="password"/></td> 19 </tr> 20 <tr> 21 <td align="center" colspan="2"><input type="submit" value="登錄"/><input type="submit" value="注冊" formaction="${pageContext.request.contextPath}/register"/></td> 22 </tr> 23 </table> 24 </form> 25 </body> 26 </html>
登錄失敗頁面LoginError.jsp:
1 <%@ page language="java" contentType="text/html; charset=UTF-8" 2 pageEncoding="UTF-8"%> 3 <!DOCTYPE html> 4 <html> 5 <head> 6 <meta charset="UTF-8"> 7 <title>登錄失敗</title> 8 </head> 9 <body> 10 用戶名或密碼錯誤! 11 </body> 12 </html>
登錄成功后的轉賬頁面Transfer.jsp:
1 <%@ page language="java" contentType="text/html; charset=UTF-8" 2 pageEncoding="UTF-8"%> 3 <!DOCTYPE html> 4 <html> 5 <head> 6 <meta charset="UTF-8"> 7 <title>轉賬</title> 8 </head> 9 <body> 10 <form action="${pageContext.request.contextPath}/transfer" method="post"> 11 <table> 12 <tr> 13 <td align="center" colspan="2">歡迎你!${user.username}</td> 14 </tr> 15 <tr> 16 <td align="right">用戶名:</td> 17 <td><input type="text" name="username"/></td> 18 </tr> 19 <tr> 20 <td align="right">金額:</td> 21 <td><input type="text" name="sum"/></td> 22 </tr> 23 <tr> 24 <td/> 25 <td align="right"><input type="submit" value="轉賬"/></td> 26 </tr> 27 </table> 28 </form> 29 </body> 30 </html>
注冊失敗頁面RegisterError.jsp:
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 3 <html xmlns="http://www.w3.org/1999/xhtml"> 4 <head> 5 <%@ page language="java" contentType="text/html; charset=UTF-8" 6 pageEncoding="UTF-8"%> 7 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 8 <title>注冊失敗</title> 9 </head> 10 <body> 11 注冊失敗! 12 </body> 13 </html>
注冊成功頁面RegisterSuccess.jsp:
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 3 <html xmlns="http://www.w3.org/1999/xhtml"> 4 <head> 5 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> 6 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 7 <title>注冊成功</title> 8 </head> 9 <body> 10 注冊成功! 11 </body> 12 </html>
轉賬失敗頁面TransferError.jsp:
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 3 <html xmlns="http://www.w3.org/1999/xhtml"> 4 <head> 5 <%@ page language="java" contentType="text/html; charset=UTF-8" 6 pageEncoding="UTF-8"%> 7 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 8 <title>轉賬失敗</title> 9 </head> 10 <body> 11 轉賬失敗! 12 </body> 13 </html>
轉賬成功頁面TransferSuccess.jsp:
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 3 <html xmlns="http://www.w3.org/1999/xhtml"> 4 <head> 5 <%@ page language="java" contentType="text/html; charset=UTF-8" 6 pageEncoding="UTF-8"%> 7 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 8 <title>轉賬成功</title> 9 </head> 10 <body> 11 轉賬成功! 12 </body> 13 </html>
到這里,該轉賬系統基本實現,最終的目錄結構如下:
運行截圖:
可見admin賬戶成功向ysy賬戶轉賬50元。