Java Web 学习(2) —— JSP
JSP
一、 什么是 JSP
JSP 和 Servlet
Servlet 有两个缺点是无法克服的:首先,写在 Servlet 中的所有 HTML 标签必须包含 Java 字符串,这使得处理HTTP响应报文的工作十分繁琐;第二,所有的文本和 HTML 标记是硬编码,导致即使是表现层的微小变化,如改变背景颜色,也需要重新编译。
JavaServer Pages(JSP)解决了上述两个问题。同时,JSP 不会取代 Servlet,相反,它们具有互补性。
JSP 页面本质上是一个 Servlet。然而,用 JSP 页面开发比使用 Servlet 更容易。首先,不必编译 JSP 页面;其次,JSP 页面是一个以 jsp 为扩展名的文本文件,可以使用任何文本编辑器来编写它们。
JSP 不需要添加注解或在部署描述符配置映射 URL。应用程序目录中的每一个JSP页面可以直接在浏览器中输入路径页面来访问。添加新的 JSP 界面后,无需重启 Tomcat。
二、 运行 JSP
JSP页面在JSP容器中运行,一个Servlet容器通常也是JSP容器。例如,Tomcat 就是一个 Servlet/JSP 容器。
当一个 JSP 页面第一次被请求时,Servlet/JSP 容器主要做以下两件事情:
1. 把 JSP 页面转换到 JSP 页面实现类,该实现类是一个实现 javax.servlet.jsp.JspPage 接口或子接口 javax.servlet.jsp.HttpJspPage 的 Java 类。JspPage 是 javax.servlet.Servlet 的子接口,这使得每一个 JSP 页面都是一个 Servlet。该实现类的类名由 Servlet/JSP 容器生成。如果出现转换错误,则相关错误信息将被发送到客户端。
2. 如果转换成功,Servlet/JSP 容器随后编译该 Servlet 类,并装载和实例化该类,像其他正常的 Servlet 一样执行生命周期操作。
对于同一个 JSP 页面的后续请求,Servlet/JSP 容器会先检查 JSP 页面是否被修改过。如果是,则该 JSP 页面会被重新转换、编译并执行。如果不是,则执行已经在内存中的 JSP Servlet。
这样一来,一个JSP页面的第一次调用的实际花费总比后来的花费多。
JSP页面可以包含模板数据和语法元素(如:'<%'元素表示Java代码块的开始)。除语法元素之外的一切都是模板数据。模板数据会原样发送给浏览器。例如,JSP页面中的HTML标记和文字都是模板数据。
在 Tomcat 中,welcome.jsp 页面在第一次请求时被转换成名为 welcome_jsp 的 Servlet。你可以在 Tomcat 工作目录下的子目录中找到生成的 Servlet,该 Servlet 继承自 org.apache.jasper.
runtime.HttpJspBase,这是一个抽象类,它继承自 javax.servlet.http.HttpServlet 并实现了 javax.
servlet.jsp.HttpJspPage。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" %>
<%@ page import="java.util.Date" %>
<%@ page import="java.text.DateFormat" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Date</title>
</head>
<body>
<%
DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.LONG);
out.println(dateFormat.format(new Date()));
%>
</body>
</html>
三、 注释
JSP支持两种不同的注释格式:
- JSP注释。该注释记录页面中做了什么,不会被发送到浏览器。以"<%--"开始,以"--%>"结束
- HTML/XHTML注释。这些注释不会被容器处理,会原样发送到浏览器。
四、 隐式对象
Servlet 容器会传递几个对象给它运行的 Servlet。例如,可以通过 Servlet 的 service 方法获取 HttpServletRequest 和 HttpServletResponse 对象。在 JSP 中,可以通过隐式对象来访问上述对象。
pageContext 提供了上下文信息,可以用于获取和设置属性(getAttribute, setAttribute)。属性值可被存储在4个范围之一:页面(JSP),请求(ServletRequest),会话(HttpSession),应用程序(ServletContext)。
public void setAttribute(String name, Object value); // page scope
public Object getAttribute(String name); // page scope
public void setAttribute(String name, Object value, int scope);
public Object getAttribute(String name, int scope);
out 引用了一个 javax.servlet.jsp.JspWriter 对象,这类似于你在调用 HttpServletResponse 的 getWriter 方法时得到 java.io.PrintWriter。可以通过调用它的 print 方法将消息发送到浏览器。
五、 指令
指令指示 JSP 转换器如何把 JSP 页面转换为 Servlet。
page
<%@ page attribute1="value1" attribute2="value2" ... %>
attributes :
- import:定义本页面中被导入的 java 类型。类型间可用','分隔。
- session:值为 True,本页面加入会话管理;值为 False 则相反。默认值为True,访问该页面时,若当前不存在javax.servlet.http.HttpSession实例,则会创建一个。
- buffer:以 kB 为单位,定义隐式对象 out 的缓冲大小。必须以 kB 后缀结尾。默认大小为8kB或更大(取决于JSP容器)。该值可以为 none,这意味着没有缓冲,所有数据将直接写入PrintWriter。
- autoFlush:默认值为 True。若值为True,则当输出缓冲满时会自写入输出流。而值为 False,则仅当调用隐式对象的flush方法时,才会写入输出流。因此,若缓冲溢出,则会抛出异常。
- isThreadSafe:定义该页面的线程安全级别。不推荐使用。
- info:指定生成的 Servlet 类的 getServletlnfo 方法的返回值。
- errorPage:定义当出错时用来处理错误的页面。
- isErrorPage:标识本页是一个错误处理页面。
- contentType:定义本页面隐式对象 response 的内容类型,默认是 "text/html"。
- pageEncoding:定义本页面的字符编码,默认是"ISO-8859-1"。
- isELIgnored:配置是否忽略 EL(Expression Language) 表达式。
- language:定义本页面的脚本语言类型,默认是 Java,这在JSP2.2中是唯一的合法值。
- extends:定义JSP实现类要继承的父类。较少使用,仅在非常特殊理由下使用。
- deferredSyntaxAllowedAsLiteral:定义是否解析字符串中出现"#{"符号,默认是False。"{#"是一个表达式语言的起始符号,因而很重要。
- trimDirectiveWhitespaces:定义是否不输出多余的空格/空行,默认是False。
大部分 page 指令可以出现在页面的任何位置,但当 contentType 或 pageEncoding 属性时,必须出现在 Java 代码发送任何内容之前。
page 指令也可以出现多次,但出现多次的指令属性必须具有相同的值,import 属性除外,多个包含 import 属性的 page 指令的结果是累加的。
include
include 指令将其他文件中的内容包含到当前JSP页面。
<%@ include file="url" %>
taglib
taglib 指令引入一个自定义标签集合的定义,包括库路径、自定义标签。
<%@ taglib uri="uri" prefix="prefixOfTag" %>
六、 脚本元素
脚本程序是 java 代码块,以"<%"符号开始,以"%>"符号结束。
Today is
<%
out. print(Calendar.getInstance().getTime());
%>
表达式会被JSP容器执行,并使用隐式对象 out 的打印方法输出结果。表达式以
"<%="开始,并由"%>"结束。表达式无需分号结尾。
Today is <%= Calendar.getInstance().getTime() %>
声明以"<%!"开始,以"%>"结束,声明页面中使用的变量和方法。
<%!
public String getTodaysDate() { return new Date().toString(); }
%>
<!DOCTYPE html>
<html>
<head><title>Declarations</title></head>
<body>
Today is <%= getTodaysDate() %>
</body>
</html>
在 JSP 页面中,一个声明可以出现在任何地方,并且一个页面可以有多个声明。
可以使用声明来重写 JSP 页面,实现类的 init 和 destroy 方法。通过声明 jsplnit 方法,来重写 init 方法。通过声明 jspDestroy 方法,来重写 destory 方法。
注意:尽量不要在 JSP 页面中编写 Java 代码。除非应用程序只包含一个或两个简单的 JSP 页面,并且永远不会增长;否则,你应该采用模型2,它规定 JSP 页面仅用于显示 Java 对象中的值。
七、 动作
动作是第三种类型的语法元素,它们被转换成 Java 代码来执行操作,如访问一个 Java 对象或调用方法。
useBean
useBean将创建一个关联 Java 对象的脚本变量。这是早期分离表示层和业务逻辑的努力之一。随着其他技术的发展,如自定义标签和表达语言,现在很少使用useBean方式。
setProperty 和 getProperty
setProperty 动作可对一个 Java 对象设置属性,而 getProperty 则会输出 Java 对象的一个属性。
include
include 动作用来动态地引入另一个资源。可以引入另一个 JSP 页面,也可以引入一个 Servlet 或一个静态的 HTML 页面。
<! DOCTYPE html>
<html><head>
<title>Include action</title>
</head>
<body>
<jsp:include page="menu.jsp">
<jsp:param name="text" value="How are you?"/>
</jsp:include>
</body></html>
对于 include 指令,资源引入发生在页面转换时,即当 JSP 容器把页面转换为生成的 Servlet 时。而 include 动作,资源引入发生在请求页面时。因此,使用 include 动作是可以传递参数的,而 include 指令不支持。
forward
forward 动作把当前页面转向到其他资源。
<jsp:forward page="login.jsp">
<jsp:param name="text" value="Please login"/>
</jsp:forward>
param
用于传递参数。可以通过 request.getParameter(String name) 取出参数值。
plugin
用于指定插件。
八、 错误处理
page 指令的 isErrorPage 属性标志一个 JSP 页面是否为错误页面。
page 指令的 errorPage 属性指向错误处理页面。
<%-- errorHandler.jsp --%>
<%@ page isErrorPage="true" %>
<! DOCTYPE html><html>
<head><title>Error</title></head>
<body>
An error has occurred.<br/>
Error message:
<%
out.print1n(exception. toString());
%>
</body></html>
<%@ page errorPage="errorHandler.jsp"%>
Deliberately throw an exception
<%
Integer. parseInt("Throw me");
%>
参考资料:《Spring MVC 学习指南》 Paul Deck 著
Java Web 学习(2) —— JSP的更多相关文章
- java web学习笔记-jsp篇
1.java web简介 1.1静态页面与动态页面 表现形式 所需技术 静态网页 网页内容固定,不会更新 html,css 动态网页 网页内容由程序动态显示,自动更新 html,css,DB,ja ...
- java web 学习笔记 - JSP标签编程
1.JSP标签编程简介 标签编程在开发中并不常见,主要是为了更好的理解struts等框架的标签而打基础,完善相关知识体系. 标签编程分为: 一个继承自TagSupport的标签类,一个在WEB-INF ...
- java web 学习笔记 jsp内置对象
jsp2 表达式语言的内置对象 使用方式${object.attributename} 或者${object["attributename"]} pageContext pageS ...
- Java Web学习笔记--JSP for循环
JSP for循环 <%@ page language="java" contentType="text/html; charset=UTF-8" %&g ...
- java web 学习笔记 - jsp用的文件上传组件 SmartUpload
---恢复内容开始--- 1. SmartUpload 此控件在jsp中被广泛的使用,而FileUpload控件主要是用在框架中 2. 如果想要使用,需要在tomcat的lib目录中,将SmartUp ...
- Java Web学习笔记之---JSP
Java Web学习笔记之---JSP (一)JSP常用语法 (1)HTML注释 <!--所要注释的内容 --> 在客户端显示一个注释. (2)隐藏注释 <%--所要注释的内容--% ...
- Java Web 学习路线
实际上,如果时间安排合理的话,大概需要六个月左右,有些基础好,自学能力强的朋友,甚至在四个月左右就开始找工作了.大三的时候,我萌生了放弃本专业的念头,断断续续学 Java Web 累计一年半左右,总算 ...
- Java web 学习之旅
java web学习之旅 来公司十天了,感觉已经慢慢地融入了这个环境中,几个学长人都很好,都是在他们帮助下,我才能比较顺利的开始了学习java web的旅途. 来这里学习的第一个阶段是做一个简单的用户 ...
- [原创]java WEB学习笔记66:Struts2 学习之路--Struts的CRUD操作( 查看 / 删除/ 添加) 使用 paramsPrepareParamsStack 重构代码 ,PrepareInterceptor拦截器,paramsPrepareParamsStack 拦截器栈
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
随机推荐
- 获取本机的IP地址
/// <summary> /// 获取本机IP地址 /// </summary> /// <returns>本机IP地址</returns> publ ...
- 我应该怎么学习SAP?
越来越多的人关注本公众号,在后台留言问我怎么进入SAP行业,应该怎么学习SAP,大部分都是外行想入行SAP的朋友.作为过来人,这些问题我也曾经问过别人,也走过不少弯路.但现在轮到别人问我了,为了让初学 ...
- CMake指南
版权申明: 本文原创首发于以下网站,您可以自由转载,但必须加入完整的版权声明 博客园:https://www.cnblogs.com/MogooStudio/ csdn博客:https://blog. ...
- Git 自救指南
Git 虽然因其分布式管理方式,不完全依赖网络,良好的分支策略,容易部署等优点,已经成为最受欢迎的源代码管理方式.但是一分耕耘一分收获,如果想更好地掌握 git,需要付出大量的学习成本.即使在各种 G ...
- python创建多维字典方法
python不直接创建多维字典,需要逐层判断不存在创建,存在追加: 例如: 不能直接 dictName['key1']['key2']['key3']['key4']['key5'] = ['123' ...
- 《HTTPS权威指南》读书笔记——SSL/TLS协议
记录协议(record protocol) 负责在传输连接上交换所有底层信息 每一条记录以短标头开始,标头包含记录内容的类型.协议版本和长度 握手协议(handshake protocol) 整个过程 ...
- Educational Codeforces Round 77 (Rated for Div. 2)
A: 尽可能平均然后剩下的平摊 #include <bits/stdc++.h> using namespace std; typedef long long ll; const int ...
- Django中的sql注入
Django中防止SQL注入的方法 方案一总是使用Django自带的数据库API.它会根据你所使用的数据库服务器(例如PostSQL或者MySQL)的转换规则,自动转义特殊的SQL参数.这被运用到了整 ...
- Java之字符编码和字符集
什么是字符编码 计算机中储存的信息都是用二进制数表示的,而我们在屏幕上看到的数字.英文.标点符号.汉字等字符是二进制数转换之后的结果.按照某种规则,将字符存储到计算机中,称为编码 .反之,将存储在计算 ...
- 使用原生代码实现一个Events模块,可以实现自定义事件的订阅、触发、移除功能
function Events() { // 放置所有添加的 监听事件 this._events = {} } Events.prototype = { on: function (name, fn, ...