spring+springMVC+mybatis的整合 part4

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操作中,需要手動管理數據庫連接的開關,數據庫資源訪問的開關等等,采用了MybatisDruid這兩個框架,那么我們可以完全不必理會數據庫連接等等的控制,只需要更加專注于業務實現的開發。

完成UserDao的封裝后,傳統的操作這一步需要自己手動實現UserDaoImpl,并實現對數據庫的操作等等。而我們使用Mybatis后,UserDaoImplMybatismapper文件夾中指定為xmlDao文件除了數據庫操作的語句其他的都無需關注,那么剩下的數據庫操作什么的我們都無需關心,畢竟Mybatisdruid都把其他的事情幫我們做了。
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目錄下建好對應的目錄,建好如下

Paste_Image.png

按照我們編程的原則,一次編碼處處運行,我們可以把這些注解放到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 **

Paste_Image.png

但程序的編譯和運行都是沒有問題的,這個錯誤提示并不會產生影響。但紅色的錯誤提示在有些有強迫癥的程序員眼里,多多少少有些不太舒服。

原因
  spring auto scan配置,在編輯情況下,無法找不到對應的bean,于是提示找不到對應bean的錯誤。常見于mybatismapper,如下:

<!-- 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>
  1. 解決方案
    降低Autowired檢測的級別,將Severity的級別由之前的error改成warning或其它可以忽略的級別。
    在project→settings中設置Autowired檢測的級別
    Paste_Image.png
    設置完后可以發現userDao的紅線消失了

主要參考于大牛Clone丶記憶的SSM集成之路

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容