JSP(Java Server Page)是一种在HTML页面中掺杂java语句从而能够动态生成HTML页面的一种技术。JSP的出现改善了在servlet中利用java对象输出大量难读,难写的html标签的情况,从而使得servlet专注于控制器层,而JSP等其他相关技术专注于表现层,进一步确立了web 开发过程中MVC模式。

  • JSP的本质依然是一个servlet。当我们编写一个jsp文件之后,客户发起一个请求,这个请求通过servlet转到某个jsp文件,这时候web容器会对当前的jsp文件进行编译,当编译成servlet文件之后,才会执行。因此往往每个jsp文件的第一个访问者,会发现速度很慢,因为jsp文件还未被容器编译成servlet文件。
  • 如果开发者是在本地进行的开发,容器用的是Tomcat,可以在Tomcat的work文件夹相对应的web名称下找到容器编译后生成的servlet文件。这也说明了jsp其实是servlet的草稿,它简化了servlet的功能,使得servlet专注控制器部分,而真正运行的是servlet。

Jsp是往静态的html语言中插入动态的java语句,从而实现页面的动态输出。那么如何在html语句中实现java语句呢?

1.四种基本语法

  1. 注释:<%- -%>

    • jsp注释语法的格式是:<%– 这里是注释 –%>
    • jsp的注释内容仅仅提供开发过程的提示作用,最后面输出到客户端的html代码中是无法看见jsp注释的。这有别于html代码的注释,html的注释是可以在客户端的源码。
  2. 声明:<%! %>

    • jsp声明的语法格式是:<%! 这里是声明内容 %>
    • 之前提到,jsp会在运行的时候由容器编译成servlet文件,而servlet是一个java 对象,因此在jsp中进java变量或者方法的声明和在servlet中的声明是一样的。容器会在编译的时候将jsp中声明的变量和方法编译到对应的servlet中去,且接受private,public,static等修饰符。值得注意的是,每个servlet在容器中只存在一个实例。
  3. 输出:<%= %>

    • jsp输出表达式的语法格式:<%=表达式(注意jsp表达式后面无需添加分号表示结束)%>
    • jsp中的表达式语句在对应的servlet中将会编译为out.print()语句。因此起到的作用就是简化jsp的输出语法。
  4. 脚本:<% %>

    • jsp脚本的语法格式是:<% 这里是java程序 %>
    • 嵌套在<% %>中的java代码就是jsp中的java脚本,jsp中的java脚本将会被容器编译成service()方法中的可执行代码,因此对于jsp脚本来说,不能在其中定义方法,因为在java中不允许在方法中定义方法。

2.四大作用域

  1. application:整个web。作用于整个Web应用,多个用户之间共享。
  2. session:单会话。作用于整个Web应用,单个用户之间共享。
  3. request:单个请求。作用于请求,转发间请求共享。
  4. page:当前页。作用于当前页面,当前页面可见。

3.九大内置对象

jsp总共包含9个内置对象。内置对象可以不要通过声明(new),就可以直接在jsp的脚本中进行使用;而在servlet中,仍需要new,所以jsp只是将这些对象内嵌了。等编译成servlet对象后,这9个内置对象要么就是编译后生成servlet的形参,要么就是servlet中service()方法的局部变量,因此在jsp的脚本中可以直接使用。

对象名对象作用
application代表当前整个web本身,存放在application中的数据可以供所有的servlet和jsp共享,无论哪次请求,无论哪次会话都有效。
configconfig代表jsp配置信息的实例。一般来说,jsp中的该对象用的比较少,在servlet中用到config比较多,但是因为servlet中没有内置对象,因此要通过getServletConfig()方法来获取当前servlet的config实例对象。
exception当当前的jsp页面是错误处理页面时,也就是isError属性设为true时,exception对象才会被实例化。常用于输出错误信息和错误栈
out对应了servlet中的输出流对象,常常用于输出变量值和常亮。在之前我们提到过jsp的表达式输出,表达式输出的实质就是out对象的输出过程,因此在jsp中能够使用表达式输出的地方都能用到out对象来输出,但表达式输出更加的简洁。
page代表页面本身
pageContext代表页面上下文。注意页面上下文和页面本身不同。页面上下文可以用于页面之间的数据共享。通过这个对象可以获取page,request,session,application对象;还可以为参数设置的scope,从而使得参数可以在不同的scope之间共享。但一般page,request,session,application四个对象在jsp中已经内置,因此往往是在servlet中才会使用pageContext来获取我们想要的对象。
request代表当前请求。客户端的所有请求信息都被封装在这个对象当中,这也是我们最经常使用的一个对象。
response代表服务器对客户端请求的响应,一般响应分为输出流和重定向。在servlet中输出流通过response获取上面的out对象进行输出,重定向表示生成新的request向一个新的页面发出请求
session代表一次会话。当客户端浏览器与站点连接,会话建立;客户端关闭浏览器,会话结束。

