jsp的基本认识与理解

简介:

JSP全称是JavaServer Pages,它和servlet技术一样,都是SUN公司定义的一种用于开发动态web资源的技术。

JSP这门技术的最大的特点在于,写jsp就像在写html,但:

它相比html而言,html只能为用户提供静态数据,而Jsp技术允许在页面中嵌套java代码,为用户提供动态数据。

相比servlet而言,servlet很难对数据进行排版,而jsp除了可以用java代码产生动态数据的同时,也很容易对数据进行排版。不管是JSP还是Servlet,虽然都可以用于开发动态web资源。但由于这2门技术各自的特点,在长期的软件实践中,人们逐渐把servlet作为web应用中的控制器组件来使用,而把JSP技术作为数据显示模板来使用。

程序的数据通常要美化后再输出:如果让jsp既用java代码产生动态数据,又做美化会导致页面难以维护。

让servlet既产生数据,又在里面嵌套html代码美化数据,同样也会导致程序可读性差,难以维护。

因此最好的办法就是根据这两门技术的特点,让它们各自负责各的,servlet只负责响应请求产生数据,并把数据通过转发技术带给jsp,数据的显示jsp来做。

Jsp的运行原理:

目标:

  • Web服务器是如何调用并执行一个jsp页面的?
  • Jsp页面中的html排版标签是如何被发送到客户端的?
  • Jsp页面中的java代码服务器是如何执行的?
  • Web服务器在调用jsp时,会给jsp提供一些什么java对象?

思考:JSP为什么可以像servlet一样,也可以叫做动态web资源的开发技术?

其实Jsp就是一个Servlet,所以我们要先介绍Servlet的相关技术,当我们第一次访问Jsp的时候,Jsp引擎都会将这个Jsp翻译成一个Servlet,这个java文件存放在Tomcat中的work目录中,这里,我们新建一个MyJsp.jsp页面,然后访问以下,我们看一下翻译后的源码:

以下是MyJsp.jsp页面的内容:

[html] view plain copy
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>  
  
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">  
<html>  
  <head>  
      
    <title>My JSP 'MyJsp.jsp' starting page</title>  
      
  </head>  
    
  <body>  
    This is my JSP page. <br>  
  </body>  
</html>

下面是翻译之后的源码:

[java] view plain copy
package org.apache.jsp;  
  
import javax.servlet.*;  
import javax.servlet.http.*;  
import javax.servlet.jsp.*;  
import java.util.*;  
  
public final class MyJsp_jsp extends org.apache.jasper.runtime.HttpJspBase  
    implements org.apache.jasper.runtime.JspSourceDependent {  
  
  private static final JspFactory _jspxFactory = JspFactory.getDefaultFactory();  
  
  private static java.util.List _jspx_dependants;  
  
  private javax.el.ExpressionFactory _el_expressionfactory;  
  private org.apache.AnnotationProcessor _jsp_annotationprocessor;  
  
  public Object getDependants() {  
    return _jspx_dependants;  
  }  
  
  public void _jspInit() {  
    _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();  
    _jsp_annotationprocessor = (org.apache.AnnotationProcessor) getServletConfig().getServletContext().getAttribute(org.apache.AnnotationProcessor.class.getName());  
  }  
  
  public void _jspDestroy() {  
  }  
  
  public void _jspService(HttpServletRequest request, HttpServletResponse response)  
        throws java.io.IOException, ServletException {  
  
    PageContext pageContext = null;  
    HttpSession session = null;  
    ServletContext application = null;  
    ServletConfig config = null;  
    JspWriter out = null;  
    Object page = this;  
    JspWriter _jspx_out = null;  
    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("<html>\r\n");  
      out.write("  <head>\r\n");  
      out.write("    \r\n");  
      out.write("    <title>My JSP 'MyJsp.jsp' starting page</title>\r\n");  
      out.write("    \r\n");  
      out.write("  </head>\r\n");  
      out.write("  \r\n");  
      out.write("  <body>\r\n");  
      out.write("    This is my JSP page. <br>\r\n");  
      out.write("  </body>\r\n");  
      out.write("</html>\r\n");  
    } catch (Throwable t) {  
      if (!(t instanceof SkipPageException)){  
        out = _jspx_out;  
        if (out != null && out.getBufferSize() != 0)  
          try { out.clearBuffer(); } catch (java.io.IOException e) {}  
        if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);  
      }  
    } finally {  
      _jspxFactory.releasePageContext(_jspx_page_context);  
    }  
  }  
}  

我们看到,这个类继承了org.apache.jasper.runtime.HttpJspBase,要想看到这个类的源码,我们需要下载tomcat的源码,然后找到这个类,源码如下:

[java] view plain copy
/* 
 * Licensed to the Apache Software Foundation (ASF) under one or more 
 * contributor license agreements.  See the NOTICE file distributed with 
 * this work for additional information regarding copyright ownership. 
 * The ASF licenses this file to You under the Apache License, Version 2.0 
 * (the "License"); you may not use this file except in compliance with 
 * the License.  You may obtain a copy of the License at 
 *  
 *      http://www.apache.org/licenses/LICENSE-2.0 
 *  
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 * See the License for the specific language governing permissions and 
 * limitations under the License. 
 */  
  
