JSP基础

JSP(Java Server Pages,java服务器页面),其根本是一个简化的Servlet设计,一种动态网页技术标准。它实现了Html语法中的java扩展(以 <%, %>形式)。

JSP与Servlet一样,是在服务器端执行的。通常返回给客户端的就是一个HTML文本,因此客户端只要有浏览器就能浏览。Java Servlet是JSP的技术基础,而且大型的Web应用程序的开发需要Java Servlet和JSP配合才能完成。
JSP是以JAVA语言作为脚本语言的。


一个JSP页面可以被分为以下几部份:

  • 静态数据
  • JSP指令
  • JSP脚本元素和变量
  • JSP动作
  • 用户自定义标签


一、JSP的执行过程和生命周期

(一)JSP的执行过程
  • 1、浏览器发送一个请求给服务器,寻找某JSP页面。
  • 2、tomcat服务器载入JSP文件,然后将jsp转化为servlet(存放在%tomcat%/work)。这种转化只是简单地将所有模板文本(html)改用println()语句输出,并且将所有的JSP元素转化成Java代码。(转化jsp文件名字的格式:在文件名前面加上一个”“符号,并且将.符号替换成符号,例如,hellow.jsp 变为 _hellow_jsp.java)
  • 3、tomcat将该servlet翻译和编译成可执行类(class文件),tomcat服务器将会构造该servlet类。
  • 4、然后服务器调用该类的方法,并将输出在HTTP响应中上交给Web服务器。Web服务器以静态HTML网页的形式将HTTP响应返回到的浏览器中。

    JSP基础_第1张图片
    这里写图片描述

一般,tomcat服务器会检查JSP文件对应的servlet是否已经存在,并且检查JSP文件的修改日期是否早于servlet。如果JSP文件的修改日期早于对应的servlet,那么容器就可以确定JSP文件没有被修改过并且servlet有效。否则,重新翻译和编译。当第一次访问该jsp页面是,需要经过翻译、编译、构造和调用过程。当第二次访问则只会直接的调用方法显示内容即可。


(二)JSP生命周期

JSP生命周期就是从创建到销毁的整个过程,类似于servlet生命周期,区别在于JSP生命周期还包括将JSP文件转化为servlet。

  • 编译阶段:解析JSP文件,将JSP文件转为servlet,编译servlet。
  • 初始化阶段:加载与JSP对应的servlet类,创建其实例,调用初始化方法
  • 执行阶段:调用与JSP对应的servlet实例的服务方法
  • 销毁阶段:调用与JSP对应的servlet实例的销毁方法,然后销毁servlet实例

这里写图片描述





二、JSP转化Servlet

在JSP执行的过程中,需要将JSP转化成servlet的。那么是如何转化的呢?
我们可以先编写一个简单的jsp文件,来看看它转化成servlet成什么样子的。

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>demotitle>
head>
<body>
    <%-- 这里表示循环输出3个标题--%>
    <%
        for(int i=0;i<3;i++){
    %>
        <h3>标题<%=i %>h3>
    <%
        }
    %>
body>
html>

假如,jsp是直接在tomcat服务器运行的,可以在tomcat目录的\work\Catalina\localhost\appsupport\org\apache\找到对应的的servlet文件。假如在eclipse上的tomcat服务其运行的,可以在workspace目录的.metadata.plugins\org.eclipse.wst.server.core\tmp1\work\Catalina\localhost\(项目名称)\org\apache\找到对应的servlet文件。

我们可以查看,该jsp文件转化成的servlet的部分代码。
我们可以看到,有类似Servlet的_jspInit()、_jspService()和_jspDestroy()方法。(在jsp的生命周期中调用)
以及,调用out对象write方法,直接输出静态内容。
以及,直接将JSP的java代码直接放在了_jspService()方法当中。

