2024年2月7日发(作者:)
JSP语法基础
1、JSP基本概念
JSP(Java Server Pages,Java服务器页面)是一种Web动态页面技术,JSP是嵌入了Java程序段的HTML文件,由HTML元素(静态部分)、JSP元素(动态部分)和JSP注释组成。JSP文件后缀名为.jsp。JSP运行时会被容器翻译为Servlet源代码(xxx_)、自动编译为.class文件(xxx_)、载入.class文件,然后生成Servlet对象。JSP和Servlet一样是服务器端技术,允许运行在Web服务器端。JSP定义在JavaWeb工程中WebRoot根路径下或其下的某个目录,其访问方式和访问HTML文件一致。注意:如果JSP文件放在WEB-INF目录中时,不能直接访问,需通过Servlet转发。
JSP在运行时会动态编译成一个Servlet,其本质上是就是一个Servlet,JSP是对Servlet技术的扩展。Servlet完全由Java程序代码构成,擅长于流程控制和业务逻辑处理,一般用作控制器(Controller);JSP由HTML元素和JSP元素构成,对页面的静态内容和动态内容进行了有效分离,擅长于内容的展示,一般用作视图(View)。
注:翻译生成的xxx_和xxx_文件的位置:Tomcat中,在apache-tomcatworkCatalina目录需;在Eclipse中,在workspace下.p0workCatalinalocalhostXXXorgapachejsp。
2、JSP元素
JSP元素包括脚本元素、指令元素和动作元素。
脚本元素(3种)
声明元素(Declaration)
<%!类成员声明或方法声明%>
在<%!与%>之间声明的代码,都将转译为Servlet中的类成员或方法,之所以称为声明元素,是指它用来声明类成员与方法。使用<%!与%>声明变量时,必须小心数据共享与线程安全的问题。Servlet容器默认会使用同一个Servlet实例来服务不同用户的请求,每个请求是一个线程,而<%!与%>间声明的变量对应至类变量成员,因此会有线程共享访问的问题。
脚本元素(Scriptlet)
<% Java语句%>
在脚本元素中可以编写Java语句。事实上,<%与%>之间所包括的内容,将被转译为Servlet源代码_jspService()方法中的内容。
表达式元素(Expression)
<%= Java表达式%>
可以在表达式元素中编写Java表达式,表达式的运算结果将直接输出为网页的一部分。例如:<%=new
Date() %>注意,表达式元素中不用加上分号(;)。这个表达式元素在转译为Servlet之后,会在jspService()中产生以下语句:(new Date());表达式是一个简化的n(“„„”)语句。简单地说,表达式元素中的表达式,会直接转译为out对象输出时的指定内容(这也是为什么表达式元素中不用加上分号的原因)。
指令元素(3个)
JSP指令(Directive)元素用于指示容器将JSP转译为Servlet源代码时,一些必须遵守的信息。在JSP中有三种常用的指令类型:page、include与taglib。指令元素的语法:
<%@ 指令类型[属性="值"]* %>
指令元素中可以有多对的属性/值,必要时,同一个指令类型可以用数个指令元素来设置。
Page指令
page指令用于设置JSP页面的属性,这些属性将用于和Web服务器通信,控制所生成的Servlet结构(告知容器如何转译当前的JSP网页)。page指令作用于整个JSP页面,从语法上讲可以将一个指令放在JSP文档中任何地方,不过通常是放在JSP页面的第一行。Page指令可以设置的页面属性如下:
属性 描述 默认值
language
定义JSP页面使用的脚本语言种类。目前只可用java语言。可省略该属性
java
contentType
定义JSP页面响应的MIME类型和页面字符编码方式。默认MIME:text/html;text/html;charset=ISO-8859-1
字符编码:ISO-8859-1
pageEncoding
定义JSP页面字符编码方式。如果contentType也设置了编码方式,则以无
pageEncoding的设置为准。
import
指定导入的java软件包或类名列表。如果要导入多个类使用逗号","隔开 无
extends
定义JSP页面产生的Servlet时继承的父类,必须指定该类全名,即包名+类HttpJspBase
名。请特别谨慎使用这一功能,否则影响JSP文件的编译
isErrorPage
指定此JSP页面是否为处理异常错误的网页。值为"true | false",表示当前JSPfalse
页面是否为其它页面的errorPage目标,如果设置为true,则可以使用exception
errorPage
session
isELIgnored
buffer
autoFlush
isThreadSafe
info
对象显示错误信息;如果设置为false,则不可以使用exception对象,即不能显示错误信息
设置当前JSP页面发生异常时,负责处理异常事件的目标JSP页面。被指默认忽略
定的目标JSP页面的page指令元素必须指定isErrorPage="true"
true
定义在JSP页面是否可以使用Session对象。值为"true | false"
false
设置JSP页面是否支持EL表达式。值为“true | false”,false表示支持
指定内置对象out发送信息到客户端浏览器的信息缓存大小,以kb为单位,8kb
可以指定缓存的大小。值为“none | 8kb | size kb”。设置为“none”即没有缓冲区,所有的输出都不经过缓存而直接输出
autoFlush="true|false",指定是否当缓存填满时自动刷新输出缓存中的内容。true
如果为true,则自动刷新,否则当缓存填满后,可能会出现严重的错误。如果把buffer设置为none时,就不能将autoFlush设置为false。
指定JSP页面是否支持多线程访问。设置为true,表示可以同时处理多个客ture
户请求,但应该在JSP页面中添加处理多线程的同步控制代码。设置为false,JSP页面在一个时刻就只能响应一个请求。
指定任何一段字符串,该字符串被直接加入到翻译好的页面中,可以通过无
vletInfo()方法得到。
示例:
<%@pagecontentType="text/html; charset=UTF-8"pageEncoding="UTF-8"import=".*"%>
<%@pageimport=".*" %>
include指令
include指令元素将file属性指定的页面内容静态包含到当前页面。
<%@includefile="" %>
include指令包含指定页面的过程是在翻译阶段完成的,所以运行时效率较高。如果被包含的文件内容发生变化,那么当前JSP文件需要重新被翻译。
taglib指令
声明用户在当前JSP页面使用JSTL标签或用户自定义的标签时使用taglib指令,将标签库描述符文件导入到JSP页面。taglib指令类型告知容器如何转译这个页面中的标签库(Tag Library)。
<%@taglibprefix="tagPrefix" tagdir="" uri="taglibURL"%>
taglib指令可以设置的页面属性如下:
属性名 说明
prefix
标签的前缀,区分多个自定义标签。不可以使用保留前缀和空前缀,遵循XML命名空间的命名约定。
uri
定位标签库描述符的位置,唯一标识和前缀相关的标签库描述符,可用绝对或相对URL。
tagdir
tag文件是类似JSP的文件,可以在JSP文件中调用该tag文件,例如,如果一个tag文件存放在web项目的WEB-INF/tags目录下,名为。则在JSP页面中使用<%@ taglibtagdir="/WEB-INF/tags"
prefix="beijing"%>引入tag文件所在的标签库,后面就可以用
动作元素(标准标签)(13个)
JSP 2.0规范中定义了一系列标准动作,是一些标签,影响JSP运行时的行为和对客户请求的响应。它是预定义的Java代码,目的在于代码的可重用性。在页面被转换为Servlet时,JSP容器遇到这些标签,就使用预先定义的对应于该标签的java代码来代替它。与JSP指令元素不同的是,JSP动作元素在请求处理阶段起作用。所有的标准动作元素都是用jsp:作为前缀。标准动作元素使用标准的XML语法:
或者
主要的标准动作元素:
动作元素 说明
s> "名-值"对的形式增加或替换主页面中发送到被包含页面的请求参数。一般和include指令和动作,forward动作等一起使用。 情况,避免使用该动作。使用servlet的RequestDispatcher的forward方法。 其中flush=“true|false”用来指定是否使用缓冲区。 来。这样的行为和RequestDispatcher类的include方法完全相同。当被包含页面需要改变响应头和设置报头时,对于这样的情况使用include指令。 其中page属性代表一个相对路径,即所要包含进来的文件位置,所包含文件可以是静态文件或者动态文件 只有在实例化Bean的时候才执行。所以依赖于scope指定的Bean生命周期。所以可以将设置bean属性的代码( id:表示实例化对象的名称;Bean共享时,仅当不存在相同id和scope的Bean时才实例化新的对象。 scope:表示此对象保存的范围,一共有四种属性范围:page(默认值,保存在一页的范围之中,跳转之后此JavaBean无效)、request(一个JavaBean对象可以保存在一次服务器跳转范围中)、session(在一个用户的操作范围中保存,重新打开浏览器的时候才会声明新的JavaBean)、application(在整个服务器上保存,服务器关闭时才会消失); class:对象所对应的包.类名称。实例化class指定的类,并将实例化后的对象绑定到_jspService中的局部变量,变量由id指定名称而类型为自身或type指定。 type属性用于将bean实例指向由id指定名称类型为type指定的变量。类型可以为父类,实现的接口,或者为自身。 在servlet中生成为:BeanInfo myBean = (); 执行过程: 1、JSP容器在scope属性指定的范围查找指定id的JavaBean实例。 2、找到该实例,该被实例被共享。“该标签内的代码也不会被执行。" 3、没有找到,只指定了class属性,则根据class属性来创建一个新实例。没有找到,只指定了beanName属性,则使用beanName作为参数调用类中的instantiate方法创建新的bean实例。 4、将变量保存到scope属性指定的范围中。使用setAttribute方法必须以id的值为key(这由容器自动处理)。 operty> 重要:Bean的属性命名规则和jsp:setProperty标签的命名规则的一致性,Bean的属性命名的不规范会导致Exception异常。Bean之所以是个Bean是由其规范来决定的,而不是由父类来决定的。bean分析器会执行一个“字母小写化的过程”来推导出属性的名字,将get/set之后的第一个字符转化为小写字母。这可能导致属性和参数名称的不一致。要命的在于对于get/set之后二个字母都为大写字母的属性,那么属性的第一个字母不会被改写为小写字母。假设方法名字为getURL 解析出的的属性为URL 而不是uRL。所以在命名bean属性的时候要么前面2个字母都大写,要么前面2个字母都大写。 property="propertyName"value="String | <%=expression %>"| property="propertyName"[param="paramName"] | property="*"}/> name属性用来标识一个bean实例; peroperty属性用来设置指定的bean的属性; value属性为bean所指定的属性设置值;value属性和param属性不能同时使用。 param属性指定某个请求参数名,并用该参数值设置bean的属性的值。对于基本类型和包装类,容器自动将属性和请求参数的类型进行转换匹配。匹配失败不采取任何动作,也就是不会传递null。如果bean属性名本与请求参数名相同,那可以不指定param属性。 实例: 法。 name属性用来标识一个bean实例;property属性指定要输出的属性名。 实例: nt>、 te>、 生成结果:<元素名元素属性名="元素属性的值">元素的内容元素名> 执行时, k> > 3、JSP隐含对象(内置对象)(9个) 隐含对象(内置对象)在JSP页面初始化时由Web容器为用户自动创建的,使用JSP进行页面编程时可以不加声明和创建,直接在Java脚本和表达式中使用这些对象。 内置对象 类型 范围 说明 request . request request请求对象用来封装客户端的请求信息,通过该对象可以HttpServletRequest 获得客户端请求信息,然后做出响应。request对象是HttpServletRequest类的实例,具有请求作用域,即完成客户端的请求之前,该对象一直有效。 response . page response响应对象封装了响应客户请求的有关信息,它是HttpServletResponse HttpServletResponse类的实例。response对象具有页面作用域,即访问一个页面时,该页面内的response对象只能对这次访问有效,其它页面的response对象对当前页面无效。 session . session session会话对象指的是客户端与服务器的一次会话,从客户端HttpSession 连到服务器的一个Web应用开始,直到客户端与服务器断开连接为止。Session对象HttpSession类的实例,具有会话作用域。 application . application application应用上下文对象实现了用户间数据的共享,可存放全ServletContext 局变量。它开始于服务器的启动,直到服务器的关闭,在此期间,此对象将一直存在;这样在用户的前后连接或不同用户之间的连接中,可以对此对象的同一属性进行操作;在任何地方对此对象属性的操作,都将影响到其他用户对此的访问。服务器的启动和关闭决定了application对象的生命。application对象是ServletContext类的实例。 pageContext . page pageContext页面上下文对象提供了对JSP页面内所有的对象及PageContext 名字空间的访问,该对象使用较少。 out . page out输出对象是JspWriter类的实例,是向客户端输出内容常用的JspWriter 对象。 config t. page config配置对象是在一个Servlet初始化时,JSP引擎向它传递信ServletConfig 息用的,此信息包括Servlet初始化时所要用到的参数(通过属性名和属性值构成)以及服务器的有关信息(通过传递一个ServletContext对象)。 page page page页面对象就是指向当前JSP页面本身,类似于类中的this指针,它是类的实例。 exception . page exception异常对象是一个异常对象,当一个页面在运行过程中Throwable 发生了异常,就产生这个对象。如果一个JSP页面要应用此对象,就必须把isErrorPage设为true,否则无法编译。exception对象是ble的对象。 4、JSP注释 JSP是嵌入了Java程序段的HTML文件,所以JSP中的注释有三种:HTML注释、Java注释和JSP注释。 1. HTML网页使用的注释方式,这并不是JSP的注释。例如这段网页中的注释: 在翻译为Servlet之后,只是产生这样的一行语句:("rn");所以这个注释文字也会输出至浏览器成为HTML注释,在查看HTML源代码时,也就可以看到注释文字。 2. JSP网页中可以在<%与%>之间直接使用Java语法编写程序,所以可在其中使用Java的注释方式来编写注释文件,也就是可以使用//或/*与*/来编写注释。例如: <% // 单行注释 n("随便显示一段文字"); /* 多行注释 */ %> 在转译为Servlet源代码之后,<%与%>之间设置的注释,在Servlet源代码中对应的位置也会有对应的注释文字。若想观察JSP转换为Servlet后的某段特定源代码,可以使用这种注释方式来当作一种标记,方便直接看到转换后的代码位于哪一行。 3. JSP有一个专用的注释,即<%--与 --%>。例如: <%-- JSP注释 --%> 容器在转译JSP至Servlet时,会忽略<%--与 --%>之间包括的文字,生成的Servlet中不会包括注释文字,也不会输出至浏览器。 JavaWeb中的URL路径问题 1、路径的基本概念 2、路径相关方法 JSP内置对象request(rvletRequest)中与路径相关的方法: public String getContextPath();//返回请求URI指示请求上下文的那一部分。同application的同名方法 public String getServletPath();//返回此请求调用servlet的URL部分。此路径以"/"字符开头,包括servlet名称或到servlet的路径,但不包括任何额外路径信息或查询字符串。 public String getRequestURI();//返回此请求的URL的一部分,从协议名称一直到HTTP请求的第一行中的查询字符串。 public StringBuffer getRequestURL();//重新构造客户端用于发出请求的URL。返回的URL包含一个协议、服务器名称、端口号、服务器路径,但是不包含查询字符串参数。 public String getPathTranslated();//返回在servlet名称之后但在查询字符串之前的额外路径信息,并将它转换为实际路径。 JSP内置对象application()中与路径相关的方法: public String getContextPath();//返回Web应用程序的上下文路径。上下文路径是用来选择请求上下文的请求URI的一部分。请求URI中首先出现的总是上下文路径。路径以"/"字符开头但不以"/"字符结束。对于默认(根)上下文中的servlet,此方法返回""。 public String getRealPath(String path); //为给定虚拟路径返回包含实际路径的String。例如,可以通过对"host/contextPath/"的请求使路径"/"返回服务器文件系统上的绝对文件路径。 3、JavaWeb开发中经常遇到的路径问题 (1)中的路径 配置Servlet映射 (2)转发和重定向中的路径 如果以"/"开头:①转发,"/"代表当前Web应用的根目录②重定向,"/"代表Web服务器的根目录。 (3)表单和链接中的路径 (4)page指令元素中errorPage属性的路径 errorPage属性值如果以"/"开头,表示相对于当前Web应用的根目录;如果是没有"/"开头的路径,表示当前目录的相对路径。 解决JSP路径问题的方法(jsp文件开头path、basePath作用) 在JSP中的如果使用"相对路径"则有可能会出现问题。以“/”作为开头有时称为环境(上下文)相对(Context-relative)路径,没有以“/”作为开头则称为请求相对(Request-relative)路径。 解决方案一:利用html中的 1. 编写/commons/文件: <%@pagecontentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%> <%@taglibprefix="c"uri="/jsp/jstl/core"%> 2. 在所有JSP页面的 <%@pagecontentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%> <%@includefile="/commons/"%> ... 在head中设置< base>后,则所有请求相对(Request-relative)路径(不能以“/”作为开头)都为在< base>href属性中设定的路径。测试页面:localhost:8080/bookstore/test/ <%@pagecontentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%> <%@includefile="/commons/"%> <%@includefile="/commons/"%>
${ }://${Name }:${Port }${tPath}/
${ }://${Name }:${Port }${tPath}/
${ }${ }
${Name }${Name }
${Port }${Port }
${tPath}${tPath}
当请求URL为localhost:8080/bookstore/test/时有:
${ }://${Name }:${Port }${tPath}/→localhost:8080/bookstore/
${ }→http
${Name }→localhost
${Port }→8080
${tPath}→/bookstore
localhost:8080/bookstore/test/和localhost:8080/bookstore/都可以正确访问。
解决方案二:直接采用绝对路径(不推荐)
举个例子: 假如我们有一个项目: MyApp 在该项目下,有一个jsp文件夹该文件夹下包括:
// 登陆页面
// 注册页面
我们在浏览器中输入地址 (注意: 地址的内容):
localhost:8080/MyApp/jsp/
这时候, 浏览器会链接到 "登陆页面" () 在文件内包含了如下 "部分代码":
那么,如果我们点击这个链接,就会在浏览器地址栏中, 出现如下错误链接:
localhost:8080/MyApp/jsp/jsp/
为什么会出现"/jsp/jsp/"呢?
因为, 网页中的"相对链接", 是相对于你所 "请求的URL路径" 所决定的。即:
因为这里请求路径是:localhost:8080/MyApp/jsp/
那么, 浏览器就会在这个路径下(即:localhost:8080/MyApp/jsp/)去找
jsp/
所以就会出现如下错误内容:
localhost:8080/MyApp/jsp/jsp/
上面的问题,就是调用页面和被调用页面的URL不同所造成的,此类错误也常常会出现在2个页面之间进行 "转发"(forward) 操作的时候。
因为forward是在后台进行的,对客户端来说是透明的。(即: URL不改变,而数据内容却是另一个页面返回来的。。。)
那么如何解决这问题呢?
(一)方法一:直接采用绝对路径 (不推荐)
在JSP页面端,获得本项目的绝对地址(如果你的项目叫MyApp,那么获得到的地址就是 localhost:8080/MyApp/):
代码如下:
<%@ page language="java" pageEncoding="GBK" contentType="text/html;charset=gbk"
isELIgnored="false"%>
<%
String path = textPath();
// 获得本项目的地址(例如: localhost:8080/MyApp/)赋值给basePath变量
String basePath =
eme()+"://"+verName()+":"+verPort()+path+"/";
// 将 "项目路径basePath" 放入pageContext中,待以后用EL表达式读出。
ribute("basePath",basePath);
%>
我们可以看到,在标签中的href属性内,我们直接采用了“本项目路径
${th}”加上 "jsp/" ,从而构成一个绝对路径(即:
localhost:8080/MyApp/jsp/)
但是这样做有一个很不好的地方,那就是我们必须要在每个链接的前面都要加上“${th}”
如果这样做的话,将是一件很可怕的事情。
(二)方法二: 利用html中的
下面是对html中的
base元素可规定页面中所有链接的基准 URL 默认情况下,页面中的链接(包括样式表、脚本和图像的地址)都是相对于当前页面的地址(即:浏览器地址栏里的请求URL)。
我们可以使用
上面说的是什么意思呢?我们来看看代码就知道咯~~
下面的代码 (十分类似上面 "方法一" 中的JSP代码) 但是这里我们并没有采用
${th}+"相对路径地址" 的方法,而是采用了html文件中的
<%@ page language="java" pageEncoding="GBK" contentType="text/html;charset=gbk"
isELIgnored="false"%>
<%
String path = textPath();
// 获得项目完全路径(假设你的项目叫MyApp,那么获得到的地址就是
localhost:8080/MyApp/):
String basePath =
eme()+"://"+verName()+":"+verPort()+path+"/";
%>
// 这里我们就可以直接使用相对路径(即: 相对于base标签)
大概看完了上面的代码,或许您还是有些疑惑 *_*~~ 不过当您看到了,下面的代码,可能就豁然开朗了 (*^__^*) 嘻嘻„„。
当我们去执行上面的那段JSP代码后,我们可以在浏览器中可以查看,他所返回给客户端的html代码:
执行完上述JSP后,所返回的html代码如下:
// 设置了
我们可以看到JSP返回的html代码中,包含了
href="localhost:8080/MyApp/">内容。
也就是说,在本html文件中,遇到的所有“相对链接(例如: )”,都是相对于base
的路径(即:localhost:8080/MyApp/),所以我们就可以进行的使用相对链接,而不必担心,
转发操作(forward)或请求地址不同不同所造成的页面无法找到的错误啦~(即: HTTP:
404)。。。


发布评论