5/12day52_mybatis嵌套查詢(xún)&緩存

MyBatis嵌套查詢(xún)&緩存.png

回顧

1. 單表高級(jí)查詢(xún)
    resultMap標(biāo)簽:手動(dòng)映射封裝
    多條件查詢(xún)
        @param("xx")  #{xx}
        User          #{屬性名}
    like模糊匹配:concat() 函數(shù)拼接
        
2. mapper映射文件深入
    返回主鍵:<selectKey> select late_insert_id </selectKey>
    動(dòng)態(tài)sql
        if 判斷
        where 條件拼接(去掉 前置 and | or)
        set 更新拼接(去掉 后置 ,)
        foreach 循環(huán)
            普通list  collection="list"
            普通array collection="array"
            實(shí)體list屬性 collection="屬性名"
    sql片段:抽取公共sql赊堪,提高復(fù)用性
3. 多表回顧
    數(shù)據(jù)庫(kù)表關(guān)系:主外鍵
    實(shí)體(模型)關(guān)系:屬性

4. 多表查詢(xún)
    一對(duì)一
    一對(duì)多
    多對(duì)多
        看老師發(fā)的畫(huà)圖

MyBatis嵌套查詢(xún)&緩存

今日目標(biāo)

1. 嵌套查詢(xún)

2. 加載策略
    立即加載
    延遲加載【講】
    
3. 緩存:提高查詢(xún)效率
    一級(jí)緩存
    二級(jí)緩存
    
4. 回顧核心配置文件常用標(biāo)簽

一 MyBatis嵌套查詢(xún)

1.1 什么是嵌套查詢(xún)

嵌套查詢(xún)就是將原來(lái)多表查詢(xún)中的聯(lián)合查詢(xún)語(yǔ)句拆成==多個(gè)單表的查詢(xún)==,再使用mybatis的語(yǔ)法嵌套在一起草描。

舉個(gè)栗子

* 需求:查詢(xún)一個(gè)訂單该抒,與此同時(shí)查詢(xún)出該訂單所屬的用戶(hù)

* 關(guān)聯(lián)查詢(xún):
        select * from orders o inner join user u on o.uid = u.id where o.id = 1;
* 缺點(diǎn):
        sql語(yǔ)句編寫(xiě)難度大
        數(shù)據(jù)量過(guò)大慌洪,笛卡爾積數(shù)量倍增顶燕,可能造成內(nèi)存溢出
* 嵌套查詢(xún):
    1.根據(jù)訂單id查詢(xún)訂單表
        select * from orders where id = 1;
    2.再根據(jù)訂單表中uid(外鍵)查詢(xún)用戶(hù)表
        select * from user where id = 訂單表uid;
    3.最后由mybatis框架進(jìn)行嵌套組合
    
* 優(yōu)點(diǎn):
        sql語(yǔ)句編寫(xiě)簡(jiǎn)單
        沒(méi)有多表關(guān)聯(lián),不會(huì)產(chǎn)生笛卡爾積

環(huán)境搭建

1589246911073.png

1.2 一對(duì)一==嵌套==查詢(xún)

需求:查詢(xún)一個(gè)訂單冈爹,與此同時(shí)查詢(xún)出該訂單所屬的用戶(hù)

sql語(yǔ)句

-- 1.根據(jù)訂單id查詢(xún)訂單表
    select * from orders where id = 1;
-- 2.再根據(jù)訂單表中uid(外鍵)查詢(xún)用戶(hù)表
    select * from user where id = 41;

① OrderMapper接口

public interface OrderMapper {

    // 一對(duì)一嵌套查詢(xún)
    public Order findByIdWithUser(Integer id);
}

② OrderMapper映射

<?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">
<mapper namespace="cn.itcast.dao.OrderMapper">

    <resultMap id="orderMap" type="cn.itcast.domain.Order">
        <id column="id" property="id"></id>
        <result column="ordertime" property="ordertime"></result>
        <result column="money" property="money"></result>
        <!--通過(guò)mybatis嵌套查詢(xún)user表-->
    </resultMap>

    <!--
        一對(duì)一嵌套查詢(xún)
            resultType:?jiǎn)伪碛成浞庋b
            resultMap:多表查詢(xún)必須手動(dòng)映射封裝
    -->
    <select id="findByIdWithUser" parameterType="int" resultMap="orderMap">
        select * from orders where id = #{id};
    </select>
</mapper>

③ UserMapper接口

public interface UserMapper {
    
    // 根據(jù)用戶(hù)id查詢(xún)user對(duì)象
    public User findById(Integer id);
}

④ UserMapper映射

<?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">
<mapper namespace="cn.itcast.dao.UserMapper">

    <!--
        根據(jù)用戶(hù)id查詢(xún)user對(duì)象
    -->
    <select id="findById" parameterType="int" resultType="cn.itcast.domain.User">
        select * from user where id = #{id};
    </select>