public final class demo_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent,
                 org.apache.jasper.runtime.JspSourceImports {
  //与生命周期相关的方法
  public void _jspInit() {
  }

  public void _jspDestroy() {
  }

  public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
        throws java.io.IOException, javax.servlet.ServletException {

//....
    //JSP的内置对象
    final javax.servlet.jsp.PageContext pageContext;
    javax.servlet.http.HttpSession session = null;
    final javax.servlet.ServletContext application;
    final javax.servlet.ServletConfig config;
    javax.servlet.jsp.JspWriter out = null;
    final java.lang.Object page = this;
    javax.servlet.jsp.JspWriter _jspx_out = null;
    javax.servlet.jsp.PageContext _jspx_page_context = null;

    try {
      //...

      //调用out对象write方法,直接输出静态内容。
      out.write("\r\n");
      out.write("\r\n");
      out.write("\r\n");
      out.write("\r\n");
      out.write("\r\n");
      out.write("demo\r\n");
      out.write("\r\n");
      out.write("\r\n");
      out.write("\t");
      out.write('\r');
      out.write('\n');
      out.write('   ');

      //直接将JSP的java代码直接放在了_jspService()方法当中。
      for(int i=0;i<3;i++){

      out.write("\r\n");
      out.write("\t\t

标题"); out.print(i ); out.write("

\r\n"
); out.write("\t"); } out.write("\r\n"); out.write("\r\n"); out.write(""); } catch (java.lang.Throwable t) { //... } finally { //... } } //... }





三、JSP语法

(一)JSP的模板,即是静态数据(HTML)

静态数据在输入文件中的内容和输出给HTTP响应的内容完全一致。JSP页面中的html代码就是JSP的模板。

(二)JSP脚本

JSP脚本可以包含任意量的Java语句、变量(局部变量)、方法或表达式。在JSP转化成servlet过程中,把脚本中java代码原封不动地拷贝到该servlet的_jspService方法方法中执行。
语法:<% 这里编写java代码 %>
例如:


<%  
    //在页面输出当前时间
    SimpleDateFormat sdf = new SimpleDateFormat();
    String curDate = sdf.format(new Date());
    out.write(curDate);
%>


(三)JSP表达式

JSP表达式中包含的脚本语言(java)表达式,先被转化成String,通过out.print()方法输出到表达式出现的地方。
语法:<%=这里编写变量或表达式%>
例如:


<%
    //声明一个变量
    String name = "lee";
%>

<%=name %>


(五)JSP声明

一个声明语句可以声明一个或多个变量(全局变量)、方法,不能重复定义同名的变量和方法。
语法:<%! 这里编写变量或方法%>
例如:


<%
    //声明一个变量(全局变量)
    String name = "lee";
    //声明一个方法
    public void method(){
        //方法体
    }
%>


(六)JSP注释

注释一段代码。在jsp页面的中,可以写html注释和jsp注释。但是html注释会作为一个html内容来输出,但是jsp注释则不会。
语法:<%-- 这里编写注释--%>
例如:


<%--
        "">
--%>


(七)例子
<%@ page language="java" contentType="text/html; charset=utf-8"
   import="java.io.IOException" pageEncoding="utf-8" buffer="1kb" %>

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>titletitle>
head>
<body>
    <%-- 在JSP声明中,声明一个全局变量,和一个方法 --%>
    <%!

        String str1 = "lee";
        //输出指定内容
        public void printContent(String content, PageContext pageContext) 
                                    throws IOException{
            //获取out对象
            JspWriter out = pageContext.getOut();
            //调用out对象输出内容
            out.write(content);
        }
    %>

    <%-- 在JSP脚本中, 声明一个局部变量,和调用自定义方法 --%>
    <%
        String str2 = "wang";
        printContent(str2,pageContext);

    %>

    <%-- 在JSP表达式中,输出全局变量 --%>
    <%= str1%>

body>
html>





四、JSP指令

JSP指令用来设置整个JSP页面相关的属性,它并不直接产生任何可见的输出,而只是告诉引擎如何处理其余JSP页面。
语法: <%@ 指令名称 属性=“值”%>

指令 描述
<%@ page %> 设定整个JSP网页的属性
<%@ include … %> 在当前页面包含其他页面,属于静态包含
<%@ taglib … %> 引入标签库


(一)include指令

JSP页面可以通过include指令来包含其他文件。例如JSP文件、HTML文件或文本文件。被包含文件是被直接添加该JSP页面中,随着JSP页面编译执行,叫做静态包含。被包含文件一般不需要全局的html内容,例如、、 等标签。
include指令的语法为:
<%@ include file="被包含页面的url" %>


(二)page指令

Page指令为容器提供JSP页面的属性说明。一个JSP页面可以有多个page指令。
语法:

<%@ page attribute="value" %>

page指令的重要属性:

属性名称 描述
language 设置JSP页面的脚本语言,默认为JAVA
import 导入指定的java类或包,多个类或者包之间用逗号分隔
contentType 设置JSP页面的MIME类型和字符编码
pageEncoding 设置字符编码
errorPage 指定当前JSP页面发生异常时需要转向的错误处理页面
isErrorPage 指定当前页面作为错误处理页面,当值为true时该JSP页面可以调用exception对象
buffer 指定该JSP页面的out对象使用缓冲区的大小
session 表示是否开启session功能,值为true该JSP页面就可以调用session对象
isELIgnored 指定该JSP页面是否使用EL表达式
autoFlush 设置out对象的缓存区
extends 指定servlet从哪一个类继承
info 设置该JSP页面的描述信息
isThreadSafe 指定对JSP页面的访问是否为线程安全
isScriptingEnabled 设置脚本元素能否被使用

errorPage可以指定当前JSP页面发生异常时需要转向的错误处理页面。例如

<%@ page errorPage="uri" %>

也可以在web.xml文件配置错误处理页面。web.xml配置和errorPage都有的话,以errorPage优先。

<error-page>
    
    <error-code>500error-code>
    <location>urilocation>
error-page>
<error-page>
    
    <error-code>404error-code>
    <location>urilocation>
error-page>


(三)taglib指令

引入一个自定义标签集合,包括库路径、自定义标签。
语法:<%@ taglib uri="uri" prefix="前缀" %>
uri属性为标签库的uri,prefix属性指定标签库的前缀。





五、JSP内置对象

JSP内置对象是JSP容器为每个页面提供的Java对象,开发者可以直接使用它们而不用显式声明。

在jsp页面加载完毕之后,服务器就会自动帮开发者创建好这些对象,开发者就可以直接调用这些对象。这些服务器创建好的对象叫做内置对象。

对象 描述
request HttpServletRequest类的实例,一个请求代表着一个requests对象。可以通过request对象来获取该请求的信息。
response HttpServletResponse类的实例,服务器创建用于相应客户端的请求的response对象。可以通过这个对象来发送信息给客户端。
out JspWriter类的实例,该对象根据页面的缓存属性来进行不同的实例化的操作
session HttpSession类的实例,该对象用来跟踪在各个客户端请求间的会话。
application ServletContext类的实例,该对象的生命周期开始于服务器的启动,直到服务器的关闭。通过该对象,可以实现JSP文件之间的数据共享。
config ServletConfig类的实例,可以通过该对象来获取Servlet或者JSP引擎的初试化参数。
pageContext PageContext类的实例,该对象储存了另外八个内置对象的引用,因此可以通过该对象来获取其他的对象的实例。该对象也包含了传递给JSP页面的指令信息和数据。
page 代表着该JSP文件转化为servlet类的实例,即是JSP页面的实例,可以当做this来用
exception Exception类的对象,该对象封装了出错的页面抛出的异常信息。


我们主要来了解一下out和pageContext对象:

(一)out对象

out对象是JspWriter的实例,是向客户端输出内容常用的对象。
1、我们可以看看的JSP转化的Servlet
JSP页面,使用了out对象输出:

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>titletitle>
head>
<body>
    <% 
        out.write("hellow world!");
    %>
body>
html>

部分Servlet代码:



public final class hellow_jsp extends HttpJspBase implements JspSourceDependent,JspSourceImports {
//...
  public void _jspService(final HttpServletRequest request, final HttpServletResponse response)
        throws IOException, ServletException {
    //...
    try {
      response.setContentType("text/html; charset=utf-8");
      //...
      //1、获取pageContext对象实例
      pageContext = _jspxFactory.getPageContext(this, request, response,
                null, true, 8192, true);
      //2、从pageContext对象的方法中获取out对象
      out = pageContext.getOut();

      //3、使用out对象输出静态内容
      out.write("\r\n");
      out.write("\r\n");
      out.write("\r\n");
      out.write("\r\n");
      out.write("\r\n");
      out.write("Insert title here\r\n");
      out.write("\r\n");
      out.write("\r\n");
      out.write("\t");
        //4、使用out对象输出指定内容
        out.write("hellow world!");

      out.write("\r\n");
      out.write("\r\n");
      out.write("");
    } catch (java.lang.Throwable t) {
      //...
    } finally {
      //...
  }
}


2、与buffer缓冲区的关系
当以下情况下,out才会输出
1)缓冲区满了
可以调用out对象的getRemaining()来查看缓冲区的剩余空间大小,调用getBufferSize()来查看缓冲区的大小。

2)刷新缓冲区
可以调用out对象的flush()来刷新缓冲区。

3)关闭缓冲区
可以通过page指令来设置buffer缓冲区的大小为0kb,关闭缓冲区。

<%@ page buffer="0kb" %>

4)执行完jsp页面

