首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JSP介绍与简单使用

JSP介绍与简单使用

作者头像
端碗吹水
发布2020-09-23 12:14:02
1.8K0
发布2020-09-23 12:14:02
举报

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介绍与简单使用
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介绍与简单使用
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介绍与简单使用
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介绍与简单使用

你也可以在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介绍与简单使用
JSP介绍与简单使用
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017-11-28 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • JSP介绍
  • JSP的访问流程与原理
    • 其实看似简单的背后,是需要经历好几个步骤的,下面我们就来看看JSP背后的运行流程原理:
    • JSP指令
    • JSP内置对象
    • 错误页面
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档