JavaWeb基礎(chǔ)(七)-Servlet交互和作用域?qū)ο?/h1>

1.Servlet交互和作用域?qū)ο?/h1>

在JavaWeb基礎(chǔ)(六)中我分享了三個(gè)主要內(nèi)容Servet3.0注解的使用磕昼、Cookie技術(shù)實(shí)現(xiàn)請(qǐng)求數(shù)據(jù)共享Session技術(shù)實(shí)現(xiàn)請(qǐng)求數(shù)據(jù)共享.在這篇博客中,我主要分享以下兩方面的內(nèi)容言沐。

  • Servlet交互
  • 作用域?qū)ο?/code>

1.1 Servlet交互

在J2EE規(guī)范中, Servlet的交互方式主要有三種。Servlet之所以需要交互是因?yàn)槲覀儾豢赡軐⑺?code>業(yè)務(wù)邏輯都揉和在一個(gè)Servlet中.所以一個(gè)Sevlet一般對(duì)應(yīng)一個(gè)功能萍程。多個(gè)Servlet之間就涉及到如何進(jìn)行數(shù)據(jù)的傳遞跳轉(zhuǎn), 這我們又稱為Servlet的交互阀湿。簡(jiǎn)而言之,Servlet的交互講的是Servlet之間的數(shù)據(jù)傳遞跳轉(zhuǎn)领猾。

1.1.1 Servlet交互方式

Servlet交互方式,主要分為以下兩種, 請(qǐng)求轉(zhuǎn)發(fā), URL重定向米同,請(qǐng)求包含

請(qǐng)求轉(zhuǎn)發(fā)

  • 獲取分發(fā)器,并調(diào)用forward開始轉(zhuǎn)發(fā).
    req.getRequestDispatcher(path).forward(req, resp);

FirstServlet

@WebServlet("/request_forward/FirstServlet")
public class FirstServlet extends HttpServlet{
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        
        PrintWriter pw = resp.getWriter();
        System.out.println("FirstServlet before");
        pw.println("FirstServlet before");
        req.getRequestDispatcher("/request_forward/SecondServlet").forward(req, resp);
        System.out.println("FirstServlet Request =" + req);
        System.out.println("FirstServlet after");
        pw.println("FirstServlet after");
    }
}

SecondServlet

@WebServlet("/request_forward/SecondServlet")
public class SecondServlet extends HttpServlet {
    
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        PrintWriter pw = resp.getWriter();
        System.out.println("SecondServlet before");
        pw.println("SecondServlet before");
        
        System.out.println("SecondServlet Request =" + req);
        System.out.println("SecondServlet after");
        pw.println("SecondServlet after");
    }
}

瀏覽器輸出

控制臺(tái)輸出

特點(diǎn)研究

我們根據(jù)瀏覽器的輸出控制器臺(tái)輸出,結(jié)合代碼來研究請(qǐng)求轉(zhuǎn)發(fā)的特點(diǎn).
我們從瀏覽器地址欄骇扇、請(qǐng)求轉(zhuǎn)發(fā)整個(gè)過程Servlet的執(zhí)行先后順序請(qǐng)求報(bào)文變化面粮、參數(shù)是否可以傳遞少孝、請(qǐng)求轉(zhuǎn)發(fā)能夠訪問的資源來研究。

  • 1.瀏覽器地址欄
    如上圖, 瀏覽器地址欄沒有發(fā)生變化.我們可以得出結(jié)論請(qǐng)求轉(zhuǎn)發(fā)不會(huì)改變?yōu)g覽器地址欄.
  • 2.請(qǐng)求轉(zhuǎn)發(fā)整個(gè)過程Servlet的執(zhí)行先后順序
    如上圖控制臺(tái)的輸出, FirstServlet before-SecondServlet before-SecondServlet after-FirstServlet after.我們可以發(fā)現(xiàn)最后響應(yīng)給瀏覽器并不是直接通過SecondServlet而是先回到了轉(zhuǎn)發(fā)位置,然后繼續(xù)執(zhí)行FirstSevrlet后的代碼熬苍。但是決定最后內(nèi)容的是SecondServlet稍走。我們可以得出以下結(jié)論一.決定最終返回?cái)?shù)據(jù)的是SecondServlet, 但是并不是直接從SecondServlet響應(yīng)給瀏覽器,而是還需要通過FirstServlet. 二.前后的請(qǐng)求對(duì)象不是同一個(gè)
  • 3.請(qǐng)求報(bào)文的變化

觀察如上圖, 在輸入http://127.0.0.1:8080/request_forward/FirstServlet后請(qǐng)求報(bào)文只有一次,并沒有發(fā)生變化。說明請(qǐng)求轉(zhuǎn)發(fā)的請(qǐng)求只有一次.

  • 4.參數(shù)是否可以傳遞

更改FirstServlet的代碼,請(qǐng)求轉(zhuǎn)發(fā)前給path增加name參數(shù),并且存放一個(gè)age數(shù)據(jù)到reqeust域中.

        req.setAttribute("age", 13);
        req.getRequestDispatcher("/request_forward/SecondServlet?name=will").forward(req, resp);

SecondServlet最后先新增如下代碼

        pw.println("name = "+req.getAttribute("name")+",age = "+req.getAttribute("age"));

瀏覽器輸出

結(jié)論:通過請(qǐng)求轉(zhuǎn)發(fā)上填寫參數(shù)無法共享,但是request對(duì)象的數(shù)據(jù)可以共享

5.請(qǐng)求轉(zhuǎn)發(fā)能夠訪問的資源
嘗試通過請(qǐng)求轉(zhuǎn)發(fā)訪問百度

        req.getRequestDispatcher("www.baidu.com").forward(req, resp);

瀏覽器輸出


可以得出以下結(jié)論:請(qǐng)求轉(zhuǎn)發(fā)無法跨域訪問

嘗試通過請(qǐng)求轉(zhuǎn)發(fā)訪問WEB-INF目錄下的資源

        req.getRequestDispatcher("/baidu.html").forward(req, resp);

瀏覽器輸出


可以得出以下結(jié)論:請(qǐng)求轉(zhuǎn)發(fā)可以訪問WEB-INF下的資源文件

總結(jié)
  • 1.請(qǐng)求轉(zhuǎn)發(fā)不會(huì)改變?yōu)g覽器地址欄(由第一點(diǎn)得出)
  • 2.請(qǐng)求轉(zhuǎn)發(fā)內(nèi)容由第二個(gè)Servlet決定,但是最后必須經(jīng)過第一個(gè)Servlet(由第二點(diǎn)得出)
  • 3.請(qǐng)求轉(zhuǎn)發(fā)的請(qǐng)求次數(shù)只有一次(由第三點(diǎn)得出)
  • 4.請(qǐng)求轉(zhuǎn)發(fā)只能共享request中的數(shù)據(jù).請(qǐng)求轉(zhuǎn)發(fā)只能填寫資源路徑,填寫參數(shù)無效.(由第四點(diǎn)得出)
  • 5.請(qǐng)求轉(zhuǎn)發(fā)只能不能跨域訪問(由第五點(diǎn)得出)
  • 6.請(qǐng)求轉(zhuǎn)發(fā)能夠訪問WEB-INF下的資源(有第五點(diǎn)得出)

URL重定向

URL重定向主要通過response對(duì)象的sendRedirect方法實(shí)現(xiàn).其會(huì)響應(yīng)瀏覽器當(dāng)前請(qǐng)求, 并讓瀏覽器再發(fā)一次請(qǐng)求到新的資源路徑柴底。所以稱之為重定向.

FirstServlet

@WebServlet("/url_redirect/FirstServlet")
public class FirstServlet extends HttpServlet{
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        
        PrintWriter pw = resp.getWriter();
        System.out.println("FirstServlet before");
        pw.println("FirstServlet before");
        req.setAttribute("age", 13);
//      req.getRequestDispatcher("/baidu.html").forward(req, resp);
        resp.sendRedirect("/request_forward/SecondServlet");
        System.out.println("FirstServlet Request =" + req);
        System.out.println("FirstServlet after");
        pw.println("FirstServlet after");
    }
}

SecondServlet


@WebServlet("/url_redirect/SecondServlet")
public class SecondServlet extends HttpServlet {
    
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        PrintWriter pw = resp.getWriter();
        System.out.println("SecondServlet before");
        pw.println("SecondServlet before");
        System.out.println("SecondServlet Request =" + req);
        System.out.println("SecondServlet after");
        System.out.println("name = "+req.getAttribute("name")+",age = "+req.getAttribute("age"));
        pw.println("name = "+req.getAttribute("name")+",age = "+req.getAttribute("age"));
        pw.println("SecondServlet after");
    }
}

瀏覽器輸出

控制臺(tái)輸出

特點(diǎn)研究
  • 瀏覽器地址欄
    如上圖瀏覽器輸出的地址欄發(fā)生了變化.可以得出結(jié)論: URL重定向會(huì)改變?yōu)g覽器地址欄為請(qǐng)求地址婿脸。

  • 請(qǐng)求轉(zhuǎn)發(fā)整個(gè)過程Servlet的執(zhí)行先后順序
    SecondServlet before-Second after.所以URL重定向后響應(yīng)給瀏覽器的內(nèi)容由SecondServlet決定, 并且是直接由SecondServlet響應(yīng)給瀏覽器,因?yàn)檫@是一次新的請(qǐng)求。

  • 請(qǐng)求報(bào)文變化


如上圖,請(qǐng)求報(bào)文的請(qǐng)求行地址就發(fā)生了改變, 說明這是第二次請(qǐng)求.
所以URL重定向的請(qǐng)求是兩次

  • 參數(shù)是否可以傳遞
    見上面的瀏覽器輸出圖,URL重定向參數(shù)不可傳遞
  • 請(qǐng)求轉(zhuǎn)發(fā)能夠訪問的資源
    跨域訪問
        resp.sendRedirect("https://www.baidu.com");

瀏覽器輸出.沒法錄制動(dòng)圖,自己嘗試下


結(jié)論: URL重定向可以跨域訪問

訪問WEB-INF

        resp.sendRedirect("/WEB-INF/views/login.html");


結(jié)論: URL重定向不能訪問WEB-INF目錄下的資源

總結(jié)
  • 1.URL重定向會(huì)改變?yōu)g覽器地址欄(由第一點(diǎn)得出)
  • 2.URL重定向內(nèi)容由第二個(gè)Servlet決定, 并且由第二個(gè)Servlet直接響應(yīng)給瀏覽器(由第二點(diǎn)得出)
  • 3.URL重定向的請(qǐng)求次數(shù)有二次(由第三點(diǎn)得出)
  • 4.URL重定向不能共享request中的數(shù)據(jù).(由第四點(diǎn)得出)
  • 5.URL重定向能跨域訪問(由第五點(diǎn)得出)
  • 6.URL重定向不能夠訪問WEB-INF下的資源(有第五點(diǎn)得出)

可見URL重定向和請(qǐng)求轉(zhuǎn)發(fā)的6個(gè)特點(diǎn)都是相反的.

請(qǐng)求包含

請(qǐng)求包含主要用在JSP中, 用在Servlet中沒有多大意義柄驻。因?yàn)槲覀兊拿總€(gè)Servlet一般有不同職責(zé), 并不能夠包含再一起狐树。而JSP頁面可以進(jìn)行復(fù)用,這時(shí)候就可以用包含.
語法:request.getRequestDispatcher(path).include(req, resp);

如何選擇請(qǐng)求轉(zhuǎn)發(fā)和URL重定向

請(qǐng)求轉(zhuǎn)發(fā)和URL重定向都是用于Web組件(Servlet和JSP)的跳轉(zhuǎn)。

  • 如果需要在跳轉(zhuǎn)后共享數(shù)據(jù), 或者訪問WEB-INF下的資源鸿脓,那么必須用請(qǐng)求轉(zhuǎn)發(fā)
  • 如果需要在跳轉(zhuǎn)后不需要共享數(shù)據(jù)抑钟,或者需要跨域訪問資源,那么必須用URL重定向野哭。
  • 其他情況任選

1.2 作用域?qū)ο?/h2>

Servlet三大作用域?qū)ο蠛推洳僮?/h3>

Servlet的三大作用域?qū)ο笃渲袃蓚€(gè), 我們已經(jīng)在之前講過, 分別是request在塔、session.之所以說他們是作用域是因?yàn)楸4嬖谒麄冎械臄?shù)據(jù)是有作用域范圍, request是在同一個(gè)請(qǐng)求對(duì)象間, session是在一次會(huì)話間, 又因?yàn)樗鼈兌际荢ervlet下的規(guī)范,所以稱為Servlet作用于對(duì)象虐拓。說了那么多, 最后一個(gè)Servlet作用域?qū)ο笫荢ervletContext對(duì)象.

ServletContext

ServletContext是一個(gè)接口, 表示Web應(yīng)用對(duì)象心俗。在JSP中將其稱為application.

  • 獲取ServletContext
    獲取Servlet可以通過request,也可以通過sessioin、還可以通過在Servlet子類中調(diào)用父類的getServletContext()方法.如下圖所示
  • ServletContext常用API
    • getRealPath(path) 獲取資源的絕對(duì)路徑
      String path = getServletContext().getRealPath("/login.html");
    
    控制臺(tái)輸出
    • getContextPath() 獲取當(dāng)前響應(yīng)的上下文路徑.即<Context path='xxx'>中path的值.
      控制臺(tái)輸出 因?yàn)楫?dāng)前Context的path我配置成空字符串,所以輸出空

代碼演示Servlet三大作用域

@WebServlet("/scope/servlet")
public class ScopeServlet extends HttpServlet {
    
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        
        final String NUM_IN_REQUEST = "NUM_IN_REQUEST";
        final String NUM_IN_SESSION = "NUM_IN_SESSION";
        final String NUM_IN_APPLICATION = "NUM_IN_APPLICATION";
        Integer numInRequest = (Integer) req.getAttribute(NUM_IN_REQUEST);
        if (null == numInRequest) {
            req.setAttribute(NUM_IN_REQUEST, 1);
        }else {
            req.setAttribute(NUM_IN_REQUEST, numInRequest+1);
        }
        
        HttpSession session = req.getSession();
        Integer numInSession = (Integer) session.getAttribute(NUM_IN_SESSION);
        if (null == numInSession) {
            session.setAttribute(NUM_IN_SESSION, 1);
        }else {
            session.setAttribute(NUM_IN_SESSION, numInSession+1);
        }
        ServletContext app = req.getServletContext();
        Integer numInApplication = (Integer) app.getAttribute(NUM_IN_APPLICATION);
        if (null == numInApplication) {
            app.setAttribute(NUM_IN_APPLICATION, 1);
        }else {
            app.setAttribute(NUM_IN_APPLICATION, numInApplication+1);
        }
        PrintWriter pw=resp.getWriter();
        pw.println("request num = " + req.getAttribute(NUM_IN_REQUEST));
        pw.println("session num = " + session.getAttribute(NUM_IN_SESSION));
        pw.println("application num = " + app.getAttribute(NUM_IN_APPLICATION));
        
    }
}

第一次訪問

第二次刷新

打開另外一個(gè)窗口,地址相同

Servlet三大作用域總結(jié)

作用域?qū)ο?/th> 作用域類型 作用域范圍 表示
request HttpServletRequest 當(dāng)前請(qǐng)求對(duì)象 每次請(qǐng)求都是一個(gè)請(qǐng)求對(duì)象
session HttpSession 一次會(huì)話的多個(gè)請(qǐng)求之間 每次會(huì)話都是表示一個(gè)session對(duì)象
application ServletContext 作用于整個(gè)Web應(yīng)用, 可以實(shí)現(xiàn)多次會(huì)話之間的數(shù)據(jù)共享 表示一個(gè)web應(yīng)用

1.3 JSP

JSP又稱為動(dòng)態(tài)網(wǎng)頁, 其專門為頁面渲染而生蓉驹。就要聊聊最初的Servlet

最初的Servlet

  • 最早Servlet誕生的時(shí)候就是為了完成動(dòng)態(tài)網(wǎng)頁的開發(fā), 是需要負(fù)責(zé)頁面的渲染, 也就是使用pw =response對(duì)象.getWriter(), 然后使用PrintWriter一行行輸出。
  • 問題:HTML代碼與業(yè)務(wù)代碼耦合揪利。
    后來發(fā)現(xiàn)這樣做不合理, 因?yàn)镾ervlet里要負(fù)責(zé)的事太多, 既要負(fù)責(zé)業(yè)務(wù)邏輯編寫, 又要負(fù)責(zé)輸出HTML頁面代碼, 導(dǎo)致了業(yè)務(wù)邏輯代碼和HTML代碼耦合在一起, 難以維護(hù)态兴。

責(zé)任分離

出于以上的問題, 就將Servlet里負(fù)責(zé)HTML頁面代碼的責(zé)任進(jìn)行了分離。讓Servlet專注于業(yè)務(wù)邏輯疟位。JSP技術(shù)就順理成章的誕生了, JSP技術(shù)就是專門為了編寫HTML代碼瞻润。