我们可以编写一个JSP页面来看看

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8" buffer="8kb" %>

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>titletitle>
head>
<body>
    <% 
        //调用out对象输出
        out.write("this is the out Object.");
        //调用response对象来输出
        response.getWriter().write("this is the response Object.");
    %>
body>
html>

我们可以看到的结果是用response对象输出的内容,在out对象输出的内容的前面。但是我们却是先调用out对象的,事情上,是因为out对象输出的内容会先输出在缓冲区(满足条件才会从缓冲区中输出),而response对象是直接输出在浏览器中。因此,才会出现先输出response对象输出的内容,等到整个JSP页面执行完后,才会从缓冲区中输出out对象输出的内容。
这里写图片描述
其它条件,这里就不多做解释。

(二)pageContext对象

pageContext对象是PageContext类的实例,该对象储存了另外八个内置对象的引用,因此可以通过该对象来获取其他的对象的实例。该对象也包含了传递给JSP页面的指令信息和数据。

1、获取其他的内置对象
pageContext对象存储了另外八个内置对象的引用。因此自定义的方法可以通过传递PageContext对象,来获取其他的内置对象。调用方法如下:

abstract Exception  getException()
//The current value of the exception object (an Exception).
abstract Object getPage()
//The current value of the page object (In a Servlet environment, this is an instance of javax.servlet.Servlet).
abstract ServletRequest getRequest()
//The current value of the request object (a ServletRequest).
abstract ServletResponse    getResponse()
//The current value of the response object (a ServletResponse).
abstract ServletConfig  getServletConfig()
//The ServletConfig instance.
abstract ServletContext getServletContext()
//The ServletContext instance.
abstract HttpSession    getSession()
//The current value of the session object (an HttpSession).
abstract JspWriter  getOut()
//The current value of the out object (a JspWriter).


