1.认识JSP
- JSP, Java Server Page, java服务器页面. 在jsp中, 既可以编写html代码, 也可以编写java代码.
- JSP本质上也是一个Servlet.
- Servlet存在缺点, 页面表现非常麻烦. 有没有一种技术能够替程序员完成转换操作, 将html转换成类似于resp.getWriter().print()方式.
- JSP就可以完成这个功能, 提供了一个jsp引擎, 可以自动将所有的html标签打印输出到客户端.
- 后期开发中使用Servlet+JSP的形式完成, Servlet负责java代码, jsp负责html代码.
- 在jsp中, html代码可以直接编写; 而java代码的编写, 必须声明java代码块(java小脚本)
- 可以使用如下标签声明java代码块:
<% %> - 可以使用如下标签声明输出:
<%= %>
<%@ page import="java.util.Random" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
这是html代码 <br>
<%--声明java代码块--%>
<%
System.out.println("Hello JSP!");
Random random = new Random();
int score = random.nextInt(100);
System.out.println("score = " + score);
// response.getWriter().print(score);
if(score >= 90) {
%>
<h1>优秀</h1>
<%
System.out.println("优秀");
} else if(score >= 60) {
%>
<h2>及格</h2>
<%
System.out.println("及格");
} else {
%>
<h6>不及格</h6>
<%
System.out.println("不及格");
}
%>
<%--引用变量输出到浏览器--%>
您的分数是: <%=score%>
</body>
</html>
2.JSP执行流程
- 分析jsp的执行流程, 需要查看服务器的work目录, 当jsp被访问时, 会在当前目录下, 生成对应的java文件和class文件.
- 当客户端访问*.jsp的路径时, 被JspServlet拦下来, 将jsp文件转换为java代码, 然后编译为class文件, 执行, 页面就看到效果了.
- jsp的执行流程文字描述:
> 客户端访问jsp资源: http://localhost:8080/项目/index.jsp
> 被JspServlet匹配成功, 执行JspServlet
> JspServlet会查找index.jsp资源文件, 将jsp文件翻译为java文件, 命名为index_jsp.java
> index_jsp.java定义了一个类, 叫index_jsp, 继承了HttpJspBase类, HttpJspBase有继承了HttpServlet. 所以说, jsp本质上就是一个Servlet.
> 在index_jsp.java中, 并没有直接定义service方法, 而是重写了父类中的_jspService方法, 这个方法会被父类中的service方法自动调用.
> 其实_jspService方法中就是将jsp文件中所有的内容转换成了java输出, 结构是out.write();
> index_jsp.java被编译为index_jsp.class, 运行后, 页面就看到效果了.
3.JSP指令标签
- 指令标签用于对jsp页面进行设置, 一共有三个指令标签:
> page: 设置当前jsp的相关信息
> include: 包含, 可以在一个页面中引用另一个页面
> taglib: 标签库, 用于在使用JSTL时倒入标签库.
(1)page指令
<%--page指令--%>
<%--contentType: 用于告知浏览器使用什么格式和编码方式解析响应信息--%>
<%@ page contentType="text/html;charset=UTF-8" %>
<%--language: 声明当前jsp页面中使用什么脚本语言, 默认java--%>
<%@ page language="java" %>
<%--pageEncoding: 设置jsp引擎在翻译成java文件时使用什么编码方式--%>
<%@ page pageEncoding="UTF-8" %>
<%--import: 在当前jsp页面中导包--%>
<%@ page import="java.util.*" %>
<%--errorPage: 用于设定当前页面发生异常时跳转到哪个页面进行处理--%>
<%@ page errorPage="error.jsp" %>
<%--isErrorPage: boolean值, true表示当前页面是一个错误处理页面, false默认值--%>
<%@ page isErrorPage="true" %>
(2)include指令
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
int a = 500;
%>
<h1>这里是主页面</h1>
<%--静态引入, 会将两个jsp合并生成一个java文件--%>
<%--<%@ include file="copyright.jsp" %>--%>
<%--动态引入, 会生成两个java文件, 通过调用include方法实现动态引入--%>
<jsp:include page="copyright.jsp"></jsp:include>
</body>
</html>
4.EL表达式
- jsp中使用<%=%>取值的问题:
> 需要导包
> 类型需要强转
> 取不到数据时, 会显示null - 可以使用EL表达式简化上述操作.
- EL, Expression Language, 表达式语言, 用来简化在jsp页面中取值操作的.
> 请求参数: ${param.参数名} / ${paramValues.参数名}
> 作用域属性: ${属性名} - EL表达式的语法规范: ${}
- 优点:
> 不需要导包
> 不需要强转
> 取不到不会显示null - 注意:
el表达式中使用的属性对应的是实体类中get方法.
EL表达式跨域取值
在EL表达式中, 针对四个作用域提供了对应的四个关键字, 用于代表着四个作用域
> pageContext -> pageScope
> request -> requestScope
> sesssion -> sessionScope
> application -> applicationScope
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
// 向pageContext作用域存放数据
pageContext.setAttribute("msg", "this is a test");
// 作用域中的name同名时, 值会进行覆盖, 相当于修改操作
pageContext.setAttribute("msg", "PageContext");
// 删除操作
// pageContext作用域会删除所有作用域中的对应的msg
// 其他作用域只删除自己作用域中的数据
pageContext.removeAttribute("msg");
%>
<html>
<head>
<title>Title</title>
</head>
<body>
${pageScope.msg}<br>
${requestScope.msg}<br>
${sessionScope.msg}<br>
${applicationScope.msg}
</body>
</html>
5.JSTL的使用
- JSTL, Jsp Standard Tag Library, jsp标准标签库
- 在jstl中, 提供了多套标签库, 用于方便在jsp中完成或简化相关操作.
- jstl的使用前提, 需要在项目中导入jstl-1.2.jar
- jstl在后台由java代码编写, jsp页面中通过标签进行使用, 使用标签时, 会自动调用后台的java方法, 标签和方法之间的映射关系在对应的tld文件中描述.
- jstl中常用的标签库:
> 核心标签库: core, 简称c
> 格式化标签库: format, 简称fmt
> 函数标签库: function, 简称fn - jstl使用的前提:
> 导包: jstl.jar
> 需要在页面中通过taglib指令引入对应的标签库, uri可以在对应的tld文件中找到
<%@ taglib uri="标签库的定位" prefix="前缀(简称)" %>
(1)核心标签库
- 核心标签库是jstl中使用频率最高的标签库, 封装了很多有效的功能, 例如: 迭代, 判断, 操作作用域的功能等…
- 常用的标签:
> <c:set>
> <c:out>
> <c:remove>
> <c:if>
> <c:choose><c:when><c:otherwise>
> <c:forEach> - forEach中的属性
> var: 迭代变量, 存放在pageContext作用域
> begin: 迭代起始值
> end: 迭代结束值
> step: 迭代变量变化的步长
> items: 要遍历的集合, 需要使用EL表达式取值
> varStatus: 迭代变量的状态
- index: 索引, 从0开始
- count: 计数, 从1开始
- first: boolean, 表示是否是第一个
- last: boolean, 表示是否是最后一个
- current: 对象, 当前爹迭代的对象值
实例:
<%@ page import="com.bjsxt.pojo.User" %>
<%@ page import="java.util.*" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--使用taglib指令引入核心标签库--%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%
Random random = new Random();
pageContext.setAttribute("score", random.nextInt(100));
User u1 = new User("张三", 20, "攻城狮", 50000D, new Date(), new Date());
User u2 = new User("李四", 22, "设计师", 0.5D, new Date(), new Date());
User u3 = new User("王五", 28, "程序猿", 30000D, new Date(), new Date());
List<User> list = new ArrayList<User>();
Collections.addAll(list, u1, u2, u3);
pageContext.setAttribute("list", list);
%>
<html>
<head>
<title>核心标签库</title>
<style type="text/css">
table {
width: 80%;
text-align: center;
border-collapse: collapse;
}
td {
border: 1px solid grey;
}
</style>
</head>
<body>
<%-- c:set --%>
<%-- 用于向指定的作用域中存放数据, scope可以省略, 默认存放到pageContext作用域 --%>
<c:set var="demo" value="page"></c:set>
<c:set var="demo" value="session" scope="session"></c:set>
<c:set var="demo" value="application" scope="application"></c:set>
<%-- c:out --%>
<%-- 用于向浏览器输出数据, 通常配合EL表达式使用, 当数据为null时, 会显示default值 --%>
<c:out value="${demo123}" default="当没有数据时, 显示默认值"></c:out>
<br>
${pageScope.demo} - ${sessionScope.demo} - ${applicationScope.demo}
<br>
<%-- c:remove --%>
<%-- 从指定作用域移除属性 --%>
<c:remove var="demo" scope="session"></c:remove>
${pageScope.demo} - ${sessionScope.demo} - ${applicationScope.demo}
<br>
<%-- c:if --%>
<%-- 用于条件判断, 单分支判断, 通过test属性指定判断条件 --%>
当前分数: ${score}<br>
分数等级:
<c:if test="${score ge 90}" var="flag1">A - ${flag1}</c:if>
<c:if test="${score ge 70 && score lt 90}" var="flag2">B - ${flag2}</c:if>
<c:if test="${score ge 60 && score lt 70}" var="flag3">C - ${flag3}</c:if>
<c:if test="${score lt 60}">D</c:if>
<br>
<c:if test="${score ge 60}" var="flag">及格</c:if>
<c:if test="${!flag}">不及格</c:if>
<br>
<%-- c:choose, c:when, c:otherwise --%>
<%-- 功能类似于switch...case...default --%>
<c:choose>
<c:when test="${score ge 90}">A</c:when>
<c:when test="${score ge 80}">B</c:when>
<c:when test="${score ge 70}">C</c:when>
<c:when test="${score ge 60}">D</c:when>
<c:otherwise>E</c:otherwise>
</c:choose>
<hr>
<%-- c:forEach --%>
<%-- 用于循环和迭代 --%>
<c:forEach var="i" begin="1" end="9" step="1">
<c:forEach var="j" begin="1" end="${i}">
${j} * ${i} = ${i * j}
</c:forEach>
<br>
</c:forEach>
<hr>
<center>
<table>
<tr>
<td>姓名</td>
<td>年龄</td>
<td>职位</td>
<td>薪资</td>
<td>生日</td>
<td>登录时间</td>
<td colspan="5">varStatus</td>
</tr>
<c:forEach items="${list}" var="u" varStatus="vs">
<tr>
<td>${u.name}</td>
<td>${u.age}</td>
<td>${u.job}</td>
<td>
<fmt:formatNumber value="${u.sal}" pattern="¥###,###,##0.00"></fmt:formatNumber>
</td>
<td>
<fmt:formatDate value="${u.birthday}" pattern="yyyy-MM-dd"></fmt:formatDate>
</td>
<td>
<fmt:formatDate value="${u.loginTime}" pattern="yyyy-MM-dd HH:mm:ss"></fmt:formatDate>
</td>
<td>
${vs.current.name}
</td>
<td>
${vs.first}
</td>
<td>
${vs.last}
</td>
<td>
${vs.index}
</td>
<td>
${vs.count}
</td>
</tr>
</c:forEach>
</table>
</center>
</body>
</html>