package org.apache.jasper.runtime;  
  
import java.io.IOException;  
  
import javax.servlet.ServletConfig;  
import javax.servlet.ServletException;  
import javax.servlet.http.HttpServlet;  
import javax.servlet.http.HttpServletRequest;  
import javax.servlet.http.HttpServletResponse;  
import javax.servlet.jsp.HttpJspPage;  
import javax.servlet.jsp.JspFactory;  
  
import org.apache.jasper.compiler.Localizer;  
  
/** 
 * This is the super class of all JSP-generated servlets. 
 * 
 * @author Anil K. Vijendran 
 */  
public abstract class HttpJspBase   
    extends HttpServlet   
    implements HttpJspPage   
          
      
{  
      
    protected HttpJspBase() {  
    }  
  
    public final void init(ServletConfig config)   
    throws ServletException   
    {  
        super.init(config);  
    jspInit();  
        _jspInit();  
    }  
      
    public String getServletInfo() {  
    return Localizer.getMessage("jsp.engine.info");  
    }  
  
    public final void destroy() {  
    jspDestroy();  
    _jspDestroy();  
    }  
  
    /** 
     * Entry point into service. 
     */  
    public final void service(HttpServletRequest request, HttpServletResponse response)   
    throws ServletException, IOException   
    {  
        _jspService(request, response);  
    }  
      
    public void jspInit() {  
    }  
  
    public void _jspInit() {  
    }  
  
    public void jspDestroy() {  
    }  
  
    protected void _jspDestroy() {  
    }  
  
    public abstract void _jspService(HttpServletRequest request,   
                     HttpServletResponse response)   
    throws ServletException, IOException;  
}  

好吧,看到了,继承了HttpServlet类,所以说其实Jsp就是一个Servlet

JSP脚本

JSP脚本就是JSP定义java代码的方式,有三种形式:

  • <% java代码 %>,该脚本中定义的java代码会出现在jsp文件生成的java文件的service方法中。所以service方法中能定义的,该脚本中都能定义。
  • <%! java代码 %>,该脚本中定义的java代码,会在成员位置。(很少用)
  • <%= java代码 %>,该脚本中定义的java代码,会输出到页面中。即输出语句中可以定义什么,这里就可以定义什么。在java类的service方法中。

JSP内置对象

在JSP页面中不需要获取和创建,可以直接使用的对象。

jsp一共有9个内置对象。(前四个为域对象)

  • PageContext pageContext。在当前页面共享数据。还可以获取其它八个内置对象。
  • HttpServletRequest request。范围为一次请求访问的多个资源(跳转)
  • HttpSession session。在一次会话的多个请求间共享数据。
  • ServletContext application。所有用户间共享数据。
  • HttpServletResponse response。响应对象。
  • Object page。当前页面(Servlet)的对象,相当于this.
  • ServletConfig config。Servlet的配置对象。
  • Throwable exception。异常对象。
  • JspWriter out。字符流输出对象,可以将数据输出到页面中。

out和response.getWriter()的区别:在tomcat给客户端做出响应之前,会先找response.getWriter()的缓冲区数据,再去找out缓冲区的数据。所以结论就是:response.getWriter()输出的内容永远在out之前,和书写位置无关。建议统一使用out来输出数据。

jsp代码修改后不用重启服务器,可以刷新后直接访问。

JSP指令

用于配置JSP页面,导入资源文件。格式如下:

指令有三个:

  1. page:用于配置JSP页面(必须的,没有这个就成了普通的静态页面了)
  2. taglib:导入标签资源(常用于导入jstl标签库)
  3. include:页面包含的,导入页面文件。通常用于提取多个jsp页面的共同内容,从而简化jsp页面,被包含的页面只需要写配置jsp标签和内容即可

比如: 

page指令的常用属性

  • contentType,设置响应体的MIME类型和字符集,并设置了当前页面的字符集(后者只有高级的开发工具才能生效,如果是低级的工具则需要配置pageEncoding属性来设置当前页面的字符集)
  • import,用来导包的,通常一个import占一行脚本。
  • errorPage,当前页面发生异常后,会自动跳转到指定的错误页面。
  • isErrorPage,标识当前页面是否是错误页面。如果该属性的值设为true,则可以直接使用内置的异常对象exception。默认为false,不让使用exception。

taglib指令,导入需要用到的标签库。

  • prefix属性来定义前缀,想定义啥就定义成啥,将来写“前缀名:”,就能展示标签库里的标签,等于是给标签库取了个别名。但是有一些约定俗成的命名,比如前缀c就代表jstl标签库。
  • uri属性定义标签库所在的地址。

include指令,通常用于将重复的jsp部分抽取成一个新的页面,然后在用到的地方用file属性来包含该页面即可。

JSP注释

  • 第一个就是使用HTML的注释,只能用于注释HTML代码片段。
  • 第二个就是JSP特有的注释<%-- 注释内容 --%>,可以注释所有。

EL表达式

发布了70 篇原创文章 · 获赞 1 · 访问量 2232

猜你喜欢

转载自blog.csdn.net/caozp913/article/details/103944676