2、往不同域对象存取数据
pageContext对象可以作为域对象使用,而且可以往不同的域对象中存取数据。因此该对象定义了不同域的范围(对应着四大域对象):
1、APPLICATION_SCOPE(application范围)
2、PAGE_SCOPE(page范围)
3、REQUEST_SCOPE(scope范围)
3、SESSION_SCOPE(session范围)
当没有指定某域,则默认page域。

//获取数据
public abstract Object getAttribute(String name)
//指定范围的
public abstract Object getAttribute(String name,
                                    int scope)

//存储数据
public abstract void setAttribute(String name,
                                  Object value)
//指定范围的
public abstract void setAttribute(String name,
                                  Object value,
                                  int scope)

//移出数据
public abstract void removeAttribute(String name)
//指定范围的
public abstract void removeAttribute(String name,
                                     int scope)

//pageContext对象还有个特殊方法,可以从不同的域中查找数据,顺序为page域-request域-session域-application域
public abstract Object findAttribute(String name)


(三)四大域对象(引用,权侵删)
(一)ServletContext

1、生命周期:当Web应用被加载进容器时创建代表整个web应用的ServletContext对象,当服务器关闭或Web应用被移除时,ServletContext对象跟着销毁。
2、作用范围:整个Web应用。
3、作用:

  • a)在不同Servlet 之间转发
    • this.getServletContext().getRequestDispatcher(“/servlet/Demo10Servlet”).forward(request, response);
      方法执行结束,service就会返回到服务器,再有服务器去调用目标servlet,其中request会重新创建,并将之前的request的数据拷贝进去。
  • b)读取资源文件。
    • 由于相对路径默认相对的是java虚拟机启动的目录,所以我们直接写相对路径将会是相对于tomcat/bin目录,所以是拿不到资源的。为了解决这个问题ServletContext提供了:
      this.getServletContext().getRealPath(“/1.properties”),给进一个资源的虚拟路径,将会返回该资源在当前环境下的真实路径。
      this.getServletContext().getResourceAsStream(“/1.properties”),给一个资源的虚拟路径返回到该资源真实路径的流。
      • 当在非servlet下获取资源文件时,就没有ServletContext对象用了,此时只能用类加载器classLoader.getResourceAsStream(“../../1.properties”),此方法利用类加载器直接将资源加载到内存中,有更新延迟的问题。
        classLoader.getResource(“../1.properties”).getPath(),直接返回资源的真实路径,没有更新延迟的问题。


(二)Request 域
  • 1、生命周期:在service 方法调用前由服务器创建,传入service方法。整个请求结束,request生命结束。
  • 2、作用范围:整个请求链(请求转发也存在)。
  • 3、作用:在整个请求链中共享数据。

(三)Session 域

HttpSession 在服务器中,为浏览器创建独一无二的内存空间,在其中保存会话相关的信息。

  • 1、生命周期:在第一次调用 request.getSession() 方法时,服务器会检查是否已经有对应的session,如果没有就在内存中创建一个session并返回。当一段时间内session没有被使用(默认为30分钟),则服务器会销毁该session。如果服务器非正常关闭(强行关闭),没有到期的session也会跟着销毁。如果调用session提供的invalidate(),可以立即销毁session。
  • 2、作用范围:一次会话。


(四)PageContext 域
  • 1、生命周期:当对JSP的请求时开始,当响应结束时销毁。
  • 2、作用范围:整个JSP页面,是四大作用域中最小的一个。
  • 3、作用:
    • (1)获取其它八大隐式对象,可以认为是一个入口对象。
    • (2)获取其所有域中的数据
    • (3)跳转到其他资源,其身上提供了forward和include方法,简化重定向和转发的操作





六、EL表达式

E L(Expression Language)表达式是为了使JSP写起来更加简单,提供了在 JSP 中简化表达式的方法。EL强制要求使用域对象保存的变量或者结果。因此,在开发过程中会尽量不在JSP页面编写JAVA代码。语法:${变量或者表达式}