1.out (JspWriter)

out对象是一个缓冲的输出流,用来向客户端返回信息。由于向客户端输出信息总是要连接,所以向客户端输出总是采用缓冲的形式。当缓冲区满足如下条件是才会写入Servlet引擎提供的缓冲区:设置page指令的buffer属性关闭了out对象的缓存功能;out对象的缓冲区已满。整个JSP页面结束。

<%
   out.println("aaa");
   response.getWriter().write("bbb");
%>
"bbb会比aaa先输出"

常用方法:

void println() // 向客户端打印字符串
void clear() // 清除缓冲区的内容,如果在flush之后调用会抛出异常。
void clearBuffer() // 清除缓冲区的内容,如果在flush之后调用不会抛出异常
void flush() // 将缓冲区内容输出到客户端
int getBufferSize() // 返回缓冲区以字节数的大小,如不设缓冲区则为0
int getRemaining() // 返回缓冲区还剩余多少可用
boolean isAutoFlush() // 返回缓冲区满是,是自动清空还是抛出异常
void close() // 关闭输出流

2.request (ServletRequest)

request对象用于封装请求数据。一般用户在表单填写的数据会被封装成request对象,通过post方法传递给目标页面。request还相应提供了一些方法用于访问这些数据。主要方法有以下几个:

String getParameter() // 返回指定参数的参数值
String[] getParameterValues() //返回指定参数的所有值
void setAttribute() // 存储此请求中的属性
object getAttribute() // 返回指定属性的属性值
String getContentType() // 得到请求体的MIME类型
String getProtocol() // 返回请求用的协议及版本号
String getServerName() // 返回接受请求的服务器主机名
int getServerPort() // 返回服务器接受此请求的端口号
String getCharacterEncoding() // 返回字符编码方式
void setContentEncoding() // 设置请求的字符编码方式
int getContentLength() // 返回请求体的长度(以字节数)
String getRemoteAddr() // 返回发送此请求的客户端IP地址
String getRealPath(String path) // 返回一个虚拟路径的真实路径或相对路径的绝对路径
StringgetContextPath() // 返回上下文路径,即项目的根目录

中文乱码问题:request.setCharacterEncoding(“UTF-8”);URL中中文乱码问题:Tomcat的/conf/server.xml 的添加<Connector URIEncoding="UTF-8">属性。

3.response (SrvletResponse)

response对象用于封装响应数据,其作用域是本页面。相关方法如下:

String getCharacterEncoding() // 返回响应用的是何种字符编码
void setContentType() // 设置响应的MIME类型,一般为"text/html, charset=UTF-8"
PrintWriter getWriter() // 返回可以向客户端输出字符的一个对象
						// PrintWriter与内置out对象的区别:PrintWriter对象的其输出总是提前于内置out对象,或者在out中手动flush
sendRedirect(loaction) // 重新定向客户端的请求

4.session (HttpSession)

会话对象,用来记录每个客户端的访问状态。常用方法如下

long getCreationTime() // 返回session创建时间
String getId() // 返回session创建时JSP引擎为它设的唯一ID号
Object setAttribute() // 使用指定名称将对象绑定到此会话
Object getAttribute() // 返回与此会话中的指定名称绑定在一起的对象,没有返回null
String[] getValueNames() // 返回一个包含此session中所有可用属性的数组
int getMaxInactiveInterval() // 返回两次强求间隔多长时间此session被取消(单位秒)
void setMaxInactiveInterval() // 设置session存活时间

