JSP隐藏对象原理及分析

1 前言

使用过JSP开发的朋友都知道,JSP页面不需要先创建即可直接使用类似request、response、session等对象,那么为什么可以直接使用呢?这就要从JSP实现原理解释了。
JSP页面最后都会解析为一个Servlet,也即一个java文件,存放路径为服务器work目录下,这里以tomcat服务器为例。
我的JSP页面解析存放路径为:
D:\neusoftProject\tomcat\学习tomcat7\work\Catalina\localhost\mybatis\org\apache\jsp
具体每个路劲解析含义如下
这里写图片描述
打开index_jsp.java文件,找到_jspService方法就会一目了然,内容如下

public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
        throws java.io.IOException, javax.servlet.ServletException {

    final javax.servlet.jsp.PageContext pageContext;
    javax.servlet.http.HttpSession session = null;
    java.lang.Throwable exception = org.apache.jasper.runtime.JspRuntimeLibrary.getThrowable(request);
    if (exception != null) {
      response.setStatus(javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
    }
    final javax.servlet.ServletContext application;
    final javax.servlet.ServletConfig config;
    javax.servlet.jsp.JspWriter out = null;
    final java.lang.Object page = this;
    javax.servlet.jsp.JspWriter _jspx_out = null;
    javax.servlet.jsp.PageContext _jspx_page_context = null;


    try {
      response.setContentType("text/html; charset=UTF-8");
      pageContext = _jspxFactory.getPageContext(this, request, response,
                null, true, 8192, true);
      _jspx_page_context = pageContext;
      application = pageContext.getServletContext();
      config = pageContext.getServletConfig();
      session = pageContext.getSession();
      out = pageContext.getOut();
      _jspx_out = out;

      out.write("\r\n");
      out.write("\r\n");
      out.write("<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \r\n");
      out.write("\t\"http://www.w3.org/TR/html4/loose.dtd\">\r\n");
      out.write("<html>\r\n");
      out.write("<head>\r\n");
      out.write("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\r\n");
      out.write("<title>Insert title here</title>\r\n");
      out.write("</head>\r\n");
      out.write("<body>\r\n");
      out.write("\tThis is my error.jsp<br/>\r\n");
      out.write("\t我可以获取错误信息:<br/>\r\n");
      out.write("\t");
      out.print(exception.fillInStackTrace());
      out.write("<br>  \r\n");
      out.write("</body>\r\n");
      out.write("</html>");
    } catch (java.lang.Throwable t) {
      if (!(t instanceof javax.servlet.jsp.SkipPageException)){
        out = _jspx_out;
        if (out != null && out.getBufferSize() != 0)
          try {
            if (response.isCommitted()) {
              out.flush();
            } else {
              out.clearBuffer();
            }
          } catch (java.io.IOException e) {}
        if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
        else throw new ServletException(t);
      }
    } finally {
      _jspxFactory.releasePageContext(_jspx_page_context);
    }
  }

对,JSP页面实际的解析工作就是放在_jspService方法中执行的,仔细看上面的变量定义,是不是很眼熟,我们的隐藏对象就是在服务器为我们自动创建了,所以才可以直接使用,那么接下来一个个讲解JSP中九大内置对象,也即隐藏对象。

2 request

request是javax.servlet.http.HttpServletRequest的实例,是作为 _jspService方法的参数传递过来的,跟我们在Servlet中的参数request使用完全一样,封装了一次请求的所有信息,每次客户端请求都会产生一个request实例。主要使用如下

<%
        // 设置属性值
        request.setAttribute("name", "张三");
        // 获取请求传递过来的参数值,注意Parameter与Attribute的区别
        request.getParameter("name");
        // 获取request域中的属性值,注意Parameter与Attribute的区别
        request.getAttribute("name");
        // 获取请求头信息
        request.getHeader("content-type");
    %>

3 response

response是javax.servlet.http.HttpServletResponse的实例,同样是作为 _jspService方法的参数传递过来的,封装了服务器返回给浏览器的所有信息,每次服务器端都会产生一个response实例,response在JSP页面并不常用,具体使用同Servlet中response对象一样。

4 pageContext

pageContext是javax.servlet.jsp.PageContext的实例,页面上下文对象,看代码可知由JSP工厂创建

pageContext = _jspxFactory.getPageContext(this, request, response,null, true, 8192, true);

主要作用是获取其他内置对象,如获取session、config、application等。

application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();

5 session

session是javax.servlet.http.HttpSession的实例,默认通过pageContext.getSession()获得,session用于服务器端保存用户信息,主要作用:session.getAttribute(“name”);用于获取session域对象值,session的作用域为一次会话。当设置page指令<%@ page session=”false” %>时,不能直接使用session隐藏对象。

6 application

application是javax.servlet.ServletContext的实例,application封装了JSP所在的Web应用程序的信息,例如web.xml中配置的全局的初始化信息。Servlet中application对象通过ServletConfig.getServletContext()来获取。JSP页面中由pageContext.getServletContext()获取,整个Web应用程序对应一个application对象。

主要方法:application.getAttribute("name"); 获取application域属性值。

7 config

config是javax.servlet.ServletConfig的实例,ServletConfig封装了配置在web.xml中初始化JSP的参数。JSP中通过config获取这些参数。每个JSP文件都有一个config对象。在JSP页面中默认由pageContext.getServletConfig()获取。主要作用:获取web.xml中定义的Servlet初始化信息

config.getInitParameter("configuration");

8 out

out是javax.servlet.jsp.JspWriter的实例,默认通过pageContext.getOut()获取,JSP页面中所有Html代码都会通过out.write方式输出。注意JspWriter与Servlet中PrintWriter的关系与区别。

1.都是继承自Java.io.Writer类.
JspWriter直接用out对象输出,PrintWrietr在JSP页面中必须用response.getWriter()方法得到其对象。

2.在JSP页面中同时调用两种方法向页面输出数据,

PrintWriter中的数据会输出在JspWriter前面.如: 
out.print("输出JspWriter");
PrintWriter pw = response.getWriter();
pw.print("输出PrintWriter");
浏览器显示:输出PrintWriter 输出JspWriter,说明不管JspWriter与PrintWriter在程序中的顺序怎么样,始终先会输出PringWriter中的数据然后再输出JspWriter中的数据.这是因为out对象相当于插入到了PrintWriter前面的缓冲区中.out对象满足一定条件时,才会调用PrintWriter对象的print()方法,把out缓冲区中的内容输出到浏览器端.如果想让上面的代码的按代码的先后顺序输出可以写成:
out.print("输出JspWriter");
out.flush();
PrintWriter pw = response.getWriter();
pw.print("输出PrintWriter");

浏览器结果:输出JspWriter输出PrintWriter 
note:out对象调用PrintWriter对象的print方法输出缓冲区中的内容的条件:
①设置page指令的buffer属性缓存为none功能,即buffer="none";
②写入到out对象中的内容充满了out对象的缓冲区;
③整个JSP页面结束;
④JSP中调用了out.flush()或response.flushbuffer()

9 page

page定义为final java.lang.Object page = this;即指向当前页面,JSP页面一般不使用该隐藏对象。

10 exception

exception定义如下

java.lang.Throwable exception = org.apache.jasper.runtime.JspRuntimeLibrary.getThrowable(request);

只要设置page指令<%@ page isErrorPage=”true” %>时才会创建exception隐藏对象,主要作用是获取异常信息。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值