访问jsp页面的过程
jsp的本质是servlet,jsp属于后端,web服务器在接收到我们在浏览器的地址栏键入的url地址时,会生成request和response对象(下面会讲),找到对应的jsp编译后的文件(由于url中包含有我们请求访问的jsp页面的文件名),调用_jspservice方法,传入request、response对象,通过out.write(下面会将)函数将jsp页面的内容生成html页面并解析(这点为本人的猜测),返回给浏览器
jsp的四种语法
jsp指的是在html页面中嵌入java脚本的技术,可以把它看成是一种特殊的servlet类,以下将jsp对应的类称为A,包含有如下四种语法。
1、<%-- --%>:注释。
2、<% %>:java脚本(这一部分内容处于_jspservice的try语句块内)。
3、<%! %>:声明java变量(为A的成员域)。
4、<%= %>:输出内容到jsp页面(即我们在浏览器上看到的页面),严格来说是输出内容到response中,本质上是out.write方法。
jsp的三种编译指令
编译指令在编译期间起作用。
page
语法格式为<%@page param=value.......%>
指定本页面的一些信息,具有如下参数:
language:指定脚本语言类型,在jsp中默认为java。
extends:指定jsp对应类的父类。
import:导入java包。
errorPage:指定错误处理页面,在非错误处理jsp页面中,java脚本不用处理异常,即使该异常是显示抛出异常也一样,因为java脚本处于jsp页面对应类的_jspservice方法的try语句块中,当检测到异常时,catch语句块会获得错误处理页面的调度器,接着将异常信息传递给错误处理页面对应的类。
isErrorPage:为true表示这个jsp页面是错误处理页面,否则为false。
buffer:指定输出缓冲区的大小。
session:设定这个页面是否需要HTTP session。
autoFlush:指定缓冲区满时是否自动刷新,为true表示自动刷新,否则,为false,此时若缓冲区满并进一步导致溢出将会抛出异常。
info:设置jsp页面的说明信息,该说明信息可以通过Servlet.getServletInfo()获取,如果在jsp页面中,可以直接调用getServletInfo()获取。
contentType:指定MIME类型和字符编码,浏览器会根据MIME类型调用对应的应用程序打开该文件(浏览器在接收到HTTP响应后,解析后会生成对应的html文件(也可能是其他类型文件)),字符编码即最终在浏览器上显示时采用的编码。
pageEncoding:通知编译器编写的jsp文件采用的编码方式,以便编译器将其转换成以UTF-8为编码方式的.java文件。
include(又称为静态include)
语法格式为:<%@include file=jsp文件名%>
被包含的jsp文件的内容会在编译时与本文件一起编译。设jsp文件A包含jsp文件B,则A中include指令所处位置在编译时会被替换成B的内容,相当于B的内容被嵌入到A中。该编译指令会将整个B的内容嵌入到A中,B的编译指令也会被嵌入,所以A与B的编译指令不能有相互冲突的地方。
taglib
定义和访问自定义标签库,以后涉及到jsp标签库在讲。
jsp的九个内置对象
application:ServletContext类型
pageContext:PageContext类型。
session:HttpServltesession类型。
request:HttpServletRequest类型。
response:HttpSerlvetResponse类型。
page:jsp的this指针。(比较少用,故不介绍)
config:ServletConfig类型。
out:JspWriter类型。
exception:Throwable类型。
application
其中设置的属性可以在整个web应用中访问。
常用函数
1、void setAttribute(String name,Object value),设置名为name,值为value的属性。
2、Object getAttribute(String name),获取名为name的属性的值。
3、String getInitParameter(String name),获取web.xml中配置的名为name的参数。
在web中配置application范围的参数格式如下:
<context-param>
<param-name>.......</param-name>
<param-value>........</param-value>
</context-param>
pageContext
可以利用其访问request、response、session、application范围的属性。
常用函数:
String getAttribute(String name):获取page范围内名为name的属性的值。
Object getAttribute(String name,int scope):获取scope指定范围内名为name的属性。
scope的取值如下:
PageContext.PAGE_SCOPE:对应于page范围
PageContext.REQUEST_SCOPE:对应于request范围
PageContext.SESSION_SCOPE:对应与session范围
PageContext.APPLICATION_SCOPE:对应与application范围
pageContext也有对应的两个setAttribute方法用于将属性放入对应范围的容器。
pageContext还可以获得其他内置对象:
ServletRequest getRequest():获取request对象。request继承了ServletRequest类和HttpServletRequest接口
ServletResponse getResponse():获取response对象。response继承了ServletResponse类和HttpServletResponse接口
ServletConfig getServletConfig():获取config对象。
ServletContext getServletContext():获取application对象。
HttpSession getSession():获取session对象。
session
其中设置的属性在一次会话中有效,即从用户请求访问服务器到用户断开与服务器的连接。
常用函数:
void setAttribute(String name,Object value):设置名为name,值为value的属性。
Object getAttribute(String name):获取名为name的属性。
session通常用于保存客户端的状态信息,这些信息被保存在web服务器的磁盘上,所以通过上述方式创建的属性必须可以序列化。
request
该对象封装了一次用户请求,所有的请求参数(均为String类型)都存放在此容器中。
常用函数:
String getParameter(String name):从Http请求中获取名为name的参数。
Map getParameterMap():获取所有参数——参数值所组成的Map对象。
Enumeration getParameterNames():获取所有请求参数的名字。
String[] getParameterValues(String name):当name对应的请求参数的值有多个时,可以利用此函数获取。
String getHeader(String name):获取请求头中名为name的请求参数。
Enumeration<String> getHeaderNames():获取所有请求头的值。
Enumeration<String> getHeaders(String name):获取请求头中名为name的请求参数的多个值。
int getIntHeader(String name):获取请求头的值并转换为int。
void setAttribute(String name,Object value):设置名为name的属性。
Object getAttribute(String name):获取名为name1的属性。
Cookie getCookies():获取客户端上的cookie(response中会介绍)
HttpServletRequest类提供了RequestDispatcher getRequestDispatcher(String path)函数用于获取path指定的jsp页面的调度器(相当于句柄),RequestDispatcher提供了如下方法:
forward(ServletRequest request,ServletResponse response):用于转发页面(下面会讲)。
include(ServletRequest request,ServletResponse response):用于动态包含页面(下面会讲)。
response
该对象写入非字符数据到http响应中(为本人理解)
常用函数:
void sendRedirect(String url):重定向,实质上是让客户端再次发送一个请求。
void addCookie(Cookie cookie):增加cookie,Cookie类可以建立一个键值对,该类构造函数如下:
Cookie(String name,String value)
在客户端上设置cookie的步骤如下:
1、创建Cookie实例。
2、设置Cookie的生命周期(通过Cookie类的setMaxAge函数,该函数只有一个表示生存时长的参数(单位为秒))。
3、向客户端写Cookie。
config
获取web.xml中的本servlet的配置参数。
application获取的是web应用本身的配置参数,所有的servlet均可以获取,而config获取的只能是本servlet的配置参数(其余servlet无法访问)。
在web.xml中的配置方法为:
<init-param>
<param-name>配置参数的名字</param-name>
<param-value>配置参数的值</param-value>
</init-param>
常用函数:
String getInitParameter(String name):获取web.xml中的配置参数。
out
写入字符数据到Http响应中(个人理解)
jsp中的<%=.......%>表达式实质上就是out.write(String value)函数
常用方法:
String write(String value):输出字符数据。
String println(Object value):将非字符数据转换成String类型后输出,实质上应该是调用了tostring函数。
exception
当jsp页面的isErrorPage为true时,该对象有效,代表的是其他jsp页面产生的异常。
jsp的七个动作指令
所谓的动作指令就是指运行时执行的指令,通过什么方式呢?函数调用的方式,所以jsp的动作指令在jsp对应的类中均被替换成函数。包括如下几个指令。
jsp:forward:用于转发页面请求,此时页面的url并不会发生改变。
jsp:param:指定参数。
jsp:include:动态包含页面。
jsp:useBean:指定javaBean的实例对象。
jsp:setAttribute:设置javaBean的属性。
jsp:getAttribute:获取javaBean对应属性的值。
jsp:pulgin:下载对应的java应用程序或是applet到本地端运行。
下面依次解释这些指令:
jsp:forward
语法格式:
<jsp:forward page="">
<jsp:param name=" " value=" "/>
</jsp:forward>
在jsp中对应的类中,函数如下,假设在first.jsp forward页面NewFile.jsp。
_jspx_page_context.forward("NewFile.jsp");//其中的_jspx_page_context是pageContext类型的对象
jsp:param中设置的参数可以在NewFile.jsp页面通过request对象的getParameter获取,forward函数的参数是一个url,其中jsp:param指定的参数位于该url的参数部分,需要注意的是,尽管该forward函数没有传入request对象,但pageContext本身可以获取request对象,所以NewFile.jsp页面的request对象可以使用first.jsp页面的request参数。转发后本页面的内容将不会存在,虽然url没有发生改变。
jsp:include(又称为动态include)
语法格式:
<jsp:include page=" ">
<jsp:param name=" " value=" " flush="true"/>
</jsp:include>
flush指定是否将输出缓存转移到被导入文件中,如果指定为true,则包含在被导入文件中,如果指定为false,则包含在原文件中。
在jsp对应的类中,函数如下,假设first.jsp include页面NewFile.jsp。
org.apache.jasper.runtime.JspRuntimeLibrary.include(request, response, "NewFile.jsp", out, false);
可以看到,request、response、out均作为参数传递,意味着在NewFile.jsp中可以使用request中的参数,在NewFile.jsp中response所进行的操作或是用out输出的字符信息均会写入回应first.jsp请求的HTTP响应中,第三个参数为一个url
jsp:param指定的参数会通过url中的参数进行传递。
动态include与静态include的区别在于
1、静态include会将导入页面的所有代码完全融入,而动态include会将导入页面的body部分代码融入本页面。
2、静态inlcude会在编译时将导入页面的代码与本页面一起编译,而动态include在运行时进行导入(通过调用函数实现)。
3、动态include可以增加额外的参数。
jsp:useBean、jsp:setProperty、jsp:getProperty
语法格式:
<jsp:useBean id=" " class=" " scope=" "/>
其实该指令就是创建javaBean的实例对象,id为指向该实例对象的引用名,class为javaBean的类名,scope的值可以为page、request、session、application,作用是将该引用的作用范围,注意要在jsp页面中import javaBean类。
<jsp:getProperty name=" " value=“ ”/>,获取javaBean的属性值进行输出,其中name的值为jsp:useBean中的id值。
<jsp:setProperty name=" " property=” ” value=“ ”/>,设置javaBean的属性。
下面给出一个实例:
项目结构如下:
javaBean Try.java代码如下:
package staticdeal;
public class Try {
private int x;
public int getx()
{
return x;
}
public void setx(int u)
{
x=u;
}
}
firstjsp.jsp页面代码如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" import="staticdeal.Try"%>
<!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>
<jsp:useBean id="deal" class="staticdeal.Try" scope="application"/>
<jsp:setProperty name="deal" property="x" value="1"/>
<jsp:getProperty name="deal" property="x"/>
</body>
</html>
接着我们访问firstjsp.jsp,得到结果如下:
可以看到jsp:getProperty获取属性值后会直接输出。接着我们来看看该jsp页面对应的java类
jsp:useBean对应的代码块如下:
deal = (staticdeal.Try) _jspx_page_context.getAttribute("deal", javax.servlet.jsp.PageContext.APPLICATION_SCOPE);//
_jspx_page_context为pageContext类型
if (deal == null){ deal = new staticdeal.Try(); _jspx_page_context.setAttribute("deal", deal, javax.servlet.jsp.PageContext.APPLICATION_SCOPE);
首先会用在application范围查找是否有名为deal的变量,若不存在,则创建一个,并将其放入application范围内。
jsp:setAttribute对应的函数如下:
org.apache.jasper.runtime.JspRuntimeLibrary.introspecthelper(_jspx_page_context.findAttribute("deal"), "x", "1", null, null, false);
introspecthelper函数比较复杂,这里不过多解释,源代码位于:点击打开链接
jsp:getAttribute对应的函数如下:
out.write(org.apache.jasper.runtime.JspRuntimeLibrary.toString((((staticdeal.Try)_jspx_page_context.findAttribute("deal")).getx())));
可以看到该指令实质上就是调用javaBean中的getxxxx函数,xxxx即为property的值。
secondjsp.jsp代码如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" import="staticdeal.Try"%>
<!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>
<%=((Try)application.getAttribute("deal")).getx()%>
</body>
</html>
输出结果为:
可以看到,application范围内存在有我们在firstjsp.jsp中利用jsp:useBean创建的deal对象,原理看上面jsp:useBean对应的代码块。
jsp:param
作用已在jsp:forward与jsp:include中指出。
jsp:plugin
使用场景并不多。