1、JSP
JSP全称是Java Server Pages,它和servle技术一样,都是SUN公司定义的一种用于开发动态web资源的技术。
JSP这门技术的最大的特点在于,写jsp就像在写html,但它相比html而言,html只能为用户提供静态数据,而Jsp技术允许在页面中嵌套java代码,为用户提供动态数据。
JSP这门技术的最大的特点在于,写jsp就像在写html,但它相比html而言,html只能为用户提供静态数据,而Jsp技术允许在页面中嵌套java代码,为用户提供动态数据。
(1)、Web服务器是如何调用并执行一个jsp页面的?
服务器在执行jsp时,会将其翻译成一个servlet。在work文件夹的相应目录下。然后利用servlet的原理进行工作,首次访问创建servlet,然后init->service。
(2)、Jsp页面中的html排版标签是如何被发送到客户端的?
创建的相应的servlet文件中,会通过out.write方法将标签进行输出给浏览器
(3)、Jsp页面中的java代码服务器是如何执行的?
创建的相应的servlet文件中,java代码会原封不动的移植过来进行执行。
(4)、Web服务器在调用jsp时,会给jsp提供一些什么java对象?
request、response、session、application(Contex)、config、out(JspWriter)、page(this)、PageContext
八大隐式对象,exception第九大需要进行配置
虽然jsp能代替servlet,但是不要jsp处理请求。servlet处理请求,jsp显示。
2、JSP的最佳实践
不管是JSP还是Servlet,虽然都可以用于开发动态web资源。但由于这2门技术各自的特点,在长期的软件实践中,人们逐渐把servlet作为web应用中的控制器组件来使用,而把JSP技术作为数据显示模板来使用。其原因为,程序的数据通常要美化后再输出:
- 让jsp既用java代码产生动态数据,又做美化会导致页面难以维护。
- 让servlet既产生数据,又在里面嵌套html代码美化数据,同样也会导致程序可读性差,难以维护。
- 因此最好的办法就是根据这两门技术的特点,让它们各自负责各的,servlet只负责响应请求产生数据,并把数据通过转发技术带给jsp,数据的显示jsp来做。
3、JSP的语法
(1)、JSP模版元素
JSP页面中的HTML内容称之为JSP模版元素。
(2)、JSP脚本表达式
可以用out,也可以用脚本表达式, 专门用于输出数据。
JSP脚本表达式(expression)用于将程序数据输出到客户端
语法:<%= 变量或表达式 %>
举例:当前时间:<%= new java.util.Date() %>
语法:<%= 变量或表达式 %>
举例:当前时间:<%= new java.util.Date() %>
不能有分号
(3)、JSP脚本片断
jsp中的java代码就会被翻译到servlet中,这样就会容易理解以下几个方面:
<%
多行java代码
%>
每条执行语句后面都
要有分号
在一个JSP页面中可以有多个脚本片断,在两个或多个脚本片断之间可以嵌入文本、HTML标记和其他JSP元素。
举例:
多个脚本片断中的代码可以相互访问,犹如将所有的代码放在一对<%%>之中的情况。如:out.println(x);
举例:
<%
int x = 10;
out.println(x);
%>
<p>这是JSP页面文本</p>
<%
int y = 20;
out.println(y);
%>
多个脚本片断中的代码可以相互访问,犹如将所有的代码放在一对<%%>之中的情况。如:out.println(x);
单个脚本片断中的Java语句可以是不完整的,但是,多个脚本片断组合后的结果必须是完整的Java语句,例如:
<%
for (int i=1; i<5; i++)
{
%>
<H1>www.it315.org</H1>
<%
}
%>
正规的jsp中是不准出现java代码的,利用自
定义标签
跟
el表达式
来实现。
取数据
(4)、JSP声明
JSP页面中编写的所有代码,默认会翻译到servlet的service方法中, 而Jsp声明中的java代码被翻译到_jspService方法的外面。语法:
<%!
java代码
%>
所以,JSP声明可用于定义JSP页面转换成的Servlet程序的 静态代码块、成员变量和方法 。
多个静态代码块、变量和函数可以定义在一个JSP声明中,也可以分别单独定义在多个JSP声明中。
JSP隐式对象的作用范围仅限于Servlet的_jspService方法,所以在JSP声明中不能使用这些 隐式对象(request、response、session、application(Contex)、config、out(JspWriter)、page(this)、PageContext)。
<%!
java代码
%>
所以,JSP声明可用于定义JSP页面转换成的Servlet程序的 静态代码块、成员变量和方法 。
多个静态代码块、变量和函数可以定义在一个JSP声明中,也可以分别单独定义在多个JSP声明中。
JSP隐式对象的作用范围仅限于Servlet的_jspService方法,所以在JSP声明中不能使用这些 隐式对象(request、response、session、application(Contex)、config、out(JspWriter)、page(this)、PageContext)。
示例:覆盖翻译后的servlet方法:
<%!
static
{
System.out.println("loading Servlet!");
}
private int globalVar = 0;
public void jspInit()
{
System.out.println("initializing jsp!");
}
%>
<%!
public void jspDestroy()
{
System.out.println("destroying jsp!");
}
%>
会显示前两个(按顺序)。 web停掉会执行destroy。
(5)、JSP注释
JSP注释的格式:
<%-- 注释信息 --%>
<%-- 注释信息 --%>
html注释也是可以的,但是不提倡,会发送给html页面的。而JSP注释则不会发送。
(6)、JSP指令
将jsp翻译成servlet的程序叫做JSP引擎。
JSP指令(directive)是为JSP引擎而设计的,它们并不直接产生任何可见输出,而只是告诉引擎如何处理JSP页面中的其余部分。在JSP 2.0规范中共定义了三个指令:
- page指令
- Include指令
- taglib指令(用于导入自定义标签)
page指令:
JSP指令的基本语法格式:
<%@ 指令 属性名="值" %>
举例:<%@ page contentType="text/html;charset=gb2312"%>
<%@ 指令 属性名="值" %>
举例:<%@ 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指令最好是放在整个JSP页面的起始位置。作用的都是整个JSP页面。
<%@ page
[ language="java" ]
[ extends="package.class" ]
[ import="{package.class | package.*}, ..." ]
[ session="true | false" ]
[ buffer="none | 8kb | sizekb" ]
[ autoFlush="true | false" ]
[ isThreadSafe="true | false" ]
[ info="text" ]
[ errorPage="relative_url" ]
[ isErrorPage="true | false" ]
[ contentType="mimeType [ ;charset=characterSet ]" | "text/html ; charset=ISO-8859-1" ]
[ pageEncoding="characterSet | ISO-8859-1" ]
[ isELIgnored="true | false" ]
%>
(a)、[ import="{package.class | package.*}, ..." ]
JSP 引擎自动导入下面的包:
java.lang.*
javax.servlet.*
javax.servlet.jsp.*
javax.servlet.http.*
JSP 引擎自动导入下面的包:
java.lang.*
javax.servlet.*
javax.servlet.jsp.*
javax.servlet.http.*
可以在一条page指令的import属性中引入多个类或包,其中的每个包或类之间使用逗号分隔:
上面的语句也可以改写为使用多条page指令的import属性来分别引入各个包或类:
(b)、 [ errorPage =" relative_url " ]
<%@ page import="java.util.Date,java.sql.*,java.io.*"%>
上面的语句也可以改写为使用多条page指令的import属性来分别引入各个包或类:
<%@ page import="java.util.Date"%>
<%@ page import="java.sql.*"%>
<%@ page import="java.io.*"%>
(b)、 [ errorPage =" relative_url " ]
errorPage属性的设置值必须使用相对路径,如果以“/”开头,表示相对于当前
WEB应用程序的根目录(WEBROOT)(注意不是站点根目录),否则,表示相对于当前页面。
可以在web.xml文件中使用<error-page>元素为整个WEB应用程序设置错误处理页面,其中的<exception-type>子元素指定异常类的完全限定名,<location>元素指定以“/”开头的错误处理页面的路径。(数据量要超过1024K,否则只能通过修改浏览器高级的友好开关)
如果设置了某个JSP页面的errorPage属性,那么在web.xml文件中设置的错误处理将不对该页面起作用。
可以在web.xml文件中使用<error-page>元素为整个WEB应用程序设置错误处理页面,其中的<exception-type>子元素指定异常类的完全限定名,<location>元素指定以“/”开头的错误处理页面的路径。(数据量要超过1024K,否则只能通过修改浏览器高级的友好开关)
如果设置了某个JSP页面的errorPage属性,那么在web.xml文件中设置的错误处理将不对该页面起作用。
错误处理页面:
[ isErrorPage="true | false" ]
设置为true可以获得隐式exception对象
exception.getcase
(c)、EL表达式:false不要忽略EL表达式
[ isELIgnored="true | false" ]
include指令:
include指令用于引入其它JSP页面,如果使用include指令引入了其它JSP页面,那么JSP引擎将把这两个JSP翻译成一个servlet。所以include指令引入通常也称之为
静态引入。
request.getRequestDispatcher("/public/head.jsp").include(request,response); 这种方式为动态引入。
性能不如静态引入
语法:
<%@ include file="relativeURL"%>
其中的file属性用于指定被引入文件的路径。路径以“/”开头,表示代表当前web应用。
<%@ include file="relativeURL"%>
其中的file属性用于指定被引入文件的路径。路径以“/”开头,表示代表当前web应用。
细节:
- 被引入的文件必须遵循JSP语法。
- 被引入的文件可以使用任意的扩展名,即使其扩展名是html,JSP引擎也会按照处理jsp页面的方式处理它里面的内容,为了见明知意,JSP规范建议使用.jspf(JSP fragments)作为静态引入文件的扩展名。
- 由于使用include指令将会涉及到2个JSP页面,并会把2个JSP翻译成一个servlet,所以这2个JSP页面的指令不能冲突(除了pageEncoding和导包除外)。
被引入的文件中不要带有全局标签(head,foot)
taglib指令:
Taglib指令用于在JSP页面中导入标签库,讲自定义标签技术时讲。
4、JSP的中文乱码问题
通过page指令的contentType属性说明JSP源文件的字符集编码
page指令的pageEncoding属性说明JSP源文件的字符集编码
page指令的pageEncoding属性说明JSP源文件的字符集编码
不同的编码方式采用不同的特征码,也可以通过特征码来得出文件的存储方式:UTF-8:EF BB BF三个特征码,一个字符占一个字节 UNICO:FF FE两个特征码,一个字符占两个字节
IO流读字节。
5、JSP的运行原理和九大隐式对象
每个JSP 页面在第一次被访问时,WEB容器都会把请求交给JSP引擎(即一个Java程序)去处理。JSP引擎先将JSP翻译成一个_jspServlet(实质上也是一个servlet) ,然后按照servlet的调用方式进行调用。由于JSP第一次访问时会翻译成servlet,所以第一次访问通常会比较慢,但第二次访问,JSP引擎如果发现JSP没有变化,就不再翻译,而是直接调用,所以程序的执行效率不会受到影响。
JSP引擎在调用JSP对应的_jspServlet时,会传递或创建9个与web开发相关的对象供_jspServlet使用。JSP技术的设计者为便于开发人员在编写JSP页面时获得这些web对象的引用,特意定义了9个相应的变量,开发人员在JSP页面中通过这些变量就可以快速获得这9大对象的引用。
这9个对象分别是哪些,以及作用也是笔试经常考察的知识点。
- Request
- Response
- Session
- Application servletContext
- Config servletConfig
- Page this
- Exception
- Out jspWriter
- pageContext
(1)、out隐式对象
out隐式对象用于向客户端发送文本数据。
out对象是通过调用pageContext对象的getOut方法返回的,其作用和用法与ServletResponse.getWriter方法返回的PrintWriter对象非常相似。
JSP页面中的out隐式对象的类型为JspWriter,JspWriter相当于一种带缓存功能的PrintWriter,设置JSP页面的 page指令的buffer属性可以调整它的缓存大小,甚至关闭它的缓存。
只有向out对象中写入了内容,且满足如下任何一个条件时,out对象才去调用ServletResponse.getWriter方法,并通过该方法返回的PrintWriter对象将out对象的缓冲区中的内容真正写入到Servlet引擎提供的缓冲区中:
- 设置page指令的buffer属性关闭了out对象的缓存功能
- out对象的缓冲区已满
- 整个JSP页面结束
示例:
<body>
<%
out.write("aaa");
response.getWriter().write("bbb");
%>
</body>
先写入了bbb,由于jsp页面结束了在写入了aaa
去掉模板的所有内容
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%@page import="java.io.FileInputStream"%><%@page import="java.io.OutputStream"%><%
String path = application.getRealPath("/1.jpg");
String filename = path.substring(path.lastIndexOf("\\")+1);
response.setHeader("content-disposition","attachment;filename=" + filename);
FileInputStream in = new FileInputStream(path);
int len = 0;
byte buffer[] = new byte[1024];
OutputStream sout = response.getOutputStream();
while((len=in.read(buffer))>0){
sout.write(buffer,0,len);
}
%>
(2)、pageContext对象 (JSP独有的对象)
pageContext对象是JSP技术中最重要的一个对象,它代表JSP页面的运行环境,- 这个对象不仅封装了对其它8大隐式对象的引用:用于自定义标签,传递数据
- 它自身还是一个域对象,可以用来保存数据;
- 这个对象还封装了web开发中经常涉及到的一些常用操作,例如引入和跳转其它资源、检索其它域对象中的属性等。
通过pageContext获得其他对象
- getException方法返回exception隐式对象
- getPage方法返回page隐式对象
- getRequest方法返回request隐式对象
- getResponse方法返回response隐式对象
- getServletConfig方法返回config隐式对象
- getServletContext方法返回application隐式对象
- getSession方法返回session隐式对象
- getOut方法返回out隐式对象
pageContext作为域对象 (作用范围整个页面)
pageContext对象的方法- 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)
- 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
引入和跳转到其他资源
PageContext类中定义了一个forward方法和两个include方法来分别简化和替代RequestDispatcher.forward方法和include方法。方法接收的资源如果以“/”开头, “/”代表当前web应用。
6、JSP标签
JSP标签也称之为Jsp Action(JSP动作)元素,它用于在Jsp页面中提供业务逻辑功能,避免在JSP页面中直接编写java代码,造成jsp页面难以维护。- <jsp:include>标签
- <jsp:forward>标签
- <jsp:param>标签
(1)、include标签
<jsp:include>标签用于把另外一个资源的输出内容插入进当前JSP页面的输出内容之中,这种在JSP页面执行时的引入方式称之为
动态引入。
语法:
<jsp:include page="relativeURL | <%=expression%>" flush="true|false" />
page属性用于指定被引入资源的相对路径,它也可以通过执行一个表达式来获得。
flush属性指定在插入其他资源的输出内容时,是否先将当前JSP页面的已输出的内容刷新到客户端。
语法:
<jsp:include page="relativeURL | <%=expression%>" flush="true|false" />
page属性用于指定被引入资源的相对路径,它也可以通过执行一个表达式来获得。
flush属性指定在插入其他资源的输出内容时,是否先将当前JSP页面的已输出的内容刷新到客户端。
<jsp:include>与include指令的比较
<jsp:include>标签是动态引入, <jsp:include>标签涉及到的2个JSP页面会被翻译成
2个servlet,这2个servlet的内容在执行时进行合并。
而include指令是静态引入,涉及到的2个JSP页面会被翻译成 一个servlet,其内容是在源文件级别进行合并。
不管是<jsp:include>标签,还是include指令,它们 都会把两个JSP页面内容合并输出,所以这两个页面 不要出现重复的HTML全局架构标签,否则输出给客户端的内容将会是一个格式混乱的HTML文档。
而include指令是静态引入,涉及到的2个JSP页面会被翻译成 一个servlet,其内容是在源文件级别进行合并。
不管是<jsp:include>标签,还是include指令,它们 都会把两个JSP页面内容合并输出,所以这两个页面 不要出现重复的HTML全局架构标签,否则输出给客户端的内容将会是一个格式混乱的HTML文档。
(2)、forward标签
<jsp:forward>标签用于把请求转发给另外一个资源。语法:
<jsp:forward page="relativeURL | <%=expression%>" />
page属性用于指定请求转发到的资源的相对路径,它也可以通过执行一个表达式来获得。
(3)、param标签
当使用<jsp:include>和<jsp:forward>标签引入或将请求转发给其它资源时,可以使用<jsp:param>标签向这个资源传递参数。语法1:
<jsp:include page="relativeURL | <%=expression%>">
<jsp:param name="parameterName" value="parameterValue|<%= expression %>" />
</jsp:include>
语法2:
<jsp:forward page="relativeURL | <%=expression%>">
<jsp:param name="parameterName" value="parameterValue|<%= expression %>" />
</jsp:include>
<jsp:param>标签的name属性用于指定参数名,value属性用于指定参数值。在<jsp:include>和<jsp:forward>标签中可以使用多个<jsp:param>标签来传递多个参数。
<jsp:include page="/public/head.jsp"/>
<br/> 这是页面内容 <br/>
<jsp:include page="/public/foot.jsp"/>
<%
String url = "/public/head.jsp";
%>
<jsp:include page="<%=url %>"/>
<jsp:forward page="/1.jsp">
<jsp:param name="xxx" value="yyyy"/>
</jsp:forward>
7、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>
8、JSP页面中的错误
(1)、JSP语法格式问题
JSP页面中的JSP语法格式有问题,导致其不能被翻译成Servlet源文件,JSP引擎将提示这类错误发生在JSP页面中的位置(行和列)以及相关信息。
unable to compile class for jsp;
(2)、java语法问题
JSP页面中的JSP语法格式没有问题,但被翻译成的Servlet源文件中出现了Java语法问题,导致JSP页面翻译成的Servlet源文件不能通过编译,JSP引擎也将提示这类错误发生在JSP页面中的位置(行和列)以及相关信息。(3)、运行异常
JSP页面翻译成的Servlet程序在运行时出现异常,这与普通Java程序的运行时错误完全一样,Java虚拟机将提示错误发生在Servlet源文件中的位置(行和列)以及相关信息。
javaexception
时好时坏,快速刷新没有问题,肯定jsp出问题
9、JSP重点
到此为止,web开发接触到了4个域对象,这4个域对象是学习web的重点,也是笔试经常考察的知识点- pageContext(称之为page域,页面范围)
- request(称之为request域,请求范围)
- session(称之为session域,会话范围)
- servletContext(称之为application域,应用程序范围)
什么是域?
这4个对象的生命周期?
哪种情况下用哪种域对象。
1、request:如果客户向服务器发请求,产生的数据,用户看完就没用了,像这样的数据就存在request域,像新闻数据,属于用户看完就没用的
2、session:如果客户向服务器发请求,产生的数据,用户用完了等一会儿还有用,像这样的数据就存在session域中,像购物数据,用户需要看到自己购物信息,并且等一会儿,还要用这个购物数据结帐
3、servletContext:如果客户向服务器发请求,产生的数据,用户用完了,还要给其它用户用,像这样的数据就存在servletContext域中,像聊天室,聊天记录
2、session:如果客户向服务器发请求,产生的数据,用户用完了等一会儿还有用,像这样的数据就存在session域中,像购物数据,用户需要看到自己购物信息,并且等一会儿,还要用这个购物数据结帐
3、servletContext:如果客户向服务器发请求,产生的数据,用户用完了,还要给其它用户用,像这样的数据就存在servletContext域中,像聊天室,聊天记录
能用小容器不用大容器