本文被 系统学习JavaWeb 收录点击订阅专栏
文章目录
1 初探JSP
1.1 何为JSP?
JSP(java server pages), 即Java的服务器界面。其主要作用是 代替 Servlet 程序回传 html 页面数据。
因为 Servlet 程序回传 html 页面数据很繁琐,维护成本比较高。
如果通过Servlet程序回传html数据,演示代码如下:
importjavax.servlet.ServletException;importjavax.servlet.http.HttpServlet;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;importjava.io.IOException;importjava.io.PrintWriter;/**
* @author 兴趣使然黄小黄
* @version 1.0
* 演示传统Servlet回传html数据的繁琐
*/publicclassPrintHtmlextendsHttpServlet{@OverrideprotectedvoiddoGet(HttpServletRequest req,HttpServletResponse resp)throwsServletException,IOException{//通过响应的输出流回传html页面数据
resp.setContentType("text/html;charset=UTF-8");PrintWriter writer = resp.getWriter();
writer.write("<!DOCTYPE html>\r\n");
writer.write("<html lang=\"en\">\r\n");
writer.write("<head>\r\n");
writer.write(" <meta charset=\"UTF-8\">\r\n");
writer.write(" <title>Title</title>\r\n");
writer.write("</head>\r\n");
writer.write("<body>\r\n");
writer.write("这是html页面数据\r\n");
writer.write("</body>\r\n");
writer.write("</html>\r\n");
writer.write("\r\n");}}
而实际开发时,html的代码多达千行万行,可见,传统Servlet程序回传html的方式相当繁琐!
而JSP的主要作用就是代替Servlet程序回传html页面的数据:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html><head><metacharset="UTF-8"><title>Title</title></head><body>
这是html页面数据
</body></html>
如何访问JSP页面?
a.jsp访问地址:
http://ip:port/工程路径/a.jsp
1.2 JSP的本质
jsp页面的本质是一个Servlet程序。
当第一次访问jsp页面时,Tomcat服务器会帮我们把jsp页面翻译成为一个java源文件,并将它翻译成为.class字节码文件。
源代码中,jsp页面所翻译出来的类继承了HttpJSPBase类,该类直接继承了HttpServlet类。即,jsp翻译出来的java类,间接继承了HttpServlet类,是一个Servlet程序。
2 JSP的page指令
jsp的page指令可以修改jsp页面中的一些重要属性或行为。
属性说明language属性表示jsp翻译后是什么语言文件,目前只支持javacontentType属性表示jsp返回的数据类型。也是源码中response.setContentType()的参数值pageEncoding属性表示当前jsp页面文件本身的字符集import属性用于导包,导类autoFlush属性设置当out输出流缓冲区满了之后,是否自动刷新缓冲区,默认值是truebuffer属性设置out缓冲区的大小,默认8kberrorPage属性设置当jsp页面运行出错时,自动跳转的错误页面路径isErrorPage属性设置当前jsp页面是否有错误信息,默认是false,如果是true可以获取异常信息session属性设置访问当前jsp页面,是否会创建HttpSession对象,默认是trueextends属性设置jsp翻译出来的java类默认继承的父类
3 JSP中的常用脚本
3.1 声明脚本
声明脚本的语法格式:
<%! 声明java代码 %>
可以给jsp翻译出来的java类定义属性和方法,甚至是静态代码块,内部类等。
演示代码如下:
<%@ page import="java.util.Map"%><%@ page import="java.util.HashMap"%><%--Created by IntelliJIDEA.
User:26510Date:2022/10/17Time:8:52To change this template use File|Settings|FileTemplates.--%><%@ page contentType="text/html;charset=UTF-8" language="java"%><html><head><meta charset="UTF-8"><title>Title</title></head><body><%--1.声明类属性--%><%!privateString id;privateString name;privateint age;privatestaticMap<String,Object> map;%><%--2.声明static静态代码块--%><%!static{
map =newHashMap<String,Object>();
map.put("key1","value1");
map.put("key2","value2");}%><%--3.声明类方法--%><%!publicintsum(int a,int b){return a+b;}%><%--4.生成内部类--%><%!publicstaticclassA{privateString telephone;}%></body></html>
3.2 表达式脚本(常用)
表达式脚本的语法格式:
<%= 表达式 %>
可以在jsp页面上输出数据。
演示代码如下:
<%--1.输出整型--%><%=12%><br><%--2.输出浮点型--%><%=12.12%><br><%--3.输出字符串--%><%="我是黄小黄"%><br><%--4.输出对象--%><%=map %><br>
表达式脚本的特点:
- 所有的表达式脚本都会被翻译到_jspService方法中
- 表达式脚本会被翻译成为out.print()输出到页面上
- 由于表达式脚本翻译的内容都在_jspService方法中,所以_jspService方法中的对象都可以直接使用
- 表达式脚本中的表达式不能以分号结束
3.3 代码脚本
代码脚本的语法格式:
<% java语句 %>
可以在jsp页面中,编写自己需要的功能。
演示代码如下:
<%--1.代码脚本:if语句--%><%int i =10;if(i ==10){System.out.println("i = 10");}else{System.out.println("i != 10");}%><%--2.代码脚本:for语句--%><%for(int j =0; j <10; j++){System.out.println(j);}%><%--3.翻译后java文件中_jspService方法内的代码都可以写--%><%String username = request.getParameter("username");System.out.println("username = "+ username);%>
代码脚本的特点:
- 代码脚本翻译后在_jspService方法中
- 所有在_jspService方法中的现有对象都可以直接使用
- 可以由多个代码脚本组合成一个完整的java语句
- 代码脚本可以与表达式脚本一起组合使用,在jsp页面上输出数据
<%for(int j =0; j <10; j++){%><%=j %><%}%>
3.4 关于注释的说明
在jsp中分为三种注释:
- html注释
<!--html注释-->
该注释会被翻译在java源代码中,在_jspService方法中,以out.write输出到客户端。
- java注释
//单行注释/*多行注释*/
java注释会被翻译到java源代码中。
- jsp注释
<%--这是jsp注释--%>
jsp注释可以注释掉jsp中所有代码。
3.5 练习:在jsp页面中输出乘法表
test.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java"%><html><head><title>乘法表</title></head><body><table><%for(int i =1; i <=9; i++){%><tr><%for(int j =1; j <= i; j++){%><td><%=j +"x"+ i +"="+(j*i)%></td><%}%></tr><%}%></table></body></html>
4 JSP的内置对象
jsp的内置对象,是指,Tomcat服务器在翻译jsp页面成为Servlet源代码后,内部提供的九大对象。
4.1 jsp的九大对象概览
对象说明request请求对象response响应对象pageContextjsp的上下文对象session会话对象applicationServletContext对象configServletConfig对象outjsp的输出流对象page指向当前的jsp对象exception异常对象
其中exception异常对象需要在page指令的参数isErrorPage="true"时才存在。
4.2 四大域对象
域对象是可以像Map一样存取数据的对象,四个域对象的功能一样,区别是对数据的存取范围。
下表列举了四个域对象和作用范围
对象作用范围pageContext(PageContextImpl类)当前jsp页面范围request(HttpServletRequest类)一次请求内session(HttpSession类)一个会话范围内(打开浏览器访问服务器,直到关闭浏览器)application(ServletContext类)整个web工程范围内有效(只要web工程不停止,数据都在)
在进行代码演示前,需要导入Tomcat中lib目录下的jsp与Servlet的jar包!
演示代码如下:
<%@ page contentType="text/html;charset=UTF-8" language="java"%><html><head><title>Title</title></head><body><h1>scope.jsp页面</h1><%//在四个域中都分别保存了数据
pageContext.setAttribute("key","pageContext");
request.setAttribute("key","request");
session.setAttribute("key","session");
application.setAttribute("key","application");%>
pageContext域是否有值:<%=pageContext.getAttribute("key")%>
request域是否有值:<%=pageContext.getAttribute("key")%>
session域是否有值:<%=pageContext.getAttribute("key")%>
application域是否有值:<%=pageContext.getAttribute("key")%></body></html>
可以尝试多创建一个jsp页面,关闭浏览器,再次部署web项目打开服务器的方式一步步扩大范围,最终结果与表中所述一致!
四个域对象虽然都可以存取数据,但是 具有自己的优先顺序,优先级从小到大如下:
- pageContext
- request
- session
- application
4.3 out输出与response.getWriter输出的区别
response表示响应,用于设置返回给客户端的内容(输出);
out 也是给用户输出使用的。
演示案例:
虽然out语句在response之前,但是结果确是response在前,out在后。
<%@ page contentType="text/html;charset=UTF-8" language="java"%><html><head><title>Title</title></head><body><%
out.write("out输出1 <br/>");
out.write("out输出2 <br/>");
response.getWriter().write("response输出1 <br/>");
response.getWriter().write("response输出2 <br/>");%></body></html>
过程图解如下:
当jsp页面中的所有代码执行完成后会做如下的操作:
- 执行out.flush()操作,把out缓冲区中的数据追加写入到response缓冲区末尾
- 执行response的刷新操作,把数据写给客户端
由于jsp翻译的servlet程序中源码都是out进行输出的,为了避免打乱页面的内容顺序,所以在jsp中一般统一使用out输出。
关于out.write()与out.print()
方法说明out.write()输出字符串out.print()输出任意数据类型(转换成字符串后调用了write输出
5 JSP中的常用标签
5.1 静态包含
静态包含一般用于加载进页面显示后就再也不变的东西, 比如页眉、背景、标题等等。静态包含不会检查所含文件的变化,把文件包含进来后,被包含文件的修改变化是不会影响已被包含进来的内容的。
静态包含发生在编译阶段。比如:a.jsp中使用了语句 <%@ include file=“b.jsp”%>,把b.jsp包含了进来,那么在编译a.jsp文件时, 会直接把b.jsp文件的内容全部内嵌到a.jsp文件中包含b的语句的位置。 然后运行a,显示a页面。也就是说,静态include是先把被包含文件的内容全部复制内嵌到包含文件中,再进行编译运行的。也 正是因为要把b包含进a,所以b中的变量等不能与a重复,否则会报错。
演示案例:将footer.jsp内嵌在main.jsp中
footer.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html><head><title>Title</title></head><body>
脚页信息<br></body></html>
main.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html><head><title>Title</title></head><body>
头部信息<br>
主体内容<br>
<%@include file="/include/footer.jsp"%>
</body></html>
静态包含小结:
- 静态包含不会翻译被包含的jsp页面;
- 静态包含实际上是把被包含的jsp页面的代码拷贝到包含的位置执行输出。
5.2 动态包含
动态包含用于加载经常变化的、要求显示最新版本内容的东西。 比如提交时间戳:用户打开博客编辑页面时,有一个时间加载进来了。用户编写完博客,点击提交时,就应该使用/显示提交瞬间的时间而不是打开编辑页面时的那个时间。所以这里要用的就是最新时间。由上面我们知道,静态include是先包含进来,再编译,运行并传回浏览器显示的,所以不能满足我们要求某些部分使用最新内容的要求。那么,我们就要用到动态include。
动态include与静态include的最大不同在于:包含文件与被包含文件都是先编译执行,再包含。二者的编译阶段是相互独立的,只有在包含文件的include语句处把被包含文件的执行结果包含进来。 换言之,包含文件先编译,执行。执行到了include语句的时候才触发被包含文件的编译、执行,并实时把结果包含进来。从而达到获取最新的被包含内容的目的。同样使用a.jsp包含b.jsp的例子:加入a.jsp中动态include了b.jsp。现在,a先编译成servlet类文件,然后运行,当运行到包含b的语句处,引起b的编译,运行,并把b的运行servlet运行结果包含进a。最后a顺利运行完毕,把a的servlet类运行结果输出到浏览器显示。
案例代码:
footer.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html><head><title>Title</title></head><body>
脚页信息<br></body></html>
main.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html><head><title>Title</title></head><body>
头部信息<br>
主体内容<br><jsp:includepage="/include/footer.jsp"></jsp:include></body></html>
运行结果页面与上个案例一致(但是底层原理和对象有区别)
原理示意图:
动态包含小结:
- 动态包含会把包含的jsp页面也翻译成java代码;
- 动态包含底层代码使用如下代码调用被包含的jsp页面执行输出:
JspRuntimeLibrary.include(request, response,"/include/footer.jsp", out,false);
- 动态包含可以传递参数。
5.3 请求转发
之前学过的请求转发:
request.getRequestDispatcher("/include/footer.jsp").forward(request, response);
另一种形式
<jsp:forward page="/include/footer.jsp"></jsp:forward>
写在最后
本文部分内容参考:尚硅谷JavaWeb课程。好了,本文内容到这里就告一段落了,欢迎大家订阅专栏,加入JavaWeb学习!点击订阅
如果你有任何问题,欢迎私信,感谢您的支持!
版权归原作者 兴趣使然黄小黄 所有, 如有侵权,请联系我们删除。