JSP:
指令
- 作用:用于配置JSP页面,导入资源文件
- 格式:
<%@ 指令名称 属性名1=属性值1 属性名2=属性值2 … %> - 分类:
- page : 配置JSP页面的
- contentType:等同于response.setContentType()
- 设置响应体的mime类型以及字符集
- 设置当前jsp页面的编码(只能是高级的IDE才能生效,如果使用低级工具,则需要设置pageEncoding属性设置当前页面的字符集)
- language:java
- import:导包
- errorPage:当前页面发生异常后,会自动跳转到指定的错误页面
- isErrorPage:标识当前也是是否是错误页面。
- true:是,可以使用内置对象exception
- false:否。默认值。不可以使用内置对象exception
- contentType:等同于response.setContentType()
- ** include : 页面包含的。导入页面的资源文件**
- <%@include file=”top.jsp”%>
- taglib : 导入资源(标签库)
- <%@ taglib prefix=”c” uri=”http://java.sun.com/jsp/jstl/core" %>
- prefix:前缀,自定义的
- <%@ taglib prefix=”c” uri=”http://java.sun.com/jsp/jstl/core" %>
- 注释:
- html注释:(不建议使用,在响应体里还会被显示) :只能注释html代码片段
- jsp注释:推荐使用 <%– –%>:可以注释所有
- page : 配置JSP页面的
内置对象
- 在jsp页面中不需要创建,直接使用的对象
- 一共有9个:
变量名 真实类型 作用
- pageContext PageContext 当前页面共享数据,还可获取其他八个内置对象
- request HttpServletRequest 一次请求访问的多个资源(转发)
- session HttpSession 一次会话的多个请求间
- application ServletContext 所有用户间共享数据
- response HttpServletResponse 响应对象
- page Object 当前页面(Servlet)的对象 this
- out JspWriter 输出对象,数据输出到页面上
- config ServletConfig Servlet的配置对象
- exception Throwable 异常对象
MVC:开发模式
jsp演变历史
- 早期只有servlet,只能使用response输出标签数据,非常麻烦
- 后来又jsp,简化了Servlet的开发,如果过度使用jsp,在jsp中即写大量的java代码,有写html表,造成难于维护,难于分工协作
- 再后来,java的web开发,借鉴mvc开发模式,使得程序的设计更加合理性
MVC:
M:Model,模型。JavaBean
- 完成具体的业务操作,如:查询数据库,封装对象
V:View,视图。JSP
- 展示数据
C:Controller,控制器。Servlet
- 获取用户的输入
- 调用模型
- 将数据交给视图进行展示
优缺点:
- 优点:
- 耦合性低,方便维护,可以利于分工协作
- 重用性高
- 缺点:
- 使得项目架构变得复杂,对开发人员要求高
- 优点:
EL表达式
概念:Expression Language ==表达式==语言
作用:替换和简化jsp页面中java代码的编写
语法:${表达式}
注意:
- jsp默认支持el表达式的。如果要忽略el表达式
- 设置jsp中page指令中:isELIgnored=”true” 忽略当前jsp页面中所有的el表达式
- ${表达式} :忽略当前这个el表达式
- jsp默认支持el表达式的。如果要忽略el表达式
使用:
运算:
- 运算符:
- 算数运算符: + - * /(div) %(mod)
- 比较运算符: > < >= <= == !=
- 逻辑运算符: &&(and) ||(or) !(not)
- 空运算符: empty
- 功能:用于判断字符串、集合、数组对象是否为null或者长度是否为0
- ${empty list}:判断字符串、集合、数组对象是否为null或者长度为0
- ${not empty str}:表示判断字符串、集合、数组对象是否不为null 并且 长度>0
- 运算符:
获取值
- el表达式只能从域对象中获取值
- 语法:
- ${域名称.键名}:从指定域中获取指定键的值
- 域名称:
- pageScope –> pageContext
- requestScope –> request
- sessionScope –> session
- applicationScope –> application(ServletContext)
- 举例:在request域中存储了name=张三
- 获取:${requestScope.name}
- 域名称:
- ${域名称.键名}:从指定域中获取指定键的值
- 语法:
- ${键名}:表示依次从最小的域中查找是否有该键对应的值,直到找到为止。
- el表达式只能从域对象中获取值
获取对象、List集合、Map集合的值
- 对象:${域名称.键名.属性名}
- 本质上会去调用对象的getter方法
- 属性名:get和set方法去掉get/set,剩余字符串首字母去掉大写,就是属性
* 如:getName --> Name --> name
- List集合:${域名称.键名[索引]}
- Map集合:
- ${域名称.键名.key名称}
* ${域名称.键名["key名称"]}
- ${域名称.键名.key名称}
- 对象:${域名称.键名.属性名}
隐式对象:
el表达式中有11个隐式对象
pageContext:
获取jsp其他八个内置对象
- ${pageContext.request.contextPath}:动态获取虚拟目录
JSTL:标签库
- 概念:JavaServer Pages Tag Library JSP标准==标签库==
- 是由Apache组织提供的开源的免费的jsp标签 <标签>
作用:用于简化和替换jsp页面上的java代码
使用步骤:
- 导入jstl相关jar包
- 引入标签库:taglib指令: <%@ taglib %>
使用标签
常用的JSTL标签
if:相当于java代码的if语句 1. 属性:
* test 必须属性,接受boolean表达式 * 如果表达式为true,则显示if标签体内容,如果为false,则不显示标签体内容 * 一般情况下,test属性值会结合el表达式一起使用
注意:
- c:if标签没有else情况,想要else情况,则可以在定义一个c:if标签
```
<c:if test="${number%2 != 0 }">
//逻辑
</c:if>
```
- choose:相当于java代码的switch语句 1. 使用choose标签声明 相当于switch声明 2. 使用when标签做判断 相当于case
- 属性:test 3. 使用otherwise标签做其他情况的声明 相当于default
```
<c:choose>
<c:when test="${number == 1}"> 星期一 </c:when>
<c:when test="${number == 2}"> 星期二 </c:when>
<c:otherwise> 输入有误 </c:otherwise>
</c:choose>
```
foreach:相当于java代码的for语句
完成重复操作
属性:
begin:开始值
end:结束值
var:临时变量
step:步长
varStatus:循环状态对象
index:容器中元素的索引,从0开始
count:循环次数,从1开始
<c:forEach begin="1" end="10" var="i" step="2" varStatus="s"(这个不常用)> ${s.index} ${s.count} </c:forEach>
遍历容器
属性:
items:容器对象
var:容器中元素的临时变量,相当于for each中的元素名称
varStatus:循环状态对象
index:容器中元素的索引,从0开始
count:循环次数,从1开始
<% List list = new ArrayList(); list.add("aaa"); request.setAttribbute("list",list); %> <c:forEach items="${list}" var="str" varStatus="s"> //索引 循环次数 遍历的元素 ${s.index} ${s.count} ${str} </c:forEach>
三层架构
- 界面层(表示层):用户看的得界面。用户可以通过界面上的组件和服务器进行交互
- 业务逻辑层:处理业务逻辑的。
- 数据访问层:操作数据存储文件。
案例1:用户信息列表展示
bug1:路径错误404
使用跳转时:不加虚拟路径,并且注意资源名称的大小写
使用超链接,按钮时:加虚拟路径,注意大小写
bug2:添加用户功能,不知道怎么在操作数据库类中获取表单数据
将添加用户方法设置有参,传入一个servlet获取表单数据后并封装好的对象即可
bug3.1:修改用户信息功能,性别获取不到值
性别的name值是sex,而数据库的是gender,修改相同即可
bug3.2:修改用户信息,获取值成功,但无法修改数据库值
sql语句书写错误,虽然没有报错,但是应修改:当需要更改多个值时 应该用","连接,而不是"and"
如: 正确:update user set gender=?,age=? where name=?;
错误:update user set gender=? and age=? where name=?;
bug3.3:登录用户信息,获取值成功,但显示账号密码错误
sql语句书写错误,看看where 后的参数名是否出错
如:错:select * from user where name=?
实际上是username=?
需求:用户信息的增删改查操作
设计:
- 技术选型:Servlet+JSP+MySQL+JDBCTempleat+Duird+BeanUtilS+tomcat
- 数据库设计:
create database day17; – 创建数据库
use day17; – 使用数据库
create table user( – 创建表
);id int primary key auto_increment, name varchar(20) not null, gender varchar(5), age int, address varchar(32), qq varchar(20), email varchar(50)
开发:(程序员主负责第二步)
环境搭建
- 创建数据库环境
- 创建项目,导入需要的jar包
编码
测试
部署运维
查询功能分析:
1.创建数据库,环境搭建(导入jar包,导入静态网页)
2.创建web.servlet、service、dao包
3.点击index.jsp进入UserListSerlet
4.UserListSerlet:调用service层中的findAll()方法,将返回值user对象存储进request域中,并转发到list.jsp页面
5.service层:需要用接口实现多态,实现类调用Dao层中的findAll()方法
6.0 创建domain包,创建user的javaBean类
6.dao层:需要用接口实现多态,实现类实现JDBC操作数据库功能实现查询,返回user对象(使用数据库连接池、JdbcTemplate技术)
7.list.jsp:将静态数据删掉,获取request域中的数据展示在页面上
案例2:综合案例分析
登录:
1.调整页面布局
2.将登录界面设置成jsp,并且展示验证码
3.0将数据库增加username,password,并且javaBean中也增加相应的成员变量和getset方法
3.登录跳转到loginServlet,获取数据,审核验证码,审核账号密码,储存信息,重定向到index.jsp,并显示名字,欢迎你
4.验证码或账号密码失败,都转发回login.jsp
添加功能:
注意:add()需要添加参数
add.jsp:提交到UserAddServlet
UserAddSerclet:设置编码格式,获取值,调用service层中的add(),转发到list.jsp页面
UserService接口:public void add(User newUser);
UserServiceImpl:public void add(User newUser){ dao.add(User newUser)}
UserDao接口:public void add(User newUser);
UserDaoImpl:public void add(User newUser){ jdbc操作数据库}
update user set gender=? and qq=? where name=?
修改:
1.list.jsp点击修改跳转到findUserServlet
2.fidUserServlet中获取id信息,调用findUser方法查询用户信息,存储到request中,跳转到update.jsp
3.update.jsp获取信息,回写信息(加上隐藏域id,用于通过id来修改对应的数据)
4.提交跳转到updateServlet,获取表单信息,调用数据库方法进行修改数据
5.uodateServlet跳转到list.jsp
删除选中:
要求:
1.复选框全选、全不选
2.点击删除选中会提交对应id值
3.删除选中加个判断,确定是否要删除
4.不选时点删除选中时,不报空指针异常,先判断复选框的状态再进行删除操作
1.用javascript,获取总复选框id,设置单击事件,事件中获取其他复选框的name,遍历将其checked状态与总复选框相同
2.1将复选框设置value值,表格外嵌套表单,删除选中按钮设置单击事件,让其拥有提交表单功能
2.2提交到delSelectServlet,获取所有id值(数组),调用service中方法转入数组,跳转到listServlet
2.3service中遍历数组,分别调用del方法,传入id
3.用javascript,confirm()实现
4.前端:用javascript,获取所有复选框的name,遍历将其checked状态是否为checked,有一个就将flag变为true进行删除操作
后端:2.3遍历数组前,判断数组是否不为空或长度大于0
分页查询:
bug1:实现当前页面被激活状态,按键消失
检查代码:<c:if test="${pb.currentPage == i}"> <li class="active">
注意:不是${pb.currentPage}==${i}||${pb.currentPage}==i
重启服务器
bug2:实现下一页禁用状态,按钮分离
检查代码:不要多复制代码
bug3:NumberFormatException: null
获取的数据为空
if(currentPage==null||"".equals(currentPage)){
currentPage="1";
}
if(rows==null||"".equals(rows)){
rows="5";
}
分页查询分析:
要求:
1.点击页数提交当前页码,查询的条数
2.实现分页查询5条数据
3.获取总记录数,总页码,当前页码,每页的数据
4.修改动态总记录数、总页码
5.实现上下页功能
6.实现当前页面为激活状态(前后端都要设置)
7.实现当前页面为1或最后一页,上下一页功能被禁用(前后端都要设置)
1.点击页码,跳转到FindUserByPageServlet,并传参currentPage当前页面和rows每页显示条数
2.0 创建PageBean类,参数:总记录数、总页码、当前页码、查询条数、每页数据
2.FindUserByPageServlet:获取参数currentPage、rows,调用Service中的findUserByPage(传入参数),返回一个PageBean集合,将PageBean存入request中,转发到list.jsp进行展示,将list.jsp:表格遍历items:${pb.list}
3.Service中findUserByPage方法实现:
创建PageBean对象,
将当前页码、查询条数保存进对象中,
调用dao中的findTotalCount()获取总记录数并保存进对象中,
计算总页码:总记录数/查询条数,向上取整,保存进对象
计算开始查询的页数:(当前页数-1)*查询条数
调用dao中的findByPage(传入开始查询的页数、查询条数)方法获取每页数据,保存进对象
返回对象
3.1dao中findTotalCount()、findByPage()方法实现
4.${pb.totalCount} ${pb.totalPage}
5.上一页:currentPage=${pb.currentPage-1}&rows=5
下一页:currentPage=${pb.currentPage+1}&rows=5
其他页数在遍历中改<c:forEach begin="1" end="${pb.totalPage}" var="i">
6.前端:<c:if test="${pb.currentPage == i}"> <li class="active">
后端:if(currentPage<=0){
currentPage=1;
}
7.<c:if test="${pb.currentPage == 1}"> <li class="disabled">
复杂条件查询:
bug0:getParameterMap获取不到值
1.form表单没有action
2.input表单没有name或name写错
bug1:拼接字符串将currentPage和row也拼了进去
在遍历key的时候,加个if判断将两个跳过
if("currentPage".equals(key)||"rows".equals(key)){
continue;
}
bug2:拼接字符串需要注意的细节:
1.使用StringBuilder
2.拼接时要加空格 不然会拼接在一起,不符合sql语法
3.?代表的值用 集合params.toArray()来写:template.queryForObject(sql,Integer.class,params.toArray());
bug3:获得参数都正确,拼接字符串也正确,查的值不对
没有添加%,如:select * from user where 1 = 1 and name like %李%
所有在获取值时应该加上%
params.add("%"+value+"%");
复杂条件查询分析:
要求:
1.输入值 模糊查询出记录数,页数
2.按照分页查询出对应的数据
3.查询之后信息回写
4.点击其他页信息传参
分析:
1.点击查询,提交表单,跳转到FindUserByPageServlet
2.FindUserByPageServlet:获取到表单的map集合,调用Service中的findUserByPage(传入map集合)
3.Service中findUserByPage方法实现:调用dao中的findTotalCount(传入map集合)
4.dao中findTotalCount()方法实现,
Map.keySet获取键集合,再用遍历键集合获取value,
判断value是否有值,如果有值证明用户输入了值,
拼接字符串 select * from user where 1 = 1 ,sb.append(" and "+key+" like "?) ,获取值 params
template.queryForObject(sql,Integer.class,params.toArray())
5.Service中findUserByPage方法实现:调用dao中的findByPage(传入map集合)
6.dao中的findByPage()方法实现,
与4相同,额外值params中加上参数startPage、rows
注意:加参数应该将 params的泛型改成Object,因为类型可以不同
7.信息回写:
将condition获取到后,可以存入request中
将表单的value值改为动态获取${condition.email[0]}
注意:存的condition是map集合,获取的时候应该加下标[0]
8.点击其他页信息传参:将分页导航的链接都加上动态参数:
&name=${condition.name[0]}&address=${condition.address[0]}……