[手把手教程][JavaWeb]SSM框架驗證、修復和實例
手把手驗證上期的SSM項目:優雅的SpringMvc+Mybatis整合之路框架。
- 說實話,這一期也應該算是上一期的,但是這起需要單獨拿出來的原因有幾個,最重要的是我個人討厭長篇大論。(最簡單的就是直接丟項目)
- 但是,直接丟出來,未免太過粗糙,也不能體驗出我們編程的思維養成,故此一步一步的走出來。
- 對于很多哥們催更的事情,這個確實也不是那么容易出來的,前面的框架搭建是從網上找的資料一步一步的組合的,但是實際使用還是有很多問題,本篇文章將會解決這些問題。
- 同時,兄弟們稍微耐心點,我這邊也是一點點實現,還請客官們放下手中的西瓜刀。
- 再次安利一波,博客地址:acheng1314.cn
工具
- IDE為idea15
- JDK環境為1.8
- maven版本為maven3
- Mysql版本為5.5.27
- Tomcat版本為7.0.52
本期目標
- 項目框架介紹和沖突解決。
- 實例Service和Dao。項目框架測試。
- 登錄、注冊業務的分析、創建和演示。
沖突解決
為什么我把沖突解決放在第一位?
因為在沖突解決后,我們可以進入測試階段,同時在解決沖突的時候,我們會一點點的體會到SSM項目框架中各個框架之間是怎么協同工作的,也就可以完成項目介紹。
重要的是,在實際生活中,我們去公司上班,一般也是先解決項目框架沖突問題。
-
打開項目后,隨意選擇一個Spring的配置文件,會彈出如下界面:
ssm框架檢測第一步我們點擊圖中右上角圈出來部分,會彈出如下界面:
ssm框架檢測第二步這里我們什么都不需要做,直接點擊OK。
上面兩步是為了告訴Idea我們的Spring配置文件在哪。類似單一Spring配置文件的ApplicationContext.xml一樣,我們只是將Spring根據模塊分發而已。
-
在Tomcat中運行本項目,運行結果應該是在瀏覽器中顯示Hello World界面。
配置Tomcat
配置項目的Tomcat啟動設置。
參考連接:點擊進入
-
在web瀏覽器中輸入:localhost:8080/druid ,查看druid是否配置成功。
ssm框架檢測第三步如上面的圖中,我們可以看到我們的druid并沒有把JDBC驅動列出來。這說明我們的項目的JDBC驅動要么沒有設置,要么是數據庫驅動的配置文件沒做好。
-
隨意輸入一個localhost:8080/下的地址,至此我們要展示錯誤404頁面。并且把Tomcat不友好的404頁面替換。
替換思路:錯誤404這種常出現的頁面,我們可以設置為靜態資源,以加快網頁訪問。
-
注意:我們需要先把WEB-IN\Fweb.xml下面的mvc-dispatcher更改為全局配置。
<servlet-mapping> <servlet-name>mvc-dispatcher</servlet-name> <!-- 默認匹配所有的請求 --> <!-- 我們默認配置這個是為了讓我們的Spring框架接管Servelt,實現Spring控制所有站點請求 --> <url-pattern>/</url-pattern> <!--<url-pattern>/css/*</url-pattern>--> <!--<url-pattern>/images/*</url-pattern>--> <!--<url-pattern>/fonts/*</url-pattern>--> </servlet-mapping>
配置了web.xml后,我們重啟重啟應用,輸入一個錯誤的地址(跳轉到404頁面),會發現提示錯誤信息,主要報錯如下
Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in file [項目所在的物理地址\WEB-INF\classes\spring\spring-dao.xml]: Initialization of bean failed; nested exception is java.lang.NoClassDefFoundError: org/slf4j/Logger //上面這個錯誤主要是提示我們:NoClassDefFoundError: org/slf4j/這個類找不到。 解決辦法:偷懶的把log4j2從maven配置文件中刪除了,開啟了logback,在maven的pom.xml中: <!-- 1.日志 --> <!--<!– 實現slf4j接口并整合 –>--> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.1.1</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${org.slf4j.version}</version> </dependency> <!--log4j2支持--> <!--<dependency>--> <!--<groupId>org.apache.logging.log4j</groupId>--> <!--<artifactId>log4j-core</artifactId>--> <!--<version>${org.apache.logging.log4j.version}</version>--> <!--</dependency>--> <!--<dependency>--> <!--<groupId>org.apache.logging.log4j</groupId>--> <!--<artifactId>log4j-api</artifactId>--> <!--<version>${org.apache.logging.log4j.version}</version>--> <!--</dependency>-->
接著,我們重啟Tomcat,等項目部署完成后,我們再次打開,再次輸入錯誤地址,我們發現還是在報錯,信息如下:
Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sqlSessionFactory' defined in file [項目物理地址\WEB-INF\classes\spring\spring-dao.xml]: Initialization of bean failed; nested exception is org.springframework.beans.TypeMismatchException: Failed to convert property value of type [java.lang.String] to required type [org.springframework.core.io.Resource[]] for property 'mapperLocations'; nested exception is java.lang.IllegalArgumentException: Could not resolve resource location pattern [classpath:mapper/*.xml]: class path resource [mapper/] cannot be resolved to URL because it does not exist 根據上面的提示信息,我們可以看到提示的是mapper下面沒有文件,那么我們就給他制定一個空的配置文件(BaseDao.xml),內容如下: <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!-- namespace是指明Mybatis掃描的目錄,mapper是我們的Dao層的映射目錄 --> <mapper namespace="cn.acheng1314.dao"> </mapper>
同樣的,我們再次重啟服務器,并且輸入錯誤的地址,現在能正常顯示錯誤404的頁面了,但是頁面太過Low了,我們得重寫一下web.xml的配置。404頁面如下所示:
ssm框架檢測404模版頁面解決思路:錯誤404的頁面是常用頁面之一,所以我們在項目的資源目錄(webapp)下創建一個static目錄,專門用來存放靜態資源,如js、css、錯誤提示頁面、登錄、注冊頁面等等。
通過網上查閱資料,我們看到大部分人都是把404頁面提示信息提交給Servelt自己管理,我們也依樣畫瓢,在web.xml中配置,如下: <error-page> <error-code>404</error-code> <Location>/static/view/404.html</Location> </error-page>
同時,我們需要給Spring寫一個web的配置,控制哪些資源被攔截。spring-web.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:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"> <!-- 配置SpringMVC --> <!-- 1.開啟SpringMVC注解模式 --> <!-- 簡化配置: (1)自動注冊DefaultAnootationHandlerMapping,AnotationMethodHandlerAdapter (2)提供一些列:數據綁定,數字和日期的format @NumberFormat, @DateTimeFormat, xml,json默認讀寫支持 --> <mvc:annotation-driven/> <!-- 2.靜態資源默認servlet配置 (1)加入對靜態資源的處理:js,gif,png (2)允許使用"/"做整體映射 --> <mvc:resources mapping="/css/**" location="/static/css/" /> <mvc:resources mapping="/images/**" location="/static/images/" /> <mvc:resources mapping="/view/**" location="/static/view/" /> <mvc:default-servlet-handler/> <!-- 3.配置jsp 顯示ViewResolver --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/> </bean> <!-- 4.掃描web相關的bean配置 --> <context:component-scan base-package="cn.acheng1314.mvc"> <!-- 制定掃包規則 ,只掃描使用@Controller注解的JAVA類 --> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan> </beans>
以上文件配置好后,我們重啟服務器,并輸入錯誤地址,現在我們插入的404頁面正常顯示了。
通過上面的資料,我們可以大膽整理下web請求的思路:
用戶發起請求→DNS解析發現服務器→建立鏈接發送請求→WEB服務器分發給應用服務器→MVC層框架處理請求過程→返回數據給用戶
而上面的SpringMvc作為框架層,我們也可以通過網上資料和我們目前的配置做出一些構想:
Tomact分發請求→Servelt收到請求→Spring接管Servelt→DispatcherServlet處理請求分發→根據Spring配置找到對應的控制器(Controller)處理業務→返回對應數據。
而下面有一張更加突出的圖片說明了這一切:
SpringMVC詳細運行流程圖總結:目前項目中的靜態資源我們已經處理完畢,加入了一部分Web的靜態資源,增加了Spring的web處理配置,修改了web.xml,log4j2替換為LogBack,Junit版本提升為4.12,加入了一個BaseMapper.xml。
web.xml文件如下:
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1" metadata-complete="true"> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> <!-- 如果是用mvn命令生成的xml,需要修改servlet版本為3.1 --> <!-- 配置DispatcherServlet --> <servlet> <display-name>SSM</display-name> <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> <!--<url-pattern>/css/*</url-pattern>--> <!--<url-pattern>/images/*</url-pattern>--> <!--<url-pattern>/fonts/*</url-pattern>--> </servlet-mapping> <!-- spring框架提供的字符集過濾器 --> <!-- spring Web MVC框架提供了org.springframework.web.filter.CharacterEncodingFilter用于解決POST方式造成的中文亂碼問題 --> <filter> <filter-name>encodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <!-- force強制,促使 --> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!--druid ==> WEB方式監控配置--> <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> <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>/public/*,*.js,*.css,/druid*,*.jsp,*.swf</param-value> </init-param> <init-param> <param-name>principalSessionName</param-name> <param-value>sessionInfo</param-value> </init-param> <init-param> <param-name>profileEnable</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>druidWebStatFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <error-page> <error-code>404</error-code> <location>/static/view/404.html</location> </error-page> </web-app>
BaseMapper.xml如下:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!-- namespace指向我們的dao所在的地址 --> <mapper namespace="cn.acheng1314.dao"> </mapper>
其他的文件修改的信息都可以在上面看到就不再次貼出來了。
SSM框架實例--倉庫管理系統--登錄注冊的功能分析
分析:
- 登錄和注冊,都是用戶的行為,也是我們開發中常說的某個行為對應的業務。
- 注冊用戶,意味著添加用戶,添加了用戶后,我們才有登錄功能的繼續執行的可能。
- 用戶登錄,也是用戶信息的查找和比對過程。一般來說用戶先把信息提交給程序,然后程序按照流程執行后提交數據給服務器(這個流程中程序可能會產生一些業務邏輯的判斷),服務器收到數據并進行數據對比,當用戶信息存在且帳號和密碼匹配才能登錄成功,否則前面的任意條件不滿足即為登錄失敗。
- 我們可以依靠單一的用戶表來實現用戶的登錄數據獲取和注冊信息的添加。
功能大概分析完畢后,我們就可以考慮下如何實現這些功能。大概圖示如下:

- 首先用戶信息需要存儲,我們需要數據庫的支撐。
- 有了數據庫的支援后,我們需要先測試用戶信息的添加和查找。就是我們常說的Dao層。
- 當我們的Dao層拿到想要的數據,我們需要Service層將Dao層的操作作為服務提供給控制器,再由控制器提供給前臺頁面。
- 同樣的用戶需要獲取某個數據,先是瀏覽器獲取到用戶請求→web層→Service層→Dao層,再接著重復上面的操作。
上面一張圖用模型已經很好的說明了java web后端各層的關系,下面一張圖是經典三層對照MVC的描述。

上面的圖引用自互聯網資料,下面的黑色字是我添加上去的。
上面圖中,我們可以看到一部分MVC設計和圖中標記的類似,但是這只是一種MVC模式的栗子。
-
關于更加詳細的MVC,我們可以百度百科查看。
上面提到的東西,我們適可而止就行了,很多東西現在還不是深究的時候,我們要先懂一個事物的外在表現,才有進一步的探索,所以我們需要等緣分的到來。
SSM框架實例--倉庫管理系統--注冊、登錄的功能模擬實現
按照前面我們的分析來講,我們需要先考慮Dao層的實現,畢竟有了Dao層對數據的封裝,才可以有后面的操作,所以后面我的栗子中,一切都是按照Dao→Service→Controller→View這樣的一個步驟來實現。
- 用戶注冊功能的Dao層實現。
數據庫基本操作為:增刪改查。
-
我們根據數據庫常規操作的類型,分別對其進行抽象,所以產生了Dao.java這個接口對象的基本模型。代碼如下:
/** * 通過接口編程 * @param <T> 泛型用于解耦,同時避免寫重復代碼 */ public interface Dao<T> { /** * 添加某個對象 * @param t 待添加的對象 * @return 返回受影響的行數 */ int add(T t); /** * 刪除某個對象,在企業開發中,我們一般不做物理刪除,只是添加某個字段對其數據進行可用控制 * @param t 待刪除對象 * @return 返回受影響的條數 */ int del(T t); /** * 更新某個對象 * @param t 待更新對象 * @return 返回受影響的條數 */ int update(T t); /** * 通過ID查找一個對象 * @param Id 待查詢的對象的ID * @return 返回該ID對應的對象 */ T findOneById(Serializable Id); /** * 查找對象集合 * @return 返回對象集合 */ List<T> findAll(); }
-
實現用戶的Dao層:
- 我們要針對用戶寫用戶的Dao層,我們需要有一個用戶對象的封裝,直接在domain包下面創建User.java,代碼如下:
/*** 創建數據庫用戶表: CREATE TABLE `user` ( `login_id` varchar(20) NOT NULL COMMENT '登陸ID', `pwd` varchar(20) NOT NULL COMMENT '用戶密碼', `name` varchar(100) NOT NULL COMMENT '用戶姓名', `age` int(3) NOT NULL COMMENT '用戶年齡', `sex` varchar(3) NOT NULL COMMENT '性別', `duty` varchar(15) COMMENT '職務', `cell_number` varchar(15) COMMENT '手機號', `photo_url` varchar(75) COMMENT '頭像地址', `used` boolean NOT NULL COMMENT '賬號是否可用', PRIMARY KEY (`login_id`) ) ENGINE=InnoDB AUTO_INCREMENT=1000 DEFAULT CHARSET=utf8 COMMENT='用戶表'; 插入默認數據: INSERT INTO `user` (`login_id`,`pwd`,`name`,`age`,`sex`,`used`) VALUES ('pc859107393','123456','阿程',20,'男',true), ('pc228568859','123456','chengcheng',20,'女',true), ('pangpang','123456','余下一整夜',25,'男',true), ('111111','123456','手拉手系列教程',22,'女',true); */ public class User implements Serializable { private String name; //名字 private String sex; //性別 private String loginId; //登陸ID private String pwd; //密碼 private String duty; //職務 private int age; //年齡 private String cellNumber; //手機號 private String photoUrl; //頭像地址 private boolean used = true; //是否可用,默認值是true ···省略get、set和toString } //推薦大家把每個bean對應的數據庫操作備注到上面。 //打開Navicat For Mysql,鏈接上數據庫,創建對應的數據庫,并運行上面的sql產生數據庫表和初始記錄。
- 當我們數據庫創建完畢后,我們需要寫一個接口對user表進行操作封裝。我們在dao包下面創建UserDao接口,代碼如下:
/** * 在傳統的jdbc操作中,我們需要手動管理數據庫連接的開關,數據庫資源訪問的開關等等 * <br/>但是,我們這里采用了Mybatis和Druid這兩個框架,那么我們可以完全不必理會數據庫連接等等的控制, * <br/>我們只需要更加專注于業務實現的開發。 */ public interface UserDao extends Dao<User> { int add(User user); int del(User user); int update(User user); User findOneById(Serializable Id); List<User> findAll(); }
- 完成UserDao的封裝后,傳統的操作這一步需要自己手動實現UserDao的Impl,并實現對數據庫的操作等等。而我們使用Mybatis后,UserDao的Impl在Mybatis的mapper文件夾中指定為xml,我們的Dao文件除了數據庫操作的語句其他的都無需關注,那么剩下的數據庫操作什么的我們都無需關心,畢竟Mybatis和druid都把其他的事情幫我們做了。UserDao.xml如下:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!-- namespace指定我們的到具體的bean --> <mapper namespace="cn.acheng1314.dao.UserDao"> <!--查找--> <select id="findOneById" resultType="User" parameterType="String"> SELECT * FROM `user` WHERE login_id = #{userId} <select> <!--增加語句--> <insert id="add" parameterType="User"> INSERT INTO `user` (`login_id`,`name`,`age`,`sex`,`duty`,`cell_number`,`photo_url`,`pwd`,`used`) VALUES (#{loginId},#{name},#{age},#{sex},#{duty},#{cellNumber},#{photoUrl},#{pwd},#{used}) </insert> <!-- 刪除 --> <update id="del" parameterType="User"> UPDATE `user` SET `used`=FALSE WHERE `login_id`=#{loginId}; </update> <!-- 更新用戶信息 --> <update id="update" parameterType="User"> UPDATE `user` SET `name`=#{name}, `age`=#{age}, `sex`=#{sex}, `duty`=#{duty}, `cell_number`=#{cellNumber}, `photo_url`=#{photoUrl} WHERE `login_id`=#{loginId}; </update> </mapper>
- mapper下面的UserDao.xml已經完成,這就意味著我們的UserDao基本完成,那么我們應該來一次單元測試來看看效果如何。UserDaoTest.java如下:
@RunWith(SpringJUnit4ClassRunner.class) //spring的單元測試 @ContextConfiguration({"classpath:spring/spring-*.xml"}) //上下文配置 public class UserDaoTest { @Autowired private UserDao userDao; //初始化Dao層,面向接口編程 /** * 添加用戶的單元測試,添加成功與否會有對應的提示。 * 當然按照我這個配置一般會正確,如果說出錯就需要你一步一步的看錯誤的提示代碼了。 * 添加同樣的LoginId的用戶會添加失敗,因為在上面把LoginId作為了數據庫表的主鍵。 */ @Test public void testAdd() { User user = new User(); user.setLoginId("pc147852369"); user.setName("雨下一整夜"); user.setPwd("123456"); user.setSex("未知"); int result = 0; //受影響的行數默認為0 try { result = userDao.add(user); } catch (Exception e) { e.printStackTrace(); System.out.println("添加用戶失敗"); } if (result>0) System.out.println("添加用戶成功"); } /** * 查找用戶測試,成功與否會有log輸出 */ @Test public void testFindOneId() throws Exception { User user = new User(); user.setLoginId("pc147852369"); User result = null; //受影響的行數默認為0 try { result = userDao.findOneById(user.getLoginId()); } catch (Exception e) { e.printStackTrace(); System.out.println("查找用戶失敗"); } if (null!=result) System.out.println("查找用戶成功\n"+result.toString()); } @Test public void testDel() { User user = new User(); user.setLoginId("pc147852369"); int result = 0; //受影響的行數默認為0 try { result = userDao.del(user); } catch (Exception e) { e.printStackTrace(); System.out.println("刪除用戶失敗"); } if (result>0) System.out.println("刪除用戶成功"); } @Test public void testUpdate() { User user = new User(); user.setLoginId("pc147852369"); user.setName("手把手教程"); user.setPwd("123456"); user.setSex("男"); int result = 0; //受影響的行數默認為0 try { result = userDao.update(user); } catch (Exception e) { e.printStackTrace(); System.out.println("更新用戶信息用戶失敗"); } if (result>0) System.out.println("更新用戶信息用戶成功"); } }
數據的操作結果我們都可以在mysql中查看,這里就不一一截圖了。當然我們也可看到每次單元測試都需要在類上面注解spring單元測試和spring的上下文,按照我們編程的原則,一次編碼處處運行,我們可以把這些注解放到BaseTest.java中,后面所有的單元測試都繼承BaseTest.java即可避免大量重復編碼。
-
UserService實現(注意編程思維的養成)
- 根據我們面向接口編程的思維來講,我們在Service中核心是實現Dao層,并調用Dao層。
- 剛才我們單元測試,我們的UserDao層通過測試了,我們現在中心就應該放在業務邏輯的實現,而不是繼續糾纏Dao層,畢竟數據持久化已經實現了。
- 從服務端程序的角度看來,用戶的主要業務有注冊、登錄、注銷登錄、注銷帳號等等,這里我們先拿注冊來說事。
-
用戶注冊流程分析(用戶角度):
- 填寫帳號相關信息
- 提交注冊信息
- 服務器返回是否注冊成功
-
用戶注冊流程分析(服務器角度):
- 收到用戶注冊請求
- 解包數據→封裝到UserBean
- 解包數據失敗(請求信息異常),返回錯誤提示信息
- 針對具體的用戶信息檢查是否符合標準
- 不符合檢查標準,返回對應的錯誤提示
- 通過檢查,調用Dao檢查是否存在同樣的用戶
- 數據庫已經存在相同的用戶信息,不能重復添加,返回錯誤提示信息
- 不存在同樣的用戶,添加新用戶,并返回成功的提示信息
流程圖反映如下:
ssm框架用戶行為解析流程圖- 代碼實現用戶注冊的Service:
//創建一個BaseService接口,用泛型解耦 public interface UserService extends BaseService<User> { //添加用戶的實例 void add(User user) throws Exception; } ------------------------------分割線---------------------------------- //創建一個UserService繼承BaseService,并指定具體的實體類型 //為什么要再寫一個UserService接口?不同對象的業務體系不同,BaseService并不能完全替代不同對象的具體行為表現 public interface UserService extends BaseService<User> { void add(User user) throws Exception; } ------------------------------分割線---------------------------------- //創建UserServiceImpl實現UserService接口 @Service("userService") public class UserServiceImpl implements UserService { @Autowired private UserDao userDao; /** * 添加用戶,一般來說需要檢查用戶為空、用戶名為空、密碼為空 */ public void add(User user) throws UserCanNotBeNullException, UserNameCanNotBeNullException, UserPwdCanNotBeNullException, UserAireadyExistException, OtherThingsException { //先檢查用戶是否存在 if (null == user) { //拋出用戶為空的自定義異常 throw new UserCanNotBeNullException("User can not be Null"); } //用戶名不能為空檢查 if (StringUtils.isEmpty(user.getLoginId())) { //拋出用戶名為空的自定義異常 throw new UserNameCanNotBeNullException("User name can not be Null"); } //用戶密碼不能為空檢查 if (StringUtils.isEmpty(user.getPwd())) { //拋出用戶密碼為空的自定義異常 throw new UserPwdCanNotBeNullException("User name can not be Null"); } //由于我這個是倉庫管理系統,根據業務需求來說,我們的用戶基本信息都是不能為空的 //基本信息包括:姓名、年齡、用戶名、密碼、性別、手機號,年齡大于18 if (StringUtils.isEmpty(user.getDuty()) || StringUtils.isEmpty(user.getSex()) || user.getAge() > 18 || StringUtils.isEmpty(user.getCellNumber())) { //其他綜合異常 throw new OtherThingsException("Some use's base info can not be null"); } //已經存在相同用戶 if (null != userDao.findOneById(user.getLoginId())) { //存在相同的用戶異常 throw new UserAireadyExistException("Register User Failed,Because the user Aiready exist"); } int result = 0; //受影響的行數默認為0 try { result = userDao.add(user); } catch (Exception e) { System.out.println("添加用戶失敗,用戶已經存在"); //其他用戶添加失敗異常 throw new OtherThingsException(e); } if (result > 0) System.out.println("添加用戶成功"); } //···省略的其他方法··· }
- 老規矩,寫完每個Service后,都需要針對具體的對象的行為進行單元測試,UserServiceTest.java代碼如下:
public class UserServiceTest extends BaseTest { @Autowired private UserServiceImpl userService; //此處直接使用UserService的實現類,主要是方便拋出異常,然后異常出現時候可以針對性的處理 @Test public void testAdd() { User user = new User(); try { userService.add(user); } catch (UserCanNotBeNullException e) { //用戶不能為空異常拋出 e.printStackTrace(); } catch (UserNameCanNotBeNullException e) { //用戶名不能為空 e.printStackTrace(); } catch (UserPwdCanNotBeNullException e) { //用戶密碼不能為空 e.printStackTrace(); } catch (UserAireadyExistException e) { //用戶存在拋出 e.printStackTrace(); } catch (OtherThingsException e) { //其他綜合異常或是不能處理的異常 e.printStackTrace(); } } //···省略的其他測試代碼··· }
- 同樣的,我們的Service的測試代碼執行后,我們可以在mysql中看到具體的數據變化,也不再一一貼圖了。
因為篇幅和時間原因,我們暫時就不寫具體功能的詳細實現了,畢竟學習不是一朝一夕,多培養思維才是重要的事情。從這一期開始代碼逐漸增多,畢竟學習過程就是這樣的遞增的,等熟悉以后可能很多地方就更多是培養思維方式,代碼就直接貼上(詳細的注釋不會少)。
這一期總結:
- 解決項目框架沖突解決,各個框架職能的簡單介紹。
- 簡單的原理解釋。
- java web經典mvc、三層架構簡單介紹。
- 部分簡單的SQL語句。
- 針對Dao層和Service層的單元測試。
- 簡單業務實現的流程分析。
下期預告:我們實現詳細的功能和Controller(Url請求分發),同時分出API接口為以后打下基礎。
項目地址:點擊訪問github