JSP介绍与简单使用

JSP全名为Java Server Pages,中文名叫java服务器页面,其根本是一个简化的Servlet设计,它是由Sun Microsystems公司倡导、许多公司参与一起建立的一种动态网页技术标准。JSP技术有点类似ASP技术,它是在传统的网页HTML(标准通用标记语言的子集)文件(.htm,.html)中插入Java程序段(Scriptlet)和JSP标记(tag),从而形成JSP文件,后缀名为(*.jsp)。 用JSP开发的Web应用是跨平台的,既能在Linux下运行,也能在其他操作系统上运行。

Servlet是JSP的技术基础,而且大型的Web应用程序的开发需要Java Servlet和JSP配合才能完成。JSP具备了Java技术的简单易用,完全的面向对象,具有平台无关性且安全可靠,主要面向因特网的所有特点。通常在项目开发中,都是以JSP来编写展示层面,Servlet则编写逻辑层。

因为在JSP中可以写HTML代码,在Servlet中则不行,就是因为在Servlet中不能直接写HTML代码,所以我们想要生成一个页面相当麻烦,只能通过Java代码一行行的输出HTML代码。而JSP就是为了解决这种问题所发展出来的技术,在JSP中我们即可以编写HTML代码也可以编写Java代码,不过主要以页面代码为主,所以才说JSP用来写展示层而Servlet则编写逻辑层。从以上介绍就可以得知JSP与Servlet最大的区别就是:前者可以在页面代码中编写Java代码,而后者只能是在Java代码中编写页面代码。只需要想想页面代码多还是Java代码多,就知道为什么需要有JSP这个技术了233。

<br>

JSP的访问流程与原理


想要访问JSP文件很简单就好像访问HTML文件一样,直接在浏览器的地址栏上输入JSP文件的路径,一回车就可以访问了:
JSP介绍与简单使用

<br>

其实看似简单的背后,是需要经历好几个步骤的,下面我们就来看看JSP背后的运行流程原理:

首先打开Tomcat中的web.xml文件,可以找到以下配置语句:

   <servlet>
        <servlet-name>jsp</servlet-name>
        <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
        <init-param>
            <param-name>fork</param-name>
            <param-value>false</param-value>
        </init-param>
        <init-param>
            <param-name>xpoweredBy</param-name>
            <param-value>false</param-value>
        </init-param>
        <load-on-startup>3</load-on-startup>
    </servlet>

    ..........................省略中间的一大堆注释

    <servlet-mapping>
        <servlet-name>jsp</servlet-name>
        <url-pattern>*.jsp</url-pattern>
        <url-pattern>*.jspx</url-pattern>
    </servlet-mapping>

从以上这段配置信息,就可以知道,JSP其实就是个Servlet,.jsp和.jspx其实就只是个web访问名称,而映射的是JspServlet这个类。所以才说Servlet是JSP的技术基础,JSP背后就是一个Servlet。

以上示例使用浏览器访问jsp文件时,浏览器发送请求到服务器上,服务器会先去这个web.xml文件中找到jsp或jspx的访问映射,就会找到被映射的JspServlet类,然后这个JspServlet就会去JSP对象池中询问是否有与访问请求相对应的JSP对象,如果有的话就拿出来调用service方法,进入服务阶段。如果没有的话,就会去工程目录下找到被访问的jsp文件,然后就会以此文件为基础生成一个java源文件,接着会把这个源文件编译成class文件,并实例化此类的对象,实例化后将对象放进对象池里,最后再拿出对象调用service方法进入服务阶段。和Servlet一样,进入服务阶段也是执行完处理请求的逻辑代码,生成响应数据后,将响应数据返回给浏览器。而且整个生命周期中,JSP对象也是只有一个。

大致流程图:

JSP介绍与简单使用

<br>

我们来看看生成的java源文件,这个文件的所在的路径你可以在Tomcat服务器启动时,在控制台中的打印信息中找到,我这里的路径如下(可能和你的不一样):

E:\Java_WebTestProject.metadata.plugins\org.eclipse.wst.server.core\tmp0

然后此目录下有个work文件夹,在此文件夹中有很多子文件夹,你需要在里面找到你的web工程名称的文件夹,找到之后点击进入,也是会有几层目录,一直点进去就会找到 index_jsp.java 源文件和一个 index_jsp.class 文件(如果你的jsp文件名叫index.jsp的话),打开这个java源文件,内容如下:

/*
 * Generated by the Jasper component of Apache Tomcat
 * Version: Apache Tomcat/9.0.1
 * Generated at: 2017-11-27 13:45:29 UTC
 * Note: The last modified time of this file was set to
 *       the last modified time of the source file after
 *       generation to assist with modification tracking.
 */
package org.apache.jsp;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;

