JSP&三层架构
目标
第一章-EL表达式
知识点-EL表达式概述
1.目标
2.讲解
2.1.什么是El表达式
? Expression Language: 表达式语言, jsp2.0之后内置在jsp里面
? 目的:为了使JSP写起来更加简单, 取值(取的域对象里面存的值)更加简单。(代替脚本 <% %>)
2.2. EL语法
? ${el表达式}
2.3. EL表达式的用途
? 1.获取数据. 获取的是域(request,session,ServletContext)对象中存储的数据
? 2.EL执行运算
- 使用EL表达式获取cookie中的数据
3.小结
- EL表达式:表达式语言
- 语法:${el表达式}
- 作用:1. 获取域对象里面的数据 2. 执行运算
知识点-El获取数据
1.目标
- 能够使用el表达式域里面的数据(先要把数据存到域对象里面)
2.路径
- 获取简单数据类型数据(基本类型,字符串)
- 获取数组
- 获取list
- 获取Map
- 获取bean
3.讲解
3.1获取简单数据类型数据
? 语法:${requestScope|sessionScope|applicationScope.属性名};
? 快捷写法:${属性名}, 属性名就是存在域对象里面的key
<%--
Created by IntelliJ IDEA.
User: Fanyi Xiao
Date: 2020/7/15
Time: 8:52
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>使用EL表达式获取域对象中的简单类型的数据</title>
</head>
<body>
<%
//往域对象存值
application.setAttribute("msg","applicationValue");
//session.setAttribute("msg","sessionValue");
//request.setAttribute("msg","requestValue");
//在我们开发过程中,是否会往多个域对象中存放同一个key??? 这是不会的
//所以我们用el表达式获取域对象里面的数据,还可以简化成${key} 获取范围最小的域对象中的这个key对应的值
%>
获取的application域对象中的msg=${applicationScope.msg}<br>
获取session域对象中的msg=${sessionScope.msg}<br>
获取request域对象中的msg=${requestScope.msg}<br>
获取存放在域对象中的msg=${msg}
</body>
</html>
3.2获取数组
? 语法: ${key[下标]} key就是域对象里面存的key
3.3获取list
? 语法:${list属性名[index]}或者${list属性名.get(index)};list属性名就是存入域对象里面的key
3.4获取Map
? 语法:${map属性名.键}或者${map属性名.get("键")},map属性名就是存入域对象里面的key
3.5 获取bean
? 语法:${key.javabean属性}
? 依赖getxxx()方法; eg: getPassword()—去掉get–>Password()----首字母小写—>password
<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.HashMap" %>
<%@ page import="java.util.List" %>
<%@ page import="java.util.Map" %>
<%@ page import="com.itheima.pojo.User" %><%--
Created by IntelliJ IDEA.
User: Fanyi Xiao
Date: 2020/7/15
Time: 9:05
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>使用EL表达式获取存储在域对象中的复杂类型的数据</title>
</head>
<body>
<%
//往域对象中存放数组类型的数据
String[] arr = {"张三","李四","王五","赵六","田七","狗娃"};
request.setAttribute("arr", arr);
//往域对象中存放一个集合
List<String> list = new ArrayList<String>();
list.add("张三");
list.add("李四");
list.add("王五");
list.add("赵六");
list.add("田七");
request.setAttribute("list", list);
//往域对象中存放一个map
Map<String,String> map = new HashMap<String,String>();
map.put("name", "张三");
map.put("password", "123456");
map.put("nickname", "张三丰");
request.setAttribute("map", map);
//往域对象中存放一个pojo对象
User user = new User(1, "jay", "台湾省");
request.setAttribute("user",user);
%>
获取存放在request域对象中的数组中的第三个元素:${arr[2]}<br>
<%--
在el表达式中,只要是根据下标获取元素,都可以写[index]
--%>
获取存放在request域对象中的集合中的第四个元素:${list[3]}<br>
<%--
在el表达式中,只要是根据对应的属性的get方法去获取数据,都可以写成".属性名" 或者 ["属性名"]
--%>
获取存储在request域对象中的map中的nickname:${map.nickname}<br>
获取存放在request域对象中的user的address属性的值:${user.address}
</body>
</html>
4.小结
4.1语法
- 获得简单类型的
${key}
- 获得数组类型的
${key[下标]}
- 获得List类型的
${key.get(index)} 或者${key[index]}
- 获得Map类型的
${key.get(键)} 或者${key.键} key是存到域对象里面的key
- 获得JavaBean类型的
${key.javaBean属性}
知识点-EL执行运算
1.目标
2.讲解
2.1算数运算
? +,-,*,/
- +不能拼接字符串,如果+两端是字符串,那么会将字符串转换成数字之后再进行加法运算,如果+两端的字符串无法转换成数字,则会报错
2.2 逻辑运算
? < >= <= != ==
2.3 关系运算
? && || !
2.4 非空判断【重点】
? empty,1. 判断一个对象是否为null, 2. 判断集合长度是否为0, 3. 判断一个字符串是否为空字符串
? not empty
? 语法: ${empyt 属性名};属性名 就是域对象里面的key值
<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.List" %>
<%@ page import="com.itheima.pojo.User" %><%--
Created by IntelliJ IDEA.
User: Fanyi Xiao
Date: 2020/7/15
Time: 9:35
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>empty 运算符的介绍</title>
</head>
<body>
<%
//el表达式中的empty可以判断一个字符串是否为空字符串,一个对象是否为null,一个集合的长度是否为0
List<String> list = new ArrayList<String>();
list.add("张三丰");
request.setAttribute("list", list);
request.setAttribute("msg","requestValue");
User user = new User();
request.setAttribute("u",user);
%>
判断域对象中的list集合的长度是否为0: ${empty list}<br>
判断域对象中的msg字符串是否为空字符串: ${empty msg}<br>
判断域对象中的user是否为null : ${empty u}<br>
</body>
</html>
3.小结
-
注意的地方: +只能做加法运算,不能拼接字符串 -
empty【重点】
- 语法
- ${empty key}
- ${not empty key}
- 作用
- 判断一个对象是否为null
- 判断一个集合长度是否为0
- 判断一个字符串是否是""
- 注意
- 如果是集合, 集合为null 是empty
- 如果是集合, 集合不为null 但是长度为0 还是empty
知识点-使用EL表达式获取存放在cookie中的数据(扩展)
? 语法:${cookie.cookie的name.value}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>使用el表达式获取存储在cookie中的数据</title>
</head>
<body>
<%--
jsp里面是内置session对象,有了session对象,那么浏览器就会携带一个名为"JSESSIONID"的cookie
我们的目标就是获取"JSESSIONID"的值
--%>
<%
Cookie[] cookies = request.getCookies();
String cookieValue = null;
if (cookies != null) {
for (Cookie cookie : cookies) {
if (cookie.getName().equals("JSESSIONID")) {
cookieValue = cookie.getValue();
}
}
}
%>
使用原始方式获取的JSESSIONID的值为: <%=cookieValue%><br>
<%--
${cookie}表示获取这次请求中的所有cookie对象
${cookie.JSESSIONID}表示获取名为"JSESSIONID"的cookie对象
${cookie.JSESSIONID.value}表示获取名为"JSESSIONID"的cookie对象的value
--%>
使用EL表达式获取JSESSIONID的值为: ${cookie.JSESSIONID.value}
</body>
</html>
第二章-JSTL标签库
知识点-JSTL标签库概述
1.目标
2.讲解
2.1 什么是JSTL标签库
? JSTL(JSP Standard Tag Library,JSP标准标签库)是一个不断完善的开放源代码的JSP标签库,是由apache的jakarta小组来维护的。这个JSTL标签库没有集成到JSP的, 要使用的话, 需要导jar包.
2.2 JSTL标签库的作用
? 为了简化在jsp页面上操作数据; eg: 遍历数据 判断数据等
2.3 JSTL标签库的类别
3.小结
- JSTL: JSP标准的标签库. 也就意味着我们可以在jsp里面使用除了html以外的其它的标签
- 作用: 遍历, 判断… 代替脚本
知识点-JSTL核心标签库
1.目标
2.讲解
2.1核心标签库使用步骤
- 导入jar包
- 在JSP页面上导入核心标签库
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
2.3if标签
<c:if test="el表达式${..}">
</c:if>
<%--
Created by IntelliJ IDEA.
User: Fanyi Xiao
Date: 2020/8/27
Time: 10:10
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head>
<title>使用jstl中的if标签进行判断</title>
</head>
<body>
<%
//往域对象中存储一个age
request.setAttribute("age",17);
//目标:判断age的值,如果大于等于18,则在浏览器页面上输出"已成年",否则输出"未成年"
//jstl的使用步骤:1. 导入jar包 2. 在jsp页面通过taglib指令引入核心标签库 3. 使用标签
%>
<%--
if标签有一个属性叫做test,它表示判断表达式,需要结合el一起使用
如果要表示相反的判断,则再添加一个if标签,然后写相反的条件就行
if标签还有一个属性叫做var,表示将判断结果存储进域对象时候的key(了解)
if标签的第三个属性叫做scope,表示将判断结果存储进哪个域对象(了解)
--%>
<c:if test="${age >= 18}" var="flag" scope="request">
已成年
</c:if>
<c:if test="${age < 18}">
未成年
</c:if>
<br>
${flag}
</body>
</html>
2.4choose标签
<%--
Created by IntelliJ IDEA.
User: Fanyi Xiao
Date: 2020/7/15
Time: 9:59
To change this template use File | Settings | File Templates.
--%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>jstl中的choose标签的使用介绍</title>
</head>
<body>
<%
request.setAttribute("course","PHP");
%>
<c:choose>
<%--
一个when标签表示一个条件
--%>
<c:when test="${course == 'Java'}">
学习Java
</c:when>
<c:when test="${course == 'Android'}">
学习Android
</c:when>
<c:when test="${course == 'C++'}">
学习C++
</c:when>
<c:otherwise>
学习,学个屁!!!
</c:otherwise>
</c:choose>
</body>
</html>
2.5 foreach标签
?
<%--
jstl中的forEach标签是用来代替for循环语句
目标1: 在浏览器上显示0-9的数字
begin属性: 从哪个下标开始遍历, 如果不写默认是从0开始
end属性: 到哪个下标结束遍历,如果不写默认是遍历到集合/数组的最后一个元素
step属性: 表示遍历时候的步长,默认步长是1
var属性: 表示将遍历的结果存放进域对象时候的key
--%>
<c:forEach begin="0" end="9" step="1" var="i">
${i}
</c:forEach><br>
?
-
复杂的使用遍历集合: <%
//往域对象存储一个集合
List<String> list = new ArrayList<String>();
list.add("张三");
list.add("李四");
list.add("王五");
list.add("赵六");
list.add("田七");
request.setAttribute("list", list);
%>
<c:forEach begin="0" end="9" step="1" var="i">
${i}
</c:forEach><br>
<%--
通过items属性指定遍历域对象里面的list
通过var属性指定遍历出来的每个数据存储到域对象时候的key
--%>
<c:forEach items="${list}" var="username">
${username}
</c:forEach>
-
c:forEach中的varStatus属性。 指向一个字符串,该字符串引用一个对象。 map.put("vs",一个对象);
这个对象记录着当前遍历的元素的一些信息:
index:返回索引。从0开始
count:返回计数。从1开始
last:是否是最后一个元素
first:是否是第一个元素
<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.List" %><%--
Created by IntelliJ IDEA.
User: Fanyi Xiao
Date: 2020/7/15
Time: 10:15
To change this template use File | Settings | File Templates.
--%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>forEach 标签的varStatus属性的介绍</title>
</head>
<body>
<%
//往域对象存储一个集合
List<String> list = new ArrayList<String>();
list.add("张三");
list.add("李四");
list.add("王五");
list.add("赵六");
list.add("田七");
request.setAttribute("list", list);
%>
<%--
forEach标签的varStatus属性:指定将遍历出来的每一个元素的状态存储进域对象时候的key
遍历出来的每一个元素都有一些状态(属性),比如:
下标 index:
计数 count:
当前元素的值 current:
是否是第一个元素:
是否是最后一个元素
--%>
<table border="1" cellspacing="0" width="700" align="center">
<tr>
<th>下标</th>
<th>计数</th>
<th>姓名</th>
<th>是否是第一个元素</th>
<th>是否是最后一个元素</th>
</tr>
<c:forEach items="${list}" varStatus="vst">
<tr>
<td>${vst.index}</td>
<td>${vst.count}</td>
<td>${vst.current}</td>
<td>${vst.first}</td>
<td>${vst.last}</td>
</tr>
</c:forEach>
</table>
</body>
</html>
3.小结
- foreach标签
<c:foreach begin="从哪里开始" end="到哪里结束" var="每次遍历的赋值变量" step="步长">
//每遍历一次 foreach里面就执行一次
</c:foreach>
<c:foreach items="使用el从域对象里面取出集合" var="每次遍历的赋值变量" varStatus="遍历的状态">
//每遍历一次 foreach里面就执行一次
</c:foreach>
回顾el和JSTL的内容
el
- el的语法: ${el表达式}
- el的作用:
- 获取域对象中的数据,${key}
- 执行运算,el表达式中可以使用运算符:±*/><与或非等等运算符都能使用,它还有一个特殊的运算符叫做empty
- 获取cookie中的数据: ${cookie.cookie的名字.value}
jstl
- jstl的使用步骤:
- 导入jar包
- 在要使用jstl的jsp页面通过tablib指令引入核心标签库
- 使用jstl的核心标签库中的标签
- jstl的常用标签:
- if
- choose
- forEach
- if标签
- 作用: 代替jsp页面中的if语句
- 属性:
- test(必须的属性): 结合el表达式编写判断条件
- var: 将判断结果存储进域对象时候的key
- scope:将判断条件存储进哪个域对象
- choose标签:
- 作用:代替多条件判断
- 它需要和when标签以及otherwise标签一起使用
- forEach标签
- 作用: 代替jsp页面的for循环语句
- 属性:
- begin 开始遍历的下标,如果没写,则从0开始遍历
- end 结束遍历的下标,如果没写,则遍历到数组或者集合的最后一个元素
- step 遍历的步长,如果没写就是1
- var 遍历出来的每一个数据存储进域对象时候的key
- varStatus 遍历出来的每一个数据的状态
- index 下标
- count 序号
- first 是否是第一个元素
- last 是否是最后一个元素
- current 遍历出来的当前元素
第三章-综合案例和开发模式
案例-完成转账的案例v1
一.需求
- 当单击提交按钮,付款方向收款方安照输入的金额转账。
二,分析
三,实现
1.案例的准备工作
-
数据库的准备 create database day29;
use day29;
create table account(
id int primary key auto_increment,
name varchar(20),
money double
);
insert into account values (null,'jay',1000);
insert into account values (null,'aobama',1000);
insert into account values (null,'ww',1000);
-
页面 <%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form method="post" action="">
<table border="1px" width="500px" align="center">
<tr>
<td>付款方</td>
<td><input type="text" name="from"></td>
</tr>
<tr>
<td>收款方</td>
<td><input type="text" name="to"></td>
</tr>
<tr>
<td>金额</td>
<td><input type="text" name="money"></td>
</tr>
<tr>
<td colspan="2"><input type="submit"></td>
</tr>
</table>
</form>
</body>
</html>
-
jar包 -
工具类 -
配置文件
2.代码实现
package com.itheima.web.servlet;
import com.itheima.utils.DruidUtil;
import org.apache.commons.dbutils.QueryRunner;
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("/account")
public class AccountServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
String fromName = request.getParameter("from");
String toName = request.getParameter("to");
Double money = Double.valueOf(request.getParameter("money"));
QueryRunner queryRunner = new QueryRunner(DruidUtil.getDataSource());
String sql1 = "update account set money=money-? where name=?";
try {
queryRunner.update(sql1,money,fromName);
String sql2 = "update account set money=money+? where name=?";
queryRunner.update(sql2,money,toName);
response.getWriter().write("转账成功!!!");
} catch (Exception e) {
e.printStackTrace();
response.getWriter().write("转账失败!!!");
}
}
}
四.小结
- 转账: 一个用户的钱减少, 一个用户的钱增加
知识点-开发模式
1.目标
2.讲解
2.1 JSP的开发模式一【了解】
javaBean:实体类。特点:私有化的属性、公共的getter setter方法、无参的构造。
2.2 JSP的开发模式二
? JSP + Servlet + JavaBean 称为MVC的开发模式.
? MVC:开发模式
? M:model 模型 (javaBean:封装数据)
? V:View 视图 (JSP:展示数据)
? C:controller 控制器 (Servlet:处理逻辑代码,做为控制器)
2.3模式三: 三层架构
- 软件中分层:按照不同功能分为不同层,通常分为三层:表现层(web层),业务层,持久(数据库)层。
分层 | 包名(公司域名倒写) |
---|
表现层(web层) | com.itheima.web | 业务层(service层) | com.itheima.service | 持久层(数据库访问层) | com.itheima.dao | JavaBean | com.itheima.bean | 工具类 | com.itheima.utils |
- 分层的意义:
- 解耦:降低层与层之间的耦合性。 (以后面向接口编程)
- 可维护性:提高软件的可维护性,对现有的功能进行修改和更新时不会影响原有的功能。
- 可扩展性:提升软件的可扩展性,添加新的功能的时候不会影响到现有的功能。
- 可重用性:不同层之间进行功能调用时,相同的功能可以重复使用。
3.小结
-
模式一: JSP+JavaBean【了解】 -
模式二: MVC
- M model JavaBean
- V View JSP
- C Controller Servlet
-
三层架构
- WEB层
- 业务层
- 持久层
- 三层架构中的包名:
- 表现层: web
- 业务层: service
- 数据访问层/持久层: dao
案例-完成转账的案例v2
一.需求
二,分析
三,实现
package com.itheima.web.servlet;
import com.itheima.service.AccountService;
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("/account")
public class AccountServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
String fromName = request.getParameter("from");
String toName = request.getParameter("to");
Double money = Double.valueOf(request.getParameter("money"));
try {
AccountService accountService = new AccountService();
accountService.transfer(fromName,toName,money);
response.getWriter().write("转账成功!!!");
} catch (Exception e) {
e.printStackTrace();
response.getWriter().write("转账失败!!!");
}
}
}
package com.itheima.service;
import com.itheima.dao.AccountDao;
import java.sql.SQLException;
public class AccountService {
private AccountDao accountDao = new AccountDao();
public void transfer(String fromName,String toName,Double money) throws SQLException {
accountDao.updateAccount(fromName,-money);
accountDao.updateAccount(toName,money);
}
}
package com.itheima.dao;
import com.itheima.utils.DruidUtil;
import org.apache.commons.dbutils.QueryRunner;
import java.sql.SQLException;
public class AccountDao {
private QueryRunner queryRunner = new QueryRunner(DruidUtil.getDataSource());
public void updateAccount(String name,Double money) throws SQLException {
String sql = "update account set money=money+? where name=?";
queryRunner.update(sql,money,name);
}
}
四.小结
- WEB层 com.itheima.web
- 业务层 com.itheima.service xxService
- 持久层 com.itheima.dao xxDao
案例-完成转账的案例v3
一.需求
- 当单击提交按钮,付款方向收款方安照输入的金额转账。 使用手动事务进行控制
二,分析
1.DBUtils实现事务管理
API | 说明 |
---|
QueryRunner() | 创建QueryRunner对象. 手动提交事务时使用 | query(connection,String sql, Object[] params, ResultSetHandler rsh) | 查询(需要传入Connection) | update(connection,String sql, Object… params) | 更新 |
2.思路
三,实现
package com.itheima.service;
import com.itheima.dao.AccountDao;
import com.itheima.utils.DruidUtil;
import java.sql.Connection;
import java.sql.SQLException;
public class AccountService {
private AccountDao accountDao = new AccountDao();
public void transfer(String fromName,String toName,Double money) {
Connection conn = null;
try {
conn = DruidUtil.getDataSource().getConnection();
conn.setAutoCommit(false);
accountDao.updateAccount(conn,fromName, -money);
int num = 10 / 0;
accountDao.updateAccount(conn,toName, money);
conn.commit();
} catch (Exception e) {
e.printStackTrace();
try {
conn.rollback();
} catch (SQLException ex) {
ex.printStackTrace();
}
throw new RuntimeException("转账失败");
}
}
}
package com.itheima.dao;
import com.itheima.utils.DruidUtil;
import org.apache.commons.dbutils.QueryRunner;
import java.sql.Connection;
import java.sql.SQLException;
public class AccountDao {
private QueryRunner queryRunner = new QueryRunner(DruidUtil.getDataSource());
public void updateAccount(Connection connection,String name, Double money) throws SQLException {
String sql = "update account set money=money+? where name=?";
queryRunner.update(connection,sql,money,name);
}
}
四.小结
- 思想1: service层将异常try起来了,怎么才能让servlet还能够获取异常呢?
在catch里面抛运行时异常
-
思想2: 如果在service和dao共享一个Connection对象 通过调用方法的时候将connection作为参数传递给Dao
-
技术点1 : 怎么开启、提交、回滚事务 connection.setAutoCommit(false)开启事务
connection.commit()提交事务
connection.rollback()回滚事务
注意: 开启事务的连接和执行SQL语句的连接要是同一个
-
技术点2 : 在使用DBUtils执行SQL语句的时候,怎么才能指定使用哪个连接呢? 调用queryRunner对象的update或者query方法的时候,可以传入connection
案例-完成转账的案例v4
一.需求
- 当单击提交按钮,付款方向收款方安照输入的金额转账。 使用事务进行控制
二,分析
1.ThreadLocal
? 在“事务传递参数版”中,我们必须修改方法的参数个数,传递链接,才可以完成整个事务操作。如果不传递参数,是否可以完成?在JDK中给我们提供了一个工具类:ThreadLocal,此类可以在一个线程中共享数据。
? java.lang.ThreadLocal,该类提供了线程局部 (thread-local) 变量,用于在当前线程中共享数据。ThreadLocal工具类底层就是一个Map,key存放的当前线程,value存放需要共享的数据
package com.itheima;
public class TestMain {
public static void main(String[] args) {
ThreadLocal<String> threadLocal = new ThreadLocal<>();
threadLocal.set("jay");
threadLocal.set("aobama");
new Thread(new Runnable() {
@Override
public void run() {
threadLocal.set("jay");
String s = threadLocal.get();
System.out.println("在新线程中获取ThreadLocal中的值为:" + s);
}
}).start();
String str = threadLocal.get();
System.out.println("在主线程中获取ThreadLocal对象中的值:" + str);
}
}
2.思路
三,代码
package com.itheima.utils;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
public class DruidUtil {
private static ThreadLocal<Connection> threadLocal = new ThreadLocal<>();
private static DataSource dataSource;
static {
try {
Properties properties = new Properties();
InputStream is = DruidUtil.class.getClassLoader().getResourceAsStream("druid.properties");
properties.load(is);
dataSource = DruidDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
}
}
public static DataSource getDataSource(){
return dataSource;
}
public static Connection getConnection() throws SQLException {
Connection connection = threadLocal.get();
if (connection == null) {
connection = dataSource.getConnection();
threadLocal.set(connection);
}
return connection;
}
public static void clear() throws SQLException {
threadLocal.get().setAutoCommit(true);
threadLocal.get().close();
threadLocal.remove();
}
}
package com.itheima.service;
import com.itheima.dao.AccountDao;
import com.itheima.utils.DruidUtil;
import java.sql.Connection;
import java.sql.SQLException;
public class AccountService {
private AccountDao accountDao = new AccountDao();
public void transfer(String fromName,String toName, Double money){
Connection conn = null;
try {
conn = DruidUtil.getConnection();
conn.setAutoCommit(false);
accountDao.updateAccount(fromName, -money);
int num = 10 / 0;
accountDao.updateAccount(toName, money);
conn.commit();
} catch (Exception e) {
e.printStackTrace();
try {
conn.rollback();
} catch (SQLException ex) {
ex.printStackTrace();
}
throw new RuntimeException(e.getMessage());
}finally {
try {
DruidUtil.clear();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
package com.itheima.dao;
import com.itheima.utils.DruidUtil;
import org.apache.commons.dbutils.QueryRunner;
import java.sql.SQLException;
public class AccountDao {
private QueryRunner queryRunner = new QueryRunner(DruidUtil.getDataSource());
public void updateAccount(String name, Double money) throws SQLException {
String sql = "update account set money=money+? where name=?";
queryRunner.update(DruidUtil.getConnection(),sql,money,name);
}
}
四.小结
- TheadLocal: jdk提供的一个对象. 只要是在同一个线程里面, 是可以共用的.
- 抽取了DruidUtil的getConnectionFromThreadLocal()方法, service和Dao里面的Connection都是从getConnectionFromThreadLocal()方法获取
补充案例: 显示所有用户
目标
在list.jsp页面中显示user表中的所有用户的信息
分析
实现
- 拷贝jar、配置文件、工具类
- 创建index.jsp和list.jsp
- 创建包结构、pojo类
- 创建ShowAllServlet、UserService、UserDao
index.jsp代码
<%--
Created by IntelliJ IDEA.
User: Fanyi Xiao
Date: 2020/7/15
Time: 12:08
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>首页</title>
</head>
<body>
<a href="/showAll">查看所有用户信息</a>
</body>
</html>
? ShowAllServlet代码
package com.itheima.web.servlet;
import com.itheima.pojo.User;
import com.itheima.service.UserService;
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.List;
@WebServlet("/showAll")
public class ShowAllServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
UserService userService = new UserService();
List<User> userList = userService.findAll();
request.setAttribute("list",userList);
request.getRequestDispatcher("/list.jsp").forward(request, response);
} catch (Exception e) {
e.printStackTrace();
}
}
}
UserService代码
package com.itheima.service;
import com.itheima.dao.UserDao;
import com.itheima.pojo.User;
import java.sql.SQLException;
import java.util.List;
public class UserService {
private UserDao userDao = new UserDao();
public List<User> findAll() throws SQLException {
List<User> userList = userDao.findAll();
return userList;
}
}
UserDao代码
package com.itheima.dao;
import com.itheima.pojo.User;
import com.itheima.utils.DruidUtil;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import java.sql.SQLException;
import java.util.List;
public class UserDao {
private QueryRunner queryRunner = new QueryRunner(DruidUtil.getDataSource());
public List<User> findAll() throws SQLException {
String sql = "select * from user";
List<User> userList = queryRunner.query(sql, new BeanListHandler<>(User.class));
return userList;
}
}
list.jsp代码
<%--
Created by IntelliJ IDEA.
User: Fanyi Xiao
Date: 2020/7/15
Time: 12:08
To change this template use File | Settings | File Templates.
--%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>展示页面</title>
</head>
<body>
<table border="1" cellspacing="0" width="800px" align="center">
<tr>
<th>序号</th>
<th>用户名</th>
<th>密码</th>
<th>地址</th>
<th>昵称</th>
<th>性别</th>
<th>邮箱</th>
</tr>
<%--
遍历出域对象里面的list中的每一个user
--%>
<c:forEach items="${list}" var="user" varStatus="vst">
<tr>
<td>${vst.count}</td>
<td>${user.username}</td>
<td>${user.password}</td>
<td>${user.address}</td>
<td>${user.nickname}</td>
<td>${user.gender}</td>
<td>${user.email}</td>
</tr>
</c:forEach>
</table>
</body>
</html>
注册登录案例改成三层架构
RegisterServlet代码
package com.itheima.web.servlet;
import com.itheima.bean.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("/register")
public class RegisterServlet extends HttpServlet {
private UserService userService = new UserService();
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=utf-8");
Map<String, String[]> map = request.getParameterMap();
User user = new User();
try {
BeanUtils.populate(user,map);
user.setStatus("0");
userService.register(user);
response.sendRedirect("login.html");
} catch (Exception e) {
e.printStackTrace();
response.getWriter().write("注册失败");
}
}
}
LoginServlet代码
package com.itheima.web.servlet;
import com.itheima.bean.User;
import com.itheima.service.UserService;
import com.itheima.utils.CookieUtil;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
private UserService userService = new UserService();
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
String username = request.getParameter("username");
String password = request.getParameter("password");
String checkCode = request.getParameter("checkCode");
HttpSession session = request.getSession();
String code = (String) session.getAttribute("code");
String remember = request.getParameter("remember");
if (code.equalsIgnoreCase(checkCode)) {
try {
User user = userService.login(username, password);
if (user != null) {
if (remember != null) {
Cookie cookie = CookieUtil.createAndSetCookie("username", username, 7 * 24 * 60 * 60, request.getContextPath());
response.addCookie(cookie);
}else {
Cookie cookie = CookieUtil.createAndSetCookie("username", username, 0, request.getContextPath());
response.addCookie(cookie);
}
session.setAttribute("user",user);
response.sendRedirect("success.jsp");
}else {
String errorMsg = "用户名或密码错误";
request.setAttribute("errorMsg",errorMsg);
request.getRequestDispatcher("login.jsp").forward(request, response);
}
} catch (Exception e) {
e.printStackTrace();
String errorMsg = "登录失败";
request.setAttribute("errorMsg",errorMsg);
request.getRequestDispatcher("login.jsp").forward(request, response);
}
}else {
String errorMsg = "验证码错误";
request.setAttribute("errorMsg",errorMsg);
request.getRequestDispatcher("login.jsp").forward(request, response);
}
}
}
UserService代码
package com.itheima.service;
import com.itheima.bean.User;
import com.itheima.dao.UserDao;
public class UserService {
private UserDao userDao = new UserDao();
public void register(User user) throws Exception {
userDao.saveUser(user);
}
public User login(String username,String password) throws Exception {
return userDao.findUser(username,password);
}
}
UserDao代码
package com.itheima.dao;
import com.itheima.bean.User;
import com.itheima.utils.DruidUtil;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import java.sql.SQLException;
public class UserDao {
public void saveUser(User user) throws Exception {
QueryRunner queryRunner = new QueryRunner(DruidUtil.getDataSource());
String sql = "insert into user values (null,?,?,?,?,?,?,?)";
queryRunner.update(sql,user.getUsername(),user.getPassword(),user.getAddress(),user.getNickname(),user.getGender(),user.getEmail(),user.getStatus());
}
public User findUser(String username,String password) throws Exception {
QueryRunner queryRunner = new QueryRunner(DruidUtil.getDataSource());
String sql = "select * from user where username=? and password=?";
User user = queryRunner.query(sql, new BeanHandler<>(User.class), username, password);
return user;
}
}
|