回顾
1. 单表高级查询
resultMap标签:手动映射封装
多条件查询
@param("xx") #{xx}
User #{属性名}
like模糊匹配:concat() 函数拼接
2. mapper映射文件深入
返回主键:<selectKey> select late_insert_id </selectKey>
动态sql
if 判断
where 条件拼接(去掉 前置 and | or)
set 更新拼接(去掉 后置 ,)
foreach 循环
普通list collection="list"
普通array collection="array"
实体list属性 collection="属性名"
sql片段:抽取公共sql,提高复用性
3. 多表回顾
数据库表关系:主外键
实体(模型)关系:属性
4. 多表查询
一对一
一对多
多对多
看老师发的画图
MyBatis嵌套查询&缓存
今日目标
1. 嵌套查询
2. 加载策略
立即加载
延迟加载【讲】
3. 缓存:提高查询效率
一级缓存
二级缓存
4. 回顾核心配置文件常用标签
一 MyBatis嵌套查询
1.1 什么是嵌套查询
嵌套查询就是将原来多表查询中的联合查询语句拆成==多个单表的查询==,再使用mybatis的语法嵌套在一起。
举个栗子
* 需求:查询一个订单,与此同时查询出该订单所属的用户
* 关联查询:
select * from orders o inner join user u on o.uid = u.id where o.id = 1;
* 缺点:
sql语句编写难度大
数据量过大,笛卡尔积数量倍增,可能造成内存溢出
* 嵌套查询:
1.根据订单id查询订单表
select * from orders where id = 1;
2.再根据订单表中uid(外键)查询用户表
select * from user where id = 订单表uid;
3.最后由mybatis框架进行嵌套组合
* 优点:
sql语句编写简单
没有多表关联,不会产生笛卡尔积
环境搭建
1589246911073.png1.2 一对一==嵌套==查询
需求:查询一个订单,与此同时查询出该订单所属的用户
sql语句
-- 1.根据订单id查询订单表
select * from orders where id = 1;
-- 2.再根据订单表中uid(外键)查询用户表
select * from user where id = 41;
① OrderMapper接口
public interface OrderMapper {
// 一对一嵌套查询
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>
<!--通过mybatis嵌套查询user表-->
</resultMap>
<!--
一对一嵌套查询
resultType:单表映射封装
resultMap:多表查询必须手动映射封装
-->
<select id="findByIdWithUser" parameterType="int" resultMap="orderMap">
select * from orders where id = #{id};
</select>
</mapper>
③ UserMapper接口
public interface UserMapper {
// 根据用户id查询user对象
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">
<!--
根据用户id查询user对象
-->
<select id="findById" parameterType="int" resultType="cn.itcast.domain.User">
select * from user where id = #{id};
</select>
</mapper>
⑤ 通过mybatis进行嵌套组合
1589247990774.png⑥ 测试
public class OrderMapperTest extends BaseMapperTest { // 继承父类,就可以直接使用 父类的方法和成员变量了
// 一对一嵌套测试
@Test
public void test01() throws Exception {
// 获取代理对象
OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class);
// 根据id查询
Order order = orderMapper.findByIdWithUser(1);
System.out.println(order);
}
}
1589247953911.png
⑦ 嵌套关系
1589248264800.png1.3 一对多嵌套查询
需求:查询一个用户,与此同时查询出该用户具有的订单
sql语句
-- 1. 先根据用户id,查询用户表(一个)
SELECT * FROM USER WHERE id = 41;
-- 2. 再根据用户id,查询订单表(多个)
SELECT * FROM orders WHERE uid = 41;
① UserMapper接口
public interface UserMapper {
// 一对多嵌套查询
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>
<!--一对多嵌套组合-->
</resultMap>
<!--一对多嵌套查询-->
<select id="findByIdWithOrders" parameterType="int" resultMap="userWithOrdersMap">
SELECT * FROM USER WHERE id = #{id};
</select>
③ OrderMapper接口
public interface OrderMapper {
// 根据用户id,查询订单列表
public List<Order> findByUid(Integer uid);
}
④ OrderMapper映射
<select id="findByUid" parameterType="int" resultType="cn.itcast.domain.Order">
SELECT * FROM orders WHERE uid = #{uid};
</select>
⑤ 通过mybatis进行嵌套组合
1589249903827.png⑥ 测试
public class UserMapperTest extends BaseMapperTest {
// 一对多嵌套查询测试
@Test
public void test01() throws Exception {
// 获取代理
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.findByIdWithOrders(41);
System.out.println(user);
}
}
1589249880000.png
⑦ 嵌套关系
1589250191685.png1.4 多对多嵌套查询(由二个一对多组成)
需求:查询用户同时查询出该用户的所有角色
mybatis的实现方案就是(一对多),区别在于sql语句不同
sql语句
-- 1. 先根据用户id,查询用户表(一个)
SELECT * FROM USER WHERE id = 41;
-- 2. 再根据用户id,查询角色表(多个)
SELECT * FROM role r INNER JOIN user_role ur ON ur.`rid` = r.`id` WHERE ur.`uid` = 41;
① UserMapper接口
public interface UserMapper {
// 多对多嵌套查询
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>
<!-- 多对多嵌套-->
</resultMap>
<!--多对多嵌套查询-->
<select id="findByIdWithRoles" parameterType="int" resultMap="userWithRolesMap">
SELECT * FROM USER WHERE id = #{id};
</select>
③ RoleMapper接口
public interface RoleMapper {
// 根据用户id,查询角色列表
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>
<!--
根据用户id,查询角色列表
-->
<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>
⑤ 通过mybatis进行嵌套组合
1589251531415.png⑥ 测试
// 多对多测试(根据用户查询角色)
@Test
public void test02()throws Exception{
// 获取代理
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.findByIdWithRoles(41);
System.out.println(user);
}
1589251469136.png
⑦ 嵌套关系
1589251724851.png1.5 知识小结
* 步骤:一对多举例
1)先查询(一方)单表
2)在查询(多方)单表
3)最后由mybatis嵌套组合
一对一配置:使用<resultMap>+<association>做配置,通过column条件,执行select查询
一对多配置:使用<resultMap>+<collection>做配置,通过column条件,执行select查询
多对多配置:使用<resultMap>+<collection>做配置,通过column条件,执行select查询
优点:1.简化sql语句编写、2.不会产生笛卡尔积
缺点:麻烦...
开发中到底使用哪一种?
传统开发,数据量小:使用关联查询
互联网开发,数据量大:使用嵌套查询
当前也有人这么玩
在java中先查用户,在查角色,不在使用嵌套....
二 MyBatis加载策略
2.1 什么是加载策略
当多个模型(表)之间存在关联关系时, 加载一个模型(表)的同时, 是否要立即加载其关联的模型, 我们把这种决策成为==加载策略==
如果加载一个模型(表)的时候, 需要立即加载出其关联的所有模型(表), 这种策略称为==立即加载==
如果加载一个模型的时候, 不需要立即加载出其关联的所有模型, 等到真正需要的时候再加载, 这种策略称为==延迟加载(懒加载)==
Mybatis中的加载策略有两种:立即加载和延迟加载, 默认是立即加载
注意:延迟加载是在嵌套查询基础上实现的
* 什么样的场景使用立即加载
一对一
* 什么样的场景使用延迟加载(什么时候用,什么时候查询,提高数据库性能)
一对多、多对多
2.2 配置延迟加载
2.2.1 全局
SqlMapConfig.xml,设置开启全局延迟加载
<!--全局配置-->
<settings>
<!--开启延迟(懒)加载 true 开始 false(默认值) 关闭-->
<setting name="lazyLoadingEnabled" value="true"/>
</settings>
2.2.3 局部
mapper映射文件,指定某一个select标签配置
<association></association> 标签
<collection></collection> 标签
fetchType=""属性
eager 立即加载
lazy 延迟加载
注意:局部优先级高于全局的...
2.3 触发(立即)加载
有这样一个全局配置lazyLoadTriggerMethods
,它定义的方法会触发立即加载
也就说当你调用它定义的方法时, 会执行数据加载, 它的默认值是equals,clone,hashCode,toString
<!--全局配置-->
<settings>
<!--开启延迟(懒)加载 true 开始 false(默认值) 关闭-->
<setting name="lazyLoadingEnabled" value="true"/>
<!--触发立即加载的配置
默认值:equals,clone,hashCode,toString
value="" 覆盖了默认值,表示在执行上述四个方法时,不会触发立即加载...
只有在执行get方法获取时,触发数据加载...
-->
<setting name="lazyLoadTriggerMethods" value=""/>
</settings>
三 MyBatis缓存
什么是缓存?
服务器内存(硬盘)中的一块区域
为什么使用缓存?
提高查询效率的
什么样的数据适合做缓存?
经常访问但又不经常修改的数据...
缓存是用来提高查询效率的,所有的持久层框架基本上都有缓存机制
Mybatis也提供了缓存策略,分为一级缓存,二级缓存
3.1 一级缓存
3.1.1 介绍
MyBatis一级缓存是:SqlSession级别的缓存,默认开启,不需要手动配置
1589201319071.png
3.1.2 验证
需求:根据id查询用户
// 一级缓存测试
@Test
public void test03() throws Exception {
// 获取sqlSession会话对象
SqlSession sqlSession = MyBatisUtils.openSession();
// 获取第一个代理对象
UserMapper userMapper1 = sqlSession.getMapper(UserMapper.class);
User user1 = userMapper1.findById(41);// 走数据库
System.out.println(user1);
// 清除缓存(自己测试增、删、改)
sqlSession.clearCache();
// 获取第二个代理对象
UserMapper userMapper2 = sqlSession.getMapper(UserMapper.class);
User user2 = userMapper2.findById(41);// 走缓存(如果上面清除缓存,还是走数据库)
System.out.println(user2);
// sqlSession关闭(清除缓存...)
MyBatisUtils.close(sqlSession);
}
3.1.3 分析
一级缓存是SqlSession范围的缓存,不同的SqlSession之间的缓存区域是互相不影响的,执行SqlSession的C(增加)U(更新)D(删除)操作,或者调用clearCache()、commit()、close()方法,都会清空缓存
1589255593980.png一级缓存源码
1589256171662.png3.2 二级缓存【了解】
3.2.1 介绍
MyBatis的二级缓存虽然是默认开启的,但需要在映射文件中配置<cache/>
标签才能使用,而且要求实体类的必须实现序列化接口
3.2.2 验证
mybatis全局配置,默认值就是开启了二级缓存
1589263893048.png指定需要开启二级缓存的映射配置文件
1589263857841.png指定User实现序列化接口
1589263995869.png// 二级缓存
@Test
public void test04() throws Exception {
// 模拟第一个用户
SqlSession sqlSession1 = MyBatisUtils.openSession();
UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);
User user1 = userMapper1.findById(41);
System.out.println(user1);
sqlSession1.close();
// 模拟第二个用户
SqlSession sqlSession2 = MyBatisUtils.openSession();
UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);
User user2 = userMapper2.findById(41);
System.out.println(user2);
sqlSession2.close();
}
3.1.3 分析
二级缓存是mapper映射级别的缓存,多个SqlSession去操作同一个Mapper映射的sql语句,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。
二级缓存相比一级缓存的范围更大(按namespace来划分)
1589264629385.png3.3 知识小结
1564842702588.png1. mybatis的缓存,都不需要我们手动存储和获取数据。mybatis自动维护的。
2. 使用mybatis,如果是中小型项目,使用自带缓存的机制是可以满足需求的。如果是大型(分布式)项目,mybatis的缓存灵活性不足,需要使用第三方的缓存技术解决问题。
四 核心配置文件回顾
4.1 properties标签
加载外部的properties文件
<properties resource="jdbc.properties"></properties>
4.2 settings标签
全局参数配置
<settings>
<!--开启懒加载-->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 指定触发延迟加载的方法,只有get方法执行时才会触发立即加载 -->
<setting name="lazyLoadTriggerMethods" value=""/>
<!--开启二级缓存 true开启(默认) false关闭-->
<setting name="cacheEnabled" value="true"/>
</settings>
4.3 typeAliases标签
为 Java 类型设置一个别名
1. 单个定义别名
<typeAliases>
<typeAlias type="cn.itcast.domain.User" alias="user"></typeAlias>
</typeAliases>
1. 使用包的形式批量定义别名
<typeAliases>
<package name="cn.itcast.domain"></package>
</typeAliases>
4.4 mappers标签
加载映射配置
1. 加载指定的src目录下的映射文件,例如:
<mapper resource="cn/itcast/mapper/UserMapper.xml"/>
1. 加载并扫描指定包下所有的映射文件(接口),例如:
<package name="cn.itcast.mapper"/>
4.5 environments标签
数据源环境配置
<environments default="mysql">
<environment id="mysql">
<!--事务管理器使用JDBC类型-->
<transactionManager type="JDBC"/>
<!--数据源使用连接池-->
<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>
老师下午总结
回顾(登陆展示用户列表)
1.环境搭建
1.创建数据库
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.创建模块然后导入对应的jar
导入jar我们需要分析我们要使用到的技术,这个过程应该是你们的项目组长负责
-
mysql的驱动
-
数据库的连接池
-
jstl
-
Beanutils
1589269607126.png
3.分包分层
1589269804767.png4. 导入静态资源文件
1589269869357.png==注意: 2019&2020版拷贝静态资源的时候经常没有拷贝到out目录中,程序运行的时候是执行out目录的内容==
1589270024992.png5. 导入工具类(在今天素材里面)
1589270143510.png6.导入字符过滤器
1589270590593.pngpackage 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;
//该字符串过滤器要解决全局乱码问题
/*
乱码的分类:
1. 请求乱码( html页面提交表单数据---servlet --- servlet通过getparameter()方法获取参数的时候是否乱码)
get请求: 没有
post请求: 有乱码
2. 响应乱码 response.getWrite().write("呵呵") 向浏览器输出数据乱码
不管任何请求方式都会乱码的。
*/
//配置过滤路径
@WebFilter("/*")
public class CharacterEncondingFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//1. 强制类型转换 (目的: 是为了使用HttpServletRequest的getmethod方法)
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
//2. 解决response响应乱码问题
response.setContentType("text/html;charset=utf-8");
//3. 获取客户请求方式,如果是post请求方式我们需要解决获取请求参数乱码问题
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.png2.修改login.jsp页面,修改其提交的地址的信息
1589271432614.png2.编写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,从而得知用户需要调用方法
String methodName = request.getParameter("action");
if("login".equalsIgnoreCase(methodName)){
//登录方法
login(request,response);
}else if("list".equalsIgnoreCase(methodName)){
//展示用户列表
list(request,response);
}
}
//用户登陆
protected void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
//1. 获取请求参数
Map<String, String[]> parameterMap = request.getParameterMap();
//2. 把请求参数封装到user对象中
User user = new User();
BeanUtils.populate(user,parameterMap); //把参数封装到user对象中了
//3.调用userService的login方法,判断是否登陆成功
boolean isLogin = userService.login(user);
if(isLogin){
//4. 登陆成功,设置登陆成功的标记,并且返回首页
request.getSession().setAttribute("loginUser",user);
//请求重定向到首页
response.sendRedirect(request.getContextPath()+"/index.jsp"); // request.getContextPath() 获取模块的根路径
}else {
//5. 登陆失败,设置登陆错误的信息,回到login.jsp页面
request.setAttribute("error","用户名或者密码错误");
//请求转发到登录页面(这里使用请求转发的原因是因为request域中存储有数据)
request.getRequestDispatcher("/login.jsp").forward(request,response);
}
} catch (Exception e) {
e.printStackTrace();
}
}
//展示用户列表
protected void list(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
3.编写UserService的login方法
package com.itheima.service;
import com.itheima.dao.UserDao;
import com.itheima.domain.User;
public class UserService {
private UserDao userDao = new UserDao();
//用户登陆
public boolean login(User user){
return userDao.login(user);
}
}
4.编写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. 通过工具类得到连接
connection = JdbcUtils.getConnection();
//2. 准备sql语句得到PreparedStatement
String sql = "SELECT * FROM USER WHERE username=? AND PASSWORD=?";
pst = connection.prepareStatement(sql);
//3. 设置参数
pst.setObject(1,user.getUsername());
pst.setObject(2,user.getPassword());
//4. 执行sql语句,得到结果
rs = pst.executeQuery();
//5. 返回结果
return rs.next();
} catch (SQLException e) {
e.printStackTrace();
} finally {
//6. 关闭资源
JdbcUtils.close(rs,pst,connection);
}
//该语句只是为了让代码不报错,让方法最终有返回值而已
return false;
}
}
3.用户展示列表
1.流程分析
1589273051193.png2.修改index.jsp页面修改连接地址
1589273149885.png3.编写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,从而得知用户需要调用方法
String methodName = request.getParameter("action");
if("login".equalsIgnoreCase(methodName)){
//登录方法
login(request,response);
}else if("list".equalsIgnoreCase(methodName)){
//展示用户列表
list(request,response);
}
}
//展示用户列表
protected void list(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1. 调用userService的findAll方法得到所有的用户信息
List<User> list = userService.findAll();
//2. 把用户信息存储到request域中
request.setAttribute("list",list);
//3. 请求转发到list页面
request.getRequestDispatcher("/list.jsp").forward(request,response);
}
}
3.编写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.编写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 {
//查询用户列表
public List<User> findAll() {
Connection connection = null;
PreparedStatement pst =null;
ResultSet rs = null;
List<User> list = new ArrayList<>();
try {
//1. 通过工具类得到连接
connection = JdbcUtils.getConnection();
//2. 准备sql语句得到PreparedStatement
String sql="select * from user";
pst = connection.prepareStatement(sql);
//3. 执行sql语句,得到查询的结果
rs = pst.executeQuery();
//4. 然后遍历resutset,把遍历结果存储到集合中
while(rs.next()){
//每一行数据就是一个用户对象的数据
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. 关闭资源
JdbcUtils.close(rs,pst,connection);
}
return list;
}
}
5.修改list.jsp的el表达式
1589273912576.png<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<!-- 网页使用的语言 -->
<html lang="zh-CN">
<head>
<!-- 指定字符集 -->
<meta charset="utf-8">
<!-- 使用Edge最新的浏览器的渲染方式 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- viewport视口:网页可以根据设置的宽度自动进行适配,在浏览器的内部虚拟一个容器,容器的宽度与设备的宽度相同。
width: 默认宽度与设备的宽度相同
initial-scale: 初始的缩放比,为1:1 -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>用户信息管理系统</title>
<!-- 1. 导入CSS的全局样式 -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<!-- 2. jQuery导入,建议使用1.9以上的版本 -->
<script src="js/jquery-2.1.0.min.js"></script>
<!-- 3. 导入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">用户信息列表</h3>
<table border="1" class="table table-bordered table-hover">
<tr class="success">
<th>编号</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发送数据
4.1 html&jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<%--1.导入jquery的js--%>
<script src="${pageContext.request.contextPath}/js/jquery-3.2.1.min.js"></script>
</head>
<body>
<%--//2. 给按钮注册点击事件--%>
<input type="button" value="发送ajax请求" onclick="send()"/><br/>
用户名:<span id="userName"></span><br/>
密码:<span id="password"></span><br/>
</body>
<script>
//需求:点击按钮发送ajax请求,获取到一个User的json对象,然后把用户用户名与密码设置对应的span中
//3. 发送ajax请求
function send(){
$.ajax(
{
url:"${pageContext.request.contextPath}/testServlet", //发送地址
data:{}, //发送的参数,目前没有参数交给testServlet,所以我留空了。
type:"get",//请求的方式
dataType:"json", //服务器返回的数据格式
success:function(user){ //成功的回调函数
$("#userName").html(user.username);
$("#password").html(user.password);
}
}
);
}
</script>
</html>
4.2 servlet接收参数
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");
//把对象转发为json
ObjectMapper objectMapper = new ObjectMapper();
String json = objectMapper.writeValueAsString(user);
//把json字符串写出
response.getWriter().write(json);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
网友评论