JSP基本語法

  • JSP語法的標(biāo)志<%符號(hào) %>.其中符號(hào)@=甜刻、!绍撞、--代替, 分別有不同的含義.和@結(jié)合表示指令, 和=結(jié)合表示輸出, 和!結(jié)合表示定義類成員, 和--結(jié)合表示注釋(--需要成對(duì))
  • JSP本質(zhì)上是一種Servlet,所以其也擁有成員,擁有service方法.以下四種語法分別代表四種含義。

注釋得院。

語法:<%-- 注釋內(nèi)容 --%>

輸出傻铣。用字符輸出流輸出

語法: <%= "sweetcs" %> 等價(jià)于 out.write("sweetcs")

腳本代碼段。(定義service方法中的代碼)

語法:

<% 
代碼1; 
代碼2; 
%>

定義類成員祥绞。

語法: <%! private int age; %>

代碼演示

<%@page import="java.util.ArrayList"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
    <%-- 這是一行注釋 --%>
    <%! private int age = 13; 
        public ArrayList<String> names = new ArrayList<String>();
    %>
    <%= "Hello JSP By SweetCS" %>
    <%
        names.add("AAA");
        names.add("BBB");
        names.add("CCC");
    %>
    <%= names %>
</body>
</html>

JSP原理剖析

看完上述語法和代碼你也許還不是懂非洲。沒事, 要理解這是怎么回事, 我們得結(jié)合底層來理解鸭限。

  • 定位對(duì)應(yīng)的Servlet
    打開項(xiàng)目部署的路徑。找到統(tǒng)一級(jí)目錄下的work目錄.以我mac下的為例, 是在tomcat安裝目錄work/Catalina/localhost/_/org/apache/jsp/views/jsp下.
  • 觀察其目錄結(jié)構(gòu)


觀察其目錄結(jié)構(gòu),我們可以發(fā)現(xiàn)我們hello.jsp是先被翻譯hello_jsp.java, 再被編譯hello_jsp.class

  • 查看源碼閱讀下面的源代碼,我們可以發(fā)現(xiàn)很多有用的信息两踏。
    • <%! %><% %>翻譯后的位置败京。<%! %><% %> 定義的代碼都被原樣的翻譯到了這個(gè)java文件中。只是<%! %>對(duì)應(yīng)的是類成員定義, <% %>中的代碼是被搬到_jspService方法之中梦染。
    • JSP本質(zhì)是Sevlet.該hello_jsp繼承自HttpJspBase.而HttpJspBase又繼承自HttpServlet, 所以我們說hello_jsp是一種servlet, 即其對(duì)應(yīng)的hello.jsp本質(zhì)上是一種servlet
    • JSP的生命周期方法赡麦。該Servlet也有_jspInit_jspDestroy帕识、_jspService.分別對(duì)應(yīng)Servlet的init方法泛粹、destory方法service方法
