JavaEE(二)JSP

JSP(java server page)

  JSP是一种语法规范,在html模板中嵌入jsp语法,其实现处理的方式是把jsp文件转换为servlet类
  当请求到达时,服务器若判别为jsp请求就会转交给jsp引擎处理,它会找到jsp文件并根据语法解析为servlet类文件,然后编译并加载该servlet(实际上jsp引擎会检查相应servlet是否已加载且加载时间是否在jsp最后更改时间之后,只有该条件不成立才会重新生成servlet并重新编译加载,这样减少生成编译和加载servlet的过程以提高访问效率)。可见jsp语法其实就是怎么将jsp文件转换为servlet的语法(jsp转换为servlet只是实现jsp规范的一种可行方案)

JSP的生命周期

  JSP文件生成的servlet都实现了HttpJspPage接口(Servlet的子接口),对于tomcat而言,jsp页面生成的servlet都继承自HttpJspPage的实现类HttpJspBase。其生命周期为:根据jsp文件生成并加载servlet->jspInit->_jspService->jspDestroy,当jsp文件发生更改重新生成并加载servlet时会先销毁系统中原来的servlet,也就是会调用老的servlet的jspDestroy方法并调用新的servlet的jspInit方法

JSP语法

  空jsp文件生成的servlet主要只有一个_jspService方法,该方法分为两段,第一段把几个有用的对象(隐式对象)列了出来,因此后面的第二段可以使用这些对象;第二段为jsp文件的某些部分生成。解析jsp文件的时候就是把jsp的各个部分按顺序插入servlet源文件的相应地方以及对插入的控制。隐式对象有9个,常用的有request(HttpServletRequst)、response(HttpServletResponse)、out(JspWriter类型表示响应的输出流)、session(HttpSession)、application(ServletContext)、config(ServletConfig)、page(就是this关键字)、pageContext(PageContext类的实例,提供对JSP页面所有对象以及命名空间的访问)、exception(当某个页面为异常处理页面时,该值为异常发生页面抛出的异常)

  • 模板部分(除去以下部分的其他部分),该部分的内容会封装为out.write(“模板部分”)插入_jspService的第二部分。
  • 注释部分(<%-- 注释部分 --%>),注释部分的内容直接被忽略,不会写入servlet,但<!-- html注释 -->会写入servlet,只是在客户端不会解析显示而已。
  • 表达式部分(<%= 表达式部分 %>),该部分的内容会封装为out.print(表达式部分)直接插入_jspService的第二部分。
  • 脚本部分(<% 脚本部分 %>),该部分的内容会直接插入_jspService的第二部分。
  • 声明部分(<%! 声明部分 %>),该部分的内容可以声明或定义一个或多个变量、方法,会被直接写入servlet类中与_jspService平行部分,也就是servlet的成员变量和成员函数。
  • 指令部分(<%@ directive attribute=“value” %>),用来设置整个JSP页面相关的属性,如网页的编码方式和脚本语言。其中directive可以有三个取值page、include或taglib。
  • 标签部分 (<prefix:tag attribute=“attr”> 标签内容 </prefix:tag>),在_jspService的第二部分新建一个Tag对象并依次调用其生命周期方法。
  • 动作部分 (<jsp:action_name attribute=“value” />),JSP动作元素在请求处理阶段起作用。

JSP指令

  JSP指令用来设置整个JSP页面相关的属性,如网页的编码方式和脚本语言,格式为<%@ directive attribute=“value” %>,其中directive可以有三个取值page、include或taglib。
  当指令部分的directive为taglib时,表示引入标签库,格式为<%@ taglib uri=“在web.xml里面标签库配置的uri” prefix=“当引用该标签库时使用的前缀” %>。
  当directive为include时,表示将另一个文件的内容全部放在此处,在转换为servlet时引入文件内容就成了整个文件的一部分并按照jsp规则解析,格式为<%@ include file=“文件相对url地址” %>。
  当directive为page时,attribute有很多取值来表示不同的指令

  • import:导入要使用的Java类,多个用逗号分隔或者从新使用个该标签,如<%@ page import=“java.util.*, java.lang.*” %>
  • contentType:指定当前JSP页面的MIME类型和字符编码,如<%@ page language=“java” contentType=“text/html;charset=GBK” %>
  • pageEncoding:指定当前JSP页面的字符编码,如果指定了pageEncoding,就以它为主,如果不存在,再找contentType的charset,如<%@ page language=“java” contentType=“text/html” pageEncoding=“GBK” %>
  • isELIgnored:是否启用el表达式,默认false,即为启用,如<%@ page isELIgnored=“true”%>
  • errorPage:指定当JSP页面发生异常时需要转向的错误处理页面,如<%@ page errorPage=“error.jsp”%>
  • isErrorPage:指定当前页面是否可以作为另一个JSP页面的错误处理页面,<%@ page isErrorPage=“true”%>
  • language:指定脚本语言,默认为java,因为我们现在只使用java,所以该值不管。

