1. JSP语法
JSP语法主要包含以下几类:
JSP模板元素
JSP脚本表达式
JSP脚本片段
JSP声明
JSP注释
JSP指令
JSP标签
JSP内置对象
2. JSP模板元素
JSP页面中的HTML内容称之为JSP的模板元素。
JSP模板元素定义了网页的基本骨架,即定义了页面的结构和外观。
3. JSP脚本表达式
JSP脚本表达式用于将程序数据输出到客户端
语法:
例如:
JSP引擎在翻译脚本表达式时,会将程序数据转成字符串,然后在相应的位置用out.print()将数据输出给客户端,上面的的例子会翻译成out.print( new Date());。
JSP脚本表达式中的变量或者表达式后面不能有分号。
4. JSP脚本片段
JSP脚本片段用于在JSP页面中编写多行Java代码。
语法:
JSP脚本片段中只能出现Java代码,不能出现其他的模板元素,JSP引擎在翻译JSP页面时,会将JSP脚本片段的Java代码原封不动的放到翻译后的Servlet的_jspService方法中。
JSP脚本片段中的Java代码必须严格遵守Java语法。
在一个JSP页面中可以有多个脚本片段,在脚本片段之间可以嵌入文本、HTML标记和JSP元素。多个脚本片段中的代码可以相互访问,犹如将所有代码放在一对中,例如:
intx= 10;
out.print(x);%>
这是JSP页面文本
inty= 20;
out.print(y);
out.print("
");
out.print(x+y);//使用上一个脚本片段定义的变量x%>
单个脚本片段中的Java代码可以是不完整的,但是多个脚本片段组合的结果必须是完整的Java语句块,例如:
for(inti= 0; i< 5; i++) {%>
这个段标题输出5次
5. JSP声明
JSP页面中编写的所有代码,默认回翻译到Servlet的_jspService方法中,而JSP声明的Java代码会被翻译到_jspService方法的外面。
语法:
java代码%>
JSP声明可用于定义JSP页面转换成的Servlet的静态代码块、成员变量和方法。
多个静态代码块、变量和函数可以定义在一个JSP声明中,也可以分别单独定义在多个JSP声明中。
JSP隐式对象的作用范围仅限于Servlet的_jspService方法,所以在JSP声明中不能使用这些隐式对象。
JSP声明举例:
static {
System.out.println("loading Servlet");
}private intglobalVar= 0;publicvoid myFunction1() {
System.out.println("myFunction1");
}%>
System.out.println("myFunction2");
}%>
6. JSP注释
语法:
JSP引擎在将JSP页面翻译成Servlet时,会忽略JSP页面中被注释的内容。
HTML的注释,用此注释,注释内容会发送给浏览器,只是浏览器不识别。JSP的注释不会发送给浏览器,并且脚本代码只能用JSP注释(因为服务器不识别HTML注释)。
7. JSP指令
JSP指令是为JSP引擎(把JSP翻译成Servlet的程序)而设计的,它们并不直接产生任何可见的输出,而只是告诉引擎如何处理JSP页面的其余部分。在JSP2.0规范中共定义了3个指令:
page指令
include指令
taglib指令(自定义标签的时候再做说明)
7.1 JSP指令简介
JSP指令的基本语法格式:
举例:
如果一个指令有多个属性,这些属性可以卸载一个指令中,也可以分开写。
例如:
也可以写作:
7.2 page指令
page指令用于定义JSP页面的各种属性,无论page指令出现在JSP页面的什么地方,它的作用范围都是整个JSP页面,为了保持程序的可读性和良好的编程习惯,page指令最好是放在整个JSP页面的起始位置。
JSP 2.0规范中定义的page指令的常用属性:
language="java" JSP里面的代码语言extends="package.class" 翻译后的Servlet继承哪个类,一般不改import="package1.class, package2.class" JSP页面导入的Java类session="true |false" 值为true会在翻译后的Servlet中创建session对象,在JSP页面中可以直接使用。默认值为true。buffer="8kb | none | sizekb" 设置JSP页面的缓冲,默认8kbautoFlush="true | false" 设置JSP页面缓冲满了是否自动刷新,默认为true,自动刷新errorPage="relative_url" 指定JSP页面的错误处理页面isErrorPage="false | true" 设置当前JSP页面是否是错误页面,默认值为falsecontentType="mimeType;charset=characterSet" 设置JSP页面类型,用于显示pageEncoding="characterSet" 设置JSP页面编码格式isELIgnored="false | true" 设置是否忽略EL表达式,默认是false,不忽略
%>
7.2.1 import属性
JSP引擎会自动导入下面的包:
java.lang.*
javax.servlet.*
javax.servlet.jsp.*
javax.servlet.http.*
可以在一条page指令的import属性中引入多个类,其中每个类之间用逗号分隔:
或者写成多条page指令的import属性分别导入:
7.2.2 errorPage属性
指定JSP的错误处理页面,就是JSP挂了会跳转的页面。errorPage的属性值设置必须使用相对路径,如果以“/”开头,表示相对于当前web应用程序的根目录,否则,表示相对于当前页面。例如:
divisioninta= 1 / 0;%>
divisorError当访问division.jsp时,由于除数为0,会抛异常。当指定了errorPage后,会跳转到对应的错误页面。
如果项目中的JSP文件比较多,对每个JSP都配置errorPage,会比较麻烦。这种情况可以使用在web.xml中配置,包含三个元素:
--配置错误码
--配置错误类型
--配置出错时跳转的页面
上面除数为0的例子,在web.xml中可以这么配置:
java.lang.ArithmeticException
/WEB-INF/errors/divisorError.jsp
对错误码进行处理,例如,在web.xml中配置404错误码,如果页面找不到,跳转到指定页面:
404
/WEB-INF/errors/notFound.jsp
添加一个404对应的提示页面:
404如果某个JSP设置了errorPage属性,那么在web.xml中设置的将对该页面不起作用。可以通过此种方式对整个项目的JSP进行统一规划,对应特定的JSP页面进行微调。
7.2.3 isErrorPage属性
isErrorPage如果设置为true,则会在翻译后的Servlet中创建exception对象,可以在JSP页面中使用,用于输出异常信息等。
7.3 include指令
语法:
include是静态包含(编译时包含),它包含的所有JSP会统一翻译成一个Servlet。被包含的页面不要写html body页签,否则新的jsp页面格式会很混乱。
request.getRequestDispatcher("/xxx").include(request, response)是动态包含,会把包含的每一个JSP分别翻译成与之对应的Servlet。
开发中常用静态包含,所以尽量使用静态包含。
举例:
include指令,静态页面包含动态包含这是页尾
这是页头
分别访问body1.jsp、body2.jsp,在翻译后的Servlet目录可以看到,body1翻译后的_jspService函数直接将其他两个jsp页面也写入了。而body2翻译后的则没有,但是把header2.jsp foot2.jsp也翻译成了Servlet
body1.jsp使用静态包含,所有JSP翻译成一个Servlet:
body2.jsp使用动态包含,多个JSP翻译成多个Servlet:
8. JSP标签
8.1 JSP标签
JSP标签也称之为JSP Action(JSP动作)元素,它用于在JSP页面提供业务逻辑功能,避免在JSP页面直接编写Java代码。
8.2 JSP常用标签
标签用于把另外的一个资源的输出内容插入进当前的JSP页面的输出内容中。此种方式是动态包含。
标签用于把请求转发给另一个资源。
语法:
"flush="true|false"/>
" >
举例:
JSP标签importjavax.servlet.ServletException;importjavax.servlet.annotation.WebServlet;importjavax.servlet.http.HttpServlet;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;importjava.io.IOException;importjava.io.PrintWriter;
@WebServlet(name= "LoginServlet")public class LoginServlet extendsHttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throwsServletException, IOException {
System.out.println("post method");
}protected void doGet(HttpServletRequest request, HttpServletResponse response) throwsServletException, IOException {
System.out.println("get method");
response.setContentType("text/html;charset=utf-8");
PrintWriter out=response.getWriter();
out.println("username = " + request.getParameter("username"));
out.println("
");
out.println("password = " + request.getParameter("password"));
}
}
运行结果:
9. JSP九大隐式对象
9.1 JSP运行原理
每个JSP页面在第一次被访问时,Web容器斗湖吧请求交给JSP引擎(一个Java程序)去处理,JSP引擎先将JSP翻译成一个Servlet,然后按照Servlet的方式调用。
由于JSP第一次访问时会翻译成Servlet,所以第一次访问时通常会比较慢,但是第二次访问,JSP引擎发现JSP没有变化,就不在翻译,而是直接调用,程序的执行效率不会受到影响。
JSP引擎在调用JSP对应的Servlet时,会创建9个与Web开发相关的对象,供翻译后的Servlet使用,在JSP页面中可以直接使用这些对象的引用。
9.2 九大隐式对象
javax.servlet.http.HttpServletRequest request
javax.servlet.http.HttpServletResponse response
javax.servlet.jsp.PageContext pageContext
javax.servlet.http.HttpSession session
java.lang.Throwable exception
javax.servlet.ServletContext application
javax.servlet.ServletConfig config
javax.servlet.jsp.JspWriter out
java.lang.Object page
其中request、response、session、exception、config这几个前面已经介绍过,不在赘述。page代表当前页面,exception代表异常。下面主要介绍out和pageContext。
9.3 out隐式对象
out隐式对象用于向客户端发送文本数据。out对象是通过调用pageContext对象的getOut方法返回的,其作用和语法与ServletResponse.getWriter方法返回的PrintWriter对象非常相似。
JSP页面中的out隐式对象的类型为JspWriter,JspWriter相当于一种带缓存功能的PrintWriter,设置JSP页面的page指令的buffer属性可以调整它的缓存大小,甚至关闭它的缓存。
只有向out对象中写入内容,且满足如下任何一个条件时,out对象才去调用ServletRespon.getWriter方法,并通过该方法返回PrintWriter对象将out对象的缓冲区的内容真正的写到Servlet引擎提供的缓冲区中:
设置page指令的buffer属性,关闭了out对象的缓存内容
out对象的缓冲区已满
整个JSP页面结束
9.4 pageContext对象
pageContext对象是JSP技术中最重要的一个对象,它代表JSP页面的运行环境,这个对象不仅封装了对其他8大隐式对象的引用,它自身还是一个域对象,可以用来保存数据。并且,这个对象还封装了web开发中经常涉及的一些常用操作,例如引入和跳转其他资源、检索其他域对象中的属性等。
9.4.1 通过pageContext获得其他对象
getException方法返回exception隐式对象
getPage方法返回page隐式对象
getRequest方法返回request隐式对象
getResponse方法返回response隐式对象
getServletConfig方法返回config隐式对象
getServletContext方法返回application隐式对象
getSession方法返回session隐式对象
getOut方法返回out隐式对象
pageContext封装其他8个内置对象的意义:
JSP应该只用来做数据输出,不应该出现Java代码,如果不可避免的需要写Java代码,可以使用自定义标签技术。实现自定义标签,需要针对自定义标签写一个Java类,如果要把JSP中的隐式对象都传给自定义标签的Java类,则需要传递8个对象。而有了pageContext则可以只传递一个对象,再通过它去获取其他8大隐式对象。
9.4.2 pageContext作为域对象
pageContext作为域对象,即page域,生命周期为当前的JSP页面。
pageContext对象方法:
public voidsetAttribute(String name, Object value)publicObject getAttribute(String name)public voidremoveAttribute(String name)public Object findAttribute(String name) //重点,从各个域中查找属性,查找顺序为page,request,session,application,这个也是EL表达式的实现原理
pageContext对象封装了访问其他域的方法:
public Object getAttribute(String name, intscope)public void setAttribute(String name, Object value, intscope)public void removeAttribute(String name, int scope)
代表各个域的常量:
PageContext.APPLICATION_SCOPE
PageContext.SESSION_SCOPE
PageContext.REQUEST_SCOPE
PageContext.PAGE_SCOPE
举例:
pageContext举例pageContext.setAttribute("bbb","222", pageContext.REQUEST_SCOPE);
pageContext.setAttribute("ccc","333", pageContext.SESSION_SCOPE);
pageContext.setAttribute("ddd","444", pageContext.APPLICATION_SCOPE);
out.println("aaa=" +pageContext.findAttribute("aaa")+ "
");
out.println("bbb=" +pageContext.findAttribute("bbb")+ "
");
out.println("ccc=" +pageContext.findAttribute("ccc")+ "
");
out.println("ddd=" +pageContext.findAttribute("ddd")+ "
");
out.println("eee=" +pageContext.findAttribute("eee")+ "
");%>使用EL表达式:
aaa=${aaa}
eee=${eee}
运行结果:
findAttribute和EL表达式的效果差不多,唯一的区别是当查找的属性不存在时,findAttribute返回null,EL表达式返回空。我们用来展示数据一般都使用EL表达式。
9.4.3 引入和跳转到其他资源
pageContext类中定义了一个forword方法和两个include方法,分别用来简化和替代RequestDispatcher的forword方法和include方法。方法接受资源如果以“/”开头,“/”代表当前web应用。
pageContext.forword("/1.jsp");
pageContext.include("/header.jsp");
10. JSP映射
和Servlet一样JSP也可以和URL进行映射:
xxx
/index.jsp
xxx
/sss