(一)强制从域对象获取变量或结果
//部分JSP页面的代码

<%
    //定义一个变量,将该变量存储在page域当中
    String name = "lee";
    pageContext.setAttribute("name",name);
%>
//实际上,下面代码等同于pageContext.findAttribute("name");
//意味着,EL表达式会在各个域对象当中寻找这个变量或结果
${name}


//因为,EL表达式是从域对象中获取数据的,因此可以指定范围的获取
//范围有:pageScope页面范围、requestScope请求范围、sessionScope会话范围、applicationScope应用程序范围
//例如:
${pageScope.name}


(二)输出基本数据类型
//部分JSP页面的代码
<%
    //这里有个Student的javabean类,封装着一些数据
    ArrayList list = new ArrayList<>();
    Student xiaoming  =  new Student();
    xiaoming.setName("xiaoming");
    list.add(xiaoming);

    //存储到域对象当中
    pageContext.setAttribute("list",list);  
%>

//输出list集合中的第一个对象的属性
${list[0].name}

//EL表达式不能进行遍历,需要借助JSP的JSTL标签


(三)EL表达式的操作符运算
//部分JSP页面的代码
<%--
1)算数表达式
2)比较运算
3)逻辑运算
4)判空 null或空字符串
--%>
//1、
${10+8}
//2、
${1>2}
//3、
${true||true}


<%
String one = null;
String two = "";
pageContext.setAttribute("one",one);
pageContext.setAttribute("two",two);
%>
//4、
${empty one}
${empty two}



七、JSP标签

(一)动作标签

JSP动作是一系列可以调用内建于网络服务器中的功能的XML标签。利用JSP动作可以动态地插入文件、重用JavaBean组件、把用户重定向到另外的页面、为Java插件生成HTML代码。
语法:
动作元素基本上都是预定义的函数,JSP规范定义了一系列的标准动作,它用JSP作为前缀,主要用到标准动作元素如下:

动作元素 描述
jsp:include 动态包含一个文件
jsp:forward 将请求转发到另外一个页面
jsp:param 可以在include、forward或params块之间使用,传入一个指定的参数
jsp:useBean 寻找或者实例化一个JavaBean到当前JSP页面
jsp:setProperty 在指定的JavaBean中设置一个属性值
jsp:getProperty 从指定的JavaBean中获取一个属性值
jsp:element 定义动态XML元素
jsp:attribute 定义动态XML元素的属性
jsp:body 定义动态XML元素的内容
jsp:plugin 标签表示执行一个applet或Bean


一些动作标签的介绍:
1、jsp:include
include动作标签用来动态包含静态和动态的文件。与通过taglib指令的静态包含不一样的是,动态包含,包含与被包含的jsp页面各自翻译成java源文件,再运行时合并在一起(动态包含)。动态包含可以传参,静态包含不能传参数。
语法:
属性:

属性 描述
page 被包含页面的url
flush 布尔属性,定义在包含资源前是否刷新缓存区。

例如:


<jsp:include page="/otherJsp.jsp" flush="true" />


<jsp:include page="/otherJsp.jsp" flush="true" >
    <jsp:param name="name1" value="value1">jsp:param>
jsp:include>


2、jsp:forward
将请求转发到另外一个页面。
语法:
例如:


<jsp:forward page="/otherJsp.jsp"/>


<jsp:forward page="otherJsp.jsp">
    <jsp:param name="name1" value="value1"/>
jsp:forward>


3、jsp:param
定义一个指定的参数
语法:


4、jsp:useBean
寻找或者实例化一个JavaBean到当前JSP页面。
语法:

属性 描述
class 指定Bean的完整包名。
type 指定将引用该对象变量的类型。
beanName 通过 java.beans.Beans 的 instantiate() 方法指定Bean的名字。


5、jsp:setProperty
用来设置已经实例化的Bean对象的属性。
语法:

属性 描述
name name属性是必需的。它表示要设置属性的是哪个Bean。
property property属性是必需的。它表示要设置哪个属性。
value value属性是可选的。该属性用来指定Bean属性的值。


6、jsp:getProperty
jsp:getProperty动作提取指定Bean属性的值。
语法:

属性 描述
name 要检索的Bean属性名称。Bean必须已定义。
property 表示要提取Bean属性的值


例如

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title heretitle>
head>
<body>
    
    <jsp:useBean id="demo1" class="tag.JavaBeanDemo">
        <jsp:setProperty name="demo1" property="name" vlaue="lee"/>
    jsp:useBean>
    
    <jsp:setProperty name="demo1" property="id" value="1"/>

    
    <jsp:getProperty name="demo1" property="name"/>
body>
html>


//javaBean代码

package tag;