public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent,
                 org.apache.jasper.runtime.JspSourceImports {

          ...............................以下代码省略

以上可以看到这个index_jsp 类继承了HttpJspBase,那么来看看HttpJspBase继承了谁:

package org.apache.jasper.runtime;

import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.*;
import javax.servlet.jsp.HttpJspPage;
import org.apache.jasper.compiler.Localizer;

public abstract class HttpJspBase extends HttpServlet
    implements HttpJspPage
{

         ...............................以下代码省略

从源码可以看到HttpJspBase继承了HttpServlet,所以实际上这个jsp就是继承了HttpServlet,只不过中间插了个HttpJspBase进来而已,因为这个HttpJspBase里面没什么代码,基本都是空的。从以上可以得知,jsp其实就是个Servlet,只不过是换了个形态的Servlet罢了,所以学JavaWeb的时候要先学Servlet,然后再学JSP的时候就简单多了。

既然知道jsp背后就是一个Servlet,那么我们来看看这个背后的Servlet是如何实现我们的页面代码的,从 index_jsp.java 文件中翻到差不多最后面,可以看到一段拼凑的HTML代码:

             ...............................以上代码省略

 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("<!DOCTYPE html>\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("\t<h1>Hello I'm JSP!</h1>\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);
    }
  }
}

接着再看看index.jsp文件中的内容:

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
    <h1>Hello I'm JSP!</h1>
</body>
</html>

对比这两个文件中的代码之后,就能明白是怎么实现页面代码的了,JSP的机制就是让我们苦逼写代码的轻松了一些,不再需要自己去手写拼凑这些页面代码,JSP的机制会自动帮我们生成这些代码,怕不是要写封感谢信给sun公司才行。

除了页面代码外,当我们在JSP文件中写的Java代码也会自动生成到此源文件中,至于如何在JSP文件中编写Java代码会在以下小节中介绍。

<br>

JSP指令


以上介绍完JSP之后,这一小节就是介绍如何在JSP文件中编写Java代码和JSP的指令。我们的Java代码就需要写在JSP指令里,因为需要通过指令来表明这是一段Java代码,而不能像HTML代码那样能直接编写在JSP文件中。JSP的指令分为两类,一类是页面指令,一类是代码指令,Java代码就需要写在代码指令里。

页面指令:

指令作用示例
<%@ page %>用于设置页面上的参数,例如缓存、输出格式、编码格式等,<br>还能用于引入java的类包,这个指令是最常用的指令。<%@ page contentType="text/html" %>
<%@ include %>标签库指令taglib –标签库指令描述了要使用的JSP标签库。<br>该指令需要指定一个前缀prefix(和C++的命名空间很类似)和标签库的描述URI<%@ taglib prefix="myprefix" uri="taglib/mytag.tld" %>
<%@ taglib %>包含指令include –包含指令通知JSP编译器把另外一个文件完<br>全包含入当前文件中。效果就好像被包含文件的内容直接被粘贴到当前文件中一样。这个功能和C预处理器所提供的很类似。被包含文件的<br>扩展名一般都是"jspf"(即JSPFragment,JSP碎片)<%@ include file="somefile.jsp" %>

下面简单的介绍一下<%@ page %>指令里的常见属性使用,因为其他两个几乎不使用,所以在这里就不做演示了:

<!-- 定义编程语言,目前仅支持Java -->
<%@ page language="java" %>

<!-- 定义响应的文件类型和编码格式 -->
<%@ contentType="text/html;charset=utf-8" %>

<!-- 定义页面的编码格式 -->
<%@ pageEncoding="utf-8" %>

<!-- 定义缓存的大小 -->
<%@ page buffer="20kb" %>

<!-- 使用此属性导入一个包 -->
<%@ page import="java.util.HashMap" %>

<!-- 定义此页面是否主动创建session对象 -->
<%@ page session="false" %>

<!-- 定义是否接收错误页面转发过来的数据,也就是定义当前是否是一个错误页面 -->
<%@ page isErrorPage="true" %>

<!-- 定义发生错误时跳转的错误页面 -->
<%@ page errorPage="error.jsp" %>

<!-- 配置信息,能够使用Servlet.getServletInfo方法得到这个配置信息 -->
<%@ page info="database handler"%>

<!-- 定义是否开启多线程 -->
<%@ page isThreadSafe="true" %>

<!-- 定义生成的java源文件中所继承的父类,一般不会去定义,而且定义的时候一定要写全名 -->
<%@ page extends="javax.servlet.http.HttpServlet" %>

<!-- 这个命令可以使jsp输出的html时去除多余的空行(jsp上使用EL和tag会产生大量的空格和空行,但是这个命令是从JSP2.1规范以后才得到支持。) -->
<%@ page trimDirectiveWhitespaces="true" %>

指令是能够像以上示例一样写多行的,一些情况下分多几行写会提高可读性。

按照以上配置,重启服务器在浏览器中刷新之前所访问的jsp页面,可能会发生405错误,但是没关系,我们主要是看一下生成的java源文件与之前的源文件发生了什么样的变化:

package org.apache.jsp;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import java.util.HashMap;