/*
 * Generated by the Jasper component of Apache Tomcat
 * Version: Apache Tomcat/7.0.90
 * Generated at: 2018-08-20 17:14:11 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.views.jsp;

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

public final class hello_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent {

  private int age = 13; 
    public ArrayList<String> names = new ArrayList<String>();
    
  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 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 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 {

    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("\n");
      out.write("\n");
      out.write("<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n");
      out.write("<html>\n");
      out.write("<head>\n");
      out.write("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n");
      out.write("<title>Insert title here</title>\n");
      out.write("</head>\n");
      out.write("<body>\n");
      out.write("\t");
      out.write('\n');
      out.write('   ');
      out.write('\n');
      out.write('   ');
      out.print( "Hello JSP By SweetCS" );
      out.write('\n');
      out.write('   ');

        names.add("AAA");
        names.add("BBB");
        names.add("CCC");
    
      out.write('\n');
      out.write('   ');
      out.print( names );
      out.write("\n");
      out.write("</body>\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三大指令

JSP指令很多,但是實(shí)際開發(fā)能用到只有少數(shù).主要分為以下三大類指令.JSP中的指令都具備以下兩個(gè)特點(diǎn)渡冻。

  • 不會(huì)向客戶端產(chǎn)生輸出戚扳。
  • 在JSP整個(gè)文件范圍內(nèi)有效。

page指令

page指令族吻。用于表示JSP頁面的相關(guān)配置信息帽借。比如響應(yīng)編碼的設(shè)置, 導(dǎo)入哪些包.

常用屬性

  • languae: 表示JSP中編寫的腳本語言類型。
  • contentType: 表示輸出的MIME類型和編碼超歌。
  • import: 表示要導(dǎo)入的包
<%@ page 
    language="java" 
    contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"
    import="java.util.ArrayList"
%>

include指令

include指令主要用來做靜態(tài)包含砍艾。后面再結(jié)合動(dòng)態(tài)包含補(bǔ)充介紹。

taglib指令

taglib指令后面分享jstl在細(xì)講.其主要為了用來引入標(biāo)簽庫

JSP的9大內(nèi)置對(duì)象

JSP中內(nèi)置了9個(gè)對(duì)象, 這9個(gè)對(duì)象是可以直接訪問,而無序創(chuàng)建的巍举。因?yàn)镴SP本質(zhì)是Servlet, 既然其本質(zhì)是Servlet, 為了便于訪問Servlet常用的對(duì)象, JSP中就有了9大對(duì)應(yīng)的對(duì)象脆荷,如下表。

內(nèi)置對(duì)象 內(nèi)置對(duì)象對(duì)應(yīng)的類型 描述 對(duì)應(yīng)代碼
request HttpServletRequest 請(qǐng)求對(duì)象
response HttpServletResponse 響應(yīng)對(duì)象
pageContext PageContext 當(dāng)前JSP作用域?qū)ο?/td> pageContext = _jspxFactory.getPageContext(this, request, response,null, true, 8192, true);
session HttpSession 會(huì)話對(duì)象, sessioin ="true" session = pageContext.getSession();
exception Throwable 異常類型, isErrorPag="true"
application ServletContext 當(dāng)前web應(yīng)用對(duì)象 pageContext.getServletContext();
config ServletCofig 當(dāng)前web.xml配置對(duì)象 config = pageContext.getServletConfig();
out JspWriter 字符輸出流對(duì)象 out = pageContext.getOut();
page Object 當(dāng)前Servlet對(duì)象 final java.lang.Object page = this;

JSP的四大作用域

Servlet有三大作用域(request懊悯、session蜓谋、application), 又因?yàn)镴SP本質(zhì)也是Servlet所以.JSP也有Servlet中的三大作用域, 并且JSP還多了一個(gè)作用域就是pageContext, 表示當(dāng)前JSP作用域.

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者

  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市炭分,隨后出現(xiàn)的幾起案子桃焕,更是在濱河造成了極大的恐慌,老刑警劉巖捧毛,帶你破解...
    沈念sama閱讀 218,525評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件观堂,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡呀忧,警方通過查閱死者的電腦和手機(jī)师痕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來而账,“玉大人胰坟,你說我怎么就攤上這事「Q铮” “怎么了腕铸?”我有些...
    開封第一講書人閱讀 164,862評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵惜犀,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我狠裹,道長(zhǎng)虽界,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,728評(píng)論 1 294
  • 正文 為了忘掉前任涛菠,我火速辦了婚禮莉御,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘俗冻。我一直安慰自己礁叔,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,743評(píng)論 6 392
  • 文/花漫 我一把揭開白布迄薄。 她就那樣靜靜地躺著琅关,像睡著了一般。 火紅的嫁衣襯著肌膚如雪讥蔽。 梳的紋絲不亂的頭發(fā)上涣易,一...
    開封第一講書人閱讀 51,590評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音冶伞,去河邊找鬼新症。 笑死,一個(gè)胖子當(dāng)著我的面吹牛响禽,可吹牛的內(nèi)容都是我干的徒爹。 我是一名探鬼主播,決...
    沈念sama閱讀 40,330評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼芋类,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼隆嗅!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起侯繁,我...
    開封第一講書人閱讀 39,244評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤榛瓮,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后巫击,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,693評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡精续,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,885評(píng)論 3 336
  • 正文 我和宋清朗相戀三年坝锰,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片重付。...
    茶點(diǎn)故事閱讀 40,001評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡顷级,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出确垫,到底是詐尸還是另有隱情弓颈,我是刑警寧澤帽芽,帶...
    沈念sama閱讀 35,723評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站翔冀,受9級(jí)特大地震影響导街,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜纤子,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,343評(píng)論 3 330
  • 文/蒙蒙 一搬瑰、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧控硼,春花似錦泽论、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至幔妨,卻和暖如春鹦赎,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背陶冷。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工钙姊, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人埂伦。 一個(gè)月前我還...
    沈念sama閱讀 48,191評(píng)論 3 370
  • 正文 我出身青樓煞额,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親沾谜。 傳聞我的和親對(duì)象是個(gè)殘疾皇子膊毁,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,955評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容