JSP动作

  JSP动作的格式为<jsp:action_name attribute=“value” />,常用的action_name如下:

  • include:在_jspService插入一条类似于RequestDispatcher的include语句,格式为<jsp:include page=“相对URL地址” flush=“true” />
  • forward:在_jspService插入一条类似于RequestDispatcher的forward语句,格式为<jsp:forward page=“相对URL地址” />
  • userBean:在_jspService中声明一个变量,并从作用域中获取相应的对象赋值给变量,如果在作用于中不存在相应的对象就新建对象并放入相应的作用域,格式为<jsp:userBean id=“变量名” scope=“page(默认)/request/session/application” class=“具有无参构造函数的带包类”/>或<jsp:userBean id=“变量名” scope="" class="">这部分jsp内容会在userBean新建的时候执行,如用jsp:setProperty/来进行新建对象的初始化</jsp:userBean>
  • setProperty:设置bean的属性,调用属性的set方法,会依次从page、request、session、和application作用域寻找bean,格式为<jsp:setProperty name=“变量名”, property=“属性名” value=“属性值”/>
  • getProperty:out.write(bean的属性),调用bean属性的get方法,会依次从page、request、session、和application作用域寻找bean,格式为<jsp:getProperty name=“变量名” property=“属性名” />

JSP表达式

  EL表达式中可以有对象、常量、标签库中注册的函数以及运算符。当JSP解析器见到 格 式 后 , J S P 解 析 器 会 产 生 代 码 来 计 算 这 个 表 达 式 , 并 用 表 达 式 的 值 来 代 替 表 达 式 的 位 置 , 如 {}格式后,JSP解析器会产生代码来计算这个表达式,并用表达式的值来代替表达式的位置,如 JSP{fn:contains(object.attr, sub)}。
  EL支持的运算符有

  • 基本运算:+、-、*、/(div)、%(mod) 加、减、乘、除(除就是除,不是取整)、取模,只适合数字或者由数字组成的字符串
  • 逻辑运算:==(eq)、!=(ne)、<(lt)、>(gt)、<=(le)、>=(ge)、&&(and)、||(or)、!(not)
  • . 、[] 访问一个Bean属性或者一个映射条目,如bean.attr、bean[“attr”]、map.key、map.[“key”],若映射条目有特殊字符只能用[],数组或者链表只能用[],如list[1].attr
  • ( ) 组织一个子表达式以改变优先级
  • ? : 条件运算的三目运算符
  • empty 测试是否空值,当为null、空字符串或空集合时返回true

  EL支持的隐藏对象有:pageScope、requestScope、sessionScope、applicationScope、param、paramValues、header、headerValues、initParam、cookie、pageContext。当对象引用不是以隐藏对象开头的,那么会依次从四大作用域中去找相应的对象