</mapper>

⑤ 通過(guò)mybatis進(jìn)行嵌套組合

1589247990774.png

⑥ 測(cè)試

public class OrderMapperTest extends BaseMapperTest { // 繼承父類(lèi)涌攻,就可以直接使用 父類(lèi)的方法和成員變量了

    // 一對(duì)一嵌套測(cè)試
    @Test
    public void test01() throws Exception {
        // 獲取代理對(duì)象
        OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class);

        // 根據(jù)id查詢(xún)
        Order order = orderMapper.findByIdWithUser(1);
        System.out.println(order);
    }
}
1589247953911.png

⑦ 嵌套關(guān)系

1589248264800.png

1.3 一對(duì)多嵌套查詢(xún)

需求:查詢(xún)一個(gè)用戶(hù),與此同時(shí)查詢(xún)出該用戶(hù)具有的訂單

sql語(yǔ)句

-- 1. 先根據(jù)用戶(hù)id频伤,查詢(xún)用戶(hù)表(一個(gè))
SELECT * FROM USER WHERE id = 41;
-- 2. 再根據(jù)用戶(hù)id恳谎,查詢(xún)訂單表(多個(gè))
SELECT * FROM orders WHERE uid = 41;

① UserMapper接口

public interface UserMapper {


    // 一對(duì)多嵌套查詢(xún)
    public User findByIdWithOrders(Integer id);

}

② UserMapper映射

<resultMap id="userWithOrdersMap" type="cn.itcast.domain.User">
    <id column="id" property="id"></id>
    <result column="birthday" property="birthday"></result>
    <result column="username" property="username"></result>
    <result column="sex" property="sex"></result>
    <result column="address" property="address"></result>
    <!--一對(duì)多嵌套組合-->
</resultMap>

<!--一對(duì)多嵌套查詢(xún)-->
<select id="findByIdWithOrders" parameterType="int" resultMap="userWithOrdersMap">
    SELECT * FROM USER WHERE id = #{id};
</select>

③ OrderMapper接口

public interface OrderMapper {

    // 根據(jù)用戶(hù)id,查詢(xún)訂單列表
    public List<Order> findByUid(Integer uid);
}

④ OrderMapper映射

<select id="findByUid" parameterType="int" resultType="cn.itcast.domain.Order">
    SELECT * FROM orders WHERE uid = #{uid};
</select>

⑤ 通過(guò)mybatis進(jìn)行嵌套組合

1589249903827.png

⑥ 測(cè)試

public class UserMapperTest extends BaseMapperTest {

    // 一對(duì)多嵌套查詢(xún)測(cè)試
    @Test
    public void test01() throws Exception {
        // 獲取代理
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

        User user = userMapper.findByIdWithOrders(41);

        System.out.println(user);
    }

}
1589249880000.png

⑦ 嵌套關(guān)系

1589250191685.png

1.4 多對(duì)多嵌套查詢(xún)(由二個(gè)一對(duì)多組成)

需求:查詢(xún)用戶(hù)同時(shí)查詢(xún)出該用戶(hù)的所有角色

mybatis的實(shí)現(xiàn)方案就是(一對(duì)多)憋肖,區(qū)別在于sql語(yǔ)句不同

sql語(yǔ)句

-- 1. 先根據(jù)用戶(hù)id因痛,查詢(xún)用戶(hù)表(一個(gè))
SELECT * FROM USER WHERE id = 41;
-- 2. 再根據(jù)用戶(hù)id,查詢(xún)角色表(多個(gè))
SELECT * FROM role r INNER JOIN user_role ur ON ur.`rid` = r.`id` WHERE ur.`uid` = 41;

① UserMapper接口

public interface UserMapper {

    // 多對(duì)多嵌套查詢(xún)
    public User findByIdWithRoles(Integer id);
}

② UserMapper映射

<resultMap id="userWithRolesMap" type="cn.itcast.domain.User">
    <id column="id" property="id"></id>
    <result column="birthday" property="birthday"></result>
    <result column="username" property="username"></result>
    <result column="sex" property="sex"></result>
    <result column="address" property="address"></result>
    <!-- 多對(duì)多嵌套-->
</resultMap>

<!--多對(duì)多嵌套查詢(xún)-->
<select id="findByIdWithRoles" parameterType="int" resultMap="userWithRolesMap">
    SELECT * FROM USER WHERE id = #{id};
</select>

③ RoleMapper接口

public interface RoleMapper {

    // 根據(jù)用戶(hù)id岸更,查詢(xún)角色列表
    public List<Role> findByUid(Integer id);
}

④ RoleMapper映射

