1.12.JSP
1.12.1.JSP工作原理
测试步骤:
1.创建一个静态jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
<meta charset="utf-8">
</head>
<body>
<form action="/Encoding" method="post">
<input type="text" name="name"/>
<input type="submit"/>
</form>
</body>
</html>
2.在tomcat的webapps中添加一个符合web组件规范的web应用目录
3.把index.jsp拷贝到这个web应用目录的根目录中
4.启动服务器并访问这个index.jsp页面 http://localhost:8080/web/index.jsp
5.查看work目录下的我们的应用目录,当我们请求这个页面后,多出了一个index_jsp.java和index_jsp.class文件,这个就是由JSP引擎根据jsp页面内容生成的Servlet源代码和编译生成的 字节码
我们看看index_jsp.java内容
jsp页面中的静态内容被转换成输出代码嵌入到Servlet代码中
1.12.2.scriptlet脚本
<%…%>块,这个块中的代码,会被拷贝到jsp引擎生成的脚本的这个脚本所在位置
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<%
int a = 20;
%>
<head>
<title>$Title$</title>
<meta charset="utf-8">
</head>
<body>
<%
out.write(new java.util.Date().toString());
%>
<form action="/Encoding" method="post">
<input type="text" name="name"/>
<input type="submit"/>
</form>
</body>
<%
String name = request.getParameter("name");
session.getAttribute("name");
a += 10;
%>
</html>
生成的源码:
对比一下scriptlet脚本在页面流中的位置和生成的源码中的位置,实际就是把scriptlet脚本拷贝到源码输出流中对应的位置
1.12.3.JSP声明块
<%!..定义Servlet类中的方法和属性… %>
JSP声明块声明Servlet类中的方法和属性
<%!
public int sum(int a,int b){
return a + b;
}
%>
生成的源码中声明块的位置
1.12.4.输出块
<%=“HelloWorld”%> 等同于<%out.println("Hello World ");%>
生成的源代码
1.13.三大指令
JSP页面中的指令是JSP页面通知引擎如何处理自己的信息
1.page指令
<%@ page contentType="text/html;charset=UTF-8" isELIgnored="false" pageEncoding="utf-8" import="java.util.*,java.io.*" language="java" %>
<%@ page contentType="text/html;charset=UTF-8"%>
<%@ page language="java" %>
<%@ page import="java.util.*,java.io.*"%>
<%@ page import="java.jdbc.*"%>
上面是page指令的常用属性,可以连起来写,也可以写多个pgae指令配置-
- contentType属性:指定jsp的内容类型
- language属性:指定jsp引擎用什么语言处理页面
- Import属性:指定页面导入的类
- isELIgnored:指定JSP引擎是否处理页面中的EL表达式
2.include指令
主要用于静态包含其它jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%@include file="header.jsp"%>
<%@include file="main.jsp"%>
<%@include file="footer.jsp"%>
</body>
</html>
header.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
Header
</body>
</html>
footer.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
Footer
</body>
</html>
main.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
Main
</body>
</html>
生成的页面
3.taglib指令
1.14.内置标签
1.14.1.UserBean标签
创建一个Bean
package edu.xalead.entity;
public class Student {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
private String sex;
}
在页面中实例化及访问实例的属性
<%--实例化Bean--%>
<jsp:useBean id="stu" class="edu.xalead.entity.Student" scope="session"/>
<%--给属性赋值--%>
<jsp:setProperty name="stu" property="id" value="10000"/>
<jsp:setProperty name="stu" property="name" value="zhangsan"/>
<jsp:setProperty name="stu" property="sex" value="M"/>
<%--取bean的属性--%>
<jsp:getProperty name="stu" property="id"/>:
<jsp:getProperty name="stu" property="name"/>:
<jsp:getProperty name="stu" property="sex"/>
输出:
1.14.2.Include标签
准备3个页面
header.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
Header
</body>
</html>
main.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
Main
</body>
</html>
footer.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
Footer
</body>
</html>
再创建inExample.jsp页面包含上面的页面
之前我们学过<%@include …%>指令静态包含其它页面
<%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2019/8/18
Time: 11:10
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%@include file="header.jsp"%>
<%@include file="main.jsp"%>
<%@include file="footer.jsp"%>
</body>
</html>
生成的Servlet代码是
静态包含是JSP引擎处理的,一次性把代码处理到一个源文件中。
而使用include标签是动态包含
<%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2019/8/18
Time: 11:10
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<jsp:include page="header.jsp"/>
<jsp:include page="main.jsp"/>
<jsp:include page="footer.jsp"/>
</body>
</html>
生成的代码是
[外链图片转存失败(img-7qcQ8aQB-1566131897953)(I:\后端\jsp,servlet\images\images\1566111854021.png)]
可见,include标签实际上是发了一个服务端的请求派发,动态的把请求数据包含在当前页面中
所以在派发过程 中可以给另一个组件传递参数
<%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2019/8/18
Time: 11:10
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<jsp:include page="header.jsp"/>
<jsp:include page="main.jsp">
<jsp:param name="key" value="11111"/>
<jsp:param name="value" value="3424"/>
</jsp:include>
<jsp:include page="footer.jsp"/>
</body>
</html>
上面给main.jsp传了两个参数,key和value,这两个参数,main.jsp是可以用request取出来的
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
Main
<%=request.getParameter("key")%>:
<%=request.getParameter("value")%>
</body>
</html>
最终生成的包含页面:
可以看到main.jsp页面多输出了两个参数的值,这两个参数值就是包含它的页面给传递过来的。这种动态包含可以给被包含页面提供动态的属性,提高被包含页面的复用性
1.15.用户自定义标签(了解)
因为内置标签评价不错,但sun公司又不知道还有什么标签比较通用。于是制定了一套定义标签的规范,之后就出现了大量用户自定义标签。最后sun公司又出面把很多优秀的开源标签收编到它自己的JSTL标准标签库中。
自定义标签
1.15.1.创建标签处理类
标签处理类要继承TagSupport或BodyTagSupport
重写四个事件处理方法
doStartTag() 当碰到配置的起始标签时执行
doEndTag() 当碰到配置的结束标签时执行
doAfterBody() 当解析完标签体时执行
下面演示一个碰到起始标签显示表格的处理类
package edu.xalead.tag;
import javax.servlet.ServletContext;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyTagSupport;
import javax.servlet.jsp.tagext.TagSupport;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
public class MyTag extends BodyTagSupport {
//定义color属生,接收页面中标签的color属性值<aaa color='green'/>
private String color = "white";
public String getColor() {
return color;
}
public void setColor(String color){
this.color = color;
}
//碰到起始标签开始执行
@Override
public int doStartTag() throws JspException {
try {
//先要拿到ServletContext
ServletContext servletContext = pageContext.getRequest().getServletContext();
//先取出离线集,这里的离线集在讲ServletContext时在ServletContext中存储过一个table属性的表集
ArrayList<ArrayList<String>> table = (ArrayList<ArrayList<String>>)servletContext.getAttribute("table");
//渲染成表格输出
//取输出字符流
JspWriter pw = pageContext.getOut();
pw.println("<table border='1' bgcolor='" + color + "'>");
pw.println("<th>");
pw.println("empno");
pw.println("</th>");
pw.println("<th>");
pw.println("ename");
pw.println("</th>");
pw.println("<th>");
pw.println("job");
pw.println("</th>");
pw.println("<th>");
pw.println("mgr");
pw.println("</th>");
pw.println("<th>");
pw.println("hiredate");
pw.println("</th>");
pw.println("<th>");
pw.println("salary");
pw.println("</th>");
pw.println("<th>");
pw.println("comm");
pw.println("</th>");
pw.println("<th>");
pw.println("deptno");
pw.println("</th>");
for(int i=0;i<table.size();i++){
pw.println("<tr>");
ArrayList<String> row = table.get(i);
for(int j = 0 ; j < row.size() ; j++){
pw.println("<td>");
pw.println(row.get(j));
pw.println("</td>");
}
pw.println("</tr>");
}
pw.println("</table>");
} catch (IOException e) {
e.printStackTrace();
}
return BodyTagSupport.SKIP_BODY;
}
//碰到结束标签时执行这个方法
@Override
public int doEndTag() throws JspException {
return super.doEndTag();
}
//解析完标签体执行这个方法
@Override
public int doAfterBody() throws JspException {
return super.doAfterBody();
}
}
1.15.2.编写标签库描述文件(my.tld)
这个文件描述了什么名字的标签,由哪个处理类来处理,文件扩展名默认.tld,可以默认放到WEB-INF目录下
<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- 标签库描述符 -->
<taglib xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
version="2.1">
<tlib-version>1.0</tlib-version>
<short-name>my</short-name>
<uri>http://www.xalead.org</uri>
<!-- aaa标签 -->
<tag>
<!-- 标签名 -->
<name>aaa</name>
<!-- 标签助手类(实现类) 放入类的全限定名 -->
<tag-class>edu.xalead.tag.MyTag</tag-class>
<!-- 标签的内容类型:empty表示空标签(使用空标签会报错),jsp表示可以为任何合法的JSP元素 -->
<body-content>empty</body-content>
<attribute>
<!-- 属性名 -->
<name>color</name>
<!-- 是否为必填项 -->
<required>false</required>
<!--是否可以填jsp表达式 el表达式 -->
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
</taglib>
1.15.3.在应用自定义标签的页面中引用(taglib处理指令)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="my" uri="/WEB-INF/my.tld"%>
<html>
<head>
<title>Title</title>
</head>
<body>
<%-- aaaa标签在页面中显示一个context中的table属性的表格 --%>
<my:aaa color="yellow"/>
</body>
</html>
输出: