JSP学习(一)——概念、语法、九大内置对象和四大作用域

前面讲解了Servlet,了解了Servlet的继承结构,生命周期等有了一些比较详细的了解,但是我们会发现在Servlet中编写一些HTML代码,需要使用out.println(HTML)逐行打印,如果html代码十分繁多那么编写代码就会十分繁琐; 因此就出现了JSP,来解决这样的问题,JSP中的内容就是html,但是能够嵌套java语言,现在来详细了解一下JSP。

什么是JSP

JSP全名为Java Server Pages,中文名叫java服务器页面,其根本是一个简化的Servlet设计,它使用JSP标签在HTML网页中插入Java代码。tomcat获得JSP文件后,先将JSP转成servlet,变成xxx.java(servlet源码),然后编译成class文件最后运行class文件将结果输出到浏览器端。

特点:

  • Servlet特点:在Java源码中嵌入html源码
  • JSP特点:在html源码中嵌入java代码

通过一个简单的例子进行讲解

新建一个method.jsp

<%--
  Created by IntelliJ IDEA.
  User: chen
  Date: 2019/4/8
  Time: 10:37
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>this is title</title>
</head>
<body>
<h3>今天天气很好适合学习</h3>
</body>
</html>

运行后可以在文件夹如下

看到转换后的java代码

/*
 * Generated by the Jasper component of Apache Tomcat
 * Version: Apache Tomcat/9.0.17
 * Generated at: 2019-04-08 06:42:31 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 method_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent,
                 org.apache.jasper.runtime.JspSourceImports {

  private static final javax.servlet.jsp.JspFactory _jspxFactory =
          javax.servlet.jsp.JspFactory.getDefaultFactory();

  private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants;

  private static final java.util.Set<java.lang.String> _jspx_imports_packages;

  private static final java.util.Set<java.lang.String> _jspx_imports_classes;

  static {
    _jspx_imports_packages = new java.util.HashSet<>();
    _jspx_imports_packages.add("javax.servlet");
    _jspx_imports_packages.add("javax.servlet.http");
    _jspx_imports_packages.add("javax.servlet.jsp");
    _jspx_imports_classes = null;
  }

  private volatile javax.el.ExpressionFactory _el_expressionfactory;
  private volatile org.apache.tomcat.InstanceManager _jsp_instancemanager;

  public java.util.Map<java.lang.String,java.lang.Long> getDependants() {
    return _jspx_dependants;
  }

  public java.util.Set<java.lang.String> getPackageImports() {
    return _jspx_imports_packages;
  }

  public java.util.Set<java.lang.String> getClassImports() {
    return _jspx_imports_classes;
  }

  public javax.el.ExpressionFactory _jsp_getExpressionFactory() {
    if (_el_expressionfactory == null) {
      synchronized (this) {
        if (_el_expressionfactory == null) {
          _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
        }
      }
    }
    return _el_expressionfactory;
  }

  public org.apache.tomcat.InstanceManager _jsp_getInstanceManager() {
    if (_jsp_instancemanager == null) {
      synchronized (this) {
        if (_jsp_instancemanager == null) {
          _jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());
        }
      }
    }
    return _jsp_instancemanager;
  }

  public void _jspInit() {
  }

  public void _jspDestroy() {
  }

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

    if (!javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) {
      final java.lang.String _jspx_method = request.getMethod();
      if ("OPTIONS".equals(_jspx_method)) {
        response.setHeader("Allow","GET, HEAD, POST, OPTIONS");
        return;
      }
      if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method)) {
        response.setHeader("Allow","GET, HEAD, POST, OPTIONS");
        response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSP 只允许 GET、POST 或 HEAD。Jasper 还允许 OPTIONS");
        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;
    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("<html>\r\n");
      out.write("<head>\r\n");
      out.write("    <title>this is title</title>\r\n");
      out.write("</head>\r\n");
      out.write("<body>\r\n");
      out.write("<h3>今天天气很好适合学习</h3>\r\n");
      out.write("</body>\r\n");
      out.write("</html>\r\n");
    } 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);
    }
  }
}

看116行到126行就应该理解,jsp就是一个可以嵌套java的html页面,tomcat服务器通过将jsp页面转换为java代码后编译运行,对于我们而言,只需要书写html代码即可。

另外可以注意到method_jsp继承自org.apache.jasper.runtime.HttpJspBase,通过查看HttpJspBase源码可以看到

public abstract class HttpJspBase extends HttpServlet implements HttpJspPage

即HttpJspBase继承自HttpServlet,看到了一个熟悉的类,HttpServlet,我们编写Servlet时就是继承自该类,这里也是继承HttpServlet,并且HttpJspBase的源码会发现,生命周期也是有init()方法,service()方法,destory()方法,相当于_jspService()方法就是servlet的service()方法的执行,所以说JSP也是一个servlet。

注意:

jsp 生成java源码,默认第一次生成,之后直接执行,除非内容修改,具体点说,由于JSP只会在客户端第一次请求的时候被编译,因此第一次请求JSP时会感觉比较慢,而之后的请求因为不会编译JSP,所以速度就快多了,如果将Tomcat保存的JSP编译后的class文件删除,Tomcat也会重新编译JSP。在开发Web程序的时候经常需要修改JSP,Tomcat能够自动检测到JSP程序的改动,如果检测到JSP源代码发生了改动,Tomcat会在下次客户端请求JSP时重新编译JSP,而不需要重启Tomcat,这种自动检测功能默认是开启的,检测改动会消耗少量的时间,在部署web应用程序的时候可以在web.xml中将它关掉。这也就是为什么我们能够在jsp页面直接修改内容,而不用重新启动服务器的原因。

因为JSP就是servlet,那么生命周期也就是跟serlvet一样。

JSP和servlet有一点区别就在于:jsp是先部署后编译,而servlet是先编译后部署。

JSP语法

JSP语法就两个东西,模板数据和元素。其中

模板数据就是JSP中的HTML代码,它的内容给是固定的,无论程序如何运行模版数据输出到客户端浏览器时都不会发生改变,当我们创建一个JSP时,模版就已经固定了。

元素又包括脚本,指令,标签。接下来我们重点学习jsp中的元素。

jsp脚本

使用<% 编写java代码 %>,中间java代码必须遵循Java语法

<%
    int a = 1;
    int b = 2;
    out.println(a+b);  //打印到浏览器端
    System.out.println(a+b);  //打印到后台
%>

其中out.println和九大内置对象中的out对象有关接下来讲 

使用<%=xxx %>来输出结果

对于上面的java代码也可以使用

<%=a+b%>

注意不要在后面加分号; 

其实两种方式在转译后的servlet中都变为out.println(a+b)来完成。 

jsp注释

  • 前端代码注释:<!-- -->     会被转译,也会被发送到浏览器端,但不会被浏览器执行
  • java代码注释://    /*  */    会被转译,但不会发送到浏览器端,也不会被浏览器执行
  • jsp注释:<%-- --%>   不会被转译,更不会被发送到浏览器和被浏览器执行

jsp中声明方法和属性(全局变量)

注意,之前我们写的所有html代码和java脚本代码最终转译成servlet时都会是在_jspService方法中,但是如果我们想要使用全局属性或者其他方法时需要使用

<%!属性或方法%>

jsp指令

JSP指令格式:<%@ directive {attribute=value}* %>

解释:

directive:指令名称,例如page指令

attribute=value:紧跟指令名称后面的就是各种属性,以键值对的形式书写

*:代表后面能跟0个或多个属性。

page指令  用来进行jsp的页面设置和转译配置

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

上面是我们创建jsp时自动生成的,可以看到page指令后面有两个属性,但这其实并不全面,page指令允许的属性如下表所示

include指令

 <%@ include file="relativeURL"%>         

 relativeURL:本应用程序内另一个JSP文件或者HTML文件的相对路径,

例如,网址内所有页面均有一个统一风格的导航栏和页脚版权,那么就可以使用该指令将其包含进来  

特点:include指令会将引入的jsp文件和当前jsp文件转译成一个java文件(servlet)使用,在网页中也就显示了合并后的结果。

注意:因为是合并两个jsp文件,所以java代码块不能使用同名变量。

 

而等下会讲到的一个JSP标签

<jsp:include page="relativeURL">

作用跟include指令一样,但是不同的是,这种方式是将引入的jsp文件单独编译然后在当前转译好的jsp文件中调用引入的jsp的编译文件,因为是单独编译,所以两个jsp文件中的java代码块可以使用同名变量。

taglib指令

JSP支持标签技术,后面会讲到标签的用法,jstl标签库的使用等,

作用:用来指明JSP页面内使用的JSP标签库,taglib指令有两个属性,uri为类库的地址,prefix为标签的前缀

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

jsp标签

标签分为JSP自带内置的标签、通过taglib指令来使用JSP标签库或者自定义标签。

JSP内置的标签就被称为JSP行为(JSP Actions)。只要书写很少的标记代码就能使用JSP提供的丰富功能,JSP行为其实是对常用的JSP功能的抽象与封装,可以取代jsp脚本,让JSP中就少一些嵌入java代码的地方。

格式:<jsp:elements {attribute="value"}* />  

jsp:标签的前缀,说明是jsp内置的标签,

elements:行为的名称,

attribute=value:使用键值对来编写属性

*:能指定0个或多个属性对

<jsp:include />行为

include行为用于运行时包含某个文件,如果被包含的文件为JSP程序,则先会执行JSP程序,然后在把执行的结果包含进来。 作用是跟include指令一样的,唯一的区别就在于,include指令是将被包含的文件的源码加入到了本JSP程序中,然后在进行编译,属于静态包含,而include行为只是将被包含的文件的运行结果包含进自己。属于动态包含

<jsp:forward />行为

实现请求转发功能,Servlet中通过request.getRequestDispatcher("someServlet").forward(request,response);而在JSP中也能够实现相同的功能,只不过用的是<jsp:forward />行为,实际上forward行为就是对其进行了封装。

<jsp:forward page="someServlet">

    <jsp:param name="param1" value="value1"/>

    <jsp:param name="param2" value="value2"/>

