回顧
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)境搭建
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)行嵌套組合
⑥ 測(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);
}
}
⑦ 嵌套關(guān)系
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)行嵌套組合
⑥ 測(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);
}
}
⑦ 嵌套關(guān)系
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)行嵌套組合
⑥ 測(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);
}
⑦ 嵌套關(guān)系
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í)緩存
3.1 一級(jí)緩存
3.1.1 介紹
MyBatis一級(jí)緩存是:SqlSession級(jí)別的緩存腊瑟,默認(rèn)開(kāi)啟聚假,不需要手動(dòng)配置
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ì)清空緩存
一級(jí)緩存源碼
3.2 二級(jí)緩存【了解】
3.2.1 介紹
? MyBatis的二級(jí)緩存雖然是默認(rèn)開(kāi)啟的,但需要在映射文件中配置<cache/>
標(biāo)簽才能使用胚迫,而且要求實(shí)體類(lèi)的必須實(shí)現(xiàn)序列化接口
3.2.2 驗(yàn)證
mybatis全局配置喷户,默認(rèn)值就是開(kāi)啟了二級(jí)緩存
指定需要開(kāi)啟二級(jí)緩存的映射配置文件
指定User實(shí)現(xiàn)序列化接口
// 二級(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)劃分)
3.3 知識(shí)小結(jié)
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.分包分層
4. 導(dǎo)入靜態(tài)資源文件
==注意: 2019&2020版拷貝靜態(tài)資源的時(shí)候經(jīng)常沒(méi)有拷貝到out目錄中,程序運(yùn)行的時(shí)候是執(zhí)行out目錄的內(nèi)容==
5. 導(dǎo)入工具類(lèi)(在今天素材里面)
6.導(dǎo)入字符過(guò)濾器
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.流程分析
2.修改login.jsp頁(yè)面,修改其提交的地址的信息
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.流程分析
2.修改index.jsp頁(yè)面修改連接地址
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á)式
<%@ 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> <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);
}
}