<?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">
<mapper namespace="cn.itcast.dao.RoleMapper">


    <resultMap id="roleResultMap" type="cn.itcast.domain.Role">
        <id column="id" property="id"></id>
        <result column="role_name" property="roleName"></result>
        <result column="role_desc" property="roleDesc"></result>

    </resultMap>

    <!--
        根據(jù)用戶(hù)id鸵膏,查詢(xún)角色列表
    -->
    <select id="findByUid" parameterType="int" resultMap="roleResultMap">
        SELECT * FROM role r INNER JOIN user_role ur ON ur.`rid` = r.`id` WHERE ur.`uid` =#{uid}
    </select>
</mapper>

⑤ 通過(guò)mybatis進(jìn)行嵌套組合

1589251531415.png

⑥ 測(cè)試

// 多對(duì)多測(cè)試(根據(jù)用戶(hù)查詢(xún)角色)
@Test
public void test02()throws Exception{
    // 獲取代理
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

    User user = userMapper.findByIdWithRoles(41);

    System.out.println(user);
}
1589251469136.png

⑦ 嵌套關(guān)系

1589251724851.png

1.5 知識(shí)小結(jié)

* 步驟:一對(duì)多舉例
    1)先查詢(xún)(一方)單表
    2)在查詢(xún)(多方)單表
    3)最后由mybatis嵌套組合


一對(duì)一配置:使用<resultMap>+<association>做配置,通過(guò)column條件怎炊,執(zhí)行select查詢(xún)

一對(duì)多配置:使用<resultMap>+<collection>做配置谭企,通過(guò)column條件,執(zhí)行select查詢(xún)

多對(duì)多配置:使用<resultMap>+<collection>做配置评肆,通過(guò)column條件债查,執(zhí)行select查詢(xún)

優(yōu)點(diǎn):1.簡(jiǎn)化sql語(yǔ)句編寫(xiě)、2.不會(huì)產(chǎn)生笛卡爾積

缺點(diǎn):麻煩...


開(kāi)發(fā)中到底使用哪一種瓜挽?
    傳統(tǒng)開(kāi)發(fā)攀操,數(shù)據(jù)量小:使用關(guān)聯(lián)查詢(xún)
    互聯(lián)網(wǎng)開(kāi)發(fā)秸抚,數(shù)據(jù)量大:使用嵌套查詢(xún)
        當(dāng)前也有人這么玩
            在java中先查用戶(hù)速和,在查角色,不在使用嵌套....

二 MyBatis加載策略

2.1 什么是加載策略

? 當(dāng)多個(gè)模型(表)之間存在關(guān)聯(lián)關(guān)系時(shí), 加載一個(gè)模型(表)的同時(shí), 是否要立即加載其關(guān)聯(lián)的模型, 我們把這種決策成為==加載策略==

? 如果加載一個(gè)模型(表)的時(shí)候, 需要立即加載出其關(guān)聯(lián)的所有模型(表), 這種策略稱(chēng)為==立即加載==

? 如果加載一個(gè)模型的時(shí)候, 不需要立即加載出其關(guān)聯(lián)的所有模型, 等到真正需要的時(shí)候再加載, 這種策略稱(chēng)為==延遲加載(懶加載)==

Mybatis中的加載策略有兩種:立即加載和延遲加載, 默認(rèn)是立即加載

注意:延遲加載是在嵌套查詢(xún)基礎(chǔ)上實(shí)現(xiàn)的

* 什么樣的場(chǎng)景使用立即加載
    一對(duì)一
    
* 什么樣的場(chǎng)景使用延遲加載(什么時(shí)候用剥汤,什么時(shí)候查詢(xún)颠放,提高數(shù)據(jù)庫(kù)性能)
    一對(duì)多、多對(duì)多

2.2 配置延遲加載

2.2.1 全局

SqlMapConfig.xml,設(shè)置開(kāi)啟全局延遲加載

<!--全局配置-->
<settings>
    <!--開(kāi)啟延遲(懶)加載  true 開(kāi)始  false(默認(rèn)值) 關(guān)閉-->
    <setting name="lazyLoadingEnabled" value="true"/>
</settings>

2.2.3 局部

mapper映射文件吭敢,指定某一個(gè)select標(biāo)簽配置

<association></association> 標(biāo)簽
<collection></collection> 標(biāo)簽
    fetchType=""屬性
        eager 立即加載
        lazy  延遲加載

注意:局部?jī)?yōu)先級(jí)高于全局的...

2.3 觸發(fā)(立即)加載

有這樣一個(gè)全局配置lazyLoadTriggerMethods,它定義的方法會(huì)觸發(fā)立即加載

也就說(shuō)當(dāng)你調(diào)用它定義的方法時(shí), 會(huì)執(zhí)行數(shù)據(jù)加載, 它的默認(rèn)值是equals,clone,hashCode,toString

