简介:JSP全称是Java Server Pages,它和Servlet技术一样,都是SUN公司定义的一种用于开发动态web资源的技术。写JSP虽然就像是在写html,但Jsp技术允许在页面中嵌套java代码,并且允许开发人员 在页面中获取request、response等web开发常用对象,实现与浏览器的交互,所以jsp也是一种动态web资源的开发技术。
JSP最佳实践
不管是JSP还是Servlet,虽然都可以用于开发动态web资源。但由于这2门技术各自的特点,在长期 的软件实践中,人们逐渐把servlet作为web应用中的控制器组件来使用,而把JSP技术作为数据显示 模板来使用。其原因为,程序的数据通常要美化后再输出:
1、让jsp既用java代码产生动态数据,又做美化会导致页面难以维护。
2、让servlet既产生数据,又在里面嵌套html代码美化数据,同样也会导致程序可读性差,难以维护。
3、因此最好的办法就是根据这两门技术的特点,让它们各自负责各的,servlet只负责响应请求产 生数据,并把数据通过转发技术带给jsp,数据的显示jsp来做。
JSP语法
JSP模版元素 :JSP页面中的HTML内容称之为JSP模版元素。
JSP模版元素定义了网页的基本骨架,即定义了页面的结构和外观。
JSP表达式 :JSP脚本表达式(expression)用于将程序数据输出到客户端
语法:<%= 变量或表达式 %>
JSP引擎在翻译脚本表达式时,会将程序数据转成字符串,然后在相应位置用out.print(…) 将数据输给客户端。
注:JSP脚本表达式中的变量或表达式后面不能有分号(;)。
例:当前时间值是:
<%
Date date = new Date();
String time = date.toLocaleString();
%>
<%=date.toLocaleString()%>
翻译成的servlet中就为out.print(date.toLocaleString())
JSP脚本片断 :JSP脚本片断(scriptlet)用于在JSP页面中编写多行Java代码。
语法: <%
多行java代码
%>
注意:JSP脚本片断中只能出现java代码,不能出现其它模板元素, JSP引擎在翻译JSP页面中,会将JSP脚本片断中的Java代码将被原封不动地放到Servlet的_jspService方法中。 JSP脚本片断中 的Java代码必须严格遵循Java语法。
在一个JSP页面中可以有多个脚本片断,在两个或多个脚本片断之间可以嵌入文本、HTML标记和其他 JSP元素。多个脚本片断中的代码可以相互访问,犹如将所有的代码放在一对<%%>之中的情况。单个脚本片断中的Java语句可以是不完整的,但是,多个脚本片断组合后的结果必须是完整的Java语句。
例: <%
for (int i=1;i<5; i++) {
%>
<H1>www.it315.org</H1>
<%
}
%>
JSP声明:JSP页面中编写的所有代码,默认会翻译到servlet的service方法中, 而Jsp声明中的java代码被翻译到_jspService方法的外面。
语法: <%!
java代码
%>
所以,JSP声明可用于定义JSP页面转换成的Servlet程序的静态代码块、成员变量和方法 。 多个静态代码块、变量和函数可以定义在一个JSP声明中,也可以分别单独定义在多个JSP声明中。JSP隐式对象的作用范围仅限于Servlet的_jspService方法,所以在JSP声明中不能使用这些隐式对象。
JSP注释
格式:<%-- 注释信息 --%>
注:JSP引擎在将JSP页面翻译成Servlet程序时,忽略JSP页面中被注释的内容。而html中的<!— 注释-->则打给浏览器,因此在JSP中多用JSP注释。
JSP指令:为JSP引擎而设计的,它们并不直接产生任何可见输出,而只是告诉引擎如何处理JSP页面 中的其余部分。在JSP 2.0规范中共定义了三个指令: 1、page指令2、Include指令3、taglib 指令。
语法:<%@ 指令 属性名="值" %>
例:<%@ page contentType="text/html;charset=gb2312"%> 告诉浏览器以gb2312解码
如果一个指令有多个属性,这多个属性可以写在一个指令中,也可以分开写。
<%@ pagecontentType="text/html;charset=gb2312"%>
<%@ pageimport="java.util.Date"%>
相当于:<%@ page contentType="text/html;charset=gb2312"import="java.util.Date"%>
1、page指令
page指令用于定义JSP页面的各种属性,无论page指令出现在JSP页面中的什么地方,它作用的都是整个JSP页面,为了保持程序的可读性和遵循良好的编程习惯,page指令最好是放在整个JSP页面的起始位置。
JSP 2.0规范中定义的page指令的完整语法:
<%@ page
[language="java" ] 页面中嵌入的是java代码
[extends="package.class" ] 翻译后的servlet继承谁(最好不要去改)
[ import="{package.class| package.*}, ..." ] 运行时导入哪些包。写在一起时,导入多个包用逗号 隔开。注:JSP自动回导入java.lang、javax.servlet、 javax.servlet.jsp、javax.servlet.http包
[ session="true| false" ] 是否用创建session,默认值为true
[buffer="none | 8kb | sizekb" ] 是否用缓冲,默认有8K的缓冲
[autoFlush="true | false" ] 是否自动刷新,默认为true
[isThreadSafe="true | false" ] 线程是否安全
[info="text" ] 通过info带信息
[ errorPage="relative_url"] 指定JSP的错误处理页面,必须用相对路径,以“/”开头,代表WEB应用的根目录。
也可以在web.xml文件中使用<error-page>元素为整个WEB应用程序设置错误处理页面,其中的<exception-type>子元素指定异常 类的完全限定名,<location>元素指定以“/”开头的错误处理页面的路径。如果设置了某个JSP页面的errorPage属性,那么在web.xml文件中设置的错误处理将不对该页面起作用。
[ isErrorPage="true| false" ] 当前页面是否是错误处理页面,默认为false。如果为true,在翻译 成servlet时,会将错误的异常对象传递给你。这个也是九大隐式对象之一exception。
[ contentType="mimeType[ ;charset=characterSet ]" | "text/html ; charset=ISO-8859-1" ] 告诉JSP页面类型与 编码
[ pageEncoding="characterSet| ISO-8859-1" ] 指定编码表
[ isELIgnored="true| false" ] 是否忽略EL表达式,默认为false
%>
JSP乱码问题(tomcat5.0会出现)
解决方法:只设置[ pageEncoding="码表" ]就行了。
2、Include指令
include指令用于引入其它JSP页面,如果使用include指令引入了其它JSP页面,那么JSP引擎将把这两个JSP翻译成一个servlet。所以include指令引入通常也称之为静态引入。
语法:<%@ includefile="relativeURL"%>
其中的file属性用于指定被引入文件的路径。路径以“/”开头,表示代表当前web应用。
注:1、被引入的文件必须遵循JSP语法。
2、被引入的文件可以使用任意的扩展名,即使其扩展名是html,JSP引擎也会按照处理jsp页 面的方式处理它里面的内容,为了见明知意,JSP规范建议使用.jspf(JSP fragments)作为静态引入文件的扩展名。
3、由于使用include指令将会涉及到2个JSP页面,并会把2个JSP翻译成一个servlet,所以 这2个JSP页面的指令不能冲突(除了pageEncoding和导包除外)。
4、动态包含为运行时包含与之区别为翻译成多个servlet,而静态包含为编译时包含,只翻译 成一个servlet。
JSP内置对象
JSP引擎在调用JSP对应的_jspServlet时,会传递或创建9个与web开发相关的对象供_jspServlet使用。JSP技术的设计者为便于开发人员在编写JSP页面时获得这些web对象的引用,特意定义了9个相应的变量,开发人员在JSP页面中通过这些变量就可以快速获得这9大对象的引用。
运行原理:每个JSP 页面在第一次被访问时,WEB容器都会把请求交给JSP引擎(即一个Java程序)去处理。JSP引擎先将JSP翻译成一个_jspServlet(实质上也是一个servlet) ,然后按照servlet 的调用方式进行调用。由于JSP第一次访问时会翻译成servlet,所以第一次访问通常会比较 慢,但第二次访问,JSP引擎如果发现JSP没有变化,就不再翻译,而是直接调用,所以程 序的执行效率不会受到影响。
九大隐式对象:1、request 2、response 3、config 4、application 5、exception 6、Session 7、page 8、out 9、pageContext
out隐式对象
用于向客户端发送文本数据。
out对象是通过调用pageContext对象的getOut方法返回的,其作用和用法与ServletResponse.getWriter方法返回的PrintWriter对象非常相似。JSP页面中的out隐式对象的类型为JspWriter,JspWriter相当于一种带缓存功能的PrintWriter,设置JSP页面的page指令的buffer属性可以调整它的缓存大小,甚至关闭它的缓存。只有向out对象中写入了内容,且满足如下任何一个条件时,out对象才去调用ServletResponse.getWriter方法,并通过该方法返回的PrintWriter对象将out对象的缓冲区中的内容真正写入到Servlet引擎提供的缓冲区中:1、设置page指令的buffer属性关闭了out对象的缓存功能2、out对象的缓冲区已满3、整个JSP页面结束。
例:用JSP实现文件下载。
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%@page import="java.io.FileInputStream"%><%
//application就是servletcontext
String path = application.getRealPath("/download/1.jpg");
String filename = path.substring(path.lastIndexOf("\\")+1);
response.setHeader("content-disposition","attachment;filename=" + filename);
FileInputStream in = new FileInputStream(path);
byte buffer[] = new byte[1024];
int len = 0;
while((len=in.read(buffer))>0){
//由于是字节数据,必须用字节流,为了避免两个流冲突,必须将所有的标签删除,这样服务器就不 调用getwriter了,注意空格也删除。
response.getOutputStream().write(buffer,0,len);
}
in.close();
%>
pageContext对象
pageContext对象是JSP技术中最重要的一个对象,它代表JSP页面的运行环境.这个对象不仅封装了对其它8大隐式对象的引用,它自身还是一个域对象,可以用来保存数据和操作其他三个域,并且这个对象还封装了web开发中经常涉及到的一些常用操作,例如引入和跳转其它资源、检索其它域对象中的属性等。
获得八大隐式对象的方法(主要用于自定义标签)
1、getException方法返回exception隐式对象
2、getPage方法返回page隐式对象
3、getRequest方法返回request隐式对象
4、getResponse方法返回response隐式对象
5、getServletConfig方法返回config隐式对象
6、getServletContext方法返回application隐式对象
7、getSession方法返回session隐式对象
8、getOut方法返回out隐式对象
注:pageContext域的作用范围为整个JSP页面
pageContext对象除了自己的setAttribute与getAttribute方法向自己的域中存储数据,还封装了访 问其它域的setAttribute与getAttribute方法操作如下:
<%
//向session域中存数据,pageContext中每个域都有代表的字段
pageContext.setAttribute("data","abc",PageContext.SESSION_SCOPE);
%>
<%=pageContext.getAttribute("data",PageContext.SESSION_SCOPE)%>
pageContext对象还提供了一个重要的方法findAttribute,用于在四个域中查找数据,先查 pageContext,再查request,再查session再查application,没有再返回空。
PageContext类中定义了一个forward方法和两个include方法来分别简化和替代 RequestDispatcher.forward方法和include方法。
注:方法接收的资源如果以“/”开头,“/”代表当前web应用。
JSP标签
定义:JSP标签也称之为Jsp Action(JSP动作)元素,它用于在Jsp页面中提供业务逻辑功能,避免在JSP页面中直接编写java代码,造成jsp页面难以维护。
<jsp:include>标签:用于把另外一个资源的输出内容插入进当前JSP页面的输出内容之中,这种在JSP页面执行时的引入方式称之为动态引入。
语法:<jsp:includepage="relativeURL"/>
<jsp:forward>标签:用于把请求转发给另外一个资源。语法:<jsp:forward page="relativeURL "/>
<jsp:param>标签:当使用<jsp:include>和<jsp:forward>标签引入或将请求转发给其它资源时,可以使用 <jsp:param>标签向这个资源传递参数。
语法:<jsp:param name="parameterName" value="parameterValue" />
JSP的映射
在web.xml文件中输入
<servlet>
<servlet-name>SimpleJspServlet</servlet-name>
<jsp-file>/jsp/simple.jsp</jsp-file>
<load-on-startup>1</load-on-startup >
</servlet>
……
<servlet-mapping>
<servlet-name>SimpleJspServlet</servlet-name>
<url-pattern>/xxx/yyy.html</url-pattern>
</servlet-mapping>
重点回顾
四个域对象的生命周期
pageContext(称之为page域) 页面范围
request(称之为request域) 请求范围
session(称之为session域) 会话范围
servletContext(称之为application域) 应用程序范围