</jsp:forward>

page:需要跳转到的页面或者servlet、 <jsp:param/>参数行为,带一些参数过去,name、value是以键值对的形式带过去的

Java bean行为

是一组与Java Bean 相关的行为,包括useBean行为、setProperty行为、getProperty行为等

Java Bean就是普通的Java类,也被称为POJO,只有私有的属性与对应的getter方法和setter方法,注意其中当私有的属性为boolean类型时,习惯上一般把getter方法写成isXxx();而不是getXxx();

useBean行为  

<jsp:useBean id="beanObject" class="className" scope="Value"> 

作用:在jsp中定义一个java bean对象,   

id:指明Java Bean对象的名称,JSP中可以使用该名称引用该Java Bean对象,相当于给new出来的对象取一个变量名,

class:Java Bean类的全名

scope:该java bean对象的作用范围,可以写的就四个,也就是JSP的四大作用域,page、request、session、application

  • page:只能在当前JSP页面使用,如果不在JSP页面,那么就会失效
  • request:这个前面学过,A页面请求转发到B页面,那么使用的是同一个request,那么A,B页面都算是request的作用域,也就是通过请求转发的页面都是其作                       用域
  • session:该作用域在一个web项目下任何位置应该读访问的到,只要cookie不关闭,并且cookie设置  的访问路径为"/",
  • application:其实就是Servlet中的servletContext,服务器下的所有项目都能访问到。

setProperty行为

<jsp:setProperty name="beanName" property="propertyName" value="">

对Java Bean对象进行属性的设置

name:java bean对象的名称,也就是在useBean行为中的id

property:对象中的属性名,

value:要对其属性进行赋值的值

getProperty行为

<jsp:getProperty name="beanName" property="propertyName" />

获取JavaBean对象的某个属性值

name:java bean 对象的名称,也就是在useBean行为中的id

property:对象的属性名

使用demo:

package a;

public class User {
    private int id;
    private String username;
    private String password;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    
    
}
<body>
    <!-- 创建一个新的javabean对象user,会先判断在page作用域内是否有叫user对象的javabean,如果有则取它,如果没有则创建新的javabean对象  -->
    <jsp:useBean id="user" class="a.User" scope="page"></jsp:useBean>
    <!-- 对javabean对象的username进行赋值 -->
    <jsp:setProperty property="username" name="user" value="wu"/>
    <!-- 获取javabean对象的username属性 -->
    <jsp:getProperty property="username" name="user"/>
</body>

<jsp:directive/>行为

directive行为,就相当于JSP指令,比如<jsp:directive.page/>相当于<%@ page %>指令,等等其它指令是一样的书写格式。

jsp九大内置对象和四大作用域

九大内置对象

内置对象:jsp文件在转译成其对应的servlet文件时自动生成并声明的对象。我们在jsp页面中直接使用即可。

pageContext:页面上下文对象,封装了其他内置对象,封存了当前jsp运行信息。  注意:每个jsp文件有一个pageContext对象

request:封存当前请求数据的对象,由tomcat服务器创建       一次请求

session:此对象用来存储用户的不同请求的共享数据。            一次会话

application:就是servletContext,一个项目只有一个,存储所有用户共享数据的对象。     项目内

response:响应对象,用来响应处理结果给浏览器。  设置响应头、重定向

out:响应对象,jsp内部使用。带有缓冲区的响应对象,效率高于response对象

page:代表当前jsp对象,相当于java中的this

exception:异常对象,存储了当前的异常信息。注意:使用此对象需要在page指定中使用属性isErrorPage=“true”开启

config:也就是ServletConfig,主要用来获取web.xml中的配置数据,完成一些初始化数据的读取。

四大作用域对象

其实就是九大内置对象中的四个,之所以称之为作用域对象,是因为他们能够进行数据的流转

pageContext:当前页面,解决了在当前页面内的数据共享问题。获取其他内置对象。

request:一次请求。一次请求的servlet共享数据。通过请求转发可以将数据流转给下一个servlet

session:一次会话。一个用户的不同请求的数据共享。将数据从一次请求流转给下一次请求。

application:项目内。不同用户的数据共享问题。将数据从一个用户流转给其他用户。

jsp路径问题总结

相对路径完成跳转但是:

1.资源的位置不可随意更改

2.使用../进行上级文件夹的跳出,使用比较麻烦。

绝对路径完成跳转(推荐

/虚拟项目名/项目资源路径

其中第一个/表示服务器根目录,相当于localhost:8080

jsp中自带的全局路径声明

myeclipse创建jsp文件时会自动生成如下代码:

<%
    String path = request.getContextPath();
    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"
%>

 使用<base href="<%=basePath%>">后相当于http:127.0.0.1:8080/虚拟项目名/     之后引用文件只需要直接书写文件位置即可

但是在idea中创建jsp文件并不会自动生成,而且只写文件位置容易不清楚,所以还是锐减第二种方式使用绝对路径。

 

JSP中还有其他两大块内容

一个是EL表达式,很重要,另一个是jstl标签库的使用,也很重要,下一篇文章中讲到。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值