JSP的基本使用总结
- JSP的全称是Java Server Pages,即Java的服务器页面
- JSP的主要作用是代替Servlet程序回传HTML页面的数据
- web目录(或其他)右击 –> new –> JSP/JSPX –> 输入文件名 –> 选择JSP file创建
JSP页面本质上是一个Servlet程序,第一次访问JSP页面时(运行Tomcat服务器后在浏览器地址栏输入路径),Tomcat服务器会将此JSP页面翻译成为一个Java源文件,并对其进行编译成为.class字节码文件(一个.java,一个.class),当打开.java文件时发现其中的内容是:
而HttpJspBase类直接继承于HttpServlet类,即JSP翻译出来的Java类间接继承于HttpServlet类,证明JSP页面是一个Servlet程序
JSP头部的page指令:
JSP头部的page指令可以修改JSP页面中的一些重要属性或行为
(以下属性均写在page指令中,默认page指令中没有出现的属性都采用默认值):
(1) contentType属性:表示JSP返回的数据类型是什么,即response.setContentType()的参数值
(2) language属性:表示JSP翻译之后是什么语言文件(目前只支持Java)
(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类默认继承谁
注意:以上默认值除非有特殊需要,否则不建议修改
格式:<%! 声明Java代码 %>
作用:可以给JSP翻译出来的Java类定义属性、方法、静态代码块、内部类等
特点:不会在浏览器的页面上显示出来,仅存在于翻译后的Java类中
代码演示:声明脚本的使用(此JSP文件在web目录下,名为First.jsp)
%@ page contentType=\”text/html;charset=UTF-8\” language=\”java\” %>
<%@ page import=\”java.util.HashMap\” %>
<%@ page import=\”java.util.Map\” %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%–1.声明类属性–%>
<%!
private String name;
private static Map<String, Object> map;
%>
<%–2.声明类方法–%>
<%!
public int sum() {
return 12;
}
%>
<%–3.声明静态代码块–%>
<%!
static {
map = new HashMap<String, Object>();
map.put(\”key1\”, \”value1\”);
}
%>
</body>
</html>
对应的翻译后的java源文件:
格式:<%=表达式 %>
作用:在浏览器的JSP页面上输出数据(只有此脚本可以在浏览器的页面上输出数据)
特点:
(1) 所有的表达式脚本都会被翻译到对应的Java类的_jspService()方法中,故表达式脚本可以 直接使用_jspService()方法参数中的对象
(2) 表达式脚本都会被编译后的Java类中的out.print()方法输出到浏览器页面上
(3) 表达式脚本中的表达式不能以分号结束
代码演示:表达式脚本的使用(此JSP文件在web目录下,名为First.jsp)
<%=22 %> <br/>
<%=\”可以输出字符串\” %> <br/>
<%=map %> <br/>
<%–使用_jspService方法中的对象–%>
<%=request.getParameter(\”username\”) %>
启动Tomcat服务器后浏览器的运行结果:
对应的翻译后的Java源文件(在_jspService方法中):
注意:
1.write方法中的标签、转义字符自动识别为对应的
功能,不在页面输出,执行各自代表的功能
2.out的两个方法也在_jspService方法中,也都是java语言
3.只有print、write方法、表达式脚本中的内容才可在浏览器中显示,其余Java代码的sout在控制台输出
格式:<% Java语句 %>
作用:在JSP页面中可以编写需要的Java代码
特点:
(1) 代码脚本翻译后都在_jspService方法中,故代码脚本可以直接使用此方法参数中的对象
(2) 可以由多个代码脚本块组合完成一个完整的Java语句
(3) 代码脚本还可以和表达式脚本一起组合使用,在JSP页面上输出数据
代码演示:代码脚本的使用(此JSP文件在web目录下,名为First.jsp)
<%–1.if语句–%>
<%
int i = 1;
if (i == 1) {
System.out.println(\”我爱祖国!\”);
} else {
System.out.println(\”我很爱祖国!\”);
}
%> <br/>
<%–2.for循环语句–%>
<%
for (int j = 0 ; j < 3; j++) {
System.out.println(\”第\” + j + \”次循环\”);
}
%> <br/>
<%–3.使用_jspService方法参数中的对象–%>
<%
String username = request.getParameter(\”username\”);
System.out.println(\”username对应的值为:\” + username);
%>
运行结果:
启动Tomcat服务器后在地址栏输入:http://localhost:8080/MyTest/First.jsp?username=Jaychou
在控制台显示:
对应的翻译后的Java源文件(在_jspService方法中):
1.HTML注释:<!–HTML注释–>
HTML注释会被翻译到JSP文件对应的Java类的_jspService方法中,以out.write()输出到客户端,
write方法会自动识别标签,执行标签对应的功能,不会在浏览器的页面上输出注释
2.Java注释:(1) //单行注释 (2) /*多行注释*/
Java注释要写在声明脚本和代码脚本中才被认为是Java注释,会被翻译到JSP文件对应的Java类的_jspService方法中,在对应的Java类中也是注释
3.JSP注释:<%- -这是JSP注释- -%>
JSP注释中的内容不会在JSP文件翻译后的Java类中出现,即注释中的内容没有任何功能
JSP的内置对象指的是Tomcat服务器将JSP页面翻译为Java类之后内部提供的九大对象:
(将page指令的isErrorPage属性写成true可以出现exception对象)
request:请求对象
response:响应对象
pageContext:JSP的上下文对象
session:会话对象
application:ServletContext对象
config:ServletConfig对象
out:JSP输出流对象
page:指向当前JSP的对象
exception:异常对象
域对象是指可以像Map一样存取数据的对象,四个域对象功能一样,只是对数据的存取范围不同
代码演示1:四个域对象存取数据的范围的不同(在web目录下创建scope1.jsp)
<%@ page contentType=\”text/html;charset=UTF-8\” language=\”java\” %>
<html>
<head>
<title>scope1</title>
</head>
<body>
<h1>scope1.jsp页面</h1>
<%
//向四个域对象中分别保存数据
pageContext.setAttribute(\”key\”, \”pageContext\”);
request.setAttribute(\”key\”, \”request\”);
session.setAttribute(\”key\”, \”session\”);
application.setAttribute(\”key\”, \”application\”);
%>
<%– <jsp:forward page=\”\”></jsp:forward>是请求转发标签,
page属性设置请求转发的路径 –%>
<jsp:forward page=\”/scope2.jsp\”></jsp:forward>
</body>
代码演示2:在web目录下创建scope2.jsp
<head>
<title>Title</title>
</head>
<body>
<h1>scope2.jsp页面</h1>
<%– JSP页面中不加任何标签直接输入的内容被write方法输出在浏览器的页面上 –%>
pageContext域是否有值:<%=pageContext.getAttribute(\”key\”)%> <br>
request域是否有值:<%=request.getAttribute(\”key\”)%> <br>
session域是否有值:<%=session.getAttribute(\”key\”)%> <br>
application域是否有值:<%=application.getAttribute(\”key\”)%> <br>
</body>
运行结果1:
运行结果2:
注意:若四个域对象在使用时范围都可满足要求,则使用的优先顺序是(范围从小到大):
pageContext –> request –> session –> application
1.相同点:response表示响应,用于给客户端(浏览器)返回内容
out同样也是用于给客户端(浏览器)输出内容
2.不同点:
3.注意:由于官方的代码中翻译后的Java代码底层都是使用out进行输出,故一般都使用out进行 输出,out又分为write方法和print方法:
(1) out.print():会将任何内容转换成字符串后调用write方法输出
(2) out.write():输出字符串没有问题,但输出int型时会将int转换成char输出,导致输出的并非是想要的数字而是数字对应的ASCII码
结论:JSP页面的代码脚本中任何要输出在浏览器的内容均使用out.print()方法
(1)使用场景:
(2)使用方法:
<%@include file=\”\”%>
其中file属性设置要包含的JSP页面,以/打头,代表http://ip:port/工程路径/,对应web目录
代码演示1:在web目录下创建body.jsp
<body>
头部信息 <br>
主体信息 <br>
<%@include file=\”/foot.jsp\”%>
</body>
代码演示2:在web目录下创建foot.jsp
<body>
页脚信息 <br>
</body>
运行结果:
(3)静态包含的特点:
①静态包含不会将被包含的JSP页面翻译成.java.class文件
②静态包含是把被包含的页面的代码拷贝到body.jsp对应的Java文件的对应位置执行输出
(1)使用方法:
<jsp:include page=””></jsp:include>
其中page属性设置要包含的JSP页面,与静态包含一致
(2)动态包含的特点:
①动态包含将被包含的JSP页面翻译成.java.class文件
②动态包含还可以传递参数
③动态包含底层使用如下代码调用被包含的JSP页面执行输出:
org.apache.jasper.runtime.JspRuntimeLibrary.include(request, response, “/foot.jsp”, out, false);
代码演示1:在web目录下创建body.jsp
<body>
头部信息 <br>
主体信息 <br>
<jsp:include page=\”/foot.jsp\”>
<jsp:param name=\”username\” value=\”Jaychou\”/>
<jsp:param name=\”password\” value=\”root\”/>
</jsp:include>
</body>
注意:
- 设置参数的标签要写在动态包含之中
- 出现Expecting “jsp:param” standard action with “name” and “value” attributes异常,两个原因:
①动态包含中未设置参数但没有把<jsp:include page=””></jsp:include>放在一行上
②动态包含中加了注释
代码演示2:在web目录下创建foot.jsp
<body>
页脚信息 <br>
<%=request.getParameter(\”username\”)%>
</body>
运行结果:
(3)动态包含的底层原理:
(1) Listener监听器是JavaWeb的三大组件之一
(2) Listener监听器是JavaEE的规范(接口)
(3) Listener监听器的作用是监听某件事物的变化,然后通过回调函数反馈给程序做一些处理
ServletContextListener监听器可以监听ServletContext对象的创建和销毁(web工程启动时创建,停止时销毁),监听到创建和销毁之后都会调用ServletContextListener监听器的方法进行反馈:
public interface ServletContextListener extends EventListener {
//在ServletContext对象创建之后调用
public void contextInitialized(ServletContextEvent sce);
//在ServletContext对象销毁之后调用
public void contextDestroyed(ServletContextEvent sce);
}
(1) 编写一个类实现ServletContextListener接口
(2) 重写两个方法
(3) 在web.xml文件中配置监听器
代码演示1:创建一个类
ublic class ListenerTest implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
System.out.println(\”ServletContext对象创建\”);
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
System.out.println(\”ServletContext对象销毁\”);
}
}
代码演示2:在web.xml中配置
<listener>
<!– <listener-class>标签中写上述程序的全类名 –>
<listener-class>com.qizegao.servlet.ListenerTest</listener-class>
</listener>
运行结果:
Tomcat服务器启动之后控制台输出ServletContext对象创建
Tomcat服务器停止之后控制台输出ServletContext对象销毁
注意:
- 查看翻译后的Java源文件的方法:启动Tomcat服务器访问到JSP页面之后在控制台输出的信息的前端找到Using CATALINA_BASE中的路径,在硬盘中打开此目录,点击work –> Catalina –> localhost,找到对应的工程文件夹寻找即可
- 访问JSP页面其实是在执行对应的翻译后的Java代码的_jspService方法:翻译后的Java类中没有service方法,而是重写了父类的_jspService方法,这个方法会被父类的service方法调用
[机智]
曾经风光无限的 JSP,为什么现在很少有人使用了?
来源 | 愚公要移山(ID:fdd_sxu_nwpu)
jsp技术作为曾经一度火爆的技术,在最近几年确实使用率越来越低了,这篇文章带你一块探究一下jsp的从生到死。
jsp技术的诞生
在很久很久以前,那时候我们的开发都是通过servlet来完成的,这个servlet是什么呢?我们先来认识一下:
servlet用Java语言编写的服务器端程序。主要功能是和浏览器进行交互,生成页面展示。
长下面这个样子:
我们可以看到前端所展示的页面,需要我们servlet去一个标签一个标签去生成,如果一个页面超级复杂,动不动几千行代码,那这个servlet效率也就太低了。而且整个servlet代码也会十分臃肿而且可读性非常差。
这时候怎么办呢?sun公司很早就意识到了这个问题,于是便倡导很多公司一块来创建了一种能够动态生成html的新技术,不久之后jsp便诞生了。有效率的解决了上面servlet所出现的问题。
jsp的发展
既然jsp技术能够解决刚刚servlet代码里面所出现的技术,我们来看一下是如何解决的:在这里我们举一个小例子,就是前端jsp向服务器servlet发送请求图书页面的功能。
首先我们看一下servlet:
我们会发现,现在的servlet没有一点html代码了。我们只需要把数据交给jsp。此时我们的页面展示就交给jsp来做了。现在我们来看一下jsp长什么样子:
这就是jsp,我们可以在html页面中写一些java代码。对于我们程序员来说,在开发当中静态的页面我们只需要用html和css写一些标签来展示即可,对于那些动态的部分我们就可以使用java代码。
那么jsp和servlet是不是就是这种协作的关系,本质上有什么区别呢?
其实jsp只是servlet的一种特殊形式,每一个jsp页面就是一个servlet实例,通俗一点的话来说:jsp就是servlet,只不过servlet把一些业务功能剥离开来交给了或者是形成了jsp。明白了吧。在我们的项目编译的时候就是把jsp编译成了servlet。
你们会发现,这样做其实挺好的,市场也验证了一切,很快jsp技术流行开来,可是随着时间的流逝,业务越来越复杂,jsp也开始跟不上时代了。
jsp的危机
我们先看一个对话场景:
java程序员:终于写完了功能,是时候在界面上展示了。
前端程序员:你功能写完了,我没有数据,在页面什么没法展示呀
java程序员:数据我写好了,你在jsp中调用XX方法就能获取了,
前端程序员:我已经在jsp中写好了这个方法,你为什么自己写了?
于是乎,无穷无尽的争吵还在继续当中。
这就是jsp的弊端,为什么呢?我们可以来总结一下:
(1)动态和静态资源放在一起,一旦服务器出现状况,前后台一起玩完,用户体验极差。
(2)一旦jsp出现了问题,就需要前端后端发开人员一块来分析解决,效率低。
(3)jsp无法使用nginx等。
(4)jsp页面复杂,难以修改。
(5)第一次加载jsp需要编译成servlet,时间久,而且业务量大的时候,jsp负担太大。
(6)jsp对于开发人员简直就是一个挥之不去的痛,太难了!!!
鉴于以上缺点,于是另外一套机制横空出世了,这就是前后端分离。什么是前后端分离呢?
前后端分离其实就是后端工程师只关注于后端页面的开发,不再处理前端问题。前端工程师只关注于自己的页面开发。需要数据交互的时候,两者会有一份接口文档。
就这样这种思想架构很快的流行开来,这也就是为什么jsp落寞的真正原因。从此java从jsp转向了restful结构,springMCV也开始流行开来,并逐渐占领了市场。前后端分离有什么优点呢?我们来总结一下:
(1)动态和静态资源分开存储。
(2)出现bug能很快定位是前端还是后端。
(3)支持nginx。在高并发状态下极其优秀。
(4)直接请求页面,不用编译,速度效率都提上来了。
(5)从此前端和后端是相亲相爱的一家人了!!!!
jsp的落幕
又随着时间的推移,jsp的时代基本上一去不复返了,因为我们又走入了移动互联时代,这时候的客户端可不是前端页面了,还包括手机、汽车、电视等等各种设备,这种情况下,前后端必须要分离了。jsp基本上彻底告别了它的舞台。
本文作者及来源:Renderbus瑞云渲染农场https://www.renderbus.com
文章为作者独立观点不代本网立场,未经允许不得转载。