Head First Servlets and JSP(二)
文章目录
- 第七章 作为JSP:使用JSP
- 第八章 没有脚本的页面:无脚本的JSP
- 第九章 强大的定制标记:使用JSTL
- 第十章 定制标记开发
第七章 作为JSP:使用JSP
在JSP中可以使用scriptlet(即放在<%…%>标记中的java代码)放入常规的java代码;
使用page指令导入包;
表达式元素自动打印放在标记之间的内容;
<%@ page import="foo.*,java.util.*"%>
<html>
<body>
The page count is:
//不要在表达式的最后加上分号
<%=Counter.getCount()%>
</body>
</html>
三种JSP元素:
- Scriptlet: <% %>
- 指令: <%@ %>
- 表达式: <%=%>(表达式会成为out.print()的参数)
所有scriptlet和表达式代码都放在服务方法中,scriptlet中声明的变量总是局部变量——在scriptlet中声明变量意味着每次运行服务方法时这个变量都会重新初始化;
JSP元素:<%!和%>标记之间的所有内容都会增加到类中——变量和方法都可以声明;
容器把JSP转换为servlet时,服务方法最前面有一堆隐式对象声明和赋值。
JSP中两种不同类型的注释:
<!–HTML注释–>:容器把它直接传递给客户,在客户端浏览器会把它解释为注释;
<%–JSP注释–%>:原文注释;
容器根据你的JSP生成一个类,这个类实现了HttpJspPage接口,关于容器生成的servlet的API:
- jspInit():这个方法由init()方法调用可以覆盖;
- jspDestroy():这个方法由servlet的destroy()方法调用,也可覆盖;
- _jspService():这个方法由servlet的service()方法调用,不能覆盖;
如果 一个Web应用包含JSP,部署这个应用时,在JSP生命周期中,整个转换和编译步骤只发生一次
初始化JSP:
配置servlet初始化参数,必须在<servlet>标记中增加一个<jsp-file>元素;
为一个JSP定义servlet时,还必须为JSP页面定义一个servlet映射;
覆盖jspInit()
<%!//使用声明覆盖jspInit()方法public void jspInit(){ServletConfig sConfig=getServletConfig();//在一个servelt中可以调用继承的方法String eamilAddr=sConfig.getInitParamenter("email");ServletContext ctx=getServletContext();//得到Servlet的一个引用,并设置一个应用作用域属性ctx.setAttribute("mail",eamilAddr);
JSP使用4个隐式对象得到和设置对应JSP中4个属性作用域的属性;
可以使用PageContext引用来得到任意作用域的属性,包括从页面作用域得到绑定到PageContext的属性;
三个指令:
指令 | 作用 |
---|---|
<%@ page import=“foo.*” session=“false”%> | 定义页面特定的属性 |
<%@ taglib tagdir=“WEB-INF/tags/cool” prefix=“cool”%> | 定义JSP可以使用的标记库 |
<%@ include file=“wickedHeader.html” %> | 定义在转换时增加到当前页面的文本和代码 |
EL:用途是提供一种更简单的方法来调用java代码,但是代码本身放别的地方;
使用<scripting-invalid>标记让JSP禁用脚本元素;
第八章 没有脚本的页面:无脚本的JSP
使用表达式语言(EL)和标准动作构建JSP页面
使用几个标准动作——消除JSP中的脚本代码(包括声明、scriplet和表达式);
//使用标准动作(不使用脚本)
<html><body>
<jsp:useBean id="person" class="foo.Person" scope="request"/>
Person created by servlet:<jsp:getProperty name="person" property="name"/>
</body></html>
<jsp:useBean>用来声明和初始化在<jsp:getProperty>中使用的具体bean对象;
用<jsp:getProperty>得到bean属性的性质值;
如果<jsp:useBean>找不到对应名的属性对象,会新建一个:
利用<jsp:useBean>体,可以有条件地运行代码,只有找不到bean属性,而且创建了一个新bean时才会运行体中的代码;(bean没有带参数的构造函数)
建立多态的引用,向标记增加type属性,例如:
<jsp:useBean id="person" type="foo.person" class="foo.Employee" scope="page">
如果在<jsp:useBean>或<jsp:getProperty>标记中没有指定作用域,容器会使用默认作用域"page";
利用param属性,可以把bean的性质值设置为一个请求参数的值。只需指定请求参数;
如果请求参数名与bean性质名匹配,就不需要在<jsp:setProperty>标记中为该性质指定值;
Bean标记会自动转换基本类型的性质;
利用<jsp:getProperty>,只能访问bean属性的性质,不能访问嵌套性质——使用EL(JSP表达式语言);
EL表达式:
${person.name}//放在大括号里,且前面有一个美元前缀符
表达式中的第一个命名变量可以是一个隐式对象,也可以是一个属性;
使用点号(.)操作符访问性质和映射值;
如果表达式变量后有一个点号,点号左边的变量必须是一个Map或一个bean;
点号右边必须是一个Map键或一个bean性质;
或者使用中括号:
数组和List中的String索引会强制转换为int;
EL有一些隐式对象。x想从请求得到HTTP请求方法,使用requestScope会得到请求性质,而不是request性质,要得到request性质,需要通过pageContext;
Method is:${pageContext.request.method}
可以编写简单的EL表达式,调用自己写的普通Java类的静态方法;
- 编写一个有公共静态方法的Java类;
- 编写一个标记库描述文件(TLD)——提供了定义函数的Java类与调用函数的JSP之间的一个映射;
- 在JSP中放一个taglib指令,定义命名空间;
- 使用EL调用函数:按照${prefix:name()}的形式从表达式调用函数;
例如:
<%@ taglib prefix="mine" uri="WEB-INF/foo.tld"%>
对于可重用的模板部件,JSP有一个处理机制——包含(include);
inlcude指令告诉容器:复制所包含文件的内同并粘贴到这个文件中;
<jsp:include>标准动作内部原理不同于include指令——include在转换时发生,<jsp:include>标准动作在运行时发生;
不要把开始和结束HTML和BODY标记放在可重用部件中;
使用<jsp:param>定制包含的内容:
完成包含的JSP:
<html><body>
<jsp:include page="Header.jsp">//没有结束反斜线jsp:param name="subTitle" value="Whatever"/>
</jsp:include>
</body></html>
使用新参数的被包含页眉:
<img src="data:images/Web-Services.jpg"><br>
<em><strong>${param.subTitle}</strong></em><br>
从一个jsp转发到另一个jsp或者servlet:<jsp:forward>标准动作;
提供条件转发的JSP(Hello.jsp)
<html><body>
Welcome to our page!
<% if (request.getParameter("userName")==null){%><jsp:forward page="HandleIt.jsp"?>
<% } %>
Hello ${param.userName}
</body></html>
请求转发到的目标JSP(HandleIt.jsp)
<html><body>
you need to log in again.
<form action="Hello.jsp" method="get">
Name: <input name="userName" type="text">
<input name="Submit" type="submit">
</form>
</body></html>
发生转发时,请求转发到的目标资源首先会清空响应缓冲区——不要先刷新输出再转发;
第九章 强大的定制标记:使用JSTL
使用JSTL之前,需要将文件(“jstl.jar"和"standard.jar”)放在Web应用的WEB-INF/lib 目录中;
使用<c:out>标记转换HTML特殊字符为实体格式;
<c:out>提供一个default属性
<b> Hello <c:out value='${user}' default='guest' />.</b>
<c:forEach>不用脚本实现循环
var属性存放集合中的各个元素,items对应具体要循环处理的集合(数组、collection、Map);可选属性varStatus得到一个循环计数器;
"var"变量的作用域仅限于标记内部;
使用<c:if>完成条件包含,例如(成员在页面看到更多的东西)
//JSP代码
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html><body>
<strong>Member comments</strong><br>
<hr>${commentList}<hr>//假设有一个servlet会根据用户的登录信息设置useType属性
<c:if test="${userType eq 'member'}">//标记和EL中单引号和双引号都能用<jsp:include page="inputComments.jsp"/>//此处省略input.Comments.jsp的构造
</c:if>
if/else的构造——<c:choose>、<c:when>和<c:otherwise>实现;
<c:set>的两个版本,var版本设置属性变量,target版本设置bean性质或Map值(一些要点和技巧)
使用<c:remove>删除一个属性;
除了include指令、<jsp:include>标准动作,使用<c:import>将资源的内容增加到JSP中;
JSP中URL的重写:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html><body>
This is a hyperlink with URL rewriting enabled.
<a href="<c:url value='/inputComments.jsp' />">Click here</a>
//在"value"相对URL的最后增加jsessionid,如果禁用了cookie.
</body></html>
URL编码把不安全/保留的字符替换为其他字符,然后在服务器端完成解码;<c:url>不会自动地对URL编码;在<c:url>的体中使用<c:param>,完成URL的重写和编码;
设计定制页面处理错误,然后使用page指令配置错误页面;
//指定的错误页面("erroePage.jsp")
<%@page isErrorPage="true" %>
<html><body>
<strong>Bummer.</strong>
You cause a ${pageContext.exception} on the server.<br>//可以得到详细错误信息
//容器为错误页面提供了一个额外的exception对象
<img src="data:images/bummerGuy.jpg">
</body></html>//抛出异常的“坏”页面("badPage.jsp")
<%@ page errorPage="erroePage.jsp" %>
<html><body>
About to be bad...
<% int x=10/0;%>//使页面抛出异常
</body></html>
可以在DD中为整个Web应用声明错误页面,甚至可以为不同的异常类型或HTTP错误码类型(404,500等)配置不同的错误页面;
使用<c:catch>标记完成一种try/catch,把有风险的标记或表达式包起来;
想在<c:catch>标记结束后访问异常,可以使用可选的var属性,把异常对象放在页面作用域,并按照声明的var值来命名;
使用非JSTL的标记库:URI是标记库描述文件(TLD)的唯一标识符,容器需要这个信息将JSP中使用的标记名映射到实际调用的java代码;
当标记的<body-content>元素值不是empty时,这个标记才能有体;
可以把TLD看作定制标记的API;
taglib<uri>只是一个名,而不是一个位置;
容器会自动建立TLD和<uri>名之间的映射;如果JSP使用多个标记库,确保taglib uri名是唯一的,不要使用保留的前缀;
第十章 定制标记开发
利用标记文件,可以使用一个定制标记调用可重用的内容;
在JSP中放一个taglib指令,并调用这个标记:
<%@ taglib prefix="myTags" tagdir="/WEB-INF/tags" %>
<html><body>
<myTags:Header/>
Welcome to our site.
</body></html>
对于标记文件,发送的不是请求参数,而是标记属性;
标记文件使用attribute指令;这个指令只能由标记文件使用;
对于标记属性很长的内容可以放在标记的体中,使用tag指令声明body-content类型;标记文件标记的体重不能使用脚本代码(默认scriptless),除非使用"empty"或"tagdependent",可以声明body-content;
如果标记文件在一个JAR中部署,就必须有一个TLD,如果直接放在Web应用中,就不需要TLD;
建立一个简单的标记处理器:
如果标记需要一个属性,就要在TLD中声明,并在标记处理器中为每个属性提供一个bean式的设置方法;
JspFragment是表示JSP代码的一个对象;getJspContext()实际上是标记体向其他对象提供信息的一个途径;
SkipPageException:停止处理页面,会显示异常出现之前的所有内容;
Tag处理器API有5个接口和3个支持类;
简单标记只有一个doTag(),但是传统标记有一个doStartTag()和一个doEndTag(),有一个doAfterBody()方法,在计算体之后并在doEndTag()运行前调用;
传统标记生命周期取决于返回值;
如果没有覆盖返回一个整数的TagSupport生命周期方法,要当心TagSupport方法实现返回的默认值;
标记处理器类必须为TLD中声明的每个标记属性实现一个设置方法,使用DynamicAttribute接口:
为使用DynamicAttributes,标记处理器类必须实现JSP API的DynamicAttributes接口,碧必须实现setDynamicAttribute()方法,使用hashmap存储属性名/值对;
通过扩展BodyTagSupport,能从Body-Tag接口得到另外两个生命周期方法——setBodyContent()和doInitBody();
标记可以调用其父标记;
标记处理器类不是一个servlet或JSP,但有PageContext的一个引用;
标记文件的查找位置(复习):
Head First Servlets and JSP(二)相关推荐
- JSP二手书交易平台设计与实现
自己已经看过不再需要的二手书,和对需要的二手书进行求购,这是一个很好的处理二手出的方式.让网站用户只要登录进去二手书交易平台就可以查看所有的内容,用户可以查看新闻以及二手书籍的及时更新的信息,能够以最 ...
- Java基于JSP二手书交易平台设计与实现
现代网络技术发展迅速,传统的书店销售模式受到诸如场地.资金.宣传等因素制约,已经不能满足人们的日益增长的图书购买需求,网上书店应运而生,基于web的网络书店给人们带来了很大便利,网络书店不仅是传统售书 ...
- 【Head First Servlets and JSP】笔记24:include指令与include动作 param动作 foward动作...
include指令与include动作 1.样例代码 <%@ page contentType="text/html;charset=UTF-8" language=&quo ...
- Why use Servlets JSPs: an introduction(Head First Servlets and JSP)
? A GET request appends form data to the end of the URL. ? A POST request includes form data in the ...
- JSP与servlets的区别
从架构上说,JSP可以被看作是从Servlets高级提炼而作为JAVA Servlet2.1 API的扩展而应用.Servlets和JSP最早都是由Sun Microsystems(升阳公司)开发的. ...
- [读书笔记]《Head First Servlets JSP》2nd
书名:Head First Servlets and JSP: Passing the Sun Certified Web Component Developer Exam 出版商:O'Reilly ...
- [JSP暑假实训] 二.JSP网站创建及Servlet实现注册表单提交、计算器运算
本系列文章是作者暑假给学生进行实训分享的笔记,主要介绍MyEclipse环境下JSP网站开发,包括JAVA基础.网页布局.数据库基础.Servlet.前端后台数据库交互.DAO等知识. 本篇文章开始讲 ...
- JSP WEB开发入门基础到高手进阶教程002
JSP WEB开发入门基础到高手进阶教程 -------开发入门 JSP与微软的Active Server Pages 兼容,但它是使用类似HTML的卷标以及Java程序代码段而不是VBScript. ...
- 160329(二)、web.xml配置详解
1.启动一个WEB项目的时候,WEB容器会去读取它的配置文件web.xml,读取<listener>和<context-param>两个结点. 2.紧急着,容创建一个Servl ...
最新文章
- 【GDKOI2016Day1T1-魔卡少女】【拆位】线段树维护区间内所有连续子区间的异或和...
- 了解下C# 类型转换
- Kettle transformation 操作内容快速查询
- from __future__ import absolute_import用法心得小结
- cannot find -lcudart
- 网易云信自研大规模传输网核心系统架构剖析
- sqlDataAdapter的FillSchema用法
- linux部署jar项目报错_Spring boot项目部署linux系统tomcat报错解决办法
- MySQL的前缀索引及Oracle的类似实现
- fscanf返回值被忽略怎么解决_pytest的fixture怎么用?
- 13. 查看网络端口、配置网络
- vlan的基本指令_vlan划分命令
- MFC控件学习:图片(bmp/png)
- vs2017 开关“/NOENTRY”只与 DLL 兼容;链接时不使用“/NOENTRY”
- 网易公司创始人兼CEO丁磊:独家版权偏离了传播的初衷,已陷入资本运作的怪圈...
- linux内核编程(hello world示例程序)
- PHP+MYSQL 可视化Echarts 完整源码,小白总结
- Unity的Animator的动画层(Layer)
- python数据分析案例分析题_Python数据分析-案例分析
- 关于windows-1252页面乱码问题