## Jsp入門
[TOC]
## 導學
Jsp:Java Server Page(Java服務器頁面),是一個動態的網頁技術標準。它和其他的 Web 服務器頁面技術:php/asp/ruby/python沒有什么不同,對于它,可以簡單的理解為 Jsp就是 HTML+Java 代碼。在本節課程中,需要了解Jsp的用途、Jsp的執行原理、Jsp的語法等知識點
## Jsp
**為什么要使用Jsp:**
雖然我們可以使用Servlet輸出動態的網頁,但是Servlet本身也有著它的局限性,比如某些復雜的網頁開發維護不方便,動態頁面和Java代碼混合到一起難以維護,Servlet利用`out.println()`語句輸出,開發效率低下,eclipse 難調試等問題。這些問題深深的困擾著我們,于是我們決定放棄使用Servlet對于復雜網頁內容的輸出,將眼光投向另一門技術Jsp。
### Jsp介紹
**Jsp特點:**
1. Jsp是j2ee的功能模塊,由web服務器執行
2. Jsp作用就是降低動態網頁開發難度
3. Jsp使用簡單,有著HTML和Java基礎就可以短時間上手
4. Jsp將HTML和Java代碼分離,降低開發難度
5. Jsp的本質就是Servlet
**Jsp的運行要求:**
1. 可正常運行的Tomcat
2. 所有Jsp的頁面擴展名必須是.jsp
3. Jsp頁面應放在web應用程序目錄下
### 第一個Jsp頁面
在Jsp頁面中,Java代碼需要使用`<% %>`包裹
~~~jsp
<%@ 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>工資年限計算表</title>
</head>
<body>
<table>
<tr>
<th>year</th>
<th>salary</th>
</tr>
<%
for(int i = 0; i <= 50; i++) {
out.println("<tr>");//Jsp中的打印輸出語句,同servlet中代碼
out.println("<td>"+ i +"</td>");
int salary = 0;
if(i <= 5) {
salary = salary + i * 150;//五年內,每年漲薪10%
} else if(i > 5 && i <= 10) {
salary = salary + 5 * 150 + 300 * (i - 5);//五年后,每年漲薪20%
} else if(i > 10) {
salary = salary + 5 * 150 + 300 * 5 + 375 * (i - 10);//十年后,每年漲薪25%
}
out.print("<td>"+ salary +"</td>");
out.println("</tr>");
}
%>
</table>
</body>
</html>
~~~
### Jsp的執行過程

關于Jsp是Servlet的直接證明我們可以在Tomcat的work文件夾中找到。

所有我們在Jsp中所寫的代碼,無論是HTML還是Java都會被轉譯為Servlet代碼。
## Jsp基本語法-Scriptlet
**Jsp的基本語法其實非常簡單,可以分為以下四種:**
1. Jsp代碼塊
2. Jsp聲明構造塊
3. Jsp輸出指令
4. Jsp處理指令
**Jsp代碼塊**
~~~
用于在JSP中嵌入Java代碼,語法:<% java代碼 %>
~~~
**Jsp聲明構造塊**
~~~
Jsp聲明構造塊用于聲明變量、方法、類,語法:<%! 聲明語句 %>
~~~
現在已經不推薦使用了!
**Jsp輸出指令**
~~~
用于在Jsp頁面中顯示java代碼執行結果,語法:<%= Java代碼 %>
~~~
**Jsp處理指令**
~~~
用于提供Jsp執行過程中的輔助信息,語法:<%@Jsp指令 %>
~~~
常用處理指令:
~~~
<%@ page %>定義當前Jsp頁面全局設置
<%@ include %>將其他Jsp頁面與當前Jsp頁面合并
<%@ taglib %>引入Jsp標簽庫
~~~
**Jsp注釋**

注意:HTML注釋和Jsp注釋不同,Jsp注釋不會做任何處理;
而Jsp中的HTML注釋仍然會被執行,但之后不會被瀏覽器解釋;
## Jsp綜合訓練
案例:質數算法
要求:列出1000以內的質數(除1以外,只能被1和自身整除的自然數)
任務:
1. 使用List保存所有的有效的質數
2. 將結果打印到頁面,格式為`<h2>X是質數</h2>`
~~~jsp
<%@page import="java.util.ArrayList"%>
<%@page import="java.util.List"%>
<!-- 當前標簽指示當前頁面語言使用的是Java語言,contenType指明當前頁面內容為text/html格式,并且字符集為UTF-8字符集 -->
<%@ 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>1000以內質數表</title>
</head>
<body>
<h1>1000以內質數表</h1>
<%-- 定義一個方法判斷是否是質數 --%>
<%!
//該方法作用域在當前頁面中,本頁面任何位置都可以調用該方法,這也是jsp方法定義的局限性
boolean isPrime(int num) {
boolean flag = true;
for(int j = 2; j < num; j++) {
if(num % j == 0) {
flag = false;
break;
}
}
return flag;
}
%>
<%
List<Integer> list = new ArrayList<Integer>();
for(int i = 2; i <= 1000; i++) {
/*boolean flag = true;
for(int j = 2; j < i; j++) {
if(i % j == 0) {
flag = false;
break;
}
} */
boolean flag = isPrime(i);
if(flag == true) {
/* out.println("<h2>"+ i +"</h2>"); */
list.add(i);
}
}
%>
<%
for(int p : list) {
//out.println("<h2>"+ p +"是質數</h2>");
%>
<h2 style="color:red;"><%=p %>是質數</h2>
<%
}
%>
</body>
</html>
~~~
## Jsp頁面重用
對于頁面來說,可能在整個項目中,每個頁面都有著相同的頭部和相同的尾部內容的。是否需要每個頁面都寫一遍這些內容呢?比如我們可以打開騰訊的門戶首頁,我們發現有些頁面只有主體內容跟換,頭尾并沒有什么改變。
>[success]include指令可以復用頁面
### 靜態包含 include
include 是包含頁面的指令,屬于靜態頁面引入。
頁面引入的好處在于:可以把多個頁面共同的部分抽象出來定義。
~~~
<%@include file="head.jsp" %>
<h1>content</h1>
<%@include file="foot.jsp" %>
~~~
### 動態包含
~~~
<%
String str = "HELLO";
%>
<jsp:include page="head.jsp"></jsp:include>
<h1><%=str %>,CONTENT</h1>
<jsp:include page="foot.jsp"></jsp:include>
~~~
### 靜態引入和動態引入的區別
在靜態引入中,子頁面是原封不動的把頁面的信息放到了父頁面中,父頁面把所有頁面的頁面信息都收集完成后,統一的進行解析,完成頁面的輸出。這樣,如果在不同的頁面中定義了相同名稱的變量,那么就會產生沖突。
但是在動態引入中,由于每一個頁面都是單獨的進行解析的。再交給父頁面合成生成一個 HTML 頁面,每個子頁面和父頁面中定義的 Scriptlet 是不會產生沖突的。
>[warning] 在實際的開發中,我們一般都是用動態的引入。