session的生命周期:

  • 创建:当客户端第一次访问某个jsp或者Servlet时候,服务器会为当前会话创建一个SessionId,每次客户端向服务端发送请求时,都会将此SessionId携带过去,服务端会对此SessionId进行校验。
  • 活动: 某次会话当中通过超链接打开的新页面属于同一次会话。只要当前会话页面没有全部关闭,重新打开新的浏览器窗口访问同一项目资源时属于同一次会话。除非本次会话的所有页面都关闭后,在重新访问某个jsp或者Servlet将会创建新的会话(但此时原有会话还存在,这个就的SessionId仍然存在于服务端,只不过再也没有客户端会携带它然后教育服务端校验,直到该会话超时。
  • 销毁:有三种销毁方式
    • 调用了session.invalidate()方法
    • Session过期(超时)可以在web.xml中配置Session超时时间1单位是分钟
    • 服务器重新启动

5.application (ServltContext)

application对象用于获取和设置servlet相关信息,application的生命周期是从服务器启动直到服务器关闭

  • application对象实现了用户间数据的共享,可存放全局变量。
  • application开始于服务器的启动,终止于服务器的关闭。
  • 在用户的前后连接或不同用户之间的连接中,可以对application对象的同一属性进行操作。
  • 在任何地方对application对象属性的操作,都将影响到其他用户对此的访问。
  • 服务器的启动和关闭决定了application对象的生命。
  • application对象是ServletContext类的实例。
void setAttribute() // 使用指定名称将对象绑定到此会话
Object getAttribute() // 返回与此会话中的指定名称绑定在一起的对象,如果没有,返回null
Enumeration getAttributeNames() // 返回所有可用属性名的枚举
String getServerInfo() // 返回JSP(Servlet)引擎名及版本号

6.page (Object)

page对象就是指向当前jsp页面本身,有点像类中的this指针,它是java.lang.Object类的实例。常用方法就是Object类的成员方法。

class getClass() // 返回当前的类名。
int getHashCode() // 返回当前类的哈希码。
String toString() // 将此对象转换成字符串。
boolean equals(object) // 比较两个对象是否是相等。
void copy(object) // 将该对象复制到指定的object对象中。

7.pageContext (PageContxt)

pageContext对象是JSP技术中最重要的一个对象,它代表JSP页面的运行环境,这个对象不仅封装了对其他8个隐式对象的引用,其自身还是一个域对象,可以用来保存数据。并且,这个对象还封装了web开发中经常涉及到的一些常用操作,例如include,forward其他资源、检索其他域对象中的属性等。

pageContext对象提供了对jsp页面内所有的对象及名字空间的访问。该对象可以访问到本页所在的Session,也可以取本页所在的application中的属性值。该对象相当也页面中所有功能的集大成者。该对象的本类名也叫pageContext。

JspWriter getOut() // 返回当前客户端响应被使用的out对象
HttpSession getSession() // 返回当前页中的Session对象
Object getPage() // 返回当前页的page对象
ServletRequest getRequest() // 返回当前页的Request对象
ServletResponse getResponse() // 返回当前页的Response对象
void setAttribute() // 设置属性及属性值
Object getAttribute() // 在指定范围内取属性的值
int getAttributeScope() // 返回某属性的作用范围
void forward() // 跳转到另一个页面,地址栏不变
void include() // 包含另一个页面,

PageContext.APPLICATION_SCOPE 代表各个域的常量
PageContext.SESSION_SCOPE
PageContext.REQUEST_SCOPE
PageContext.PAGE_SCOPE
findAttribute() // 查找各个域中的属性

8.Config (ServletConfig)

Config对象是在一个Servlet初始化时,JSP引擎向它传递信息用的,此信息包括Servlet初始化时所要用到的参数(通过属性名和属性值构成)以及服务器的有关信息(通过传递一个ServletContext对象)

ServletContext getServletContext() // 返回含有服务器信息的ServletContext对象
String getInitParameter() // 返回初始化参数的值
Enumeration getInitparameterNames() // 返回Servlet初始化所需所有参数的枚举

9.Exception (Throwable)

Exception对象是一个异常对象,当一个页面在运行过程中发生了异常,就产生这个对象。如果一个jsp页面要应用此对象,就必须报isErrorPage设为true,否则无法编译。

它实际上是java.lang.Throwable的对象。页面要想在有异常时得到处理,就要指定异常处理页面<% page errorPage=“exception.jsp”%>

String getMessage() // 返回描述异常的消息
String toString() // 返回关于异常的简短描述消息
void printStackTrace() // 显示异常及其栈轨迹
ThrowableFillInStackTrace() // 重写异常的执行栈轨迹

0.0 Cookie

除此之外,在web开发过程中,还有一个重要的概念是cookie。

  • 因为当客户端断开与服务器的连接时,会话就会结束,当前会话的所有信息就被丢失。如果我们想保存某些信息,可以利用cookie将相关信息保存到我们的机器上,直到cookie失效。
  • 往客户端机器添加cookie也是response内置对象的责任。可以通过response.addCookie()的方法来添加cookie。cookie的使用很简单,利用即将存储的信息实例化一个cookie对象,
  • 一定记得设置cookie的失效时间,否则cookie会默认会话结束,cookie失效,最后由response对象添加即可。
  • 那么如何获得当前客户端机器的cookie呢,这就是request对象的任务了,通过getCookies()对象就可以获取当前客户端机器的所有cookie了。

4.三大编译指令

jsp的编译指令不直接生成输出,这些编译指令会通知jsp引擎或者servlet引擎对当前的jsp文件在进行编译的过程中起作用。

  • 常用的编译指令有:page, include和taglib
  • 在jsp中插入编译指令的语法是:<%@ 编译指令名 属性名1=“属性值1” 属性名2=“属性值2” …%> 注意,各属性定义之间不要用符号分隔开

4.1 编译当前页:<%@ page ...%>

page 的编译指令是针对当前页面,常用的属性有:

属性名作用
language声明当前页面脚本的语言,默认为java
extends指定jsp编译成servlet之后所需要继承的类,或者所实现的接口
import常用的,用于导入当前脚本中可能使用到的其他包里面的类
info包含jsp的信息,一般作为当前jsp文件的说明用。可以通过getServletInfo()来获取
errorPage常用。指定当前jsp文件发生错误时,自动调用改属性值指定的jsp文件。如果不指定当前属性值,当发生错误时,会抛出异常信息给客户。
contentType指定生成网页的文件格式和编码字符集
isErrorPage用于指定当前jsp文件是否为错误处理jsp文件

一个常见的jsp编译指令的使用可能是:

<%--指定脚本语言是java,指定生成网页的文件格式和编码字符集--%>
<%@ page language="java" contentType="text/html; charset=GBK" %>

<%--指定导入的包的位置--%>
<%@ page import="java.package.*" %>

<%--指定当前jsp文件发生错误时,处理错误的jsp文件--%>
<%@ page errorPage="error.jsp" %>

<%--说明当前jsp文件不是用来处理错的jsp文件--%>
<%@ page isErrorPage="false"%>

4.2 包含指定页:<%@ include ...%>

include 用于指定当前页面包含另一个页面,通常是静态包含:

  • include指令可以将一个外部文件静态导入到当前的jsp文件当中,使得当前jsp文件在生成servlet后会嵌入外部文件所生成的代码
  • include指令可以包含一个静态的文本,也可以导入动态的jsp文件。注意,这里说的静态导入和动态jsp文件不是指的一回事,导入动态jsp文件并不意味着动态导入,而依然是静态导入。指令格式如下:
<%@ include file=”xxx.txt”%>
<%@ include file=”xxx.jsp”%>

jsp的include静态导入对象如果是一个jsp文件的话,静态导入的结果还会把目标jsp文件的编译指令导入进来,因此如果两个jsp文件的编译指令发生冲突,那么在容器生成servlet的过程中就会发生错误。

4.3 导入标签库:<%@ taglib ...%>

taglib 的编译指令作用由名字也可以知道,就是导入一个标签库,指定标签库的uri以及在当前jsp中使用该标签库中标签的prefix(前缀),就可以完成标签库的导入了。语法如下:

<%@ taglib uri=”xxx/yyy/zzz” prefix=”myTag” %>
<%-使用导入标签库的方式-%>
<myTag:tagName/>

5.三大动作元素

jsp的动作指令有区别于编译指令,编译指令是jsp在通知容器进行编译的过程中起作用的,而动作指令则是在编译之后运行过程中起作用的。常见的jsp的动作指令有:

5.1 跳转:<jsp:forward ...>

forward动作指令是将当前页面的响应转到一个新的页面,这个新的页面会继续相应。注意:forward指令并不会生成一次新的请求request,这也就是说请求参数不会丢失,在新的页面中还是能够通过request.getParameter()方法获取参数值。除此之外,在转向新的页面之前,还可以通过jsp:param指令向request中添加额外参数。其完整使用语法如下:

<jsp:forward page="URL|<%=expression%>">  
	<jsp:param name="" value="" />  
</jsp:forward>

转到的目标page不仅可以是相对路径下的合法url,还可以是jsp的表达式输出。

5.2 导入:<jsp:include ...>

include动作指令和编译指令中的include指令作用相似,都是用于导入某个jsp文件。但include动作指令是一个动态导入指令,不同于静态include导入指令,区别在于:

  • 动态导入指令只会导入被导入文件的主体body部分,其余部分不会导入,也就是说编译指令不会被导入,而静态在导入也会一并把编译指令导入;

  • 动态导入指令并不是真正将被导入文件内容插入到自身,而是调用编译后的servlet中的include方法将被导入文件的主体body部分导入进来,而静态指令是两者合二为一生成一个servlet;

  • 动态导入还可以利用jsp的param动作指令为被导入文件添加而外的参数;

jsp的include指令的语法如下:

  <jsp:include page="{url|<%=expression%>}">
  	<jsp:param name="" value="" />
  </jsp:include>

5.3 传递参数:<jsp:param ...>

当使用<jsp:include><jsp:forward>标签引入或将请求转发给其它资源时,可以使用<jsp:param>标签向这个资源传递参数。

  • <jsp:param>标签的name属性用于指定参数名,value属性用于指定参数值。
  • <jsp:include><jsp:forward>标签中可以使用多个<jsp:param>标签来传递多个参数。
<jsp:include page="relativeURL | <%=expression%>">
	<jsp:param name="parameterName" value="parameterValue|<%= expression %>" />
</jsp:include>
<jsp:forward page="relativeURL | <%=expression%>">
	<jsp:param name="parameterName" value="parameterValue|<%= expression %>" />
</jsp:include>
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