/**
 * Description:
 * 一个javabean实例
 * 1、提供无参数的构造方法
 * 2、类中属性都必须私有化
 * 3、该类提供公开的getter和setter方法
 * 4、boolean类型的getter方法的名称为isXXX()
 * 
 * @author lee
 * */
public class JavaBeanDemo {
    private int id;
    private String name;
    private String introduce;

    /**
     * Description:
     * 默认的构造方法
     * 
     * */
    public void JavaBeanDemo(){}

    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 getIntroduce() {
        return introduce;
    }

    public void setIntroduce(String introduce) {
        this.introduce = introduce;
    }


}


7、jsp:element、jsp:attribute、jsp:body动作标签
动态定义XML元素。


    <jsp:element name="first">
        
        <jsp:attribute name="id">1jsp:attribute>
        
        <jsp:body>leejsp:body>

    jsp:element>


(二)JSTL标签

JSTL(java standard tag libarary java,标准标签库)是一个JSP标签集合,它封装了JSP应用的通用核心功能。JSTL分为以下几种:

  • 核心标签库(c标签库)
  • 国际化标签库(fmt标签库)
  • EL函数库(fn标签库)
  • xml标签库(x标签库)
  • sql标签库(sql标签库)


1、使用JSTL标签步骤

(1)导入jstl支持的jar包
可以在这个网站中找到JSTL的jar包,然后在整个web项目中buildpath导入jar包。
JSP基础_第2张图片
(2)使用taglib指令导入指定的JSTL库
在JSP页面的前面输入taglib指令,例如:

//uri和prefix属性分别为JSTL标签库的tld配置文件中的<uri><short-name>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

//例如,c标签库的tld文件(部分代码)


<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">
  
  <description>JSTL 1.1 core librarydescription>
  <display-name>JSTL coredisplay-name>
  <tlib-version>1.1tlib-version>
  
  <short-name>cshort-name>
  
  <uri>http://java.sun.com/jsp/jstl/coreuri>

  
  <tag>
    <description>description>
    <name>catchname>
    <tag-class> org.apache.taglibs.standard.tag.common.core.CatchTag
    tag-class>
    <body-content>JSPbody-content>
    <attribute>
        <description>description>
        <name>varname>
        <required>falserequired>
        <rtexprvalue>falsertexprvalue>
    attribute>
  tag>
taglib>

这些标签库的tld文件都在jstl的jar包里的META-INF文件夹中,当需要导入某个标签库时,知道寻找对应的tld文件获取其uri和short-name,就可以用tagib指令导入JSP页面使用了。
JSP基础_第3张图片
(3)使用标签


2、一些常用的核心标签库

(1)
该标签用于输出一段文本到浏览器中。
有以下属性:

属性 是否支持EL 属性类型 属性描述
value true Object 指定要输出的内容
escapeXml true Boolean 指定是否将>、<、&、’、” 等特殊字符进行HTML编码转换后再进行输出。默认值为true
default true Object 指定如果value属性的值为null时所输出的默认值


(2)
该标签用于把某一个对象存在指定的域范围内,或者设置Web域中的java.util.Map类型的属性对象或JavaBean类型的属性对象的属性。
有以下属性:

属性名称 是否支持EL 属性值类型 属性描述
value true Obeject 用指定属性值
var false String 用于指定要设置的web域属性的名称
scope false String 用于指定属性所在的web域
target false Object 用于指定要设置属性的对象,这个对象必须是javaBEAN对象或者是Map对象
property false String 用于指定当前要为对象设置的属性名称


(3)
该标签可以构造简单的“if-then”结构的条件表达式

属性名 是否支持EL 属性类型 属性描述
test true boolean 决定是否处理标签体中的内容
var false String 用于指定将test属性的执行结果保存在某个web域中的某个属性的名称
scope false String 指定将test属性执行结果保存到那个web域中


(4)
标签用于指定多个条件选择的组合边界,它必须与和标签一起使用。使用,和三个标签,可以构造类似 “if-else if-else” 的复杂条件判断结构。


(5)
该标签用于对一个集合对象中的元素进行循环迭代操作,或者按指定的次数重复迭代执行标签体中的内容。

属性名称 是否支持EL 属性类型 属性描述
var false String 指定将当前迭代到的元素保存到page域中的属性名称
items true object 将要迭代的对象
varStatus false String 指定将代表当前迭代状态信息的对象保存到page域中的属性名称
begin true int 如果指定items属性,就从集合中的第begin个元素开始进行迭代,begin的索引值从0开始编号;如果没有指定items属性,就从begin指定的值开始迭代,直到end值时结束迭代
end true int 参看begin属性的描述
step true int 指定迭代的步长,即迭代因子的迭代增量

