EL表达式
这篇文章写的很好:
https://www.cnblogs.com/xdp-gacl/p/3938361.html
简单标签
jsp的内置标签,标签库,自定义标签
点我
第57个视频
为什么需要简单标签?好处是什么?
- List item 自定义标签可以降低 jsp 开发的复杂度和维护量,从 html 角度来说,可以使 html 不用去过多的关注那些比较复杂的商业逻辑(业务逻辑)。
- 利用自定义标签,可以使得软件开发人员和页面设计人员合理分工: 页面设计人员可以把精力集中在使用标签(HTML,XML或者JSP)创建网站上,而软件开发人员则可以将精力集中在实现底层功能上面,如国际化等. 从而提高了工程生产力,将具有共用特性的tag库应用于不同的项目中,体现了软件复用的思想.
什么是自定义标签?
用户定义的一种自定义的jsp标记 。当一个含有自定义标签的jsp页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为 标签处理类 的对象的操作。于是,当jsp页面被jsp引擎转化为servlet后,实际上tag标签被转化为了对tag处理类的操作。
标签的API
标签库 API 定义在 javax.servlet.jsp.tagext 包中
所有的标签都放到WebContent/tag目录下, 下面是个实例simpletag.jsp
<%
List<Customer> customers = new ArrayList<Customer>();
customers.add(new Customer(1,"aa") )
%>
要想使用标签,则
- 需要导入JSTL标签库
放入WebContent/lib中 - 在jsp页面中
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
简单的使用
自定义标签的开发步骤
- 新建一个类,并继承SimpleTag接口
package simpleTag;
import java.io.IOException;
import javax.servlet.jsp.JspContext;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.JspTag;
import javax.servlet.jsp.tagext.SimpleTag;
public class SimpleTagTest implements SimpleTag{
//标签体逻辑实际应该编写到该方法中.
@Override
public void doTag() throws JspException, IOException {
// TODO Auto-generated method stub
System.out.println("doTag");
}
@Override
public JspTag getParent() {
// TODO Auto-generated method stub
System.out.println("JspTag");
return null;
}
@Override
public void setJspBody(JspFragment jspBody) {
// TODO Auto-generated method stub
System.out.println("setjspBody");
}
/JSP 引擎调用, 把代表 JSP 页面的 PageContext 对象传入
//PageContext 可以获取 JSP 页面的其他 8 个隐含对象.
//所以凡是 JSP 页面可以做的标签处理器都可以完成.
@Override
public void setJspContext(JspContext pc) {
// TODO Auto-generated method stub
System.out.println("setJspContext");
}
@Override
public void setParent(JspTag parent) {
// TODO Auto-generated method stub
System.out.println("setParent");
}
}
- WEB-INF/ .tld (标签库描述文件) 的XML的文件, 并拷入固定的部分,. 在 WEB-INF 文件夹下新建一个 .tld(标签库描述文件) 为扩展名的 xml 文件. 并拷入固定的部分: 并对
description, display-name, tlib-version, short-name, uri 做出修改
<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
version="2.0">
<description>JSTL 1.1 core library</description>
<display-name>JSTL core</display-name>
<tlib-version>1.1</tlib-version>
<short-name>c</short-name>
<uri>http://java.sun.com/jsp/jstl/core</uri>
</taglib>
- 描述自定义的标签 mytag.tld文件
<?xml version="1.0" encoding="UTF-8"?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
version="2.0">
<description>JSTL 1.1 core library</description>
<display-name>MyTags core</display-name>
<tlib-version>1.0</tlib-version>
<!-- 建议在 JSP 页面上使用的标签的前缀 -->
<short-name>c</short-name>
<!-- 作为 tld 文件的 id, 用来唯一标识当前的 TLD 文件, 多个 tld 文件的 URI 不能重复. 通过 JSP 页面的 taglib 标签的 uri 属性来引用. -->
<uri>http://www.atguigu.com/mytag/core</uri>
<!-- 描述自定义的 HelloSimpleTag 标签 -->
<tag>
<!-- 标签的名字: 在 JSP 页面上使用标签时的名字 -->
<name>hello</name>
<!-- 标签所在的全类名 -->
<tag-class>simpleTag.SimpleTagTest</tag-class>
<!-- 标签体的类型 -->
<body-content>empty</body-content>
</tag>
</taglib>
- 在jsp页面,使用tablib导入标签库描述文件,使用自定义标签
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://www.atguigu.com/mytag/core" prefix="c"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<c:hello/>
</body>
</html>
- 控制台打印
小结 :
从图中可以看出, 使用标签的时候会调用setJspContext和doTag方法.这两个方法蕴含这巨大的能量.
setJspContext方法中传入了一个类型为JspContext的参数, setJspContext: 一定会被 JSP 引擎所调用, 先于 doTag, 把代表 JSP 引擎的 pageContext 传给标签处理器类. pageContext类有许多属性和方法,就这就操作页面元素的关键.
使用方法:
private PageContext pageContext;
@Override
public void setJspContext(JspContext arg0) {
System.out.println(arg0 instanceof PageContext);
this.pageContext = (PageContext) arg0;
}
- . 带属性的自定义标签:
①. 先在标签处理器类中定义 setter 方法. 建议把所有的属性类型都设置为 String 类型.
private String value;
private String count;
public void setValue(String value) {
this.value = value;
}
public void setCount(String count) {
this.count = count;
}
②. 在 tld 描述文件中来描述属性:
<!-- 描述当前标签的属性 -->
<attribute>
<!-- 属性名, 需和标签处理器类的 setter 方法定义的属性相同 -->
<name>value</name>
<!-- 该属性是否被必须 -->
<required>true</required>
<!-- rtexprvalue: runtime expression value
当前属性是否可以接受运行时表达式的动态值 -->
<rtexprvalue>true</rtexprvalue>
</attribute>
③. 在页面中使用属性, 属性名同 tld 文件中定义的名字.
<atguigu:hello value="${param.name }" count="10"/>
在开发过程中,若写一些简单的标签直接使用SimpleTag接口的实现类SimpleTagSupport类就可以啦.可以直接调用对应的getter方法开来获取对应API.
下面是这个类的代码
public class SimpleTagSupport implements SimpleTag{
public void doTag()
throws JspException, IOException{}
private JspTag parentTag;
public void setParent( JspTag parent ) {
this.parentTag = parent;
}
public JspTag getParent() {
return this.parentTag;
}
private JspContext jspContext;
public void setJspContext( JspContext pc ) {
this.jspContext = pc;
}
protected JspContext getJspContext() {
return this.jspContext;
}
private JspFragment jspBody;
public void setJspBody( JspFragment jspBody ) {
this.jspBody = jspBody;
}
protected JspFragment getJspBody() {
return this.jspBody;
}
}
读取文件的实例
- java代码
package com.atguigu.javaweb.tag;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.regex.Pattern;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.SimpleTagSupport;
public class ReadFileTag extends SimpleTagSupport{
//相对于当前 WEB 应用的根路径的文件名
private String src;
public void setSrc(String src) {
this.src = src;
}
@Override
public void doTag() throws JspException, IOException {
PageContext pageContext = (PageContext) getJspContext();
InputStream in = pageContext.getServletContext().getResourceAsStream(src);
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String str = null;
while((str = reader.readLine()) != null){
//将文件中<和> 进行转换,否则输出时不会识别这些符号
str = Pattern.compile("<").matcher(str).replaceAll("<");
str = Pattern.compile(">").matcher(str).replaceAll(">");
pageContext.getOut().println(str);
pageContext.getOut().println("<br>");
}
}
}
- 描述文件
<?xml version="1.0" encoding="UTF-8" ?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
version="2.0">
<!-- 描述 TLD 文件 -->
<description>MyTag 1.0 core library</description>
<display-name>MyTag core</display-name>
<tlib-version>1.0</tlib-version>
<!-- 建议在 JSP 页面上使用的标签的前缀 -->
<short-name>atguigu</short-name>
<!-- 作为 tld 文件的 id, 用来唯一标识当前的 TLD 文件, 多个 tld 文件的 URI 不能重复. 通过 JSP 页面的 taglib
标签的 uri 属性来引用. -->
<uri>http://www.atguigu.com/mytag/core</uri>
<tag>
<name>readerFile</name>
<tag-class>com.atguigu.javaweb.tag.ReadFileTag</tag-class>
<body-content>empty</body-content>
<attribute>
<name>src</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
</taglib>
- jsp文件
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!-- 导入标签库(描述文件) -->
<%@taglib uri="http://www.atguigu.com/mytag/core" prefix="atguigu" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<atguigu:readerFile src="/WEB-INF/note.txt"/>
</body>
</html>