<!--全局配置-->
<settings>
    <!--開(kāi)啟延遲(懶)加載  true 開(kāi)始  false(默認(rèn)值) 關(guān)閉-->
    <setting name="lazyLoadingEnabled" value="true"/>
    <!--觸發(fā)立即加載的配置
            默認(rèn)值:equals,clone,hashCode,toString
            value="" 覆蓋了默認(rèn)值碰凶,表示在執(zhí)行上述四個(gè)方法時(shí),不會(huì)觸發(fā)立即加載...
            只有在執(zhí)行g(shù)et方法獲取時(shí)鹿驼,觸發(fā)數(shù)據(jù)加載...
        -->
    <setting name="lazyLoadTriggerMethods" value=""/>
</settings>

三 MyBatis緩存

什么是緩存欲低?

服務(wù)器內(nèi)存(硬盤(pán))中的一塊區(qū)域

為什么使用緩存?

提高查詢(xún)效率的

什么樣的數(shù)據(jù)適合做緩存畜晰?

經(jīng)常訪(fǎng)問(wèn)但又不經(jīng)常修改的數(shù)據(jù)...

緩存是用來(lái)提高查詢(xún)效率的砾莱,所有的持久層框架基本上都有緩存機(jī)制
Mybatis也提供了緩存策略,分為一級(jí)緩存凄鼻,二級(jí)緩存

1589254870618.png

3.1 一級(jí)緩存

3.1.1 介紹

MyBatis一級(jí)緩存是:SqlSession級(jí)別的緩存腊瑟,默認(rèn)開(kāi)啟聚假,不需要手動(dòng)配置


1589201319071.png

3.1.2 驗(yàn)證

需求:根據(jù)id查詢(xún)用戶(hù)

// 一級(jí)緩存測(cè)試
@Test
public void test03() throws Exception {
    // 獲取sqlSession會(huì)話(huà)對(duì)象
    SqlSession sqlSession = MyBatisUtils.openSession();

    // 獲取第一個(gè)代理對(duì)象
    UserMapper userMapper1 = sqlSession.getMapper(UserMapper.class);
    User user1 = userMapper1.findById(41);// 走數(shù)據(jù)庫(kù)
    System.out.println(user1);

    // 清除緩存(自己測(cè)試增、刪闰非、改)
    sqlSession.clearCache();

    // 獲取第二個(gè)代理對(duì)象
    UserMapper userMapper2 = sqlSession.getMapper(UserMapper.class);
    User user2 = userMapper2.findById(41);// 走緩存(如果上面清除緩存膘格,還是走數(shù)據(jù)庫(kù))
    System.out.println(user2);

    // sqlSession關(guān)閉(清除緩存...)
    MyBatisUtils.close(sqlSession);
}

3.1.3 分析

? 一級(jí)緩存是SqlSession范圍的緩存,不同的SqlSession之間的緩存區(qū)域是互相不影響的财松,執(zhí)行SqlSession的C(增加)U(更新)D(刪除)操作瘪贱,或者調(diào)用clearCache()、commit()辆毡、close()方法菜秦,都會(huì)清空緩存

1589255593980.png

一級(jí)緩存源碼

1589256171662.png

3.2 二級(jí)緩存【了解】

3.2.1 介紹

? MyBatis的二級(jí)緩存雖然是默認(rèn)開(kāi)啟的,但需要在映射文件中配置<cache/>標(biāo)簽才能使用胚迫,而且要求實(shí)體類(lèi)的必須實(shí)現(xiàn)序列化接口

1589202614175.png

3.2.2 驗(yàn)證

mybatis全局配置喷户,默認(rèn)值就是開(kāi)啟了二級(jí)緩存

1589263893048.png

指定需要開(kāi)啟二級(jí)緩存的映射配置文件

1589263857841.png

指定User實(shí)現(xiàn)序列化接口

1589263995869.png
// 二級(jí)緩存
@Test
public void test04() throws Exception {
    // 模擬第一個(gè)用戶(hù)
    SqlSession sqlSession1 = MyBatisUtils.openSession();
    UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);
    User user1 = userMapper1.findById(41);
    System.out.println(user1);
    sqlSession1.close();

    // 模擬第二個(gè)用戶(hù)
    SqlSession sqlSession2 = MyBatisUtils.openSession();
    UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);
    User user2 = userMapper2.findById(41);
    System.out.println(user2);
    sqlSession2.close();

}

3.1.3 分析

? 二級(jí)緩存是mapper映射級(jí)別的緩存唾那,多個(gè)SqlSession去操作同一個(gè)Mapper映射的sql語(yǔ)句访锻,多個(gè)SqlSession可以共用二級(jí)緩存,二級(jí)緩存是跨SqlSession的闹获。

二級(jí)緩存相比一級(jí)緩存的范圍更大(按namespace來(lái)劃分)

1589264629385.png

3.3 知識(shí)小結(jié)

1564842702588.png
1. mybatis的緩存,都不需要我們手動(dòng)存儲(chǔ)和獲取數(shù)據(jù)避诽。mybatis自動(dòng)維護(hù)的龟虎。

