天天看點

8. EL & JSTL & 檔案上傳下載下傳

1. EL表達式

1.1 介紹

  • EL全稱Expression Language,表達式語言
  • EL表達式主要用于代替jsp頁面中的表達式腳本在jsp頁面中進行資料的輸出
  • EL表達式的格式:${表達式}
  • jsp腳本輸出null值時,顯示的是null字元串;EL表達式輸出null值時,輸出的是空串
  • EL表達式主要是輸出域對象中的資料,當4個域中都有相同key的資料時,EL表達式會按4個域從小到大的順序進行搜尋,找到就輸出

1.2 EL表達式輸出Bean對象

<%
    Person person = new Person();
    ----對person對象進行初始化----
    pageContext.setAttribute("p",person);
%>

輸出Person:${p}<br/>
輸出name字元串:${p.name}<br/>
輸出phones數組:${p.phones}<br/>
輸出cities集合:${p.cities[1]}<br/>
輸出map集合:${p.map.key1}<br/>
           

1.3 EL表達式中的運算

EL表達式支援多種運算符,文法:${運算表達式}

  • 關系運算:① ==或eq:等于;② !=或ne:不等于;③ <或lt:小于;④ >或gt:大于;⑤ <=或le:小于等于;⑥ >=或ge:大于等于
  • 邏輯運算:① &&或and:與運算;② ||或or:或運算;③ !或not:取反運算
  • 算術運算:① +:加法;② -:減法;③ *:乘法;④ /或div:除法;⑤ %或mod:取模
  • empty運算:用于判斷一個資料是否為空。文法:${empty 對象}
  • 點運算和中括号運算:點運算可以輸出Bean對象中某個屬性的值,中括号運算可以輸出有序集合中某個元素的值和map集合中某個key的value

1.4 EL表達式中11個隐含對象

EL表達式中11個隐含對象,是EL表達式自己定義的,可以直接使用:

變量 類型 作用
pageContext PageContextImpl 可以擷取jsp中的九大内置對象
pageScope Map<String,Object> 可以擷取pageContext域中的資料
requestScope Map<String,Object> 可以擷取Request域中的資料
sessionScope Map<String,Object> 可以擷取Session域中的資料
applicationScope Map<String,Object> 可以擷取ServletContext域中的資料
param Map<String,String> 可以擷取請求參數的值
paramValues Map<String,String[]> 可以擷取多個請求參數的值
header Map<String,String> 可以擷取請求頭的資訊
headerValues Map<String,String[]> 可以擷取多個請求頭的資訊
cookie Map<String,Cookie> 可以擷取目前請求的Cookie資訊
initParam Map<String,String> 可以擷取在web.xml中配置的<context-param>上下文參數u
擷取協定:${pageContext.request.scheme}<br>
擷取伺服器ip:${pageContext.request.serverName}<br>
擷取伺服器端口:${pageContext.request.serverPort}<br>
擷取工程路徑:${pageContext.request.contextPath}<br>
擷取請求方法:${pageContext.request.method}<br>
擷取用戶端ip位址:${pageContext.request.remoteHost}<br>
擷取會話id編号:${pageContext.session.id}<br>
           

2. JSTL

2.1 介紹

  • JSTL全稱JSP Standard Tag Library——JSP标準标簽庫
  • EL表達式主要是為了替換jsp中的表達式腳本,而标簽庫則是為了替換代碼腳本
  • JSTL由五個不同功能的标簽庫組成
功能範圍 URI 字首
核心标簽庫(重點) http://java.sun.com/jsp/jstl/core c
格式化 http://java.sun.com/jsp/jstl/fmt fmt
函數 http://java.sun.com/jsp/jstl/functions fn
資料庫(不使用) http://java.sun.com/jsp/jstl/sql sql
XML(不使用) http://java.sun.com/jsp/jstl/xml x

2.2 标簽庫的使用步驟

  • 導入jstl所需要的jar包,或導入maven依賴(需導入jstl和标簽庫兩個依賴)
  • 使用taglib指令引入标簽庫
<dependency>
    <groupId>jstl</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
</dependency>
<dependency>
    <groupId>taglibs</groupId>
    <artifactId>standard</artifactId>
    <version>1.1.2</version>
</dependency>
           
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
           

2.3 使用core核心庫

2.3.1 set标簽

  • 作用:往域中儲存資料,等同于:域對象.setAttribute(key,value)
  • scope屬性:設定儲存到哪個域,page表示PageContext域(預設值)
  • var屬性:設定key
<c:set scope="request" var="abc" value="123"/>
${requestScope.abc}
           

2.3.2 if标簽

  • 作用:用于判斷
  • test屬性:設定判斷的條件,使用EL表達式輸出
<c:if test="${10==10}">
    <h1>10等于10</h1>
</c:if>
           

2.3.3 choose、when、otherwise标簽

  • 作用:多路判斷,等同于switch - case - default
  • 注意:标簽中要使用jsp注釋,不能使用html注釋
<%
    request.setAttribute("abc", 123);