public final class index_jsp extends javax.servlet.http.HttpServlet
    implements org.apache.jasper.runtime.JspSourceDependent,
                 org.apache.jasper.runtime.JspSourceImports {

  public java.lang.String getServletInfo() {
    return "database handler";
  }

        ...............................省略以上代码

try {
      response.setContentType("text/html; charset=utf-8");
      pageContext = _jspxFactory.getPageContext(this, request, response,
                null, false, 20480, true);

        ...............................省略以下代码

从以上的代码片段中,可以看到继承类变为了 HttpServlet,并且导入了 java.util.HashMap 包,而且还重写了Servlet中的getServletInfo方法,此方法返回的字符串也是我们在指令中使用info属性所定义的字符串。最后面那段代码可以看到一个20480的数字,这是缓存的大小,在指令中配置的是20kb,这里显示的是字节单位,在没有配置之前默认的是8192,也就是8kb。

<br>

代码指令:

指令作用示例
<% %>脚本指令,可以在这个指令里编写Java代码<% String str="test"; %>
<%! %>声明指令,属性声明和方法声明都需要写在这个标签里<%!<br> String name="lisi"<br>public void method(){<br>} <br>%>
<%= %>表达式指令,可以进行数据的输出<%="output data" %>

简单演示一下这些指令的使用方式,其中<% %>指令比较常用:

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
    <%
        // 声明变量
        String str="test";
        if(str.equals("test")){
            // 这个输出是输出到页面上
            out.print(str+"<br>");
        }
    %>

    <%! 
        // 声明属性和方法
        String name=null;

        public String getName(){
            return name;
        }

    %>

    <!-- 这个和这个语句的作用是一样的:out.print("test output"); -->
    <%="test output" %>
</body>
</html>

运行结果:
JSP介绍与简单使用

<br>

JSP内置对象


JSP的内置对象共有以下九个,我们可以在JSP中通过内置对象来使用它里面的方法:

  • request :实际上就是HttpServletRequest对象,详细内容参考之前介绍HttpServletRequest对象的文章
  • response :实际上就是HttpServletResponse 对象,详细内容参考之前介绍HttpServletResponse 对象的文章
  • pageContext :这是一个隐含对象,此对象代表jsp页面的上下文关系,能够调用、存取其他隐含对象,使用该对象可以访问页面中的共享数据,在JSP开发中并不经常使用。
  • session :实际上就是HttpSession对象,详细内容参考之前介绍HttpSession对象的文章
  • application :实际上就是ServletContext 对象,详细内容参考之前介绍ServletContext 对象的文章
  • config :实际上就是ServletConfig对象,可以得到web.xml中的初使化参数,详细内容参考之前介绍ServletConfig对象的文章
  • out :此对象用于输出数据、字节流,以上的示例中也使用到了
  • page :此对象代表jsp这个实体本身,即当前页面有效,相当于java中的this
  • exception :这是异常对象,代表运行时的异常

实际上我们在生成的源文件里就可以找到这些内置对象的声明:

            ...............................省略以上代码

// request 和 response 对象在这里
public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
      throws java.io.IOException, javax.servlet.ServletException {

    final java.lang.String _jspx_method = request.getMethod();
    if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method) && !javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) {
      response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSPs only permit GET POST or HEAD");
      return;
    }

    // 其他的对象声明在这里
    final javax.servlet.jsp.PageContext pageContext;
    javax.servlet.http.HttpSession session = null;
    final javax.servlet.ServletContext application;
    final javax.servlet.ServletConfig config;
    javax.servlet.jsp.JspWriter out = null;
    final java.lang.Object page = this;

            ...............................省略以下代码

其中还有一个exception 对象没有被声明在这里,因为这个对象需要在接收错误的JSP页面上才能获得,这些内置对象并没有什么特别的,你在Servlet中怎么用在JSP中就怎么用。

<br>

错误页面


错误页面是一个专门用来接收JSP运行过程中所发生的错误,错误信息会转发到这个错误页面上。配置错误页面的方式也很简单,首先在错误页面中通过指令的isErrorPage属性定义当前是一个错误页面,然后再非错误页面中使用errorPage属性定义跳转的错误页面即可。示例:

定义跳转的错误页面:

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<!-- 定义发生错误时跳转的错误页面 -->
<%@ page errorPage="error.jsp" %>

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
    <%
        // 故意制造一个错误
        System.out.println(1 / 0);
    %>
</body>
</html>

定义错误页面:

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<!-- 定义当前页面是一个错误页面 -->
<%@ page isErrorPage="true" %>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>error</title>
</head>
<body>
    <!-- 在错误页面中才能使用exception对象 -->
    <%=exception.toString() %>
</body>
</html>

运行结果:
JSP介绍与简单使用

你也可以在JSP中使用 try-catch 语句去捕获运行时所发生的异常:

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<!-- 定义发生错误时跳转的错误页面 -->
<%@ page errorPage="error.jsp" %>

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
    <%
        // 故意制造一个错误
        try {
            System.out.println(1 / 0);
        } catch (ArithmeticException e) {
            out.print("发生 ArithmeticException 异常!");
        }
    %>
</body>
</html>

运行结果:
JSP介绍与简单使用



本文转自 ZeroOne01 51CTO博客,原文链接:http://blog.51cto.com/zero01/2044929,如需转载请自行联系原作者

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值