SSM框架實例--管理系統--登錄注冊的功能分析
分析:
登錄和注冊,都是用戶的行為,也是開發中常說的某個行為對應的業務。
注冊用戶:意味著添加用戶,添加了用戶后,才有登錄功能的繼續執行的可能。
用戶登錄:也是用戶信息的查找和比對過程。一般來說用戶先把信息提交給程序,然后程序按照流程執行后提交數據給服務器(流程中程序可能會產生一些業務邏輯的判斷),服務器收到數據并進行數據對比,當用戶信息存在且帳號和密碼匹配才能登錄成功,否則前面的任意條件不滿足即為登錄失敗。
可以依靠單一的用戶表來實現用戶的登錄數據獲取和注冊信息的添加。
功能大概分析完畢后,就可以考慮下如何實現這些功能。大概圖示如下:

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

ssm框架經典三層分析對照Mvc
上面圖中,可以看到一部分MVC設計和圖中標記的類似,但是這只是一種MVC模式的栗子。
關于更加詳細的MVC,我們可以百度百科查看。
SSM框架實例--管理系統--注冊、登錄的功能模擬實現
所以在開發的時候需要先考慮Dao
層的實現,畢竟有了Dao
層對數據的封裝,才可以有后面的操作。
一切都是按照Dao→Service→Controller→View這樣的一個步驟來實現。
用戶注冊功能的Dao層實現。
數據庫基本操作為:增刪改查。
根據數據庫常規操作的類型,分別對其進行抽象,所以產生了Dao.java這個接口對象的基本模型。代碼如下:
使用泛型,<T> 泛型用于解耦,同時避免寫重復代碼
public interface Dao<T> {
/**
* 添加某個對象
* @param t 待添加的對象
* @return 返回受影響的行數
*/
int add(T t);
/**
* 刪除某個對象,在企業開發中,我們一般不做物理刪除,只是添加某個字段對其數據進行可用控制
* @param t 待刪除對象
* @return 返回受影響的條數
*/
int delete(T t);
/**
* 更新某個對象
* @param t 待更新對象
* @return 返回受影響的條數
*/
int update(T t);
/**
* 通過ID查找一個對象
* @param Id 待查詢的對象的ID
* @return 返回該ID對應的對象
*/
T findOneById(Serializable Id);
/**
* 查找對象集合
* @return 返回對象集合
*/
List<T> findAll();
}
創建用戶實體類,需要封裝一個用戶對象,直接在domain包下面創建類User
實現Serializable
接口是為了序列化。方便網絡傳輸等,傳遞對象的時候,序列化
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
private String nextUrl; //下一步的的操作地址
//省略get、set和toString
}
sessionId
不需要封裝在實體類中
數據庫中對應的用戶表user
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 '賬號是否可用',
`session_id` varchar(45) COMMENT '當前登錄的sessionId',
PRIMARY KEY (`login_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1000 DEFAULT CHARSET=utf8 COMMENT='用戶表';
對user表進行操作封裝的接口UserDao
接口,繼承DAO
接口,在dao
包下
public interface UserDao extends Dao<User>{
int add(User user);
int delete(User user);
int update(User user);
User findOneById(Serializable Id);
void updateLoginSession(@Param("sessionId") String sessionId, @Param("loginId") String loginId);
}
在傳統的jdbc操作中,需要手動管理數據庫連接的開關,數據庫資源訪問的開關等等,采用了Mybatis
和Druid
這兩個框架,那么我們可以完全不必理會數據庫連接等等的控制,只需要更加專注于業務實現的開發。
完成UserDao
的封裝后,傳統的操作這一步需要自己手動實現UserDao
的Impl
,并實現對數據庫的操作等等。而我們使用Mybatis
后,UserDao
的Impl
在Mybatis
的mapper
文件夾中指定為xml
,Dao
文件除了數據庫操作的語句其他的都無需關注,那么剩下的數據庫操作什么的我們都無需關心,畢竟Mybatis
和druid
都把其他的事情幫我們做了。
UserDao.xml:
注意:namespace
要指定到對應dao的位置,不然無法找到
<?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="pjb.ssm.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="delete" 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>
<!--更新session的id-->
<update id="updateLoginSession">
UPDATE
`user`
SET
`session_id`=#{sessionId}
WHERE
`login_id`=#{loginId};
</update>
</mapper>
mapper
下面的UserDao.xml
已經完成,這就意味著我們的UserDao
基本完成,下面做的是來編寫測試類
先在test
目錄下建好對應的目錄,建好如下
按照我們編程的原則,一次編碼處處運行,我們可以把這些注解放到
BaseTest
中,后面所有的單元測試都繼承BaseTest
即可避免大量重復編碼。BaseTest是主測試類
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:spring/spring-*.xml"})
public class BaseTest {
}
@RunWith(SpringJUnit4ClassRunner.class)
是為了讓測試在Spring容器環境下執行。
@ContextConfiguration({"classpath:spring/spring-*.xml"})
用于指定配置文件所在的位置
代碼非常簡單,用與dao,service測試類繼承用
UserDaoTest
,每個@Test
單獨測試,由于測試結果不回滾,可以在數據庫看到測試是否成功
public class UserDaoTest extends BaseTest {
@Autowired
private UserDao userDao;
@Test
public void testAdd() {
User user = new User();
user.setLoginId("2015081040");
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("添加用戶成功");
}
@Test
public void testFindOneId() throws Exception {
User user = new User();
user.setLoginId("2015081040");
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 testDelete() {
User user = new User();
user.setLoginId("2015081040");
int result = 0; //受影響的行數默認為0
try {
result = userDao.delete(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("2015081040");
user.setName("pjb");
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("更新用戶信息用戶成功");
}
}
**在測試的時候可能會發現userDao
顯示Could not autowire, No beans of 'UserDao' type found
**
但程序的編譯和運行都是沒有問題的,這個錯誤提示并不會產生影響。但紅色的錯誤提示在有些有強迫癥的程序員眼里,多多少少有些不太舒服。
原因
spring auto scan
配置,在編輯情況下,無法找不到對應的bean
,于是提示找不到對應bean
的錯誤。常見于mybatis
的mapper
,如下:
<!-- 4.配置掃描Dao接口包,動態實現Dao接口,注入到spring容器中 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 注入sqlSessionFactory -->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<!-- 給出需要掃描Dao接口包 -->
<property name="basePackage" value="pjb.ssm.dao"/>
</bean>
- 解決方案
降低Autowired
檢測的級別,將Severity
的級別由之前的error
改成warning
或其它可以忽略的級別。
在project→settings中設置Autowired
檢測的級別
Paste_Image.pnguserDao
的紅線消失了
主要參考于大牛Clone丶記憶的SSM集成之路