%>
<c:choose>
    <c:when test="${requestScope.abc>150}">
        <h2>no.1</h2>
    </c:when>
    <c:when test="${requestScope.abc>120}">
        <h2>no.2</h2>
    </c:when>
    <c:otherwise>
        <h2>no.3</h2>
    </c:otherwise>
</c:choose>
           

2.3.4 forEach标簽

  • 作用:周遊輸出使用
  • begin和end屬性:表示周遊的開始和結束索引,可以和items屬性結合使用
  • step屬性:周遊的步長
//普通周遊
<c:forEach begin="1" end="10" var="i">
    ${i}
</c:forEach>

//周遊對象類型的數組
<%
    request.setAttribute("arr",new String[]{"123","456","789"});
%>
<c:forEach items="${requestScope.arr}" var="item">
    ${item}
</c:forEach>

//周遊Map集合
<%
    HashMap<String, Object> map = new HashMap<>();
    map.put("key1","value1");
    map.put("key2","value2");
    map.put("key3","value3");
    request.setAttribute("map",map);
%>
<c:forEach items="${requestScope.map}" var="entry">
    ${entry}
    ${entry.key}
    ${entry.value}
</c:forEach>
           

3. 檔案的上傳和下載下傳

3.1 檔案的上傳要求

  • 要有一個form标簽,method=post請求
  • form标簽的encType屬性值必須為multipart/form-data值
  • 在form标簽中使用input type=file添加上傳的檔案
  • 編寫伺服器代碼接收、處理上傳的資料
<form action="/EL_JSTL/uploadServlet" method="post" enctype="multipart/form-data">
    使用者名:<input type="text" name="username"/><br>
    頭像:<input type="file" name="photo"> <br>
    <input type="submit" value="上傳">
</form>
           

3.2 檔案上傳的Http協定内容介紹

  • Content-Type:表示送出的資料類型,其值為enctype的值。multipart/form-data表示送出的資料以多段的形式進行拼接(每一個表單項一個資料段),然後以二進制流的形式發送給伺服器
  • boundary:表示每段資料的分隔符,由浏覽器随機生成

3.3 在伺服器中擷取上傳的檔案資訊

3.3.1 擷取上傳的檔案資訊

在Servlet中可以通過流的方式擷取上傳的檔案資訊:

ServletInputStream inputStream = req.getInputStream();
byte[] buffer = new byte[1024000];
int read = inputStream.read(buffer);
System.out.println(new String(buffer, 0, read));
           

3.3.2 解析上傳的資料

有現成的jar包可用于解析上傳的資料,導入commons-fileupload和commons-io兩個jar包,其中ServletFileUpload類用于解析上傳的資料,該類中提供了多種方法:

  • boolean isMultipartContent(HttpServletRequest request):判斷目前上傳的資料是否是多段的格式
  • List<FileItem> parseRequest(HttpServletRequest request):解析上傳的資料為FileItem類型的清單

FileItem類中的方法用于輔助解析上傳的資料:

  • boolean isFormField():判斷目前表單項是否是普通的表單項,false表示為上傳的檔案
  • String getFieldName():擷取目前表單項的name
  • String getString():擷取目前表單項的值
  • String getName():擷取上傳的檔案名
  • void write(File var1):将上傳的檔案寫到var1所指向的硬碟位置
if (ServletFileUpload.isMultipartContent(req)) {
    FileItemFactory fileItemFactory = new DiskFileItemFactory();
    ServletFileUpload servletFileUpload = new ServletFileUpload(fileItemFactory);
    try {
        List<FileItem> fileItems = servletFileUpload.parseRequest(req);
        for (FileItem fileItem : fileItems) {
            if (fileItem.isFormField()) {
                System.out.println(fileItem.getFieldName());
                System.out.println(fileItem.getString("UTF-8"));
            } else {
                System.out.println(fileItem.getFieldName());
                System.out.println(fileItem.getName());
                fileItem.write(new File("D:/" + fileItem.getName()));
            }
        }
    } catch (FileUploadException e) {
        e.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
    }
}
           

3.4 檔案下載下傳的步驟

  • 用戶端發請求告訴伺服器要下載下傳的檔案
  • 伺服器擷取用戶端要下載下傳的檔案名
  • 伺服器通過響應頭告訴用戶端傳回的資料類型,以及收到的資料是用于下載下傳使用
  • 伺服器讀取要下載下傳的檔案内容
  • 伺服器把下載下傳的檔案内容回傳給用戶端
String downloadFile = "smile.jpg";
ServletContext servletContext = getServletContext();
String mimeType = servletContext.getMimeType("/file/" + downloadFile);
System.out.println(mimeType);
response.setContentType(mimeType);
response.setHeader("Content-Disposition", "attachment;filename=" + downloadFile);
InputStream resourceAsStream = servletContext.getResourceAsStream("/file/" + downloadFile);
OutputStream outputStream = response.getOutputStream();
IOUtils.copy(resourceAsStream, outputStream);
           

注意:要下載下傳的檔案若不在resource目錄下,則要手動設定檔案所在目錄為Tomcat編譯目錄