JSP简介
JSP是为了简化Servlet的工作出现的替代品,Servlet输出HTML非常困难,JSP就是替代Servlet输出HTML的。
JSP的响应
浏览器第一次请求1.jsp时,Tomcat会将1.jsp转化成1_jsp.java这么一个类,并将该文件编译成class文件。编译完毕后再运行class文件来响应浏览器的请求。
以后访问1.jsp就不再重新编译jsp文件了,直接调用class文件来响应浏览器。当然了,如果Tomcat检测到JSP页面改动了的话,会重新编译的。
既然JSP是一个Servlet,那JSP页面中的HTML排版标签是怎么样被发送到浏览器的?用write()出去的。说到底,JSP就是封装了Servlet的java程序罢了。
JSP比Servlet更方便更简单的一个重要原因就是:内置了9个对象!内置对象有:out、session、response、request、config、page、application、pageContext、exception
生命周期
JSP也是Servlet,运行时只有一个实例,JSP初始化和销毁时也会调用Servlet的init()和destroy()方法。另外,JSP还有自己初始化和销毁的方法
1 | public void _jspInit() { |
语法
JSP代码分为两个部分:
- 模板数据:HTML代码
- 定义了网页的基本骨架————页面的结构和外观
- 元素:JSP页面中的java代码、JSP指令和JSP标签
脚本
- JSP的脚本就是JSP页面中的java代码,也叫做scriptlet。JSP的脚本必须使用<%%>括起来,不然会被当成是模板数据的!
- JSP脚本有三种方式:
- <%%>【定义局部变量,编写语句】
- <%!%>【定义类或方法,但是没人这样用!】
- <%=%>(也称之为表达式输出)【输出各种类型的变量,int、double、String、Object等】
- 表达式和变量后面不能有分号(;)
- 在<% %>中可以定义变量、编写语句,不能定义方法。
- 如果过多地使用<%%>会导致代码混乱,JSP还提供了一种scriptlet标签,使用此标签和<%%>有相同的功能,只不过它更美观了一些
1 | <jsp:scriptlet> |
指令
JSP指令用来声明JSP页面的相关属性,例如编码方式、文档类型等等
1 | <"值" > @指令 属性名= |
page指令
page指令可以帮助跳到提示页面或是错误页面上。为了保持程序的可读性和遵循良好的编程习惯,page指令最好是放在整个JSP页面的起始位置。
- 我在idea生成的JSP页面就有page指令了。
1 | <%@ page contentType="text/html;charset=UTF-8" language="java" %> |
- page指令常见属性:
1 | <%@ page |
一般地,在eclipse或idea这些高级开发工具上开发,我们只需要在page指令中指定contentType=”text/html;charset=UTF-8”,就不会出现中文乱码问题!当然了contentType 不仅仅可以指定以text/html的方式显示,还可以使用其他的形式显示出来。在conf/web.xml文件中可以查询出来
import属性
可以在一条page指令的import属性中引入多个类或包,其中的每个包或类之间使用逗号(,)分隔
```jsp
<%@ page import=”java.util.*,java.io.*,java.sql.*”%>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
### errorPage属性
- rrorPage属性的设置值必须使用相对路径,如果以“/”开头,表示相对于当前Web应用程序的根目录(注意不是站点根目录),否则,表示相对于当前页面
- 可以在web.xml文件中使用\<error-page\>元素为整个Web应用程序设置错误处理页面。
- \<error-page\>元素有3个子元素,\<error-code\>、\<exception-type\>、\<location\>
- \<error-code\>子元素指定错误的状态码,例如:\<error-code\>404\</error-code\>
- \<exception-type\>子元素指定异常类的完全限定名,例如:\<exception-type\>java.lang.ArithmeticException\</exception-type\>
- \<location>子元素指定以“/”开头的错误处理页面的路径,例如:\<location\>/ErrorPage/404Error.jsp\</location\>
- 如果设置了某个JSP页面的errorPage属性,那么在web.xml文件中设置的错误处理将不对该页面起作用。
web.xml的代码下:
```xml
<web-app version="3.0"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<display-name></display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!-- 针对404错误的处理页面 -->
<error-page>
<error-code>404</error-code>
<location>/ErrorPage/404Error.jsp</location>
</error-page>
</web-app>404Error.jsp代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<html>
<head>
<title>404错误友好提示页面</title>
<!-- 3秒钟后自动跳转回首页 -->
<meta http-equiv="refresh" content="3;url=${pageContext.request.contextPath}/index.jsp">
</head>
<body>
<img alt="对不起,你要访问的页面没有找到,请联系管理员处理!"
src="${pageContext.request.contextPath}/img/404Error.png"/><br/>
3秒钟后自动跳转回首页,如果没有跳转,请点击<a href="${pageContext.request.contextPath}/index.jsp">这里</a>
</body>
</html>
include指令
在JSP中对于包含有两种语句形式:
- @include指令
- jsp:include指令
include指令是静态包含。静态包含的意思就是:把文件的代码内容都包含进来,再编译!
include指令细节注意问题:
- 被引入的文件必须遵循JSP语法。
- 被引入的文件可以使用任意的扩展名,即使其扩展名是html,JSP引擎也会按照处理jsp页面的方式处理它里面的内容,为了见明知意,JSP规范建议使用.jspf(JSP fragments(片段))作为静态引入文件的扩展名。
- 由于使用include指令将会涉及到2个JSP页面,并会把2个JSP翻译成一个servlet,所以这2个JSP页面的指令不能冲突(除了pageEncoding和导包除外)。
在1.jsp中把页头和页尾包含进来:
1 | <%@ page contentType="text/html;charset=UTF-8" language="java" %> |
taglib指令
用来说明JSP页面内使用的标签库
行为(内置标签)
JSP行为(JSP Actions)是一组JSP内置的标签,只书写少量的标记代码就能够使用JSP提供丰富的功能,JSP行为是对常用的JSP功能的抽象和封装。
jsp的常用标签有以下三个
- jsp:include标签
- jsp:forward标签
- jsp:param标签
include标签
- include标签语法是这个样子的
1 | <jsp:include page="relativeURL | <%=expression%>" flush="true|false" /> |
- jsp标签包含文件就是先编译被包含的页面,再将页面的结果写入到包含的页面中————属于动态包含
include标签和include指令的区别
<jsp:include>标签是动态引入, <jsp:include>标签涉及到的2个JSP页面会被翻译成2个servlet,这2个servlet的内容在执行时进行合并。
而include指令是静态引入,涉及到的2个JSP页面会被翻译成一个servlet,其内容是在源文件级别进行合并。
param标签
- 当使用<jsp:include>和<jsp:forward>标签引入或将请求转发给其它资源时,可以使用<jsp:param>标签向这个资源传递参数。
forward标签
<jsp:forward>标签用于把请求转发给另外一个资源。
forward标签就是对request.getRequestDispatcher(String url).forward(request,response)的封装
语法:
1
2<jsp:forward page="relativeURL | <%=expression%>" />
page属性用于指定请求转发到的资源的相对路径,它也可以通过执行一个表达式来获得。
directive标签
- directive的中文意思就是指令。该行为就是替代指令<%@%>的语法的
- <jsp:directive.include file=””/> 相当于<%@include file=”” %>
- <jsp:directive.page/> 相当于<%@page %>
- <jsp:directive.taglib/> 相当于<%@taglib %>
内置对象
每个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大对象的引用。
九个内置对象:
NO. | 内置对象 | 类型 |
---|---|---|
1 | pageContext | javax.servlet.jsp.PageContext |
2 | request | javax.servlet.http.HttpServletRequest |
3 | response | javax.servlet.http.HttpServletResponse |
4 | session | javax.servlet.http.HttpSession |
5 | application | javax.servlet.ServletContext |
6 | config | javax.servlet.ServletConfig |
7 | out | javax.servlet.jsp.JspWriter |
8 | page | java.lang.Object |
9 | exception | java.lang.Throwable |
————无需定义,即可直接使用
out对象
out对象的API
1 | int getBufferSize()【得到缓存大小】 |
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页面结束
out对象的原理如下:
- 只有向out对象中写入了内容,且满足如下任何一个条件时,out对象才去调用ServletResponse.getWriter方法,并通过该方法返回的PrintWriter对象将out对象的缓冲区中的内容真正写入到Servlet引擎提供的缓冲区中:
- 设置page指令的buffer属性关闭了out对象的缓存功能
- out对象的缓冲区已满
- 整个JSP页面结束
- 一般我们在JSP页面输出都是用表达式(<%=%>),所以out对象用得并不是很多!
page对象
内置对象page是HttpJasPage对象,其实page对象代表的就是当前JSP页面,是当前JSP编译后的Servlet类的对象。也就是说:page对象相当于普通java类的this
在开发中几乎不用
exception对象
- 内置对象exception是java.lang.Exception类的对象,exception封装了JSP页面抛出的异常信息。exception经常被用来处理错误页面
pageContext对象
pageContext是内置对象中最重要的一个对象,它代表着JSP页面编译后的内容(也就是JSP页面的运行环境)!
pageContext获取8个内置对象
既然它代表了JSP页面编译后的内容,理所当然的:它封装了对其他8大内置对象的引用!,也就是说,通过pageContext可以获取到其他的8个内置对象!
1 | <%@ page contentType="text/html;charset=UTF-8" language="java" %> |
pageContext作为域对象
类似于request,session,ServletContext作为域对象而言都有以下三个方法:
1 | 1、setAttribute(String name,Objcet o) |
当然了,pageContext也不例外,pageContext也有这三个方法!
pageContext本质上代表的是当前JSP页面编译后的内容,作为域对象而言,它就代表着当前JSP页面(也就是page)!也就是说:pageContext域对象只在page范围内有效,超出了page范围就无效了!
findAttribute(String name)方法介绍:
该方法是用于查找各个域中的属性的。当要查找某个属性时,findAttribute方法按照查找顺序”page→request→session→application”在这四个对象中去查找,只要找到了就返回属性值,如果四个对象都没有找到要查找的属性,则返回一个null。
pageContext对象中封装了访问其它域的方法:
1 | 1 public java.lang.Object getAttribute(java.lang.String name,int scope) |
代表各个域的常量
1 | 1 PageContext.APPLICATION_SCOPE |
PageContext引入和跳转到其他资源
PageContext类中定义了一个forward方法(用来跳转页面)和两个include方法(用来引入页面)来分别简化和替代RequestDispatcher.forward方法和include方法。
1 | <%"text/html;charset=UTF-8"%> contentType= |
使用include方法引入资源:
1 | <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> |
其他对象
request对象
- 内置对象request其实就是HttpServletRequest
response对象
- 内置对象response其实就是HttpServletResponse
config对象
- 内置对象config其实就是ServletConfig
session对象
- 内置对象session其实就是HttpSession。
注意:在page指令配置如下信息,session将不可使用
1 | <%@page session="false" %> |
application对象
- 内置对象application其实就是ServletContext对象
四种属性范围
- page【只在一个页面中保存属性,跳转页面无效】
- request【只在一次请求中保存属性,服务器跳转有效,浏览器跳转无效】
- session【在一个会话范围中保存属性,无论何种跳转均有效,关闭浏览器后无效】
- application【在整个服务器中保存,所有用户都可以使用】
4个内置对象都支持以下的方法:
No. | 方法 | 描述 |
---|---|---|
1 | public void setAttribute(String name,Object value) | 设置属性 |
2 | public object getAttribute(String name) | 取得属性 |
3 | public void removeAttribute(String name) | 删除属性 |
使用场景
1、request:如果客户向服务器发请求,产生的数据,用户看完就没用了,像这样的数据就存在request域,像新闻数据,属于用户看完就没用的。
2、session:如果客户向服务器发请求,产生的数据,用户用完了等一会儿还有用,像这样的数据就存在session域中,像购物数据,用户需要看到自己购物信息,并且等一会儿,还要用这个购物数据结帐。
3、application(servletContext):如果客户向服务器发请求,产生的数据,用户用完了,还要给其它用户用,像这样的数据就存在application(servletContext)域中,像聊天数据。
JavaBean
JavaBean遵循着特定的写法,通常有以下的规则:
- 有无参的构造函数
- 成员属性私有化
- 封装的属性如果需要被外所操作,必须编写public类型的setter、getter方法
————就是普通的java类。
在jsp中使用javabean
- <jsp:useBean>【在JSP页面中查找javaBean对象或者实例化javaBean对象】
- <jsp:setProperty>【设置javaBean的属性】
- <jsp:getProperty>【获取javaBean的属性】
jsp:useBean
<jsp:useBean>
标签用于在指定的域范围内查找指定名称的JavaBean对象:- 存在则直接返回该JavaBean对象的引用。
- 不存在则实例化一个新的JavaBean对象并将它以指定的名称存储到指定的域范围中。
语法:
1 | <jsp:useBean id="beanName" class="package.class" scope="page|request|session|application"/> |
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36如果JSP不支持`<jsp:useBean>`这个行为,我们要使用Person类是这样使用的:
<%--这里需要导入Person类--%>
<%@ page import="domain.Person" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title></title>
</head>
<body>
<%
//new出对象
Person person = new Person();
person.setName("zhongfucheng");
System.out.println(person.getName());
%>
</body>
</html>
使用<jsp:useBean>:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title></title>
</head>
<body>
<jsp:useBean id="person" class="domain.Person" scope="page"/>
<%
person.setName("zhongfucheng");
System.out.println(person.getName());
%>
</body>
</html>
jsp:setProperty
- 语法:
1 | <jsp:setProerty name="对象名称" property="属性名" param="参数名" value="值"> |
在语法上可分为4种模式
- <jsp:setProperty name=”对象名称” property=”*“/>自动匹配
- <jsp:setProperty name=”对象名称” property=”属性名称”/>指定属性
- <jsp:setProperty name=”对象名称” property=”属性名称” param=”参数名称”/>指定参数【很少用】
- <jsp:setProperty name=”对象名称” property=”属性名称” value=”内容”/>指定内容【很少用】
当我们没有学习到
<jsp:setProperty>
时,我们获取表单的信息,然后导入到javaBean对象中是这样的一种情况:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33//表单页面代码:
<form action="/zhongfucheng/1.jsp" method="post">
用户名:<input type="text" name="username">
年龄:<input type="text " name="age">
<input type="submit" value="提交">
</form>
//处理表单提交过来数据的jsp的代码:
<jsp:useBean id="person" class="domain.Person" scope="page"/>
<%
int age = Integer.parseInt(request.getParameter("age"));
person.setAge(age);
System.out.println(person.getAge());
%>
//使用<jsp:setProperty>:
<jsp:useBean id="person" class="domain.Person" scope="page"/>
<%--指定属性名称为age--%>
<jsp:setProperty name="person" property="age"/>
<%
System.out.println(person.getAge());
%>
jsp:getProperty
<jsp:getProperty>标签用于读取JavaBean对象的属性,也就是调用JavaBean对象的getter方法,然后将读取的属性值转换成字符串后插入进输出的响应正文中。
语法:
1
<jsp:getProperty name="对象名" property="属性名"/>
EL表法式
主要用于读取数据,进行内容的显示。
语法:
1 | ${标识符} |
EL表达式如果找不到相应的对象属性,返回的的空白字符串“”,而不是null,这是EL表达式最大的特点。
获取数据
EL表达式语句在执行时,会调用pageContext.findAttribute方法,用标识符为关键字,分别从page、request、session、application四个域中查找相应的对象,找到则返回相应对象,找不到则返回”” (注意,不是null,而是空字符串)。
EL表达式可以很轻松获取JavaBean的属性,或获取数组、Collection、Map类型集合的数据
1 | <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> |
执行运算
支持关系运算符和逻辑运算符。
1 | <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> |
EL表达式11个内置对象
EL表达式主要是来对内容的显示,为了显示的方便,EL表达式提供了11个内置对象。
- pageContext 对应于JSP页面中的pageContext对象(注意:取的是pageContext对象)
- pageScope 代表page域中用于保存属性的Map对象
- requestScope 代表request域中用于保存属性的Map对象
- sessionScope 代表session域中用于保存属性的Map对象
- applicationScope 代表application域中用于保存属性的Map对象
- param 表示一个保存了所有请求参数的Map对象
- paramValues表示一个保存了所有请求参数的Map对象,它对于某个请求参数,返回的是一个string[]
- header 表示一个保存了所有http请求头字段的Map对象
- headerValues同上,返回string[]数组。
- cookie 表示一个保存了所有cookie的Map对象
- initParam 表示一个保存了所有web应用初始化参数的map对象
1 | <%--pageContext内置对象--%> |