目录
概述
jsp全称Java Server Pages(即java的服务器页面),是一种动态网页开发技术;
JSP的主要作用是代替Servlet程序回传HTML页面的数据;
jsp页面允许我们在html代码中嵌入java代码,这样就可以在html中使用java代码来完成功能;
创建步骤:web目录(或其他)右击 --> new --> JSP/JSPX --> 输入文件名 --> 选择JSP file创建
JSP和Servlet的关系:JSP本质上也是Servlet程序,
关系
浏览器可以直接运行html页面,但是不能直接运行jsp页面。
jsp是需要在web容器中运行(例如tomcat中),因为web容器中有JSP的运行环境。
第一次访问JSP页面时(运行Tomcat服务器后在浏览器地址栏输入路径),Tomcat服务器会将此JSP页面翻译成为一个Java源文件,并对其进行编译成为.class字节码文件(一个.java,一个.class),保存在在tomcat服务器里面的work目录中;运行完之后,把动态生成的html页面再使用io流写回给浏览器,浏览器接 收并且解析后再呈现出来;
jsp被tomcat服务器编译编译成的类,被默认继承HttpJspBase 类,而 HttpJspBase 类是 HttpServlet 的子类;即JSP翻译出来的Java类间接继承于HttpServlet类,证明JSP页面是一个Servlet程序
最核心的是有JSP的引擎(jasper.jar),它可以将jsp页面翻译成java程序,并编译成class文件,然后再运行。
综上可得:
-
jsp上本质是还是一个servlet程序
-
jsp=htm+java代码
生命周期
1.编译阶段
客户端第一次访问jsp的时候,服务器会把这个jsp页面翻译成对应的java文件,然后把java文件编译成对应的class文件
2.初始化阶段
服务器会加载这个class文件内容,并且创建出此servlet对象(因为jsp就是一个servlet),然后调用这个servlet对象中的init方法进行初始化。
如果我们想给jsp进行自定义的初始化内容,只要在【jsp声明(<%! %>)】中重写jspInit()方法即可;
3.执行阶段
客户端访问jsp页面的时候,服务器会调用其对应的servlet对象中的一个指定方法_jspService(request,response)。
是在这个_jspService(request,response)方法中使用io流,把动态生成的html一行一行写给了浏览器。
注:本来是调用servlet对象中的service方法的,但是在HttpJspBase中重写的service方法中又调用了这个_jspService(request,response)方法。
4.销毁阶段
当服务器正常关闭的时候,jsp对应的servlet对象会被销毁,并且调用servlet中的destroy方法。
如果我们在jsp对应的servlet对象销毁时完成一些工作时,只要在jsp声明中重写jspDestroy()方法即可。
指令
jsp的指令是给jsp引擎看的,让jsp引擎在翻译jsp页面成java文件的时候,知道需要注意哪些地方的设置。
格式:
<%@指令名字 属性="值" .. %>
同时对多个属性进行设置,中间以空格分隔
1,page指令
page是常用的一个jsp指令,可以用来指定当前jsp的一些基本设置;
常用属性: (1) language属性:表示JSP翻译之后是什么语言文件(目前只支持Java)
(2) contentType属性:表示JSP返回的数据类型是什么,即response.setContentType()的参数值(3) pageEncoding属性:表示当前JSP文件本身的字符集(可在IDEA右下角看到) (4) import属性:表示导包(导类),与Java一致 (5) autoFlush属性:设置当out输出流缓冲区满了之后是否自动刷新缓冲区,默认值是true (6) buffer属性:设置out缓冲区的大小,默认是8kb 注意:out缓冲区满了之后不能自动刷新的话会报错 (7) errorPage属性:设置当JSP页面运行出错时自动跳转到的页面(错误信息页面)的路径,这个 路径一般都是以斜杠打头,表示请求的地址是http://ip:port/工程路径/,对应代码web目录 (8) isErrorPage属性:设置当前JSP页面是否是错误信息页面,默认是false,如果是true指定当前页面为显示错误的页面,可以获取错误信息; (9) session属性:设置访问当前JSP页面时是否会创建HttpSession对象,默认值是true (10) extends属性:设置JSP页面翻译出来的Java类默认继承谁
2,include指令
include指令,可以将另一个页面的显示内容,引入到当前页面中的指定位置
格式:
<%@include file="" %>
3,taglib指令
taglib指令,在jsp中可以引入标签库,然后就可以使用标签库中的标签,来完成相应的功能了;
格式
<%@ taglib uri="*" prefix="*" %>
注意:
-
引入标签库,需要先在项目中引入对应的jar包
-
uri属性,指的是标签库的设置的URI地址
-
prefix属性,指的是给引入的标签库起一个别名,可以方便使用
代码
jsp页面中嵌入Java代码共有三种方式:
-
表达式脚本(expression)
-
代码脚本(scriptlet)
-
声明脚本(declaration)
1,表达式脚本
格式:
<%=表达式 %>
作用:在浏览器的JSP页面上输出数据(只有表达式可以在浏览器的页面上输出数据)
特点:
(1) 所有的表达式都会被翻译到对应的Java类的_jspService()方法中,故表达式可以直接使用_jspService()方法参数中的对象 (2) 表达式都会被编译后的Java类中的out.print()方法输出到浏览器页面上 (3) 表达式中的表达式不能以分号结束
2,代码脚本
格式:
<% Java语句 %>
作用:在JSP页面中可以编写需要的Java代码
特点: (1) 代码脚本翻译后都在_jspService方法中,代码脚本可以直接使用此方法参数中的对象 (2) 可以由多个代码脚本块组合完成一个完整的Java语句 (3) 代码脚本还可以和表达式脚本一起组合使用,在JSP页面上输出数据
3,声明脚本
格式:
<%! 声明Java代码 %>
作用:可以给JSP翻译出来的Java类定义属性、方法、静态代码块、内部类等
特点:不会在浏览器的页面上显示出来,仅存在于翻译后的Java类中
注释
JSP三种注释:
1,html/xml中的注释
格式:
<!-- html/xml中的注释方式 -->
特点:
HTML注释会被翻译到JSP文件对应的Java类的_jspService方法中,以out.write()输出到客户端, write方法会自动识别标签,执行标签对应的功能,不会在浏览器的页面上输出注释;
即:
-
用户在浏览器中右键查看源代码 【能】 看到这个注释
-
在服务器端,这个jsp页面被翻译成的java文件中 【能】 看到这个注释.
2,jsp中的注释
格式:
<%-- jsp中的注释方式(隐藏注释) --%>
特点:
JSP注释中的内容不会在JSP文件翻译后的Java类中出现,即注释中的内容没有任何功能
即:
-
用户在浏览器中右键查看源代码 【不能】看到这个注释。
-
在服务器端,这个jsp页面被翻译成的java文件中 [不能] 看到这个注释
3,java中的注释
java中的注释方式,只能在jsp的脚本或者声明中使用。也只有在脚本和声明中才会被认为是注释,会被翻译到JSP文件对应的Java类的_jspService方法中,在对应的Java类中也是注释;
特点:
-
用户在浏览器中右键查看源代码 【不能】 看到这个注释。
-
在服务器端,这个jsp页面被翻译成的java文件中 【能】 看到这个注释.
动作
JSP中内置的标签,称为jsp的动作元素;
本质就是把固定的Java代码,封装成标签的形式;
jsp的动作元素中,常用的有两个:
1,forward:页面跳转
<jsp:forward page="目标页面"></jsp:forward>
2,include:在当前页面包含另一个页面:
<jsp:include page="目标页面"></jsp:include>
页面包含
一个页面包含/引入另外一个页面有俩种方式
1,静态包含:
在jsp翻译成java程序的时候,直接将另一个页面的内容原封不动的写入到代码中。
使用指令:<%@include file="" %>
特点:
-
静态包含不会将被包含的JSP页面翻译成.java.class文件
-
静态包含是把被包含的页面的代码拷贝到body.jsp对应的Java文件的对应位置执行输出
适用场景:
2,动态包含:
在jsp翻译成java程序的时候,只会把包含的动作翻译成一个方法的调用,将来在访问的时候 才会真正的去获取另一个页面的内容。
使用动作:<jsp:include page="">/jsp:include
特点:
-
动态包含将被包含的JSP页面翻译成.java.class文件
-
动态包含还可以传递参数
-
动态包含底层使用如下代码调用被包含的JSP页面执行输出:org.apache.jasper.runtime.JspRuntimeLibrary.include(request, response, “/foot.jsp”, out, false);
底层原理:
动态包含可以传参,静态包含不能穿参
对象
在jsp页面代码中,可以直接使用的内置的对象,只要对象名字写对即可。
JSP九大内置对象:
类型 | 名字 | 作用 |
---|---|---|
PageContext | pageContext | 页面范围对象 |
HttpServletRequest | request | 请求对象 |
HttpSession | session | 会话对象 |
ServletContext | application | ServletContext对象 |
Object | page | 指向当前JSP的对象 |
HttpServletResponse | response | 响应对象 |
JspWriter | out | JSP输出流对象 |
ServletConfig | config | ServletConfig对象 |
Throwable | exception | 异常对象 |
注意:这些对象的类型和名字都是固定的,任意打开一个jsp页面翻译成的java代码,查看 _jspService方法,就可以看到这些内置的对象
默认情况下,jsp页面中是不能使用exception这个对象的,除非页面中设置了isErrorPage属性:
<%@ page isErrorPage="true" %>
JSP四大域对象:
域对象是指可以像Map一样存取数据的对象,四个域对象功能一样,只是对数据的存取范围不同
注意:若四个域对象在使用时范围都可满足要求,则使用的优先顺序是(范围从小到大): pageContext --> request --> session --> application
路径
jsp中 可以动态获得该项目的URL地址
代码演示:
<% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %>
将项目的基础URL地址,动态的拼接了出来,并且使用base标签,来指定页面中相对路径的参照点;
EL表达式
EL(Expression Language),称为EL表达式,目的是为了使JSP写起来更加简单
作用:代替jsp页面中的表达式在jsp页面中进行数据的输出。因为el表达式在输出数据的时候要比jsp的表达式脚本简洁的多;
语法格式:
${表达式}//例${name} 作用:获取域(javaweb四个域对象)中key为name的值
注:EL表达式在输出null值的时候输出的是空串,但是jsp表达式输出null值的时候输出的是null字符串;
EL表达式获取数据
代码示例:
<%--代码脚本--%> <% request.setAttribute("username","zs"); %> jsp表达式输出username:<%=request.getAttribute("username")%><br> jsp表达式输出password:<%=request.getAttribute("password")%><br> EL表达式输出username:${username}<br> EL表达式输出password:${password}<br>
结果:
EL表达式在jsp页面输出数据,主要是输出域对象中的数据
对于四个域对象,可以指定范围查找元素,也可以不指定范围寻值:
代码演示:
<% pageContext.setAttribute("key","pageContext"); request.setAttribute("key","request"); session.setAttribute("key","session"); application.setAttribute("key","application"); %> El表达式不指定范围查找:${key}<br> EL表达式指定范围查找:<br> pageContext:${pageScope.key}<br> request:${requestScope.key}<br> session:${sessionScope.key}<br> application:${applicationScope.key}<br>
结果:
EL表达式不指定范围寻值的搜索规则:按照从小到大(pageContext->request->session->application)的顺序搜索,找到就输出
EL表达式获取对象数据
代码示例
<body> <% String hobbies[]={"打篮球","下棋"}; List<String>friends=new ArrayList<>(); friends.add("zs"); friends.add("ls"); Map<String,String>map=new HashMap<>(); map.put("key1","value1"); map.put("key2","value2"); Person p=new Person(); p.setName("www"); p.setFriends(friends); p.setHobbies(hobbies); p.setMap(map); pageContext.setAttribute("person",p); %> EL表达式输出P对象:${person}<br> EL表达式输出name成员变量:${person.name}<br> EL表达式输出hobbies数组第一个元素:${person.hobbies[0]}<br> EL表达式输出hobbies数组的越界:${person.hobbies[10]}<br> EL表达式输出fiiends集合:${person.friends}<br> EL表达式输出friends集合的第一个元素:${person.friends[0]}<br> EL表达式输出map:${person.map}<br> EL表达式输出map集合第一个键对应的值:${person.map.key1}<br> <!--针对map集合的另一种写法,在key值有特殊符号时使用--> EL表达式输出map集合第一个键对应的值:${person.map[key1]}<br> </body>
结果:
EL表达式获取值其实是通过类的getter方法获取数据
EL的11个隐含对象
EL 个达式中 11 个隐含对象,是 EL 表达式中自己定义的,可以直接使用:
变量 | 类型 | 作用 |
---|---|---|
pageContext | PageContextImpl | 它可以获取 jsp 中的九大隐含对象 |
pageScope | Map<String,Object> | 它可以获取 pageContext 域中的数据 |
requestScope | Map<String,Object> | 它可以获取 request 域中的数据 |
sessionScope | Map<String,Object> | 它可以获取 session 域中的数据 |
applicationScope | Map<String,Object> | 它可以获取 application 域( ServletContext)中的数据 |
param | Map<String,String> | 它可以获取请求参数的值 |
paramValues | Map<String,String[]> | 它也可以获取请求参数的值,获取多个值的时候使用。 |
header | Map<String,String> | 它可以获取请求头的信息 |
headerValues | Map<String,String[]> | 它可以获取请求头的信息,它可以获取多个值的情况 |
cookie | Map<String,Cookie> | 它可以获取当前请求的 Cookie 信息 |
initParam | Map<String,String> | 它可以获取在 web.xml 中配置的<context-param>上下文参数 |
pageContext的使用:
EL表达式中的pageContext可以获取JSP中的九个隐含对象,JSP中的几个对象的原型我们可以查看其转换后的Servlet类得知。比如JSP中的request对象就是HttpRequest对象,session就是HttpSession对象,所以我们可以调用其暴露出来的getter方法,而EL表达式只不过是以“.”的形式执行其getter方法。 代码演示:
<body> 1.获取请求的协议: ${pageContext.request.scheme }<br> 2.获取服务器IP: ${pageContext.request.serverName }<br> 3.获取服务器端口: ${pageContext.request.serverPort }<br> 4.获取工程路径: ${pageContext.request.contextPath }<br> 5.获取请求方法: ${pageContext.request.method }<br> 6.获取客户端 IP: ${pageContext.request.remoteHost }<br> 7.获取会话ID: ${pageContext.session.id }<br> </body>
结果:
其他隐含对象的使用
代码演示:
<body> <%--隐含对象cookie的使用--%> 1.获取 Cookie 的名称:${cookie.JSESSIONID.name } <br> 2.获取 Cookie 的值:${cookie.JSESSIONID.value } <br> ------------------------------------<br> <%--隐含对象param,获取请求参数的值--%> <%--请求参数:?userName=123&hobby=c&hobby=java --%> 1.获取请求参数userName的值:${param.userName }<br> 2.获取请求参数userName的值:${paramValues.userName[0] }<br> 3.获取请求参数hobby的值 : ${paramValues.hobby[0] }<br> 4.获取请求参数hobby的值 : ${paramValues.hobby[1] }<br> --------------------------------------<br> <%--隐含对象header headerValues 获取请求头信息--%> 1.输出请求头【User-Agent】的值:${header['User-Agent'] } <br /> 2.输出请求头【User-Agent】的值:${headerValues['User-Agent'][0] } <br> 3.输出请求头【Accept-Language】的值:${header['Accept-Language'] } <br> 4.输出请求头【Connection】的值:${header.Connection } <br> 5.输出请求头【Host】的值:${header.Host } <br> -------------------------------------<br> <%--隐含对象initParam 获取web.xnl中配置的<context-param>上下文参数--%> 获取全局配置userName 的值:${initParam.userName } <br> </body>
结果:
EL表达式的运算符
1.关系运算
关系运算符 | 示例 | 结果 |
---|---|---|
== 或 eq | ${5 == 5} 或 ${5 eq 5} | true |
!= 或 ne | ${5 != 5} 或 ${5 ne 5} | false |
< 或 lt | ${2 < 8} 或 ${2 lt 8 } | true |
> 或 gt | ${2 > 8 } 或 ${2 gt 8 } | false |
<= 或 le | ${2 <= 2 } 或 ${2 le 2 } | true |
>= 或 ge | ${2 >= 6} 或 ${2 ge 6} | false |
2.逻辑运算
逻辑运算符 | 示例 | 结果 |
---|---|---|
&& 或 and | ${12 < 20 && 2 > 1} 或 ${12 < 20 and 2 > 1} | true |
|| 或 or | ${12 == 12 || 1 > 6} 或 ${12 == 12 or 1 > 6} | true |
! 或 not | ${! true} 或 ${not true} | false |
3.算数运算
算数运算符 | 示例 | 结果 |
---|---|---|
+ | ${10 + 1} | 11 |
- | ${10 - 1} | 9 |
* | ${10 * 2} | 20 |
/ 或 div | ${10 / 2} 或 ${10 div 2} | 5 |
% 或 mod | ${11 % 10} 或 ${11 mod 10} | 1 |
4.empty运算
empty 运算可以判断一个数据是否为空,如果为空,则输出 true,不为空输出 false。
为空的情况:
-
值为 null 值的时候,为空
-
值为空串的时候,为空
-
值是 Object 类型数组,长度为零的时候
-
list 集合,元素个数为零
-
map 集合,元素个数为零
5.三元运算符
表达式 1?表达式 2:表达式 3
如果表达式 1 的值为真,返回表达式 2 的值,如果表达式 1 的值为假,返回表达式 3 的值。
6."."点运算和[]中括号运算符
.点运算,可以输出 Bean 对象中某个属性的值。
[]中括号运算,可以输出有序集合中某个元素的值。
并且[]中括号运算,还可以输出 map 集合中 key 里含有特殊字符的 key 的值。
总结:
EL表达式目的是替代JSP脚本表达式可以使页面变得整洁,方便,避免<%= %>的出现。由于JSP中Java代码就是写在<%%>中的,这将导致不能与EL表达式一起使用,可以利用JSP中的各种标签替代Java代码,以结合EL表达式;
JSTL
JSTL(JSP Standard Tag Library),jsp标准的标签库,其目的也是简化jsp中java代码的编写;
使用:
导入坐标
<dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>taglibs</groupId> <artifactId>standard</artifactId> <version>1.1.2</version> </dependency>
在jsp页面上引入JSTL标签
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
标签使用
讲解:
<c:if>:逻辑判断,替换Java中的if选择结构c
<c:if test="true"> <h1>true/EL表达式</h1> </c:if> <c:if test="false"> <h1>false</h1> </c:if> //true和false的位置一般在使用常为EL表达式;构成更合适的结构
<c:forEach>:相当于for循环,用于遍历域中的集合,或者编写HTML页面中重复的部分;
重要的属性:
items:被遍历的容器
var:遍历产生的临时变量
varStatus:遍历状态对象
begin:开始数
end:结束数
step:步长
<c:forEach items="${lists}" var="list" varStatus="status"> //varStatus:属性,index从0开始,count:从1开始,记录循环的次数 <td>${status.count}</td> <td>${list.属性1}</td> <td>${list.属性2}</td> ...... <td>${list.属性3}</td> </c:forEach>
总结:jsp其本质还是servlet,jsp最后也会被tomcat(服务器)编译成一个.java与.class文件;jsp就是html+java,让我们能够将网页与java代码结合,但在实际中html加Ajax的形式已经在替代jsp,只是作为后端开发人员,你还是需要学习明白这一项技术;