关于varStatus属性的说明:
varStatus=“status”事实上定义了一个status名的对象作为varStatus的绑定值。该绑定值也就是status封装了当前遍历的状态。例如:
1、status.index可以看其遍历的index值
2、status.count表示当前遍历的个数
3、status.last和status.first都为boolean值,分别表示是否遍历到最后一个和最后一个元素


(6)
对带有相同符合格式内容进行分割输出。

属性名称 是否支持EL 属性类型 属性描述
Items true Object 将要迭代的对象
delims false String 字符串的分割符,可以同时有多个分割符(依次写在引号内即可。)
varStatus false String 指定将代表当前迭代状态信息的对象保存到page这个Web域中的属性名称
begin true int 如果指定items属性,就从集合中的第begin个元素开始进行迭代,begin的索引值从0开始编号;如果没有指定items属性,就从begin指定的值开始迭代,直到end值时结束迭代
end true int 参看begin属性的描述
step true int 指定迭代的步长,即迭代因子的迭代增量
var false String 指定将当前迭代到的元素保存到page这个Web域中的属性名称


(7)
该标签用于将当前的访问请求转发或重定向到其他资源,它可以根据url属性所指定的地址,执行类似这个JSP标准标签的功能,将访问请求转发到其他资源;或执行response.sendRedirect()方法的功能,将访问请求重定向到其他资源。

属性名称 是否支持EL 属性类型 属性描写
url true String 指定要转发或重定向到的目标资源的URL地址


3、常用标签库的使用实例
<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title heretitle>
head>
<body>
    
    <c:set var="name1" value="value1" scope="request" >c:set>

    
    <c:out value="${name1}" default="not find">c:out><br>

    
    <c:if test="${true}">
        条件成立!
    c:if><br>

    
    <c:set var="test" value="77" scope="request">c:set>
    <c:choose>
        <c:when test="${test<40}">条件1成立c:when>
        <c:when test="${test>70}">条件2成立c:when>
        <c:otherwise>否则c:otherwise>
    c:choose><br><br>

    
    <%
        //先定义了数组,并将它保存到pageContext域当中
        String[] strs = {"1","2","3","4"};
        pageContext.setAttribute("strs", strs);
    %>
    <c:forEach begin="0" end="3" step="1" items="${strs}" var="var" varStatus="status">
        ${status.count} :  ${var}<br>
    c:forEach><br><br>

    
    <c:forTokens items="1.2.3.4.5.6" delims="." var="item" varStatus="status">
        ${status.index} :  ${item}<br>
    c:forTokens>  

    
    <%--
    "/demo.jsp">
    
    --%>

body>
html>


(三)自定义标签

自定义标签是用户定义的JSP标签。

1、自定义标签的使用步骤

(1)创建一个java类,继承SimpleTagSupport类,重写doTag()方法,在该方法里面实现自定义的业务逻辑。

package tag;

import java.io.IOException;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.SimpleTagSupport;

/**
 * Description:
 * 自定义标签类,
 * 
 * @author lee
 * */
public class TagDemo1 extends SimpleTagSupport{
    /**
     * 重写toTag()方法,执行自定义内容
     * 
     * 输出标签内容。
     * */
    @Override
    public void doTag() throws JspException,IOException{
        //获取标签体内容
        JspFragment jspBody = this.getJspBody();

        //获取out对象
        JspWriter out = this.getJspContext().getOut();

        //执行invoke方法,把表前提内容执行到指定的writer对象当中
        //当该方法参数为null,则默认输出到浏览器当中
        jspBody.invoke(out);

    }
}

(2)编写标签库描述符tld文件。tld文件包含着该标签库的声明和标签的声明。并将该tld文件放在WEB-INF目录中。
JSP基础_第4张图片
该tld文件如下:




<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.1tlib-version>
     
    <short-name>customshort-name> 
    <uri>http://custom.cnuri>

    
    <tag>
        
        <name>showname>
        
        <tag-class>tag.TagDemo1tag-class>
        
        <body-content>JSPbody-content>
    tag>

     
    <tag>
        <name>upname>
        <tag-class>tag.TagDemotag-class>

         
        <attribute>
            <name>idname>
        attribute>
    tag>
 
taglib>

标签中描述属性的元素有:

元素名 是否必须制定 描述
description 用于指定属性的描述信息。
name 用于指定属性的名称。属性名称是大小写敏感的,并且不能以jsp、_jsp、java和sun开头。
required 用于指定在JSP页面中调用自定义标签时是否必须设置这个属性。其取值包括true和false,默认值为false,true表示必须设置,否则可以设置也可以不设置该属性。
rtexprvalue rtexprvalue是runtime expression value(运行时表达式)的英文简写,用于指定属性值是一个静态值或动态值。其取值包括true和false,默认值为false,false表示只能为该属性指定静态文本值,例如”123”;true表示可以为该属性指定一个JSP动态元素,动态元素的结果作为属性值,例如JSP表达式<%=value %>。
type 用于指定属性值的Java类型。


