一、Jsp
1、Jsp (Java Server Pages),它和 Servlet 技术一样,都是 SUN 公司定义的一种用于开发动态 Web 资源的技术。
Jsp 技术允许在页面中嵌套 Java 代码,并且允许开发人员在页面中获取 request、response 等 Web 常用对象。实现服务器与浏览器之间的交互,所以 Jsp 也是一种动态 Web 资源的开发技术。
2、Jsp 的执行过程。当用户第一次访问一个 Jsp 页面时,服务器会将 Jsp 的内容翻译为一个 Servlet,然后将字节码和源文件存放在服务器 work 目录的主机目录下。服务器通过 Servlet 将 Jsp 页面的内容通过 out 对象输出到客户机的浏览器中。当 Jsp 内嵌了 Java 代码时,服务器会原封不动的将 Java 代码交给 Servlet 执行。如果服务器中已经存在了编译好的 Servlet 字节码,那么用户再访问 Jsp 的时候,其实不是访问的 Jsp 而是直接访问 Servlet。
3、Jsp 的九大隐式对象:
(1) request:封装了用户提交信息 ---(用户请求期 Request)
(2) pageContext:封装了其它所有对象。--- (页面执行期 Page)
(3) session:在用户首次访问时获得。是一个 Jsp 的内置域对象。--- (整个会话期 Session)
(4) application:服务器启动时创建的 ServletContext 对象。也就是一个 Web 应用。--- (整个应用运行期 Application)
(5) out:向客户机输出数据的流对象。用于各种数据的输出。内部是一个 JspWriter,默认缓存大小为 8kb。--- (页面执行期 Page)
(6) config:配置 Servlet ,该对象用于存取servlet实例的初始化参数。。--- (页面执行期 Page)
(7) page:指当前 Jsp 页面,等同于 Servlet 中的 this 关键字,表示从该页面产生的一个servlet实例。。--- (页面执行期 Page)
(8) response:对客户的请求做出动态响应,向客户发送数据。 --- (页面执行期 Page)
(9) exception:异常。。--- (页面执行期 Page)
4、Jsp 最佳实践
Servlet 只负责响应请求产生数据,并把数据通过转发技术带给 Jsp,Jsp 只用作数据的显示。
二、Jsp 语法
1、Jsp 模版元素。Jsp 页面中的 HTML 内容称为 Jsp 模版元素。Jsp 模版元素定义了网页的基本骨架,即定义了页面的结构和外观。
2、Jsp 脚本表达式。<%= 表达式%>。当前时间:<%= new Date().toLocalString()%>。
3、Jsp 脚本片段。用于在页面内加入多行 Java 代码。 <% Java 代码 %>
4、Jsp 声明。Jsp 页面中所编写的代码会默认的翻译到 Servlet 中的 service 中,而 Jsp 声明中的 Java 代码被翻译到 _jspService 方法的外面。即定义了 Servlet 的全局变量、方法、静态代码块。由于 Jsp 的隐式对象是在 service 方法中生命的,所以在 Jsp 声明中定义的成员不能访问。
5、Jsp 指令。Jsp 指令是为服务器而设计的,它们并不直接产生任何可见输出,而是告诉服务器如何处理 Jsp 页面中的其余部分。
<%@ 指令 属性名="值" %> 例如:<%@ contextType="text/html charset=gb2312" %>
(1) page 指令。page 指令用于定义 Jsp 页面的各种属性,无论 page 指令出现在 Jsp 页面中的什么位置,它作用的都是 Jsp 页面。
<%@ page
[language="java"] //用于指定当前页面内嵌的是 Java 代码。
[extends="package.class"] //用于指定翻译后的 Servlet 继承哪个类。
[import="java.io.*"] //用于导入 Java 代码所需要的包,所个之间用" , "号分割,也可以分开写。
[session="true | false"] //指定翻译后的 Servlet 是否自动创建 Session 对象,默认值为 true。我们常常要置为 false。因为 Session 有效期较长,所以我们不需要 Session 对象的时候就不要创建,以减轻服务器压力。
[buffer="none | 8kb | sizekb"] //用于指定 out 对象的传冲区大小,也就是 JspWriter 的缓冲区大小,默认为 8kb。
[autoFlush="true | false"] //指定上面 buffer 缓冲区是否自动刷新,默认为 true。
[isThreadSage="true | false"] //默认值为 true,采用继承 SingleThreadModel 标记接口的方式实现。
[info="text"] //指定当前页面信息为文本。
[errorPage="error.index"] //指定错误信息页面,其中指定 URL 的目录必须使用相对路径,如果以 "/" 开头,那么表示相对于当前 Web 应用程序的根目录,不是站点的根目录。设置错误页面的另一种方式:在 web.xml 配置文件中,<web-app> 元素下加入子元素:
<exception-type>异常类型全限定名</excetion-type> 或者 <error-code>错误号</error-code>
<location>错误信息显示页面</location> 注意,错误页面的大小必须超过 1kb 才能正常显示。如果在 web.xml 文件中配置了错误信息页面,那么在 Jsp 中设置的 errorPage 指令将不起作用。传递错误信息就是用到了 exception 隐式对象。
[isErrorPage="true | false"] //指定这个页面是否为错里处理页面,如果是的话最好改为 true。
[contentType] //指定页面的 MIME 类型,说明页面是什么页面,页面采用什么编码方式。其中 charset 用于说明 Jsp 源文件字符编码集。是指发送给客户机的时候采用什么编码方式。
[pageEncoding="characterset | ISO-8859-1"] // 用于指定当前 Jsp 文件的编码方式,是文件本身的编码方式。
[isELIgnored="true | false"] // 指定页面是否忽略 EL 表达式,默认值为 false。
(2) include 指令:用于引入其它 Jsp 页面,如果使用 include 指令引入了其它 Jsp 页面,那么 Jsp 服务器将把这两个 Jsp 翻译成一个 Servlet,所以 include 指令引入通常称为静态引入。
<%@ include file="url" %> 其中如果 URL 的路径以 "/" 开头则表示当前的 Web 应用。Jsp 的规范中建议被引入的页面后缀名是 .jspf。由于静态引入是将两个 Jsp 编译成一个 Servlet 来打给客户机的,所以两个被引入的 Jsp 页面指令不能冲突。并且被引入的 Jsp 页面不要出现 Jsp 模版元素,也就是 HTML 的标签,否则 HTML 的标签内容会被打给客户机,造成代码不优雅。
动态引入:利用 request 对象的 getRequestDispatcher("URL").include(request,response); 方法。原理:是在 Servlet 运行时动态的将其它的 Servlet 加入到页面中,要多次向服务器请求,所以效率要低。我们在开发中要尽量使用静态引入的方法。静态引入是将多个 Servlet 集合成一个 Servlet 后再打给客户机。
三、Jsp 乱码问题分析
Jsp 乱码出现的原因:我们在编辑 Jsp 的时候,由于编辑器不同,所保存的 Jsp 源文件指定的编码方式也不同,如果我们用记事本编辑 Jsp ,那么 Jsp 的源文件编码方式为 gb2312 保存到了我们硬盘上。当用户访问服务器的时候,服务器通过硬盘上编辑好的 Jsp 文件翻译为 Servlet ,由于服务器不是中国人设计的,所以经常采用 ISO-8859-1 的编码方式,由于 ISO-8859-1 码表中没有对应的中文字符,所以不能正常编译数据,然后编译成的 .class 文件也是乱码,也就导致了发给客户机的数据也不能正常显示。
解决方案:既然我们找到了乱码的原因,那么我们应当控制服务器将 Jsp 源文件编译成 Servlet 时采用可以编译中文的码表。所以编辑源文件的编码方式应该与服务器编译 Jsp 的编码方式相一致。那么我们可以在 page 指令中增加 pageEncoding="utf-8" ,告诉服务器以 utf-8 的码表编码。由于最新的服务器会自动的将设置好的编码方式以响应头的形式写给客户机,所以就没有必要再加入 contentType="text/html;charset=utf-8" 这个 page 指令,但是为了兼容老的服务器,谨慎起见加入也可以。
四、Out 隐式对象
1、out 隐式对象用于向客户端发送文本数据。out 对象是通过调用 pageContext 对象的 getOut() 方法返回的,其作用和用法与 ServletResponse.getWriter() 方法返回的 PrintWriter 对象非常相似。
2、Jsp 页面中的 out 隐式对象的类型为 JspWriter,JspWriter 相当于一种带缓存功能的 PriterWriter,设置 Jsp 页面的 page 指令的 buffer 属性可以调整它的缓存大小,甚至关闭缓存。
3、当向 out 中写入了数据,那么该数据什么时候才会写给客户机的浏览器?
(1) 设置 page 指令的 buffer 属性关闭了 out 对象的缓存功能,那么一旦写入到了 out 对象中,out 就直接送给 printWriter 对象的缓冲区中。
(2) out 对象的缓冲区已满。
(3) 整个 Jsp 页面结束。
4、out 缓冲区工作原理:
将数据写入 out 中,并不是直接写给客户机,先写在了 out 的缓冲区中。同样,在 Servlet 的 PrintWriter 中写数据是写在 PrintWriter 的缓冲区中,当 out 的缓冲区满了,或者 Jsp 页面执行完毕时,服务器会将 out 缓冲区中的数据写到 PrintWriter 的缓冲区中,然后在写给客户机。所以如果既在 PrintWriter 中写数据,又在 out 中写数据,那么无论写入的先后顺序,最后打给客户机时,总是 PrintWriter 的数据先送给客户机。out 对象就是对 PrintWriter 的再一次缓冲。我们在写 Jsp 页面的时候尽量使用 out 对象输出数据。
五、Jsp 实现文件下载
- <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%><%@page import="java.io.FileInputStream"%><%@page import="java.io.OutputStream"%>
- <%@page import="java.net.URLEncoder"%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><%
- String path = application.getRealPath("download/图片.jpg");
- String filename = path.substring(path.lastIndexOf("\\") + 1);
- FileInputStream in = new FileInputStream(path);
- int len = 0;
- byte[] b = new byte[1024];
- OutputStream os = response.getOutputStream();
- response.setHeader("content-disposition","attachment;filename=" + URLEncoder.encode(filename,"utf-8"));
- while((len = in.read(b)) != -1){
- os.write(b, 0 ,len);
- }
- in.close();
- %>
六、pageContext 对象
pageContext 对象是 Jsp 技术中最重要的一个对象,它代表 Jsp 页面的运行环境。pageContext 不仅封装了其它 8 大隐式对象,它自身还是一个域对象,可以用来保存数据。并且这个对象还封装了 Web 开发中经常设计到的一些常用操作,例如引入和跳转其它资源,检索其它域对象中的属性等。
1、pageContext 封装其它8大对象的意义。用于自定义标签,在真实的软件工程项目里面,Jsp 页面是严禁出现一行 Java 代码的,如果要使用 Java 代码,我们必须使用自定义标签把它封装掉,然后用一个 Java 类对逻辑数据进行处理,那么其它 Java 类是没有该请求的数据的,我们必须传 request 过去,这样是很麻烦的。我们可以使用 pageContext 域来获取其它对象,也就是传递 pageContext 一个对象过去就可以了。
2、pageContext 对象的生命周期和作用范围。pageContext 的生命周期与页面是相应的,页面被创建后 pageContext 也就被创建,页面关闭,pageContext 也就随之摧毁。它的作用范围也是在当前的页面范围之内。
3、pageContext 操作其他域。getAttribuate(String name) 方法有一个重载,第一个形式是默认从当前的 pageContext 中检索数据,第二个 getAttribuate(String name,int SCOPE ) 是从指定的域里面获取数据。
pageContext 域提供了统一操作四个域的入口,以前如果要取出数据,必须指定从哪里取,现在可以统一的从 pageContext 中取出数据。其中 PAGE_SCOPE 常量表示的是 pageContext 域,而不是当前页面 page。
* pageContext.findAttribuate(""); 首先从 pageContext 域中查找,如果找不到,就从 request 域中找,找不到,就从 session 域中找,找不到就从 application 中找,如果还是找不到就返回 null。page域--->request--->session--->application。
pageContext 还可以做转发、包含等操作。(forward、include)
七、Jsp 简单标签
Jsp 标签也称为 Jas Action(Jsp 动作元素),它用于在 Jsp 页面中提供业务逻辑功能,避免在 Jsp 页面中直接编写 Java 代码,造成 Jsp 页面难以维护。
1、SUN 公司提供的 Jsp 常用标签
<jsp:include>
<jsp:forward>
<jsp:param>
2、映射 Jsp。因为 Jsp 本身就是一个 Servlet,所以我们可以使用映射 Servlet 的方式把 Jsp 映射到另外一个地址上去。
<servlet>
<servlet-name>servletDemo</servlet-name>
<jsp-file>/index.jsp</jsp-file>
</servlet>
<servlet-mapping>
<servlet-name>servletDemo</servlet-name>
<url-pattern>/xxx.jsp</url-pattern>
<serlvet-mapping>
八、Jsp 操作 JavaBean 标签
Jsp 技术提供了三个关于 JavaBean 标签元素
1、<jsp:useBean>:用于在 Jsp 页面中查找或实例化一个 JavaBean 组件。
2、<jsp:setProperty>:用于在 Jsp 页面中设置一个 JavaBean 组件的属性。
3、<jsp:getProperty>:用于在 Jsp 页面中获取一个 JavaBean 组件的属性。
<jsp:useBean>:在指定的域范围内查找制定名称的 JavaBean 对象,如果存在则直接返回该对象的引用,如果不存在则实例化一个新的 JavaBean 对象并将它以指定的名称存储到指定的域范围中。
注意:在用 setProperty 为 JavaBean 赋值的时候,JavaBean 标签只支持8种基本数据类型的自动类型转换,其它类型不能自动转换。
九、Jsp 开发模式
Jsp 有两种开发模式,一种是 Jsp + JavaBean 模式,一种是 Jsp + Servlet +JavaBean 模式。Jsp + JavaBean 适合开发业务逻辑不复杂的 Web 应用程序,这种模式下,JavaBean 用于封装业务数据,Jsp 负责处理用户请求又显示数据。Jsp + Servlet +JavaBean (MVC Model/View/Control)模式适合开发复杂的 Web 应用,在这种模式下, Servlet 负责处理用户请求,Jsp 负责数据显示,JavaBean 负责封装数据。
简单的 Jsp + JavaBean 模式案例
- <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
- <html>
- <head>
- <title>计算器</title>
- </head>
- <jsp:useBean id="calc" class="bean.Calculator" scope="session"/>
- <jsp:setProperty property="*" name="calc" />
- <%
- calc.operate();
- %>
- <body>
- <hr width="30%">
- <div align="center">
- 计算结果是:<jsp:getProperty property="firstNum" name="calc"/>
- <jsp:getProperty property="operator" name="calc"/>
- <jsp:getProperty property="secondNum" name="calc"/>=
- <jsp:getProperty property="result" name="calc"/>
- </div>
- <hr width="30%"><br><br>
- <form action="/Day_07_Jsp_EL/calculator.jsp" method="post">
- <table width="30%" border="1" align="center">
- <tr>
- <td colspan="2">简单的计算器</td>
- </tr>
- <tr>
- <td>第一个参数:</td>
- <td><input type="text" name="firstNum"/></td>
- </tr>
- <tr>
- <td>运算符:</td>
- <td>
- <select name="operator">
- <option value="+">+</option>
- <option value="-">-</option>
- <option value="*">*</option>
- <option value="/">/</option>
- </select>
- </td>
- </tr>
- <tr>
- <td>第二个参数:</td>
- <td><input type="text" name="secondNum"/></td>
- </tr>
- <tr>
- <td colspan="2">
- <input type="submit" value="提交"/>
- </td>
- </tr>
- </table>
- </form>
- </body>
- </html>
十、EL 表达式
EL (Expression Language)。主要作用:获取数据、执行运算、获取 Web 开发常用对象。
1、获取数据:EL 表达式主要用于替换掉 Jsp 页面中的脚本表达式,以从各种类型的 Web 域中检索 Java 对象、获取数据
(1) 获取域里面的数据:${data},取出域里面关键字为 data 的数据
服务器会将 ${data} 翻译为:pageContext.findAttribuate("data");
找不到不会返回 null,而是返回 ""
(2) 获取 JavaBean 中的数据:${bean.property}
(3) 获取 JavaBean 中维护的其它的 JavaBean中的数据:${bean1.bean2.property}
(4) 获取集合中的数据:${list[1].property},如果 "." 搞不出数据的话就换成[]
(5) 获取 Map 中的数据:${map.key.property},有可能取不出,比如 key 为数字,那么就加 '',${map['key'].property}
2、执行运算:利用 EL 表达式可以在 Jsp 页面中执行一些基本的关系运算、逻辑运算和算数运算。
(1) ${user==null}
${username=='aaa' && password='bbb'}
${1+1}
(2) empty 运算符:检查集合是否为 null 或 "空"
(3) 二元运算符:${gender=='male'?checked:''}
3、获取 Web 开发常用对象:EL 表达式定义了 11 个隐式对象
语法:${对象名称}
(1)、${pageContext} 获取到 pageContext 对象,它不是在四个域里面去找,而是先在自己定义的对象中找,如果找到了就取出来。
${pageContext.request.contextPath} 获取针对当前工程的相对路径,应用于 URL 上,因为我们不应该将 URL 写死在代码中。
(2)、${pageScope} 得到的是 page 域 (pageContext) 中保存数据的 Map集合。也就是指定在 page 域中查找。
(3-5)、${requestScope}、${sessionScope}、${applicationScope} 和上面的 pageScope 一样,都是在特定的域中检索数据。
(4)、${param} 获取存在 request 中请求参数的 Map,常用在数据回显上。
(5)、${paramValues} 获取存在 request 中请求参数名相同的值的 String[] 数组。
(8)、${header} 获取 HTTP 请求头的 Map 对象。
(9)、${headValues} 获取 HTTP 请求头值的 Map 对象
(10)、${cookie} 获取所有 cookie 的 Map 对象
(11)、${initParam} 获取保存所有 Web 应用初始化参数的 Map 对象
4、EL 函数:
EL 表达式语法允许开发人员开发自定义函数,以调用 Java 类的方法。在 EL 表达式中调用的只能是 Java 类的静态方法,并且这个方法必须在以恶搞 TLD 文件中描述。例如现在在 cn 包中有一个 Demo 的 类,类中有一个静态方法 public static String join(String s1, String s1),然后写一个 TLD 描述文件,在 <taglib> 元素中加入子元素 :
<function>
<name>dk</name>
<function-class>cn.Demo</function-class>
<function-signature>public static java.lang.String join(java.lang.String s1, java.lang.String s1)</function-signature>
</function>
<uri>/driverking</uri>
然后在 Jsp 页面中加入标签库声明:
<%@ taglib uri="/driverking" prefix="TLD文件名前缀" %>
然后就可以在 Jsp 页面中使用名为 dk 的标签了:
${dk:join("aaa","bbb")}
十一、EL 函数库
在页面显示的时候我们常常对字符串进行处理,SUN 公司提供了一个 EL 函数库方便我们的操作。
1、fn:toLowerCase
2、fn:toUpperCase
3、fn:trim (删除字符串的首尾空格)
4、fn:length (返回集合、数组的大小,或返回字符串的字符个数)
5、fn:split 以指定字符串分割字符串
6、fn:join 以字符串为分隔符将一个字符串数组以分隔符的形式连接起来,如果第二个参数为空字符串,那么是将字符串整个连起来。
7、fn:indexof 返回指定字符串在一个字符串中首次出现的位置。如果没有包含则返回 -1,如果第二个参数为空字符串那么返回 0
8、fn:contains
9、fn:replace
10、fn:sunstring (与 java 不同,截取字符串不是按长度来截取,是按从开始到结束的索引号来截取)
11、fn:substringAfter (截取并返回一个字符串中的指定字符串第一次出现之后的字符串)
9、fn:containsIgnoreCase
10、fn:startsWith 检测一个字符串是否以指定字符串开始
----------------------------------------------------------------------------------------------------------------------
转载地址:http://blog.csdn.net/earbao/article/details/36417165