一、什么是JSP
2、为什么JSP技术也是一种动态web资源的开发技术?
答:因为JSP技术允许在页面中嵌套java代码,以产生动态数据,并且web服务器在执行jsp时,web服务器会传递web开发相关的对象给jsp,jsp通过这些对象,可以与浏览器进行交互,所以jsp当然也是一种动态web资源开发技术.
3、强调一个概念:对现在的用户而言,认为通过浏览器看到的东西都是网页.但我们程序员心里要清楚,开一个浏览器访问网页,这些网页有可能是一个html页面(即静态web资源),也有可能是一个动态web资源(即servlet或jsp程序输出的).
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" import="java.util.Date"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <% Date date = new Date(); %> <%= date %> </body> </html>
package org.apache.jsp.jsp; import java.io.IOException; import java.util.Date; import java.util.Map; import javax.el.ExpressionFactory; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.jsp.JspApplicationContext; import javax.servlet.jsp.JspFactory; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.PageContext; import javax.servlet.jsp.SkipPageException; import org.apache.jasper.runtime.HttpJspBase; import org.apache.jasper.runtime.InstanceManagerFactory; import org.apache.jasper.runtime.JspSourceDependent; import org.apache.tomcat.InstanceManager; public final class NewFile_jsp extends HttpJspBase implements JspSourceDependent { private static final JspFactory _jspxFactory = JspFactory.getDefaultFactory(); private static Map<String, Long> _jspx_dependants; private ExpressionFactory _el_expressionfactory; private InstanceManager _jsp_instancemanager; public Map<String, Long> getDependants() { return _jspx_dependants; } public void _jspInit() { this._el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory(); this._jsp_instancemanager = InstanceManagerFactory.getInstanceManager(getServletConfig()); } public void _jspDestroy() { } public void _jspService(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { JspWriter out = null; JspWriter _jspx_out = null; PageContext _jspx_page_context = null; try { response.setContentType("text/html; charset=UTF-8"); PageContext pageContext = _jspxFactory.getPageContext(this, request, response, null, true, 8192, true); _jspx_page_context = pageContext; pageContext.getServletContext(); pageContext.getServletConfig(); pageContext.getSession(); out = pageContext.getOut(); _jspx_out = out; out.write(" "); out.write("<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> "); out.write("<html> "); out.write("<head> "); out.write("<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> "); out.write("<title>Insert title here</title> "); out.write("</head> "); out.write("<body> "); out.write(" "); Date date = new Date(); out.write(13); out.write(10); out.write(9); out.print(date); out.write(" "); out.write("</body> "); out.write("</html>"); } catch (Throwable t) { if (!(t instanceof SkipPageException)) { out = _jspx_out; if ((out != null) && (out.getBufferSize() != 0)) try { out.clearBuffer(); } catch (IOException localIOException) { } if (_jspx_page_context != null) _jspx_page_context.handlePageException(t); else throw new ServletException(t); } } finally { _jspxFactory.releasePageContext(_jspx_page_context); } } }
二、JSP技术在开发中该怎么去用
三、JSP语法
1、JSP模版元素
语法:<%= 变量或表达式 %> 举例:当前时间:<%= new java.util.Date() %>
<%
多行java代码
%>
<% int x = 10; out.println(x); %> <p>这是JSP页面文本</p> <% int y = 20; out.println(y); %>
多个脚本片断中的代码可以相互访问,犹如将所有的代码放在一对<%%>之中的情况.如:out.println(x);
3>单个脚本片断中的Java语句可以是不完整的,但是,多个脚本片断组合后的结果必须是完整的Java语句,例:
<% for (int i=1; i<5; i++) { %> <H1>www.it315.org</H1> <% } %>
4、JSP声明,一般很少使用
<%!
java代码
%>
<%@ 指令 属性名="值" %> 举例:<%@ page contentType="text/html;charset=gb2312"%>
<%@ page contentType="text/html;charset=gb2312"%> <%@ page import="java.util.Date"%> 或 <%@ page contentType="text/html;charset=gb2312" import="java.util.Date"%>
Page指令
<%@ page [ language="java" ] //页面嵌套的语言 [ extends="package.class" ] //jsp servlet继承的包,一般不要修改 [ import="{package.class | package.*}, ..." ] //jsp Servlet引入的包 [ session="true | false" ] //是否引入session,ture的话,jsp引擎会传给jsp Session 对象 [ buffer="none | 8kb | sizekb" ] //关于缓存 [ autoFlush="true | false" ] //关于缓存 [ isThreadSafe="true | false" ] //ture的话JSP servlet 会继承SingleThreadModel [ info="text" ] [ errorPage="relative_url" ] //JSP出错的错误页面(必须采用相对路径),web.xml也可设置 [ isErrorPage="true | false" ] //true的话,JSP引擎会传给jsp错误的Excepiotn 对象 [ contentType="mimeType [ ;charset=characterSet ]" | "text/html ; charset=utf-8" ]//页面类型 [ pageEncoding="characterSet | ISO-8859-1" ] //页面采用的编码,只写这句就可解决JSP乱码问题 [ isELIgnored="true | false" ] //是否支持使用el表达式 %>
include指令
include指令用于引入其它JSP页面,如果使用include指令引入了其它JSP页面,那么JSP引擎将把这两个JSP翻译成一个servlet.所以include指令引入通常也称之为静态引入.
语法:
<%@ include file="relativeURL"%>
其中的file属性用于指定被引入文件的相对路径. file属性的设置值必须使用相对路径,如果以“/”开头,表示相对于当前WEB应用程序的根目录(注意不是站点根目录),否则,表示相对于当前文件.
细节:
被引入的文件必须遵循JSP语法.(被引入的jsp文件不要有架构性的标签,可以有指令)
被引入的文件可以使用任意的扩展名,即使其扩展名是html,JSP引擎也会按照处理jsp页面的方式处理它里面的内容,为了见明知意,JSP规范建议使用.jspf(JSP fragments)作为静态引入文件的扩展名.
由于使用include指令将会涉及到2个JSP页面,并会把2个JSP翻译成一个servlet,所以这2个JSP页面的指令不能冲突(除了pageEncoding和导包除外).
taglib指令
用于引入标签库。
四、JSP运行原理和九大隐式对象
1、每个JSP 页面在第一次被访问时,WEB容器都会把请求交给JSP引擎(即一个Java程序)去处理.JSP引擎先将JSP翻译成一个_jspServlet(实质上也是一个servlet) ,然后按照servlet的调用方式进行调用.
2、由于JSP第一次访问时会翻译成servlet,所以第一次访问通常会比较慢,但第二次访问,JSP引擎如果发现JSP没有变化,就不再翻译,而是直接调用,所以程序的执行效率不会受到影响.
3、JSP引擎在调用JSP对应的_jspServlet时,会传递或创建9个与web开发相关的对象供_jspServlet使用.JSP技术的设计者为便于开发人员在编写JSP页面时获得这些web对象的引用,特意定义了9个相应的变量,开发人员在JSP页面中通过这些变量就可以快速获得这9大对象的引用.
4、JSP九大隐式对象与servlet的对应关系
request HttpServletRequest response HttpServletResponse session HttpSession application servletContext config servletConfig out JspWriter -----> PrintWriter exception page this pageContext
out隐式对象
1、out隐式对象用于向客户端发送文本数据.
2、out对象是通过调用pageContext对象的getOut方法返回的,其作用和用法与ServletResponse.getWriter方法返回的PrintWriter对象非常相似.
3、JSP页面中的out隐式对象的类型为JspWriter,JspWriter相当于一种带缓存功能的PrintWriter,设置JSP页面的page指令的buffer属性可以调整它的缓存大小,甚至关闭它的缓存.
4、只有向out对象中写入了内容,且满足如下任何一个条件时,out对象才去调用ServletResponse.getWriter方法,并通过该方法返回的PrintWriter对象将out对象的缓冲区中的内容真正写入到Servlet引擎提供的缓冲区中:
1>设置page指令的buffer属性关闭了out对象的缓存功能,2>out对象的缓冲区已满,3>整个JSP页面结束
5、out工作原理图,底层其实是调用response的writer回写给客户端的.
*开发的时候不用同时使用servlet中的Writer和Jsp中的out,否则可能打印到页面的内容会有先后问题,因为缓冲的原因.
pageContext对象
pageContext对象是JSP技术中最重要的一个对象,它代表JSP页面的运行环境,这个对象不仅封装了对其它8大隐式对象的引用,它自身还是一个域对象,可以用来保存数据.并且,这个对象还封装了web开发中经常涉及到的一些常用操作,例如引入和跳转其它资源、检索其它域对象中的属性等.
1、通过pageContext可以获得其它八大对象,它存在的意义是什么呢,因为我们可以直接在jsp中获得九大对象.它的意义在于统一管理入口,比如用在自定义标签中,我们只要传递这一个对象给标签解析器,标签就可获得其它所有对象而不需要传递所有的对象给标签,这应该是一种思想,很多地方有体现.
2、pageContext作为域对象(page域)
public void setAttribute(java.lang.String name,java.lang.Object value) public java.lang.Object getAttribute(java.lang.String name) public void removeAttribute(java.lang.String name)
3、pageContext对象中还封装了访问其它域的方法,同样的问题,我们可以直接获得相应域,为什么还要间接通过pageContext?同样的答案.
public java.lang.Object getAttribute(java.lang.String name,int scope) public void setAttribute(java.lang.String name, java.lang.Object value,int scope) public void removeAttribute(java.lang.String name,int scope)
上面方法会用到下面代表各个域的常量:
PageContext.APPLICATION_SCOPE
PageContext.SESSION_SCOPE
PageContext.REQUEST_SCOPE
PageContext.PAGE_SCOPE
4、findAttribute方法 (*重点,查找各个域中的属性),其实el表达式就是在各个域中查找.
5、web开发的四个域对象,重点,1>域的含义;2>生命周期;3>什么时候使用什么域
pageContext(称之为page域)
request(称之为request域)
session(称之为session域)
servletContext(称之为application域)
6、PageContext类中定义了一个forward方法和两个include方法来分别简化和替代RequestDispatcher.forward方法和include方法,传递给这些方法的资源路径都只能是相对路径,如果路径以“/”开头,表示相对于当前WEB应用程序的根目录,否则,表示相对于当前JSP所映射到的访问路径.这写方法基本不用,动态包含,用的少.而且后面有专门的标签来使用动态包含.
五、JSP标签
1、虽然我们希望JSP页面仅用作数据显示模块,不要嵌套任何java代码引入任何业务逻辑,但在实际开发中不引入一点业务逻辑是不可能的,但引入业务逻辑会导致页面出现难看java代码,怎么办?Sun公司允许用户开发自定义标签封装页面的java代码,以便jsp页面不出现一行java代码.当然sun公司在jsp页面中也内置了一些标签(这些标签叫做jsp标签),开发人员使用这些标签可以完成页面的一些常用业务逻辑.JSP标签也称之为Jsp Action(JSP动作)元素,它用于在JSP页面中提供业务逻辑功能.
2、JSP常用标签:<jsp:include>标签、<jsp:forward>标签 、<jsp:param>标签
3、<jsp:include>标签
语法:
<jsp:include page="relativeURL | <%=expression%>" flush="true|false" />
flush属性指定在插入其他资源的输出内容时,是否先将当前JSP页面的已输出的内容刷新到客户端.
4、<jsp:include>与include指令的比较
1><jsp:include>标签是动态引入, <jsp:include>标签涉及到的2个JSP页面会被翻译成2个servlet,这2个servlet的内容在执行时进行合并.
2>而include指令是静态引入,涉及到的2个JSP页面会被翻译成一个servlet,其内容是在源文件级别进行合并.
3>不管是<jsp:include>标签,还是include指令,它们都会把两个JSP页面内容合并输出,所以这两个页面不要出现重复的HTML全局架构标签,否则输出给客户端的内容将会是一个格式混乱的HTML文档
4、<jsp:forward>标签
<jsp:forward>标签用于把请求转发给另外一个资源.
语法:
<jsp:forward page="relativeURL | <%=expression%>" />
page属性用于指定请求转发到的资源的相对路径,它也可以通过执行一个表达式来获得.
使用场景:比如在首页中,在tomcat,web.xml中<welcome-file-list>标签中可以指定jsp页面,但是不能指定servlet,这时可以使用<jsp:forward>转发给一个servlet.<welcome-file-list>的作用:只要输域名,就可调到首页.
5、<jsp:param>标签,了解即可
当使用<jsp:include>和<jsp:forward>标签引入或将请求转发给其它资源时,可以使用<jsp:param>标签向这个资源传递参数.
6、映射JSP,例:其实和servlet一样,感觉用的不多,一般是通过servlet跳转到jsp,而不会直接访问jsp.
<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>