JSP标签与函数

  标签能过通过pageContext获取很多对象,所以常用来进行过程处理,而函数只能拿到输入参数并得到处理后的返回值
  函数的定义很简单,其所在的类不需要实现和继承任何类,但要求函数必须是public static修饰的公有静态函数,函数的调用见EL表达式
  JSP标签对应着一个实现了JspTag的标签处理类,在JSP引擎解析到JSP标签时,会在_jspService的第二部分创建标签对应的处理类,并依次执行其生命周期方法。定义JSP标签的过程分为两步,首先要实现标签处理类,其实现方式有两种,分别为传统方式和简单方式,然后需要将处理类进行注册,注册到标签库文件中。使用标签时需要先在web.xml中用标签下的标签引入标签库,然后需要在需要使用标签的jsp页面用<%@ taglib/>指令引入标签库。
  JSP标签库在一个xml格式的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">

    <!-- 标签库对应的名字,不常用 -->
    <display-name>name</display-name>
    <!-- 标签库的描述,不常用 -->
    <description>description</description>
    <!-- 指定标签库版本 -->
    <tlib-version>1.0</tlib-version>
    <!-- 在jsp中建议使用的前缀,只是建议 -->
    <short-name>myshortname</short-name>
    <!-- 指定引用该标签的uri地址,如果标签库指定了该值,那么在jsp页面可以直接用该值引入标签库,而无需在web.xml中引入该标签库,当然也可以在web.xml中引入该标签库并指定一个新的uri,在jsp页面依然可以通过新的uri引入标签库 -->
    <uri>http://mycompany.com</uri>

    <!-- 各个标签的注册,可以有多个 -->
    <tag>
        <!-- tag对应的名字,不常用 -->
        <display-name>name</display-name>
        <!-- tag的描述,不常用 -->
        <description>description</description>
        <!-- 标签的名字,供调用 -->
        <name>tagName<name>
        <!-- 标签处理类 -->
        <tag-class>com.ejie.MyTag</tag-class>
        <!-- 对标签体的定义,当为empty时,其内容就算不为空也会被当做空,当为JSP时会当中JSP解析出结果,当为scriptless时,可以为EL表达式和JSP动作元素不能为JSP脚本如<% %>与<%= %>等,当为tagdependent时,不会对内容做任何解析 -->
        <body-content>empty/JSP(简单标签不支持该值)/tagdependent/scriptless</body-content>
        <!-- 未声明的属性是否允许使用,默认false,不可以与attribute共存 -->
        <dynamic-attributes>true/false</dynamic-attributes>
        <!-- 定义标签可以有的属性,可以有多个 -->
        <attribute>
            <!-- 属性名 -->
            <name>att</name>
            <!-- s属性的描述,不常用 -->
            <description>description</description>
            <!-- 是否必须赋值的属性,默认false -->
            <required>true/false</required>
            <!-- 属性是否支持运行时表达式,如JSP表达式(<%=value%>)和EL表达式(${value}) -->
            <rtexprvalue>true/false</rtexprvalue>
            <!-- 参数类型 -->
            <type>java.lang.String</type>
        </<attribute>
    </tag>
    
    <function>
        <!-- 函数对应的名字,不常用 -->
        <display-name>name</display-name>
        <!-- 函数的描述,不常用 -->
        <description>description</description>
        <!-- 函数对应的名字,供调用 -->
        <name>funName</name>
        <!-- 函数的定义所在类 -->
        <function-class>org.apache.taglibs.standard.functions.Functions</function-class>
        <!-- 函数的签名 -->
        <function-signature>java.lang.String substringBefore(java.lang.String, java.lang.String)</function-signature>
    </function>

</taglib>

  JSP标签处理器的传统定义方式都是实现了JspTag的子接口Tag,他的生命周期方法依次为 setPageContext(PageContext pageContext)->setParent(Tag tag)->doStartTag()->doEndTag()->release()。release方法用于释放资源,在容器关闭时才会调用。PageContext对象可以用来获取几大隐藏对象。当读到标签时调用doStartTag方法,返回值为SKIP_BODY(不会将标签的内容写入response的输出流)与EVAL_BODY_INCLUDE(将标签内容写入response的输出流),当读到结束标签时调用doEndTag方法,其返回值可以取EVAL_PAGE(继续处理标签后面的页面)与SKIP_PAGE(该标签后面的jsp页面不再处理),一般继承有Tag默认实现方法的基类BodyTagSupport
  JSP标签处理器的简单定义方式都是实现了JspTag的子接口SimpleTag,它是jsp2.0之后引入的,除了部分老的框架在使用传统定义方式外,都建议使用简单定义方式。其生命周期方法依次为setJspContext(JspContext jspContext)->setJspBody(JspFragment jspFragment)->setParent(JspTag jspTag)->doTag()。为了定义简单标签的方便,一般继承有SimpleTag默认实现方法的基类SimpleTagSupport,几个set方法都用javabean的方式设置了成员变量并提供了get方法,doTag方法默认为空,一般继承自SimpleTagSupport的标签处理器只需要实现doTag方法,负责解析标签就可以了。只有该标签在另一个自定义标签里面的时候才会有父标签,否则父标签为null。
  在标签处理类中定义与属性名相同的成员变量,并定义其set方法,在doTag中就可以使用这些成员变量来获取标签的属性值。获取标签内容的方式为JspFragment(通过getJspBody获取)的invoke(Writer writer)方法,当writer传null的时候,默认为写入response的输出流,如果希望自己处理,可以定义一个StringWriter获取标签内容,通过其toString方法获取标签内容。如果希望该标签之后的jsp页面不再处理,只需要抛出SkipPageException异常