2. 使用mybatis,如果是中小型項(xiàng)目沙庐,使用自帶緩存的機(jī)制是可以滿(mǎn)足需求的鲤妥。如果是大型(分布式)項(xiàng)目,mybatis的緩存靈活性不足拱雏,需要使用第三方的緩存技術(shù)解決問(wèn)題棉安。

四 核心配置文件回顧

4.1 properties標(biāo)簽

加載外部的properties文件

<properties resource="jdbc.properties"></properties>

4.2 settings標(biāo)簽

全局參數(shù)配置

<settings>
    <!--開(kāi)啟懶加載-->
    <setting name="lazyLoadingEnabled" value="true"/>
    <!-- 指定觸發(fā)延遲加載的方法,只有g(shù)et方法執(zhí)行時(shí)才會(huì)觸發(fā)立即加載 -->
    <setting name="lazyLoadTriggerMethods" value=""/>
    <!--開(kāi)啟二級(jí)緩存 true開(kāi)啟(默認(rèn)) false關(guān)閉-->
    <setting name="cacheEnabled" value="true"/>
</settings>

4.3 typeAliases標(biāo)簽

為 Java 類(lèi)型設(shè)置一個(gè)別名

1. 單個(gè)定義別名

    <typeAliases>
        <typeAlias type="cn.itcast.domain.User" alias="user"></typeAlias>
    </typeAliases>

1. 使用包的形式批量定義別名

    <typeAliases>
        <package name="cn.itcast.domain"></package>
    </typeAliases>

4.4 mappers標(biāo)簽

加載映射配置

1. 加載指定的src目錄下的映射文件铸抑,例如:

    <mapper resource="cn/itcast/mapper/UserMapper.xml"/>

1. 加載并掃描指定包下所有的映射文件(接口)贡耽,例如:

    <package name="cn.itcast.mapper"/>

4.5 environments標(biāo)簽

數(shù)據(jù)源環(huán)境配置

<environments default="mysql">
    <environment id="mysql">
        <!--事務(wù)管理器使用JDBC類(lèi)型-->
        <transactionManager type="JDBC"/>
        <!--數(shù)據(jù)源使用連接池-->
        <dataSource type="POOLED">
            <property name="driver" value="${jdbc.driver}"/>
            <property name="url" value="${jdbc.url}"/>
            <property name="username" value="${jdbc.username}"/>
            <property name="password" value="${jdbc.password}"/>
        </dataSource>
    </environment>
</environments>

老師下午總結(jié)

回顧(登陸展示用戶(hù)列表)

1.環(huán)境搭建

1.創(chuàng)建數(shù)據(jù)庫(kù)

CREATE TABLE user (
  id INT(11) NOT NULL,
  username VARCHAR(32) DEFAULT NULL,
  password VARCHAR(32) DEFAULT NULL,
  sex VARCHAR(6) DEFAULT NULL,
  email VARCHAR(50) DEFAULT NULL,
  PRIMARY KEY (id),
  KEY email (email)
) ENGINE=INNODB DEFAULT CHARSET=utf8;