(3)在JSP页面使用taglib指令导入该标签库,使用自定义标签。
例如导入上面声明的自定义标签库:

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>

<%@ taglib uri="http://custom.cn" prefix="custom" %>

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>自定义标签的使用title>
head>
<body>
    
    <custom:show>
        标签体内容
    custom:show>
body>
html>



2、自定义标签案例

这里实现一个类似JSTL核心标签库里的 功能的自定义标签。
三个自定义标签的类的:
(1)choose标签类

package tag;

import java.io.IOException;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;

/**
 * Descr的iption:
 * 一个标签处理类,该标签处理类实现了类似JSTL核心标签库
 * 标签处理方法。
 * 
 * @author lee
 * */
public class CustomChoose extends SimpleTagSupport{
    /**
     * Description:
     * test代表着该标签子标签custom:when的test值。
     * 
     * */
    private boolean test;

    /**
     * Description:
     * 返回test的值
     * 
     * @return test代表着该标签子标签custom:when的test值
     * */
    public boolean getTest(){
        return this.test;
    }

    /**
     * Description:
     * 设置test的值
     * 
     * @param test代表着该标签子标签custom:when的test值
     * */
    public void setTest(boolean test){
        this.test = test;
    }

    /**
     * Description:
     * 重写了SimpleTagSupport类的doTag方法
     * 输出了标签体的内容。
     * 
     * */
    @Override
    public void doTag()
        throws JspException, IOException
    {
        //调用JspFragment对象的invoke方法,默认想浏览器输出
        this.getJspBody().invoke(null);
    }
}


(2)when标签类

package tag;

import java.io.IOException;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.JspTag;
import javax.servlet.jsp.tagext.SimpleTagSupport;

/**
 * Description:
 * 一个标签处理类,该标签处理类实现了类似JSTL核心标签库
 * 标签的处理方法
 * 
 * @author lee
 * */
public class CustomWhen extends SimpleTagSupport{
    /**
     * Description:
     * test是when标签的判断条件
     * 
     * */
    private boolean test;

    /**
     * Description:
     * 设置test的值
     * 
     * @param test when标签的判断条件
     * */
    public void setTest(boolean test){
        this.test = test;
    }

    /**
     * Description:
     * 重写了SimpleTagSupport类的doTag方法
     * 获取该标签的属性test的值,为true就输出标签体内容,
     * 否则不输出
     * 
     * */
    @Override
    public void doTag()
        throws JspException, IOException
    {
        //获取父标签choose
        CustomChoose customChoose = (CustomChoose)this.getParent();
        //设置其test值
        customChoose.setTest(test);

        if(test){
            this.getJspBody().invoke(null);
        }
    }
}


(3)otherwise标签类

package tag;

import java.io.IOException;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;

import org.eclipse.jdt.internal.compiler.ast.ThrowStatement;

/**
 * Description:
 * 一个标签处理类,该标签处理类实现了类似JSTL核心标签库的
 * 标签处理方法。
 * 
 * @author lee
 * */
public class CustomOtherwise extends SimpleTagSupport{

    /**
     * Description:
     * 重写了SimpleTagSupport类的doTag方法
     * 获取其父标签的标签体的test值,
     * test值为false输出其标签体内容,否则不输出
     * 
     * */
    @Override
    public void doTag()
        throws JspException, IOException
    {
        //获取其父标签
        CustomChoose customChoose = (CustomChoose)this.getParent();
        //获取其test值
        boolean test = customChoose.getTest();

        if(!test){
            this.getJspBody().invoke(null);
        }

    }
}


(4)tld文件声明



<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.1tlib-version>
    <short-name>customshort-name>
    <uri>http://custom.cnuri>



    <tag>
        <name>choosename>
        <tag-class>tag.CustomChoosetag-class>
        <body-content>scriptlessbody-content>
    tag>

    <tag>
        <name>whenname>
        <tag-class>tag.CustomWhentag-class>
        <body-content>scriptlessbody-content>
        <attribute>
            <name>testname>
            <required>truerequired>
            <rtexprvalue>truertexprvalue>
        attribute>

    tag>

    <tag>
        <name>otherwisename>
        <tag-class>tag.CustomOtherwisetag-class>
        <body-content>scriptlessbody-content>
    tag>
taglib>


(5)使用标签

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<%@ taglib uri="http://custom.cn" prefix="custom" %>

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title heretitle>
head>
<body>
        <custom:choose>
            <custom:when test="true">条件1成立custom:when>
            <custom:when test="false">条件2成立custom:when>
            <custom:otherwise>条件3成立custom:otherwise>
        custom:choose>


body>
html>

你可能感兴趣的:(jsp)