JSTL

  JSP标准标签库(JSTL:Java Standard Tag Library)是一个JSP标签集合,它封装了JSP应用的通用核心功能,使用时需要引入相应的standard包和jstl包。主要的标签库有核心标签库、格式化标签、SQL标签与XML标签以及JSTL函数。
  标准库里最常用的就是核心包,引用方式<%@ taglib prefix=“c” uri=“http://java.sun.com/jsp/jstl/core” %>,其标签如下:

  • if,条件判断,如同代码中的if,格式为<c:if test=“条件判断” var=“保存判断的结果” scope=“结果保留的作用域”>…</c:if>示例如下:
<c:if test="${booleanA}" var="result" scope="page">
    <p>booleanA = true<p>
</c:if>
<c:if test="${result}">
    <p>booleanA = false<p>
</c:if>
  • choose、when与otherwise,当某个when成立的时候,后面的when和otherwise都无用了,如同代码中的swatch、case与default。
<c:choose>
    <c:when test="${booleanA}">
        <p>A</p>
    </c:when>
    <c:when test="${booleanB}">
        <p>B</p>
    </c:when>
    <c:otherwise>
        <p>都不是</p>
    </c:otherwise>
</c:choose>
  • forEach,循环,格式为<c:forEach items=“被遍历的集合对象,默认为一个由begin-end的连续整数集合” begin=“遍历的起始位置,默认为0” end=“遍历的结束位置,默认为最后一个元素下标” step=“遍历的步长,默认1” var=“保存遍历出来的当前对象” varStatus=“可以通过该对象获取如当前的索引index、第几次进入循环count”>…</c:foreach>。
<c:forEach items="list" var="item" begin="6" end="15" step="2" varStatus="status">
    <p>${item}</p>
    <p>${status.count}</p>
    <p>${status.index}</p>
</c:forEach>
  • forTokens,循环,与forEach相似,只是items为用符号分割的元素,因此比forEach多一个属性delims来指定分割符号。
<c:forEach items="item1,item2,item3" var="item" begin="6" end="15" step="2" varStatus="status" delims=",">
    <p>${item}</p>
    <p>${status.count}</p>
    <p>${status.index}</p>
    </c:forEach>
</c:forEach>
  • redirect,重定向,如<c:redirect url=“url”/>
  • out,在jsp中显示数据,如<c:out value=“输出” default=“当value通过EL表达式取值为null时的默认值,该属性的默认值为该标签的内容” escapeXml=“true/false”/>
  • set,设置变量值或某个变量的属性值,格式为<c:set var=“变量名” value=“变量值” scope=""/>或<c:set target=“对象名” property=“属性名” value=“变量值值” scope=""/>
  • catch,异常捕获<c:catch var =“catchException”>可能发生异常的部分</c:catch>,当异常发生时异常被捕获catchException

  标准库里还常用的就是函数,引用方式<%@ taglib prefix=“fn” uri=“http://java.sun.com/jsp/jstl/functions”%>,其标签如下:

  • trim(),移除首尾的空白符,public static String trim(String input)
  • length(),返回字符串长度,public static int length(Object obj)
  • replace(),将输入字符串中指定的位置替换为指定的字符串然后返回,public static String replace(String input, String substringBefore, String substringAfter)
  • contains(),测试输入的字符串是否包含指定的子串,public static boolean contains(String input, String substring)
  • containsIgnoreCase(),测试输入的字符串是否包含指定的子串,大小写不敏感,public static boolean containsIgnoreCase(String input, String substring)
  • substring(),返回字符串的子集,public static String substring(String input, int beginIndex, int endIndex)
  • substringBefore(),返回字符串在指定子串之前的子集,public static String substringBefore(String input, String substring)
  • substringAfter(),返回字符串在指定子串之后的子集,public static String substringAfter(String input, String substring)
  • indexOf(),返回指定字符串在输入字符串中出现的位置,public static int indexOf(String input, String substring)
  • startsWith(),测试输入字符串是否以指定的前缀开始,public static boolean startsWith(String input, String substring)
  • endsWith(),测试输入的字符串是否以指定的后缀结尾,public static boolean endsWith(String input, String substring)
  • join(),将数组中的元素合成一个字符串然后输出,public static String join(String[] array, String separator)
  • split(),将字符串用指定的分隔符分隔然后组成一个子字符串数组并返回,public static String[] split(String input, String delimiters)
  • toLowerCase(),将字符串中的字符转为小写,public static String toLowerCase(String input)
  • toUpperCase(),将字符串中的字符转为大写,public static String toUpperCase(String input)

JSP + Servlet

  用JSP作为显示层,Servlet作为控制层,请求来到Servlet,然后Servlet将处理好的数据放在请求的attribute中,JSP从请求的attribute中获取数据显示

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值