SP指令是指:用于設(shè)置JSP頁面相關(guān)屬性的一個(gè)語法命令,例如:設(shè)置頁面編碼字符集、導(dǎo)入其他包等等。JSP中提供了三個(gè)指令,分別是:page指令、include指令、taglib指令。其中page指令用于設(shè)置JSP頁面屬性,include指令用于引入其他的JSP文件,taglib指令用于引入標(biāo)簽庫。這一小節(jié)內(nèi)容介紹include指令的使用。
include指令作用:將指定的文件引入到當(dāng)前JSP頁面里面。include指令會(huì)將引入的文件內(nèi)容嵌入到當(dāng)前JSP頁面中的對(duì)應(yīng)位置。
<%@ include file="文件的相對(duì)路徑" %>
案例代碼:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>這是HTML頭部</title>
</head>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%-- 引入頭部文件 --%>
<%@ include file="header.jsp" %>
<body>
<div style="background-color: cadetblue">
這是正文內(nèi)容區(qū)域
</div>
<%-- 引入底部文件 --%>
<%@ include file="footer.html" %>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<div style="background-color: antiquewhite;">
這是footer底部?jī)?nèi)容區(qū)域
</div>
啟動(dòng)Tomcat容器,瀏覽器訪問http://localhost:8080/servlet/include.jsp,結(jié)果如下:
include指令的本質(zhì)是什么呢???我們來查看下編譯之后的Java源代碼,找到上面include.jsp文件編譯之后的源文件,如下所示:
/*
* Generated by the Jasper component of Apache Tomcat
* Version: Apache Tomcat/8.5.98
* Generated at: 2024-02-25 05:06:41 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 com.gitcode.servlet;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
public final class include_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;
static {
_jspx_dependants = new java.util.HashMap<java.lang.String,java.lang.Long>(2);
_jspx_dependants.put("/footer.jsp", Long.valueOf(1708837593266L));
_jspx_dependants.put("/header.jsp", Long.valueOf(1708837593271L));
}
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 {
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, "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');
out.write('\n');
out.write('\r');
out.write('\n');
out.write("\r\n");
out.write("<html>\r\n");
out.write("<head>\r\n");
out.write(" <title>這是HTML頭部</title>\r\n");
out.write("</head>");
out.write("\r\n");
out.write("<body>\r\n");
out.write("\r\n");
out.write("<div style=\"background-color: cadetblue\">\r\n");
out.write(" 這是正文內(nèi)容區(qū)域\r\n");
out.write("</div>\r\n");
out.write("\r\n");
out.write('\r');
out.write('\n');
out.write("\r\n");
out.write("<div style=\"background-color: antiquewhite;\">\r\n");
out.write(" 這是footer底部?jī)?nèi)容區(qū)域\r\n");
out.write("</div>");
out.write("\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);
}
}
}
通過上面源代碼,可以看到,使用include指令引入的兩個(gè)文件,最終都會(huì)將兩個(gè)文件中的內(nèi)容直接嵌入到當(dāng)前include.jsp文件里面,如下所示:
所以include指令的本質(zhì)就是將引入文件中的內(nèi)容,直接拼接到當(dāng)前JSP頁面的對(duì)應(yīng)位置。這里也就會(huì)存在一個(gè)問題,引入的JSP文件中,不能存在和當(dāng)前JSP頁面相同的變量名稱,因?yàn)樽兞棵Q相同會(huì)導(dǎo)致編譯失敗。另外,使用include指令引入其他的JSP文件時(shí)候,只會(huì)生成訪問的那個(gè)JSP文件的源代碼,被引入的JSP文件不會(huì)生成對(duì)應(yīng)的源代碼。
以上,就是include指令的使用及其本質(zhì)。
今天就到這里,未完待續(xù)~~
PHP中有兩個(gè)引入文件的語言結(jié)構(gòu):include、require
1、注意這兩個(gè)都是語言結(jié)構(gòu)不是方法,與echo、print、isset()、empty()、unset()等類似都是語言結(jié)構(gòu)不是函數(shù)!!!!!
2、include與require都是引入外部文件到當(dāng)前上下文環(huán)境,但是他們有一些區(qū)別:
一、被包含文件先按參數(shù)給出的路徑尋找,如果沒有給出目錄(只有文件名)時(shí)則按照 include_path 指定的目錄尋找。如果在 include_path 下沒找到該文件則 include 最后才在調(diào)用腳本文件所在的目錄和當(dāng)前工作目錄下尋找。如果最后仍未找到文件則 include 結(jié)構(gòu)會(huì)發(fā)出一條警告;這一點(diǎn)和 require 不同,后者會(huì)發(fā)出一個(gè)致命錯(cuò)誤。(在這點(diǎn)上include_once與require_once類似,但是他們?cè)趯?dǎo)入一個(gè)已導(dǎo)入的文件都會(huì)忽略,但是他們?cè)谝胛募r(shí)會(huì)判斷是否引入會(huì)降低性能)
二、關(guān)于引入的文件:當(dāng)一個(gè)文件被包含時(shí),其中所包含的代碼繼承了 include、require 所在行的變量范圍。從該處開始,調(diào)用文件在該行處可用的任何變量在被調(diào)用的文件中也都可用。不過所有在包含文件中定義的函數(shù)和類都具有全局作用域。
EG1:
vars.php
<?php
$color = 'green';
$fruit = 'apple';
?>
test.php
<?php
echo "A $color $fruit"; // A
include 'vars.php';
echo "A $color $fruit"; // A green apple
?>
如果 include 出現(xiàn)于調(diào)用文件中的一個(gè)函數(shù)里,則被調(diào)用的文件中所包含的所有代碼將表現(xiàn)得如同它們是在該函數(shù)內(nèi)部定義的一樣。所以它將遵循該函數(shù)的變量范圍。此規(guī)則的一個(gè)例外是魔術(shù)常量,它們是在發(fā)生包含之前就已被解析器處理的。
3、include返回值:
處理返回值:在失敗時(shí) include 返回 FALSE 并且發(fā)出警告。成功的包含則返回 1,除非在包含文件中另外給出了返回值。可以在被包括的文件中使用 return 語句來終止該文件中程序的執(zhí)行并返回調(diào)用它的腳本。同樣也可以從被包含的文件中返回值。可以像普通函數(shù)一樣獲得 include 調(diào)用的返回值。不過這在包含遠(yuǎn)程文件時(shí)卻不行,除非遠(yuǎn)程文件的輸出具有合法的 PHP 開始和結(jié)束標(biāo)記(如同任何本地文件一樣)。可以在標(biāo)記內(nèi)定義所需的變量,該變量在文件被包含的位置之后就可用了。因?yàn)?include 是一個(gè)特殊的語言結(jié)構(gòu),其參數(shù)不需要括號(hào)。在比較其返回值時(shí)要注意。
EG2:
<?php
// won't work, evaluated as include(('vars.php') == TRUE), i.e. include('')
if (include('vars.php') == TRUE) {
echo 'OK';
}
// works
if ((include 'vars.php') == TRUE) {
echo 'OK';
}
講解:
$bar 的值為 1 是因?yàn)?include 成功運(yùn)行了。注意以上例子中的區(qū)別。第一個(gè)在被包含的文件中用了 return 而另一個(gè)沒有。如果文件不能被包含,則返回 FALSE 并發(fā)出一個(gè) E_WARNING 警告。如果在包含文件中定義有函數(shù),這些函數(shù)不管是在 return 之前還是之后定義的,都可以獨(dú)立在主文件中使用。如果文件被包含兩次,PHP 5 發(fā)出致命錯(cuò)誤因?yàn)楹瘮?shù)已經(jīng)被定義,但是 PHP 4 不會(huì)對(duì)在 return 之后定義的函數(shù)報(bào)錯(cuò)。推薦用 include_once 而不是檢查文件是否已包含并在包含文件中有條件返回.
3、include引入文件的處理:(這點(diǎn)很重要)
當(dāng)一個(gè)文件被包含時(shí),語法解析器在目標(biāo)文件的開頭脫離 PHP 模式并進(jìn)入 HTML 模式,到文件結(jié)尾處恢復(fù)。由于此原因,目標(biāo)文件中需要作為 PHP 代碼執(zhí)行的任何代碼都必須被包括在有效的 PHP 起始和結(jié)束標(biāo)記之中。并且當(dāng)執(zhí)行完成之后直接加入到緩沖區(qū),將被導(dǎo)入的文件中的變量加入到當(dāng)前的作用域變量鏈上。
EG3:
//t1.php 文件內(nèi)容
1234<?php $name="PQS"; ?>5678<?php return 1; ?>9
//t2.php文件內(nèi)容
<?php
include "t1.php";
echo $name;
//開始執(zhí)行t2.php
會(huì)輸出:12345678PQS
案例解析:
首先當(dāng)include "t1.php";文件時(shí)PHP解析器脫離PHP模式進(jìn)入HTML模式開始解析,因?yàn)镠TML模式是將內(nèi)容直接加入到緩沖區(qū),所以沒有標(biāo)簽1234會(huì)被首先加入到緩沖區(qū),然后在執(zhí)行<?php $name="PQS"; ?>這里就會(huì)把$name這個(gè)變量加入到t2.php的include "t1.php"這句代碼的上線文變量作用域中。然后接著在回到HTM模式將5678加入到緩沖區(qū),接下來遇到<?php return 1;?>就開始進(jìn)入PHP模式進(jìn)行執(zhí)行代碼,因?yàn)閕nclude是接受return的,所以當(dāng)這里return 1之后整個(gè)文件的加載就到此處結(jié)束了, 返回到t2的代碼執(zhí)行域中了,這也是為什么最后沒有輸出9的原因。
舉個(gè)例子證明PHP將文件輸入到緩沖區(qū):
//t3.php
1234567
//t4.php
<?php
$string = get_include_contents('t3.php');
function get_include_contents($filename) {
if (is_file($filename)) {
ob_start();
include $filename;
$contents = ob_get_contents();
ob_end_clean();
return $contents;
}
return false;
}
echo $string;
//執(zhí)行t4.php
1234567
案例分析:
函數(shù)get_include_contents($filename)
在include之前開啟緩沖區(qū),當(dāng)include將t3.php文件引入后就使用ob_get_contents()方法獲取緩沖區(qū)數(shù)據(jù)賦值給$contents,然后使用ob_end_clean將緩沖區(qū)數(shù)據(jù)丟棄最后將$contents返回,最后輸出返回值就是t3.php在經(jīng)過php運(yùn)行的值。
4、include支持引入U(xiǎn)RL:
如果“URL include wrappers”在 PHP 中被激活,可以用 URL(通過 HTTP 或者其它支持的封裝協(xié)議——見支持的協(xié)議和封裝協(xié)議)而不是本地文件來指定要被包含的文件。如果目標(biāo)服務(wù)器將目標(biāo)文件作為 PHP 代碼解釋,則可以用適用于 HTTP GET 的 URL 請(qǐng)求字符串來向被包括的文件傳遞變量。嚴(yán)格的說這和包含一個(gè)文件并繼承父文件的變量空間并不是一回事;該腳本文件實(shí)際上已經(jīng)在遠(yuǎn)程服務(wù)器上運(yùn)行了,而本地腳本則包括了其結(jié)果。
<?php
/* This example assumes that www.example.com is configured to parse .php *
* files and not .txt files. Also, 'Works' here means that the variables *
* $foo and $bar are available within the included file. */
// Won't work; file.txt wasn't handled by www.example.com as PHP
include 'http://www.example.com/file.txt?foo=1&bar=2';
// Won't work; looks for a file named 'file.php?foo=1&bar=2' on the
// local filesystem.
include 'file.php?foo=1&bar=2';
// Works.
include 'http://www.example.com/file.php?foo=1&bar=2';
$foo = 1;
$bar = 2;
include 'file.txt'; // Works.
include 'file.php'; // Works.
此案例是PHP官網(wǎng)案例,如果不懂之處請(qǐng)移步值PHP官網(wǎng)include章節(jié)!
var aedes = new aedes_1.default();
^
TypeError: aedes_1.default is not a constructor
Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
(Use node --trace-warnings ... to show where the warning was created)
/Users/jiechengyang/src/node-app/mqtt-examples/dist/01/mqtt-server.js:1
import Aedes from 'aedes';
^^^^^^
SyntaxError: Cannot use import statement outside a module
import Aedes from 'aedes'
import { createServer } from 'net'
const port = 1883
const aedes = new Aedes()
const server = createServer(aedes.handle)
server.listen(port, function () {
console.log('server started and listening on port ', port)
})
import Aedes, { AedesOptions } from './types/instance'
export declare function createBroker(options?: AedesOptions): Aedes
export * from './types/instance'
export * from './types/packet'
export * from './types/client'
export { default } from './types/instance'
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"esModuleInterop": true,
"strict": true
},
"include": ["src/**/*.ts"],
"exclude": ["node_modules"]
}
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"esModuleInterop": true,
"strict": true
},
"include": ["src/**/*.ts"],
"exclude": ["node_modules"]
}
因?yàn)槭浅鯇W(xué)ts,造成上面的問題的原因是:個(gè)人使用的編譯選項(xiàng)不對(duì)導(dǎo)致,因此,應(yīng)該熟悉tsconfig.json 的編譯參數(shù).最后的tsconfig.json配置如下:
{
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"declaration": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"lib": [
"DOM",
"ES2022"
],
"module": "ES2022",
"moduleResolution":"node",
// "outDir": "dist",
"rootDir": "src",
"sourceMap": true,
"strict": true,
"target": "ES2022"
},
"include": [
"src/**/*.ts"
]
}
報(bào)錯(cuò)信息表明您的 JavaScript 文件被 Node.js 解釋為 ECMAScript 模塊(ES module),而不是 CommonJS 模塊。這通常是因?yàn)槲募U(kuò)展名是 .mjs,或者因?yàn)?type: module 被設(shè)置在了 package.json 文件中。
在您的情況下,看起來您正在使用 import 語句導(dǎo)入模塊,這是 ECMAScript 模塊的語法。然而,默認(rèn)情況下,Node.js 將文件當(dāng)作 CommonJS 模塊處理。
為了解決這個(gè)問題,有幾個(gè)選項(xiàng):
將文件擴(kuò)展名更改為 .mjs:
將您的文件擴(kuò)展名從 .js 更改為 .mjs。這會(huì)告訴 Node.js 將文件視為 ECMAScript 模塊。
將 type 設(shè)置為 module:
在您的 package.json 文件中,可以添加 "type": "module",以將所有 .js 文件視為 ECMAScript 模塊。
{
"type": "module",
"scripts": {
"start": "node your-script.js"
}
}
注意:將 "type": "module" 添加到 package.json 可能會(huì)影響到項(xiàng)目中其他依賴的模塊。這是因?yàn)?CommonJS 和 ECMAScript 模塊有一些不同之處。確保您的項(xiàng)目及其依賴項(xiàng)對(duì) ECMAScript 模塊提供了正確的支持。
當(dāng)配置 TypeScript 編譯器選項(xiàng)時(shí),各個(gè)屬性有著不同的作用。以下是您 tsconfig.json 文件中使用的一些關(guān)鍵屬性的解釋:
選擇使用 CommonJS 還是 ECMAScript 模塊(ES module)通常取決于您的項(xiàng)目的特定要求和部署環(huán)境。下面是一些建議:
使用 CommonJS:
Node.js 項(xiàng)目: 如果您的項(xiàng)目是一個(gè) Node.js 項(xiàng)目,特別是在舊版 Node.js 中,使用 CommonJS 是很自然的選擇。Node.js 長(zhǎng)期以來一直使用 CommonJS 模塊系統(tǒng)。
現(xiàn)有項(xiàng)目: 如果您的項(xiàng)目中已經(jīng)使用了 CommonJS,為了保持一致性,可能更容易繼續(xù)使用 CommonJS。
npm 生態(tài)系統(tǒng): 大多數(shù) Node.js 包都是以 CommonJS 格式發(fā)布的,因此在使用 npm 生態(tài)系統(tǒng)中,使用 CommonJS 通常更為方便。
使用 ECMAScript 模塊:
前端項(xiàng)目: 在瀏覽器環(huán)境或支持 ES module 的環(huán)境中,可以考慮使用 ECMAScript 模塊。現(xiàn)代前端開發(fā)中,許多工具和框架都支持 ES module。
靜態(tài)分析和優(yōu)化: ECMAScript 模塊在靜態(tài)分析和優(yōu)化方面具有一些優(yōu)勢(shì),因?yàn)樗鼈兲峁┝烁嗟男畔ⅲ@有助于一些工具進(jìn)行更好的代碼優(yōu)化。
模塊化加載器: 如果您的項(xiàng)目中使用了模塊加載器(如Webpack、Rollup等),這些工具通常支持 ES module,并且可以更好地進(jìn)行代碼分割和懶加載等優(yōu)化。
組合使用:
在某些場(chǎng)景下,您也可以在同一項(xiàng)目中同時(shí)使用 CommonJS 和 ES module,這種混合使用的方式在過渡期或特定的工作流中可能會(huì)有用。例如,在一些前端項(xiàng)目中,可以使用 Babel 或 Webpack 進(jìn)行模塊的轉(zhuǎn)換,將 CommonJS 轉(zhuǎn)換為 ES module 以獲得一些優(yōu)勢(shì)。
總體而言,選擇 CommonJS 還是 ES module 取決于您項(xiàng)目的具體需求、使用的環(huán)境以及團(tuán)隊(duì)的偏好。在許多情況下,Node.js 項(xiàng)目會(huì)繼續(xù)使用 CommonJS,而前端項(xiàng)目則更傾向于使用 ES module。
*請(qǐng)認(rèn)真填寫需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。