一、JSP基础
概述:JSP是一个用于解决servlet程序难于输出静态HTML标签困难而诞生的,它巧妙的结合了servlet程序可编程的优点和静态文件可简便而大量输出静态标签的优点与一体。因此JSP中的组成元素有HTML、Java脚本、标签指令
本质:JSP本质就是servlet程序;它的转换过程如下: 第一次访问JSP--->JSP引擎(其实就是servlet)检查和编译该JSP页面---->编译为.java源程序和.class的文件并创建对应的servlet实例--->调用其_jspService(其实就是service)方法来响应。
源码分析:JSP编译成的.java源程序是继承HttpJspBase抽象类并且覆写了HttpJspBase里的jspInit和jspDestory方法;同时HttpJspBase抽象类又继承了HttpServlet和实现了HttpJspPage接口,并且覆写了HttpServlet里定义的servlet的生命周期方法并在这三个生命周期方法上添加了final的修饰符,同时HttpJspBase还实现了HttpJspPage的父接口里定义的jspInit和jspDestory这两个方法,其覆盖方法为jspInit和_jspInit、jspDestory和_jspDestory;其中注意的是在jsp编译成的源码里只是覆写了jspInit和jspDestory这两个,而剩下的两个是给JSP引擎使用的;同时JSP编译成的源码还覆写了HttpJspPage里定义的_jspService方法。还有注意的一点是:HttpJspBase里的方法调用,即HttpJspBase覆写的servlet生命周期方法里分别对应调用了jspInit、_jspInit这些方法,但在service中只调用了_jspService方法;因此JSP由JSP引擎编译后成servlet程序后之后它的响应是由servlet引擎来调用其_jspService方法响应的。
注意:对于JSP编译成的servlet源程序中JSP的九大内置对象只在_jspService方法内部有效而在JSP的声明里则不能使用九大内置对象
二、转发和包含与重定向 1、转发
1.1、ServletContext.getRequestDispatcher().forward(request,response); 这种方法的转发与常见的request.getRequestDispatcher().forward(request,response)并无本质区别。
1.2、pageContext.forward();这种方式的转发,其中的相对路径如果不是以“/”开头那么就是相当于当前访问的URL,以“/”开头就是web应用的根路径 <jsp:forward page="">JSP动态标签的动态转发带编译为源码后本质就是pageContext.forward这条语句。所以这两者无本质区别,但要注意动态标签的转发之后的比如模板元素或者其他脚本语言都不会再执行了因为在这条动态标签生成的源码后多了一条return语句。
转发注意:1.1的转发要求调用程序往servlet引擎缓存写的内容没有真的传送到浏览器,如果在转发之前传到了浏览器那么就会报错,如果没有传送到就可以调用转发,转发后会清空缓存里调用者程序写的内容,而调用之后如果还继续往缓存里写,那么这些内容也都会被视为无效。
1.2的转发要注意的是,调用程序往JSP内置对象out里的缓存里写的内容,在调用了转发后会被清空,但调用了转发后继续往out对象缓存写的内容是视为有效的
2、包含
2.1、ServletContext.getRequestDispatcher().include(); 与request.getRequestDispatcher().include()、pageContext.include()、<jsp:include page="">;这四个方法本质没区别,都属于动态包含 <%@include file="">而JSP的指令包含属于静态包含,指的是在JSP引擎编译JSP为servlet时把两个源程序合而为一,所以对于在被包含的JSP中声明的指令属性中除了pageEncoding和import可以不一样外其他的指令的属性值必须一样否则会报错。同时如果引入的是静态资源,那么被引入的资源的输出位置是看这个指令在调用程序里的位置
2.2、转发和包含特别注意:转发时调用程序可以设置响应头信息但设置的响应实体都无效,而被调用者,可以设置响应头但;而包含时调用者可以设置响应头与响应实体内容,但被调用者只能设置响应实体内容,设置的响应头无效
3、重定向 重定向本质上是两次不同的请求,而对于重定向时,调用者程序如果往servelt引擎里写了内容那么但只要未传送到浏览器就可以调用重定向,否则就会报错,而写入缓存里的内容也会被清空,而调用之后如果还往缓存里写的内容那么也会被视为无效。在这里关于重定向与转发的区别就不写了。
4、JSP的内置对象out的缓存
4.1、out、print与out、write的区别就是,如果输出的是null的字符串,前者会输出“null”的字符串而后者会包空指针异常。
4.2、而对于out对象它的输出首先是输出到out对象的缓存,如果out的缓存里有内容那么在以下三种情况会调用response.getWriter()方法把缓存的内容加载进servlet引擎的缓存里。 *JSP页面结束 *关闭了out对象的缓存 *out对象的缓存满了