深入理解JSP
在前面的登录案例中,登录失败后为了能够响应登录的错误信息。我特意创建了一个LoginErrorServlet用来动态地拼接错误信息。
【代码如下】
- LoginErrorServlet:登录失败,手动拼接login.html页面,并将错误信息动态地添加进去。
2. LoginErrorServlet:手动拼接html页面,动态展示登录错误信息。
说明:上述虽然能够达到我的需求。但是他有以下两个缺点:
- 拼接麻烦开发效率低;
- 阅读性差,代码难以维护;
问题:思考既然以前在servlet有上述缺点,为什么还要使用拼接呢?
因为如果我们想在html页面显示错误的信息,我们只能采用这种方式,html页面不能够书写java代码。而我们既不采用上述拼接标签的方式,还想实现简单的效果。我们可以使用jsp技术,在jsp中可以书写java代码同时还可以书写html标签。这样 就能够使用jsp技术在客户端和服务端直接进行数据交互了。
JSP全名为Java Server Pages,中文名叫java服务器页面,其本质是一个Servlet ,它是由Sun 公司倡导、许多公司参与一起建立的一种动态网页 技术标准。其实就是一个既能书写Servlet代码又能书写HTML代码的文件。
【图1 创建JSP】
文件内容如下:
jsp中既可以书写java代码,同时还可以书写html标签。我们完成练习如何在jsp页面中书写java代码。
【需求】
- 在jsp页面上获取当前日期,并将其格式化成字符串\”yyyy-MM-dd HH:mm:ss\”;
- 将这个字符串展示在浏览器上;
说明:
1)jsp中的注释:<%–注释内容–%>,添加注释的快捷键是:ctrl+/;
2)在jsp中书写代码有三种方式,我们这里先介绍一种,格式:
<%java代码%>
【参考代码】demo01.jsp
【运行结果】启动tomcat,并且访问这个jsp页面。
在浏览器看到 format格式的日期:
【控制台输出】
通过上面的jsp初体验, 我们看到jsp中既可以编写java代码也可以直接编写html代码,相对servlet更加方便.并且我们通过浏览器访问到的jsp页面,最后在浏览器中看到了响应到浏览器中的结果。那么整个过程的执行流程是怎样的呢,我们可以参考如下图:
通过上面的执行流程,我们可以找到jsp生成的.java源文件,这样就可以知道jsp的真正原理,同时可以看下jsp为什么是servlet。
如何查看生成的.java源文件呢?
我们可以到tomcat中查看一下上面案例中的jsp页面是怎么样的一种存在。IDEA借助tomcat发布web项目的机制:动态发布(为每一个web项目创建一个单独的发布文件)。我们可以通过tomcat其中日志中的CATALINA_BASE路径找到我们当前这个JSP页面在tomcat中的位置:
【图1 IDEA发布项目的路径】
找到这个目录后,会看到以下3个文件夹:
【图2 文件目录】
我们打开C:\\Users\\admin.IntelliJIdea2017.3\\system\\tomcat\\Tomcat_8_5_311_day05目录发现有两个文件:
【图3 JSP被翻译后的代码】
打开demo01_jsp.java文件后,代码如下所示:
我们可以看到当前的jsp文件被翻译成了一个类,这个类继承HttpJspBase类,那么这个HttpJspBase类又是什么?
注意:jsp的翻译由服务器完成,HttpJspBase类一定也是tomcat服务器的内容,所以我们需要找到org.apache.jasper.runtime.HttpJspBase这个类,这个类可以到tomcat的安装目录下的lib文件夹下找到jasper.jar,将其解压,找如下目录:org\\apache\\jasper\\runtime,找到HttpJspBase.class。
使用反编译工具打开,如下所示:
通过观察源码,根据我们所学习的继承关系,我们发现JSP其实底层就是一个servlet。通过观察源码,我们发现我们刚刚编写的所有代码都在该Servlet里面的service方法内部。
总结:
1.<% %>中书写的代码被直接解析成java代码;
2.jsp之所以可以编写html代码,其实本质上也是类似我们使用Servlet直接输出的。也就是说底层还是像我们之前做法一样进行标签拼接。html部分都被out.write(\”\”)方法以字符串的形式拼接,然后响应给浏览器;
3.在这个java文件中有个_jspService,这个方法有两个参数request,response;
4.由于我们自己编写的代码全部都落入到了service方法内部一开始就已经声明了request,response,session,application(ServletContext)等对象了,这些对象成为之jsp内置对象。
在JSP页面的body标签中,可以直接书写html代码和JS代码。但是,如果在JSP页面中书写java代码。必须遵循固定的格式,才能够生效;JSP页面中书写java代码有三种方式:1.脚本片段;2.脚本声明;3.脚本表达式;
脚本片段指的是一段java代码。书写格式:<% java 代码 %>
【示例】 demo02.jsp
【被翻译后的源码】
【页面结果】:
说明:通过查看jsp的源代码我们发现,脚本片段的代码都会存在service方法中,而方法中是不可以定义一个方法的。
脚本声明的格式:<%! 书写Java代码 %>
【示例一】声明成员变量 demo03.jsp
【被翻译后的代码】成员变量
虽然脚本声明和脚本片段已经可以书写Java代码了,但是如果我们要使用java代码向页面输出一些内容,还是需要 使用原来的response对象,比较繁琐,因此,我们需要一个更加简便的方式,可以代替response向页面输出内容 ——这个就是脚本表达式。
脚本表达式的格式:<%= 向浏览器输出的内容 %> 等价于:out.print( 向浏览器输出的内容)
【示例】在页面输出信息
注意:
上面代码中,我们书写代码的顺序是先:
再:
可是浏览器查看数据的结果是
原因:response.getWriter()获取的输出流是:PrintWriter。而脚本表达式<%=%> 等价于:out.print( 向浏览器输出的内容).并且这种方式获取的输出流是:JspWriter。其实导致上述输出结果前后顺序就是PrintWriter和JspWriter。
JspWriter:将输出的内容先放到jsp内置的缓冲区中,然后再刷新输出。
PrintWriter:是不使用jsp内置的缓冲区,直接将内容写到网页中。
总结:
1.不要同时使用脚本表达式和response同时往页面输出信息,会出现顺序不一致。现象:response会出现在最前面。使用一种输出即可。
2.脚本表达式<%= str %> :在页面输出内容,在service方法中起作用;
3.脚本片段<% %> :在service方法中,原样输出的代码片段;属于局部为,放在_jspService方法中
4.脚本声明:<%! String str = \”程序员\” %> :定义成员变量;
JSP指令(directive)是为JSP引擎而设计的,它们并不直接产生任何可见输出效果,而只是告诉引擎如何处理JSP页面中的其余部分。
指令用来声明JSP页面的一些属性,比如编码方式,文档类型。我们在servlet中也会声明我们使用的编码方式和响应的文档类型的,而JSP就是用指令来声明的。
【作用】
【格式】
【作用】
【格式】
【使用示例】
需求:课后的原型中的页面放到web文件夹下面。然后打开主页index.jsp.在主页中引入header.jsp页面。
【效果】
三大指令是什么?分别的作用是?
- page:设置网页上一些属性
- taglib:导入标签库
- include:包含另一个JSP页面
page是jsp中必须使用的一个指令,用于设置JSP上各种页面的属性,告诉tomcat如何将一个JSP翻译成Servlet
可以放在JSP中任何位置,一般建议放在页面的最顶部
方式一: 每个page指令导入一个类
方式二: 一个page指令的import属性导入所有的包,包之间使用逗号分隔
作用:相当于导包
【代码演示】
【作用】设置响应编码
1、通过page指令的errorPage属性指定:如果页面出错,转发到error.jsp这个页面
代码演示:
页面效果:
2、通过web.xml文件指定错误码:响应状态码为404则跳转到404.jsp页面
如果不指定,那么按照以前报错方式,会出现如下错误页面:
我们可以在web.xml进行配置跳转到更加好看一些的页面。
404.jsp页面代码:
3、通过web.xml文件指定错误类型:发生空指针,则跳转到null.jsp页面
demo02.jsp
报空指针异常后的页面:null.jsp
浏览器效果:
JSP动作标签利用XML语法格式的标记来控制Servlet引擎的行为 。利用JSP动作标签可以动态包含其他jsp页面、把用户跳转到另外的页面、为Java插件生成HTML代码。
JSP页面动作标签很多,常用的主要有以下3种:
【作用】
【语法】
【使用示例】
a.jsp
b.jsp
【动态包含和静态包含】
说明:
如果只是引入jsp,不需要改变,那么使用静态引入。如果引入的jsp页面是变化的,那么使用动态引入。
用于页面的转发,与request.getRequestDispatcher(\”/URL\”).foward(request,response);功能一样的
用于给<jsp:forward>和<jsp:include>提供参数
- forward作用
- param的功能
- 功能:用于转发,相当于request.getRequestDispatcher(\”/URL\”).forward(request, response)
- 语法
- 功能:给forward和include提供参数名和值
- 语法:做为子标签存在
- 需求:在c.jsp页面中使用转发标签forward转发到d.jsp页面。
- c.jsp页面
d.jsp页面:
- 从c.jsp转发到d.jsp
- c在请求域中添加键和值,d看能够得到值并且输出
- c转发的时候带参数,username和age,在d中获取并且输出
- 汉字乱码问题的解决
- 转发,url地址栏并没有发生改变
- forward作用:在JSP页面上实现转发
- param的功能:在转发的时候提供其它的参数名和参数值
我们发现,我们在JSP页面中书写的代码最终都会翻译到_jspService()方法中,我们发现这个方法中有两个形参:HttpServletRequest对象 ,HttpServletResponse对象 。所以说,JSP的本质就是一个Servlet。我们可以直接在JSP页面上使用这两个对象。
改造登录后的页面,用户登陆失败以后,跳转到login.jsp,在jsp页面中动态显示用户登陆错误中的信息。
【思路】
- 登录失败后直接转发到一个jsp页面;
- 在jsp页面上使用request对象获取request中的值;
【LoginServlet代码】
说明:LoginServlet中,登录失败之后,直接转发到login.jsp页面。
【login.jsp页面】
说明:上述代码中:
能够使用msg获取数据,因为编译之后存在于同一个类中,编译jsp如下所示:
效果图:浏览器访问login.html页面
登录密码输入错误:
小结:
- JSP作用:给浏览器生成响应信息;
- JSP特点:动态网页,html+java,由服务器来运行的。本质上是一个Servlet;
- 书写Java代码的三种方式:
- 脚本片段:java代码片段,在service方法中起作用。格式:<% System.out.println(\”hello\”) %>;
- 脚本表达式:直接在页面输出内容,在service方法中起作用,等价于out.print(内容)。格式:<%= \”上海打工摸鱼\”%>
- 脚本声明:定义成员变量,方法。在当前类中都起作用。<%!int a=10;%>
- JSP页面常用的对象:request,response;
迅速了解Servlet和JSP两者间的区别
JSP和Servlet都是与使用Java构建基于Web的应用程序有关的重要概念。 基本上,Servlet是Java中HTML,而JSP是HTML中的Java。 任何典型的Web开发面试都可能有几个基于JSP和Servlet的Java面试问题 。
尽管JSP和Servlet的主要目的是相同的,但是两者之间还是有一些重要的区别。 在深入研究两个Java概念之间的差异之前,让我们首先对它们有一个很好的了解。
Java Servlet或简称Servlet是在某些Web或应用程序服务器上运行的程序。 它们充当来自Web浏览器或HTTP客户端的入站请求与HTTP服务器上存在的应用程序或数据库之间的中间层。 Servlet允许:
- 通过网页表单收集用户输入
- 显示来自数据库或其他来源的记录
- 动态创建网页
由于它们是用Java编写的,因此Servlet与平台无关。 Servlet可以访问Java类库的完整功能。 Servlet能够通过套接字和RMI机制与applet,数据库和软件进行交互。
JSP的完整形式是Java Server Pages。 它是一项允许开发支持动态内容的网页的技术。 JSP使开发人员可以使用特殊的JSP标记在HTML网页中插入Java代码,这些标记通常以<%开头,以%>结尾。
JSP网页中JavaScript或HTML代码在客户端运行,而JSP本身与在服务器端运行的ASPX或PHP页面相同。 Java Server Pages是一种服务器端技术,它允许创建动态的,独立于平台的基于Web的应用程序。
JSP组件是一种Java Servlet,它可以充当基于Java的Web应用程序的用户界面。 JSP组合了HTML或XHTML代码,嵌入式JSP操作和命令以及嵌入式JSP操作。
可以将JSP标记用于多种用途,范围从数据库检索数据到访问JavaBeans组件以及在请求之间共享信息。
JSP是Java Enterprise Edition的基本部分。 因此,它是用于构建企业级应用程序的综合平台。
- 自定义标签
Servlet不提供用于构建可以直接调用Java bean的自定义标签的条件。 在这种情况下,JSP编程提供了一个优势,因为开发人员可以在JSP中构建可直接调用Java bean的自定义标签。
- 定义
从技术上讲,JSP是包含静态和动态数据的文本文档。 静态数据以基于文本的格式表示(例如HTML,XML和SVG),而JSP元素表示动态数据。
Servlet是一个Java类,它按照请求-响应模型扩展了承载应用程序的服务器的功能。
Servlet通常用于扩展由Web服务器托管的应用程序。 尽管如此,他们也可以响应各种类型的请求。 专门针对此类应用程序,Java Servlet技术指定了HTTP特定的servlet类。
- 轻松编码
尽管JSP和Servlet都能够生成动态内容,但是前者是网页脚本语言,而后者是Java程序。 使用JSP进行编码比编写Java Servlet更容易。 而且,JSP被编译为Java Servlet。
- 实作
在Java Servlet中,我们需要实现所有内容,例如业务逻辑。 单个Servlet文件包含业务逻辑和表示逻辑。 相反,在JSP中使用JavaBeans将业务逻辑与表示逻辑分离。
- 修改
修改Java Servlet需要大量时间。 这是因为它需要重新加载,重新编译和重新启动服务器。 相比之下,JSP修改很快。 一个简单的刷新就足以执行所有最新更改。
- MVC模式
当Servlet在MVC模式中扮演控制器角色时,JSP充当视图,即用于显示输出。
- 包
需要在Java Servlet中使用的任何软件包都必须导入到Servlet的顶部。 对于JSP,没有强制性的条件,在该程序包中,可以在顶部,中间或底部的任何位置导入软件包。
- 性能
Java Servlet和Java Server Pages的目的与使用Common Gateway Interface(即CGI)执行的程序的目的相同。 尽管两者都比CGI更好,但是JSP比Servlet慢。
Servlet以预编译形式出现。 因此,仅需要执行它。 JSP比Servlet慢。 这是因为JSP生命周期中的第一步是将JSP转换为Java代码,然后进行编译。
Servlet实现了用于开发基于Web的应用程序的基于组件,与平台无关的方法,但没有CGI程序的性能限制。 而且,Java Servlet可以访问完整的Java API集,并且还提供了更好的CGI性能。
除了具有在Web服务器的地址空间内执行的能力外,Servlet不必开发用于管理每个客户请求的单独流程。 使用Servlet和JSP优于使用CGI。
- 在后端运行JavaScript
JSP支持在客户端运行JavaScript以实现某些功能,但Java servlet不支持。
- 会话管理
在JSP中,会话管理是自动启用的。 相反,默认情况下禁用Java Servlet中的会话管理。 需要显式启用它。
- 结构体
Java Servlet与Java类相同,但是JSP编程则不是这样,因为JSP编程包含HTML和JavaScript代码。 尽管JSP应用程序已转换为Servlet,但它类似于包含嵌入HTML代码的Java代码的PHP文件。
- 支持请求
虽然JSP仅接受HTTP请求,但是Java Servlet可以接受所有类型的协议请求。 此外,我们可以在Servlet中重写service()方法,但在JSP编程中不允许这样做。
- 用例
JSP和Servlet都可以创建基于Web的应用程序。 但是,偏好是不同的。 当不需要大量数据处理时,首选JSP。 另一方面,当需要大量数据操作和处理时,Java Servlet最适合使用。
Servlet是用Java开发的服务器端程序。 另一方面,JSP是建立在Java Servlet之上的接口。 它将HTML代码嵌入一些基本Java代码。 JSP可以处理UI,并减少了设计屏幕所需的工作。
JSP的定制标记功能允许构建可重用的组件,因此比Servlet提供更大的灵活性。 此外,JSP是处理cookie管理以及会话跟踪的首选方法。
尽管如此,除了没有Servlet的概念就无法存在JSP之外,Servlet的功能远比JSP强大。
Web服务器与应用程序服务器之间的主要区别在于,Web服务器用于服务静态页面(例如HTML和CSS),而Application Server负责通过执行服务器端代码(例如JSP,Servlet或EJB)来生成动态内容。
感谢阅读,如果觉得本文对你有帮助,记得点个赞再走哦~
曾经风光无限的 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
文章为作者独立观点不代本网立场,未经允许不得转载。