INSERT INTO user VALUES(1,'admin','123','男','admin@itcast.cn'),(2,'guest','123','男','admin@itcast.cn'),(3,'gouwa','123','男','admin@itcast.cn'),(4,'gousheng','123','男','admin@itcast.cn');
       ```

2.創(chuàng)建模塊然后導(dǎo)入對(duì)應(yīng)的jar

導(dǎo)入jar我們需要分析我們要使用到的技術(shù),這個(gè)過(guò)程應(yīng)該是你們的項(xiàng)目組長(zhǎng)負(fù)責(zé)

  • mysql的驅(qū)動(dòng)

  • 數(shù)據(jù)庫(kù)的連接池

  • jstl

  • Beanutils

    1589269607126.png

3.分包分層

1589269804767.png

4. 導(dǎo)入靜態(tài)資源文件

1589269869357.png

==注意: 2019&2020版拷貝靜態(tài)資源的時(shí)候經(jīng)常沒(méi)有拷貝到out目錄中,程序運(yùn)行的時(shí)候是執(zhí)行out目錄的內(nèi)容==

1589270024992.png

5. 導(dǎo)入工具類(lèi)(在今天素材里面)

1589270143510.png

6.導(dǎo)入字符過(guò)濾器

1589270590593.png
package com.itheima.web.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

//該字符串過(guò)濾器要解決全局亂碼問(wèn)題
/*
亂碼的分類(lèi):
     1. 請(qǐng)求亂碼( html頁(yè)面提交表單數(shù)據(jù)---servlet --- servlet通過(guò)getparameter()方法獲取參數(shù)的時(shí)候是否亂碼)
           get請(qǐng)求: 沒(méi)有
           post請(qǐng)求: 有亂碼
     2. 響應(yīng)亂碼     response.getWrite().write("呵呵")  向?yàn)g覽器輸出數(shù)據(jù)亂碼
          不管任何請(qǐng)求方式都會(huì)亂碼的鹊汛。
 */
//配置過(guò)濾路徑
@WebFilter("/*")
public class CharacterEncondingFilter implements Filter {

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
       //1. 強(qiáng)制類(lèi)型轉(zhuǎn)換 (目的: 是為了使用HttpServletRequest的getmethod方法)
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;

        //2. 解決response響應(yīng)亂碼問(wèn)題
        response.setContentType("text/html;charset=utf-8");

        //3. 獲取客戶(hù)請(qǐng)求方式蒲赂,如果是post請(qǐng)求方式我們需要解決獲取請(qǐng)求參數(shù)亂碼問(wèn)題
        String method = request.getMethod();
        if("post".equalsIgnoreCase(method)){
            request.setCharacterEncoding("utf-8");
        }

        //解決完畢亂碼之后記得要放行
        chain.doFilter(request, response);
    }


    public void destroy() {
    }



    public void init(FilterConfig config) throws ServletException {

    }

}

2.登陸

1.流程分析

1589271149898.png

2.修改login.jsp頁(yè)面,修改其提交的地址的信息

1589271432614.png

2.編寫(xiě)Userservlet的login方法

package com.itheima.web.servlet;

import com.itheima.domain.User;
import com.itheima.service.UserService;
import org.apache.commons.beanutils.BeanUtils;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;

@WebServlet("/userServlet")
public class UserServlet extends HttpServlet {

    private UserService userService = new UserService();

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //獲取action刁憋,從而得知用戶(hù)需要調(diào)用方法
        String methodName = request.getParameter("action");
        if("login".equalsIgnoreCase(methodName)){
            //登錄方法
            login(request,response);
        }else if("list".equalsIgnoreCase(methodName)){
            //展示用戶(hù)列表
            list(request,response);
        }
    }

    //用戶(hù)登陸
    protected void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        try {
            //1. 獲取請(qǐng)求參數(shù)
            Map<String, String[]> parameterMap = request.getParameterMap();
            //2. 把請(qǐng)求參數(shù)封裝到user對(duì)象中
            User user = new User();
            BeanUtils.populate(user,parameterMap); //把參數(shù)封裝到user對(duì)象中了
            //3.調(diào)用userService的login方法滥嘴,判斷是否登陸成功
            boolean isLogin = userService.login(user);
            if(isLogin){
                //4. 登陸成功片吊,設(shè)置登陸成功的標(biāo)記胆萧,并且返回首頁(yè)
                request.getSession().setAttribute("loginUser",user);
                //請(qǐng)求重定向到首頁(yè)
                response.sendRedirect(request.getContextPath()+"/index.jsp");  // request.getContextPath() 獲取模塊的根路徑
            }else {
                //5. 登陸失敗,設(shè)置登陸錯(cuò)誤的信息磺芭,回到login.jsp頁(yè)面
                request.setAttribute("error","用戶(hù)名或者密碼錯(cuò)誤");
                //請(qǐng)求轉(zhuǎn)發(fā)到登錄頁(yè)面(這里使用請(qǐng)求轉(zhuǎn)發(fā)的原因是因?yàn)閞equest域中存儲(chǔ)有數(shù)據(jù))
                request.getRequestDispatcher("/login.jsp").forward(request,response);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

    }


    //展示用戶(hù)列表
    protected void list(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {


    }

        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
}

3.編寫(xiě)UserService的login方法

package com.itheima.service;

import com.itheima.dao.UserDao;
import com.itheima.domain.User;

public class UserService {

    private UserDao userDao = new UserDao();


    //用戶(hù)登陸
    public boolean login(User user){
        return userDao.login(user);
    }
}

4.編寫(xiě)UserDao的login方法

package com.itheima.dao;

import com.itheima.domain.User;
import com.itheima.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class UserDao {



    public boolean login(User user) {
        Connection connection = null;
        PreparedStatement pst =null;
        ResultSet rs = null;
        try {
            //1. 通過(guò)工具類(lèi)得到連接
            connection = JdbcUtils.getConnection();
            //2. 準(zhǔn)備sql語(yǔ)句得到PreparedStatement
            String sql = "SELECT * FROM USER WHERE username=? AND PASSWORD=?";
             pst = connection.prepareStatement(sql);
            //3. 設(shè)置參數(shù)
            pst.setObject(1,user.getUsername());
            pst.setObject(2,user.getPassword());

            //4. 執(zhí)行sql語(yǔ)句,得到結(jié)果
             rs = pst.executeQuery();
            //5. 返回結(jié)果
            return rs.next();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            //6. 關(guān)閉資源
            JdbcUtils.close(rs,pst,connection);
        }

        //該語(yǔ)句只是為了讓代碼不報(bào)錯(cuò)是尖,讓方法最終有返回值而已
        return false;
    }
}

3.用戶(hù)展示列表

1.流程分析

1589273051193.png

2.修改index.jsp頁(yè)面修改連接地址

1589273149885.png

3.編寫(xiě)Userservlet的login方法

@WebServlet("/userServlet")
public class UserServlet extends HttpServlet {

    private UserService userService = new UserService();

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //獲取action意系,從而得知用戶(hù)需要調(diào)用方法
        String methodName = request.getParameter("action");
        if("login".equalsIgnoreCase(methodName)){
            //登錄方法
            login(request,response);
        }else if("list".equalsIgnoreCase(methodName)){
            //展示用戶(hù)列表
            list(request,response);
        }
    }

  

    //展示用戶(hù)列表
    protected void list(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1. 調(diào)用userService的findAll方法得到所有的用戶(hù)信息
        List<User> list =  userService.findAll();
       //2. 把用戶(hù)信息存儲(chǔ)到request域中
        request.setAttribute("list",list);
        //3. 請(qǐng)求轉(zhuǎn)發(fā)到list頁(yè)面
        request.getRequestDispatcher("/list.jsp").forward(request,response);
    }
}

3.編寫(xiě)UserService的login方法

package com.itheima.service;

import com.itheima.dao.UserDao;
import com.itheima.domain.User;

import java.util.List;

public class UserService {

    private UserDao userDao = new UserDao();



    public List<User> findAll() {
        return userDao.findAll();
    }
}

4.編寫(xiě)UserDao的login方法

package com.itheima.dao;

import com.itheima.domain.User;
import com.itheima.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class UserDao {



    //查詢(xún)用戶(hù)列表
    public List<User> findAll() {
        Connection connection = null;
        PreparedStatement pst =null;
        ResultSet rs = null;
        List<User> list = new ArrayList<>();
        try {
            //1. 通過(guò)工具類(lèi)得到連接
            connection = JdbcUtils.getConnection();
            //2. 準(zhǔn)備sql語(yǔ)句得到PreparedStatement
            String sql="select * from user";
            pst = connection.prepareStatement(sql);
            //3. 執(zhí)行sql語(yǔ)句,得到查詢(xún)的結(jié)果
             rs = pst.executeQuery();
            //4. 然后遍歷resutset饺汹,把遍歷結(jié)果存儲(chǔ)到集合中
            while(rs.next()){
                //每一行數(shù)據(jù)就是一個(gè)用戶(hù)對(duì)象的數(shù)據(jù)
                User user = new User();
                user.setId(rs.getInt("id"));
                user.setUsername(rs.getString("username"));
                user.setPassword(rs.getString("password"));
                user.setSex(rs.getString("sex"));
                user.setEmail(rs.getString("email"));
                list.add(user);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            //6. 關(guān)閉資源
            JdbcUtils.close(rs,pst,connection);
        }
        return list;
    }
}

5.修改list.jsp的el表達(dá)式

1589273912576.png
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<!-- 網(wǎng)頁(yè)使用的語(yǔ)言 -->
<html lang="zh-CN">
<head>
    <!-- 指定字符集 -->
    <meta charset="utf-8">
    <!-- 使用Edge最新的瀏覽器的渲染方式 -->
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <!-- viewport視口:網(wǎng)頁(yè)可以根據(jù)設(shè)置的寬度自動(dòng)進(jìn)行適配蛔添,在瀏覽器的內(nèi)部虛擬一個(gè)容器,容器的寬度與設(shè)備的寬度相同兜辞。
    width: 默認(rèn)寬度與設(shè)備的寬度相同
    initial-scale: 初始的縮放比迎瞧,為1:1 -->
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- 上述3個(gè)meta標(biāo)簽*必須*放在最前面,任何其他內(nèi)容都*必須*跟隨其后逸吵! -->
    <title>用戶(hù)信息管理系統(tǒng)</title>

    <!-- 1. 導(dǎo)入CSS的全局樣式 -->
    <link href="css/bootstrap.min.css" rel="stylesheet">
    <!-- 2. jQuery導(dǎo)入凶硅,建議使用1.9以上的版本 -->
    <script src="js/jquery-2.1.0.min.js"></script>
    <!-- 3. 導(dǎo)入bootstrap的js文件 -->
    <script src="js/bootstrap.min.js"></script>
    <style type="text/css">
        td, th {
            text-align: center;
        }
    </style>
</head>
<body>
<div class="container">
    <h3 style="text-align: center">用戶(hù)信息列表</h3>
    <table border="1" class="table table-bordered table-hover">
        <tr class="success">
            <th>編號(hào)</th>
            <th>姓名</th>
            <th>性別</th>
            <th>郵箱</th>
            <th>操作</th>
        </tr>
     <c:forEach items="${list}" var="user">
        <tr>
            <td>${user.id}</td>
            <td>${user.username}</td>
            <td>${user.sex}</td>
            <td>${user.email}</td>
            <td><a class="btn btn-default btn-sm" href="update.jsp">修改</a>&nbsp;<a class="btn btn-default btn-sm" href="">刪除</a></td>
        </tr>
     </c:forEach>
    </table>
</div>
</body>
</html>

4.ajax發(fā)送數(shù)據(jù)

4.1 html&jsp頁(yè)面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
    <%--1.導(dǎo)入jquery的js--%>
    <script src="${pageContext.request.contextPath}/js/jquery-3.2.1.min.js"></script>
</head>
<body>


<%--//2. 給按鈕注冊(cè)點(diǎn)擊事件--%>
<input type="button" value="發(fā)送ajax請(qǐng)求" onclick="send()"/><br/>

    用戶(hù)名:<span id="userName"></span><br/>
    密碼:<span id="password"></span><br/>
</body>
<script>

    //需求:點(diǎn)擊按鈕發(fā)送ajax請(qǐng)求,獲取到一個(gè)User的json對(duì)象,然后把用戶(hù)用戶(hù)名與密碼設(shè)置對(duì)應(yīng)的span中
    //3. 發(fā)送ajax請(qǐng)求
    function send(){
        $.ajax(
            {
              url:"${pageContext.request.contextPath}/testServlet",  //發(fā)送地址
              data:{},  //發(fā)送的參數(shù),目前沒(méi)有參數(shù)交給testServlet扫皱,所以我留空了足绅。
              type:"get",//請(qǐng)求的方式
              dataType:"json", //服務(wù)器返回的數(shù)據(jù)格式
              success:function(user){  //成功的回調(diào)函數(shù)
                  $("#userName").html(user.username);
                  $("#password").html(user.password);
              }
            }
        );

    }

</script>

</html>

4.2 servlet接收參數(shù)

package com.itheima.web.servlet;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.itheima.domain.User;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/testServlet")
public class TestServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        User user = new User();
        user.setUsername("狗娃");
        user.setPassword("123");
        //把對(duì)象轉(zhuǎn)發(fā)為json
        ObjectMapper objectMapper = new ObjectMapper();
        String json = objectMapper.writeValueAsString(user);
        //把json字符串寫(xiě)出
        response.getWriter().write(json);

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市韩脑,隨后出現(xiàn)的幾起案子氢妈,更是在濱河造成了極大的恐慌,老刑警劉巖段多,帶你破解...
    沈念sama閱讀 217,185評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件首量,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡进苍,警方通過(guò)查閱死者的電腦和手機(jī)加缘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)觉啊,“玉大人拣宏,你說(shuō)我怎么就攤上這事”樱” “怎么了蚀浆?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,524評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)搜吧。 經(jīng)常有香客問(wèn)我市俊,道長(zhǎng),這世上最難降的妖魔是什么滤奈? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,339評(píng)論 1 293
  • 正文 為了忘掉前任摆昧,我火速辦了婚禮,結(jié)果婚禮上蜒程,老公的妹妹穿的比我還像新娘绅你。我一直安慰自己伺帘,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評(píng)論 6 391
  • 文/花漫 我一把揭開(kāi)白布忌锯。 她就那樣靜靜地躺著伪嫁,像睡著了一般。 火紅的嫁衣襯著肌膚如雪偶垮。 梳的紋絲不亂的頭發(fā)上张咳,一...
    開(kāi)封第一講書(shū)人閱讀 51,287評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音似舵,去河邊找鬼脚猾。 笑死,一個(gè)胖子當(dāng)著我的面吹牛砚哗,可吹牛的內(nèi)容都是我干的龙助。 我是一名探鬼主播,決...
    沈念sama閱讀 40,130評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼蛛芥,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼提鸟!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起常空,我...
    開(kāi)封第一講書(shū)人閱讀 38,985評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤沽一,失蹤者是張志新(化名)和其女友劉穎盖溺,沒(méi)想到半個(gè)月后漓糙,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,420評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡烘嘱,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評(píng)論 3 334
  • 正文 我和宋清朗相戀三年昆禽,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蝇庭。...
    茶點(diǎn)故事閱讀 39,779評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡醉鳖,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出哮内,到底是詐尸還是另有隱情盗棵,我是刑警寧澤,帶...
    沈念sama閱讀 35,477評(píng)論 5 345
  • 正文 年R本政府宣布北发,位于F島的核電站纹因,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏琳拨。R本人自食惡果不足惜瞭恰,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望狱庇。 院中可真熱鬧惊畏,春花似錦恶耽、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,716評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至缰盏,卻和暖如春社搅,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背乳规。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,857評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工形葬, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人暮的。 一個(gè)月前我還...
    沈念sama閱讀 47,876評(píng)論 2 370
  • 正文 我出身青樓笙以,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親冻辩。 傳聞我的和親對(duì)象是個(gè)殘疾皇子猖腕,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評(píng)論 2 354