JSP&Servlet6(一) --- 初探JSP
2017-06-12 22:55
274 查看
前面总结完了Servlet相关的基础知识, 现在来学习总结一下JSP.
下面我们以一个Hello World的例子, 来分析以下JSP和Servlet的关系, 以及JSP的生命周期.
例: 用JSP输出Hello Word, 并分析转译的Servlet代码.
JSP代码如下:
这就是最简单地JSP的一段代码, 那么, 我们看看它转译成Servlet将会变成什么样子. 转译后的Servlet代码如下(将会略去部分代码, 只保留部分代码):
那么, 这三个方法时从哪里来的呢? 如果我们想对请求来临的初始化/处理/善后想进行特别的处理是否应该重定义这三个方法?
在上述转译后的Servlet代码中, 我们可以看到, 该转译后的Servlet继承了org.apache.jasper.runtime.HttpJspBase类, 那么我们来大致查看一下HttpJspBase类中都有哪些方法, 他们的关系有时如何, HttpJspBase类代码如下:
通过上述代码可以看出Servlet的init()/destroy()/service()里面都调用了哪些方法.
init(): 其中调用了jspInit()和_jspInit().
_jspInit()是由转译后的Servlet进行自动重定义.
如果想自己设置初始化的操作, 可以重定义jspInit().
destroy(): 其中调用了jspDestroy()和_jspDestroy().
_jspDestroy()是由转译后的Servlet进行自动重定义.
如果想自己设置善后的操作, 可以重定义jspDestroy().
service(): 其中调用了_jspService(), JSP转译为Servlet后, 其中所定义的核心代码都在_jspService()中.
Servlet代码如下:
转译成JSP代码如下:
JSP中穿插Java代码: 写在<%%>中, 如下:
<% String name = request.getParameter(“name”); %>
JSP中穿插赋值语句: 写在<%=%>中, 如下:
<h1> hello!” + name + “!</h1> 转化为JSP代码为:<h1> hello! <%= name%></h1>
JSP中指示元素的格式: <%@指示元素 [属性=”值”]* %>, 如下:
<%@page contentType = “text/html” pageEncoding = “UTF-8” %>
类成员或方法的声明: 写在<%!%>中, 具体示例使用方法后面会详细谈到.
指示元素是在容器将JSP转译成Servlet代码的时候, 声明的一些必须遵守的信息. 在JSP中, 主要由三种常用的指示类型: page, include, taglib.
page: 告知容器如何转译目前的JSP网页.
include: 告知容器将别的JSP包含进来转译.
taglib: 告知容器如何转译这个页面的标签库(后面会谈到).
上述代码中的import/contentType/pageEncoding都是page指示元素的属性.
contentType: 告知容器在转译JSP时, 使用的HttpServletRequest的setContentType(), 属性值即为setContentType()方法的属性值.
pageEncoding: 告知容器这个JSP网页文字的编码, 以及内容类型附加的charset设置.
还有一些不常用的属性在此暂不列出.
假设有如下代码: includeDemo.jsp
header.jspf代码如下(.jspf文件是被.jsp文件include的文件, 本质上就是.jsp文件):
foot.jspf代码如下:
在上述includeDemo.jsp进行转译时, 会将header.jspf和foot.jspf包含进来进行转译, 也就是说将<%@include file = “header.jspf” %>和<%@include file = “foot.jspf” %>分别用header.jspf和foot.jspf文件进行替换.
include指示元素包含进来的JSP们, 最终只会转译生成一个Servlet文件, 而后面提到的的网页则会生成一个个独立的Servlet.
上述代码转译后在Servlet中会生成如下代码:
你可能会想, 这样声明和直接写Java代码(即后面提到的Scriptlet元素)有什么区别, 不都是转译到Servlet中了吗?
当然不是, 声明元素中所写的Java代码将会生成HttpJspBase类中像init()/destroy()/service()这样的方法成员或数据成员. 而直接写的Java代码, 都将转译到_jspService()方法中.
声明元素的作用之一就是前面提到的: 我们想自定义JSP的一些初始和结尾工作时, 可以在声明元素中重定义jspInit()和jspDestroy()方法.
JSP隐式对象的说明如下:
- out: 转译后对应JspWriter对象, 其内部关联一个PrintWriter对象.
- request: 转译后对应HttpServletRequest对象.
- response: 转译后对应HttpServletResponse对象.
- config: 转译后对应ServletConfig对象.
- application: 转译后对应ServletContext对象.
- session: 转译后对应HttpSession对象.
- pageContext: 转译后对应pageContext对象, 它提供了JSP页面资源的封装, 并可设置页面范围属性.
- exception: 转译后对应Throwable对象, 代表由其他JSP页面抛出的异常对象, 只会出现于JSP错误页面(isErrorPage属性设置为true的JSP页面).
- page: 转译后对应this.
需要注意的是: 隐式对象只能在<%%>与<%=%>之间使用, 因为隐式对象为_jspService()里面的局部变量, 无法在其他成员方法中使用.
然后在error.jsp中将page元素的isError属性设置为true. 随后在error.jsp中可通过打印隐式对象exception的错误信息(如异常堆栈信息), 以便后续处理.
1. JSP简介
JSP全称Java Server Pages, 是一种动态网页开发技术. JSP与Servlet是一体两面的, 因为JSP网页最终会被容器转译为Servlet源代码, 然后自动编译为.class文件, 再载入.class文件, 最后生成Servlet对象.下面我们以一个Hello World的例子, 来分析以下JSP和Servlet的关系, 以及JSP的生命周期.
例: 用JSP输出Hello Word, 并分析转译的Servlet代码.
JSP代码如下:
<html> <head> <title>Hello JSP</title> </head> <boay> <h1>Hello World!</h1> </body> </html>
这就是最简单地JSP的一段代码, 那么, 我们看看它转译成Servlet将会变成什么样子. 转译后的Servlet代码如下(将会略去部分代码, 只保留部分代码):
pubilc final class hello_jsp extends org.apache.jasper.runtime.HttpJspBase implements org.apache.jasper.runtime.JspSourseDependent{ //略... public void _jspInit(){ //略... } public void _jspDestroy(){ //略... } public void _jspService(HttpServletRequest request, HttpServletResponse response) throws java.io.IOException, ServletException{ //以下开始为JSP里面的隐式对象 PageContext pageContext = null; HttpSession session = null; ServletContext application = null; ServletConfig config = null; JspWriter out = null; Object page = this; //以上为JSP里面的隐式对象 JspWriter _jspx_out = null; PageContext _jspx_page_context = null; try{ //略... out.write("<html>\n"); out.write("<head>\n"); out.write("<title>Hello JSP</title>\n"); out.write("</head>\n"); out.write("<body>\n"); out.write("<h1>Hello World!</h1>\n"); out.write("</body>\n"); out.write("</html>\n"); }catch(Throwable t){ //略... }finally{ //略... } } }
JSP的生命周期
通过上面转译后的Servlet代码可以看到主要有三个重要的方法:_jspInit(), _jspDestroy(), _jspService()这三个方法, 对比Servlet, 我们可以大概猜到这三个方法分别是请求来临时的初始化操作, 请求来临时的善后操作, 请求来临时的处理操作.那么, 这三个方法时从哪里来的呢? 如果我们想对请求来临的初始化/处理/善后想进行特别的处理是否应该重定义这三个方法?
在上述转译后的Servlet代码中, 我们可以看到, 该转译后的Servlet继承了org.apache.jasper.runtime.HttpJspBase类, 那么我们来大致查看一下HttpJspBase类中都有哪些方法, 他们的关系有时如何, HttpJspBase类代码如下:
public abstract class HttpJspBase extends HttpServlet implements HttpJspPage{ //HttpJspBase是一个抽象类,说明该类的所有方法都应该由其子类来实现. public final void init(ServletConfig config) throws ServletException{ super.init(config); jspInit(); _jspInit(); } //略... public final void destroy(){ jspDestroy(); _jspDestroy(); } public final void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{ _jspService(request, response); } public void jspInit(){} public void _jspInit(){} public void jspDestroy(){} public void _jspDestroy(){} public abstract void _jspService(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException; }
通过上述代码可以看出Servlet的init()/destroy()/service()里面都调用了哪些方法.
init(): 其中调用了jspInit()和_jspInit().
_jspInit()是由转译后的Servlet进行自动重定义.
如果想自己设置初始化的操作, 可以重定义jspInit().
destroy(): 其中调用了jspDestroy()和_jspDestroy().
_jspDestroy()是由转译后的Servlet进行自动重定义.
如果想自己设置善后的操作, 可以重定义jspDestroy().
service(): 其中调用了_jspService(), JSP转译为Servlet后, 其中所定义的核心代码都在_jspService()中.
2. Servlet到JSP的转换
例: 将下面的Servlet代码转换为JSP代码Servlet代码如下:
@WebServlet("/hello.view") public class FirstServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); String name = request.getParameter("name"); out.println("<html>"); out.println("<head>"); out.println("<title>hello Servlet</title>"); out.println("<head>"); out.println("<body>"); out.println("<h1> hello!" + name + "!</h1>"); out.println("</body>"); out.println("</html>"); out.close(); } }
转译成JSP代码如下:
<%@page contentType = "text/html" pageEncoding = "UTF-8"%> <html> <head> <title>hello servlet</title> </head> <body> <% String name = request.getParameter("name"); %> <h1>hello! <%= name%></h1> </body> </html>
JSP代码格式总结
JSP的代码格式与HTML基本类似. 如等这些标签都遵循和HTML一样的格式.JSP中穿插Java代码: 写在<%%>中, 如下:
<% String name = request.getParameter(“name”); %>
JSP中穿插赋值语句: 写在<%=%>中, 如下:
<h1> hello!” + name + “!</h1> 转化为JSP代码为:<h1> hello! <%= name%></h1>
JSP中指示元素的格式: <%@指示元素 [属性=”值”]* %>, 如下:
<%@page contentType = “text/html” pageEncoding = “UTF-8” %>
类成员或方法的声明: 写在<%!%>中, 具体示例使用方法后面会详细谈到.
3. 指示元素
什么是指示元素?指示元素是在容器将JSP转译成Servlet代码的时候, 声明的一些必须遵守的信息. 在JSP中, 主要由三种常用的指示类型: page, include, taglib.
page: 告知容器如何转译目前的JSP网页.
include: 告知容器将别的JSP包含进来转译.
taglib: 告知容器如何转译这个页面的标签库(后面会谈到).
page指示类型
page指示类型使用示例:<%@page import = "java.util.Date" %> <%@page contentType = "text/html pageEncoding = UTF-8" %> ...
上述代码中的import/contentType/pageEncoding都是page指示元素的属性.
page指示元素的属性
import: 告知容器在转译JSP时, 必须在源代码包括的import陈述, 比如需要用到的Java的包等.contentType: 告知容器在转译JSP时, 使用的HttpServletRequest的setContentType(), 属性值即为setContentType()方法的属性值.
pageEncoding: 告知容器这个JSP网页文字的编码, 以及内容类型附加的charset设置.
还有一些不常用的属性在此暂不列出.
include指示类型
include指示类型使用示例:假设有如下代码: includeDemo.jsp
<%@ page contentType="text/html" pageEncoding="UTF-8" language="java" %> <%@include file="header.jspf"%> <h1>include 示范主体</h1> <%@include file="foot.jspf" %>
header.jspf代码如下(.jspf文件是被.jsp文件include的文件, 本质上就是.jsp文件):
<html> <head> <%@page pageEncoding="UTF-8" %> <title>include 示范开头</title> </head> <body>
foot.jspf代码如下:
<%@page pageEncoding="UTF-8" %> </body> </html>
在上述includeDemo.jsp进行转译时, 会将header.jspf和foot.jspf包含进来进行转译, 也就是说将<%@include file = “header.jspf” %>和<%@include file = “foot.jspf” %>分别用header.jspf和foot.jspf文件进行替换.
include指示元素包含进来的JSP们, 最终只会转译生成一个Servlet文件, 而后面提到的的网页则会生成一个个独立的Servlet.
4. 声明元素 Scriptlet元素 表达式元素 注释元素
声明元素
声明元素的语法为: <%! 类成员声明或方法声明%>, 示例如下:<%! String name = "dela"; String passwd = "123456"; boolean checkUser(String name, String passwd){ return this.name.equals(name) && this.passwd.equals(passwd); } %>
上述代码转译后在Servlet中会生成如下代码:
pubilc final class index_jsp extends org.apache.jasper.runtime.HttpJspBase implements org.apache.jasper.runtime.JspSourseDependent{ String name = "dela"; String passwd = "123456"; boolean checkUser(String name, String passwd){ return this.name.equals(name) && this.passwd.equals(passwd); } //略... }
你可能会想, 这样声明和直接写Java代码(即后面提到的Scriptlet元素)有什么区别, 不都是转译到Servlet中了吗?
当然不是, 声明元素中所写的Java代码将会生成HttpJspBase类中像init()/destroy()/service()这样的方法成员或数据成员. 而直接写的Java代码, 都将转译到_jspService()方法中.
声明元素的作用之一就是前面提到的: 我们想自定义JSP的一些初始和结尾工作时, 可以在声明元素中重定义jspInit()和jspDestroy()方法.
Scriptlet元素
Scriptlet元素就是前面提到的直接在JSP中编写Java代码, 格式为: <% Java语句 %>. 其示例前面都有提到过, 在此不过多赘述.表达式元素
表达式元素就是前面提到的赋值语句, 格式为<%=Java表达式 %>.其示例前面也都有提到过, 在此不过多赘述.注释元素
注释元素就是在JSP中的注释, 格式为:< !– 注释 – > .5. 隐式对象
简单的讲, 就是将Servlet里面一些常用的对象设置为JSP里面的隐式对象. 比如, JSP中的out就是Servlet里面的PrintWriter对象, request就是HttpServletRequest对象. 隐式对象的存在就是为了简化Java代码, 我们不必要再通过getxxxx()来取得这些常用的对象.JSP隐式对象的说明如下:
- out: 转译后对应JspWriter对象, 其内部关联一个PrintWriter对象.
- request: 转译后对应HttpServletRequest对象.
- response: 转译后对应HttpServletResponse对象.
- config: 转译后对应ServletConfig对象.
- application: 转译后对应ServletContext对象.
- session: 转译后对应HttpSession对象.
- pageContext: 转译后对应pageContext对象, 它提供了JSP页面资源的封装, 并可设置页面范围属性.
- exception: 转译后对应Throwable对象, 代表由其他JSP页面抛出的异常对象, 只会出现于JSP错误页面(isErrorPage属性设置为true的JSP页面).
- page: 转译后对应this.
需要注意的是: 隐式对象只能在<%%>与<%=%>之间使用, 因为隐式对象为_jspService()里面的局部变量, 无法在其他成员方法中使用.
6. 错误处理
在JSP中, 可用page指示元素的errorPage属性来指定错误处理页面来进行错误处理. 如下:<%@page errorPage = "error.jsp" %>
然后在error.jsp中将page元素的isError属性设置为true. 随后在error.jsp中可通过打印隐式对象exception的错误信息(如异常堆栈信息), 以便后续处理.
相关文章推荐
- JSP&Servlet6(二) --- JSP标准标签
- 关于开发高手2004第8期中,<jsp创建基于WEB的动态图表>一文中的些许错误
- Windows中Drag&Drop初探(一)
- Oracle & JSP 开发的小型信息管理系统 (五) 源代码4
- 编写 "纯HTML" jsp应用--学会使用 JSTL
- 编写 "纯HTML" jsp应用--学会使用 JSTL
- JSP页面错误:No form found under in locale 'zh_CN'
- Oracle & JSP 开发的小型信息管理系统 (六) 运行截图
- jsp+tomcat+mysql&sevlet&javabean配置全过程
- jsp+tomcat+mysql&sevlet&javabean配置全过程
- Windows中Drag&Drop初探(二)
- include file=""和jsp:include page=""的区别
- Oracle & JSP 开发的小型信息管理系统 (二) 源代码1
- Oracle & JSP 开发的小型信息管理系统 (四) 源代码3
- 如何使 FlashGet "正常合法" 下载 Session 中的自定义文件链接呢? JSP/Servlet 实现!
- Windows中Drag&Drop初探(三)
- 如何使 FlashGet "正常合法" 下载 Session 中的自定义文件链接呢? JSP/Servlet 实现!
- 在jsp页面上获取request.getAttribute("")
- Oracle & JSP 开发的小型信息管理系统 (七) 源代码5
- Hans's Top Ten JSP Tips(ZZ)