EL表達式語言,JSTL,文件的上傳與下載

1、EL表達式簡介

EL 全名爲Expression Language。

EL表達式不能嵌套${${}}

EL主要作用:
獲取數據:
EL表達式主要用於替換JSP頁面中的腳本表達式,以從各種類型的web域 中檢索java對象、獲取數據。(某個web域 中的對象,訪問javabean的屬性、訪問list集合、訪問map集合、訪問數組)
執行運算:
利用EL表達式可以在JSP頁面中執行一些基本的關係運算、邏輯運算和算術運算,以在JSP頁面中完成一些簡單的邏輯運算。${user==null}
獲取web開發常用對象
EL 表達式定義了一些隱式對象,利用這些隱式對象,web開發人員可以很輕鬆獲得對web常用對象的引用,從而獲得這些對象中的數據。
調用Java方法
EL表達式允許用戶開發自定義EL函數,以在JSP頁面中通過EL表達式調用Java類的方法。

(1)、獲取數據

使用EL表達式獲取數據語法:“${標識符}”
EL表達式語句在執行時,會調用pageContext.findAttribute方法,用標識符爲關鍵字,分別從page、request、session、application四個域中查找相應的對象,找到則返回相應對象,找不到則返回”” (注意,不是null,而是空字符串)。 
示例:${user}

EL表達式也可以很輕鬆獲取JavaBean的屬性,或獲取數組、Collection、Map類型集合的數據,例如:
  • ${user.address.city}
  • ${user.list[0]}:訪問有序集合某個位置的元素
  • ${map.key}  : 獲得map集合中指定key的值
結合JSTL的foreach標籤,使用EL表達式也可以很輕鬆迭代各種類型的數組或集合,示例:
  • 迭代數組
  • 迭代collection類型集合
  • 迭代map類型集合

(2)、執行運算

語法:${運算表達式},EL表達式支持如下運算符:  數學運算與邏輯運算



empty運算符:檢查對象是否爲null或“空”,       很好用!!!       判斷傳送過來的map,list進行迭代:$"{!empty(list)}
二元表達式:${user!=null?user.name : “”} ,     很好用!!!       判斷如果登錄就顯示用戶名,否則啥都不顯示
[ ] (取動態變量的值)和 . 號運算符

<% 
	User user = new User();
	user.setGender("male");
	
	//數據回顯
	request.setAttribute("user",user);
%>
<input type="radio" name="gender" value="male" ${user.gender=='male'?'checked':'' }>男
<input type="radio" name="gender" value="female" ${user.gender=='female'?'checked':'' }>女
<br/>

(3)、獲得web開發常用對象

EL表達式語言中定義了11個隱含對象,使用這些隱含對象可以很方便地獲取web開發中的一些常見對象,並讀取這些對象的數據。
語法:${隱式對象名稱}  :獲得對象的引用
隱含對象 描述
pageContext 對應於JSP頁面中的pageContext對象(注意:取的是pageContext對象。)
pageScope 代表page域中用於保存屬性的Map對象
requestScope 代表request域中用於保存屬性的Map對象
sessionScope 代表session域中用於保存屬性的Map對象
applicationScope 代表application域中用於保存屬性的Map對象
param 表示一個保存了所有請求參數的Map對象
paramValues 表示一個保存了所有請求參數的Map對象,它對於某個請求參數,返回
的是一個string[]
header 表示一個保存了所有http請求頭字段的Map對象
headerValues 同上,返回string[]數組。注意:如果頭裏面有“-” ,例Accept-Encoding,
則要headerValues[“Accept-Encoding”]
cookie 表示一個保存了所有cookie的Map對象
initParam 表示一個保存了所有web應用初始化參數的map對象

注意事項
  • 測試headerValues時,如果頭裏面有“-” ,例Accept-Encoding,則要headerValues[“Accept-Encoding”]
  • 測試cookie時,例${cookie.key}取的是cookie對象,如訪問cookie的名稱和值,須${cookie.key.name}或${cookie.key.value}
示例:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>el隱式對象</title>
  </head>
  
  <body>
    
    ${pageContext }  <!-- pageContext.findAttribute("name") -->
    
    
    <br/>
    
    <br/>---------------從指定的page域中查找數據------------------------<br/>
    <% 
    	pageContext.setAttribute("name","aaa");  //map
    %>
    ${pageScope.name }
   
   
   	<br/>---------------從request域中獲取數據------------------------<br/>
   	<% 
   		request.setAttribute("name","bbb");  //map
   	%>
   	${requestScope.name }
   	
   	<br/>---------------從session域中獲取數據------------------------<br/>
   	${sessionScope.user }
   	
   	
   	<br/>--------------獲得用於保存請求參數map,並從map中獲取數據------------------------<br/>
   	<!-- http://localhost:8080/day12/3.jsp?name=aaa  -->
   	${param.name }  
   	
   	<!-- 此表達式會經常用在數據回顯上 -->
   	<form action="${pageContext.request.contextPath }/servlet/RegisterServlet" method="post">
   		<input type="text" name="username" value="${param.username }">
   		<input type="submit" value="註冊">
   	</form>
   	
   	<br/>--------------paramValues獲得請求參數 //map{"",String[]}------------------------<br/>
   	<!-- http://localhost:8080/day12/3.jsp?like=aaa&like=bbb -->
   	${paramValues.like[0] }  
   	${paramValues.like[1] } 
   	
   	<br/>--------------header獲得請求頭------------------------<br/>
   	${header.Accept } 
   	${header["Accept-Encoding"] }
   	
   	
   	<br/>--------------獲取客戶機提交的cookie------------------------<br/>
   	<!-- 從cookie隱式對象中根據名稱獲取到的是cookie對象,要想獲取值,還需要.value -->
   	${cookie.JSESSIONID.value }  //保存所有cookie的map
   	
   	
   	<br/>--------------獲取web應用初始化參數------------------------<br/>
   	${initParam.xxx }  //servletContext中用於保存初始化參數的map
   	${initParam.root }
   	
  </body>
</html>

(4)、使用EL表達式調用Java方法

EL表達式語法允許開發人員開發自定義函數,以調用Java類的方法。
示例:${prefix:method(params)}
  • 在EL表達式中調用的只能是Java類的靜態方法
  • 這個Java類的靜態方法需要在TLD文件中描述,纔可以被EL表達式調用。
EL自定義函數用於擴展EL表達式的功能,可以讓EL表達式完成普通Java程序代碼所能完成的功能。

一般來說, EL自定義函數開發與應用包括以下三個步驟
  • 編寫一個Java類的靜態方法
  • 編寫標籤庫描述符(tld)文件,在tld文件中描述自定義函數。
  • 在JSP頁面中導入和使用自定義函數

示例:開發對html標籤進行轉義的el function
實現類:
A、編寫一個包含靜態方法的類
package cn.itcast;

import java.util.List;

public class HtmlFilter {

	 public static String filter(String message,int arr[]) {
		 
		 System.out.println(arr[0]);

	        if (message == null)
	            return (null);

	        char content[] = new char[message.length()];
	        message.getChars(0, message.length(), content, 0);
	        StringBuffer result = new StringBuffer(content.length + 50);
	        for (int i = 0; i < content.length; i++) {
	            switch (content[i]) {
	            case '<':
	                result.append("<");
	                break;
	            case '>':
	                result.append(">");
	                break;
	            case '&':
	                result.append("&");
	                break;
	            case '"':
	                result.append(""");
	                break;
	            default:
	                result.append(content[i]);
	            }
	        }
	        return (result.toString());

	    }
}
B、在web-inf\目錄下新建一個tld文件,對想被jsp頁面調用的函數進行描述
<?xml version="1.0" encoding="UTF-8" ?>

<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
    version="2.0">
    
    <description>A tag library exercising SimpleTag handlers.</description>
    <tlib-version>1.0</tlib-version>
    <short-name>SimpleTagLibrary</short-name>
    <uri>/itcast</uri>
    
    <function>
        <name>filter</name>
		<function-class>cn.itcast.HtmlFilter</function-class>
		<function-signature>java.lang.String filter(java.lang.String,int[])</function-signature>
    </function>
</taglib>
C、在jsp頁面導入標籤庫,並調用el函數
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib uri="/WEB-INF/itcast.tld" prefix="fn" %>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>My JSP '4.jsp' starting page</title>
  </head>
  
  <body>
  
  	${fn:filter("<a href=''>點點</a>") }
  	
  </body>
</html>

2、JSTL中的常用EL函數

由於在JSP頁面中顯示數據時,經常需要對顯示的字符串進行處理,SUN公司針對於一些常見處理定義了一套EL函數庫供開發者使用。
這些EL函數在JSTL開發包中進行描述,因此在JSP頁面中使用SUN公司的EL函數庫,需要導入JSTL開發包,並在頁面中導入EL函數庫,如下所示:
在頁面中使用JSTL定義的EL函數:
<%@taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>

(1)、fn:toLowerCase 

fn:toLowerCase函數將一個字符串中包含的所有字符轉換爲小寫形式,並返回轉換後的字符串,它接收一個字符串類型的參數,例如
fn:toLowerCase("Www.IT315.org") 的返回值爲字符串“www.it315.org”
fn:toLowerCase("")的返回值爲空字符串

(2)、fn:toUpperCase 

fn:toUpperCase函數將一個字符串中包含的所有字符轉換爲大寫形式,並返回轉換後的字符串,它接收一個字符串類型的參數。例如:
fn:toUpperCase("Www.IT315.org") 的返回值爲字符串“WWW.IT315.ORG”
fn:toUpperCase("")的返回值爲空字符串

(3)、fn:trim 

fn:trim函數刪除一個字符串的首尾的空格,並返回刪除空格後的結果字符串,它接收一個字符串類型的參數。需要注意的是,fn:trim函數不能刪除字符串中間位置的空格。
例如,fn:trim("   www.it315.org  ") 的返回值爲字符串“www.it 315.org”。

(4)、fn:length

fn:length函數返回一個集合數組大小,或返回一個字符串中包含的字符的個數,返回值爲int類型。fn:length函數接收一個參數,這個參數可以是<c:forEach>標籤的items屬性支持的任何類型,包括任意類型的數組、java.util.Collection、java.util.Iterator、java.util.Enumeration、java.util.Map等類的實例對象和字符串。

如果fn:length函數的參數爲null或者是元素個數爲0的集合或數組對象,則函數返回0;如果參數是空字符串,則函數返回0。 

(5)、fn:split

fn:split函數以指定字符串作爲分隔符,將一個字符串分割成字符串數組並返回這個字符串數組

fn:split函數接收兩個字符串類型的參數,第一個參數表示要分割的字符串,第二個參數表示作爲分隔符的字符串。

例如,fn:split("www.it315.org", ".")[1]的返回值爲字符串“it315”。

(6)、fn:join

fn:join函數以一個字符串作爲分隔符,將一個字符串數組中的所有元素合併爲一個字符串並返回合併後的結果字符串

fn:join函數接收兩個參數,第一個參數是要操作的字符串數組,第二個參數是作爲分隔符的字符串。

如果fn:join函數的第二個參數是空字符串,則fn:join函數的返回值直接將元素連接起來。例如:

假設stringArray是保存在Web域中的一個屬性,它表示一個值爲{"www","it315","org"}的字符串數組,則fn:join(stringArray, “.")返回字符串“www.it315.org”
fn:join(fn:split("www,it315,org", ","), ".") 的返回值爲字符串“www.it315.org”

(7)、fn:indexOf  

fn:indexOf函數返回指定字符串在一個字符串中第一次出現的索引值,返回值爲int類型

fn:indexOf函數接收兩個字符串類型的參數,如果第一個參數字符串中包含第二個參數字符串,那麼,不管第二個參數字符串在第一個參數字符串中出現幾次,fn:indexOf函數總是返回第一次出現的索引值;如果第一個參數中不包含第二個參數,則fn:indexOf函數返回-1。如果第二個參數爲空字符串,則fn:indexOf函數總是返回0。例如:
fn:indexOf("www.it315.org","t3") 的返回值爲5

(8)、fn:contains 

fn:contains函數檢測一個字符串中是否包含指定的字符串,返回值爲布爾類型。fn:contains函數在比較兩個字符串是否相等時是大小寫敏感的。

fn:contains函數接收兩個字符串類型的參數,如果第一個參數字符串中包含第二個參數字符串,則fn:contains函數返回true,否則返回false。如果第二個參數的值爲空字符串,則fn:contains函數總是返回true。實際上,fn:contains(string, substring)等價於fn:indexOf(string, substring) != -1。


忽略大小寫的EL函數:fn:containsIgnoreCase 

(9)、fn:startsWith 

fn:startsWith函數用於檢測一個字符串是否是以指定字符串開始的,返回值爲布爾類型

fn:startsWith函數接收兩個字符串類型的參數,如果第一個參數字符串以第二個參數字符串開始,則函數返回true,否則函數返回false。如果第二個參數爲空字符串,則fn:startsWith函數總是返回true。例如:

fn:startsWith("www.it315.org","it315")的返回值爲false

與之對應的EL函數:fn:endsWith 

(10)、fn:replace 

fn:replace函數將一個字符串中包含的指定子字符串替換爲其它的指定字符串,並返回替換後的結果字符串。

fn:replace方法接收三個字符串類型的參數,第一個參數表示要操作的源字符串,第二個參數表示源字符串中要被替換的子字符串,第三個參數表示要被替換成的字符串。例如:

fn:replace("www it315 org", " ", ".")的返回值爲字符串“www.it315.org”


(10)、fn:substring 

fn:substring函數用於截取一個字符串的子字符串並返回截取到的子字符串

fn:substring函數接收三個參數,第一個參數是用於指定要操作的源字符串,第二個參數是用於指定截取子字符串開始的索引值,第三個參數是用於指定截取子字符串結束的索引值,第二個參數和第三個參數都是int類型,其值都從0開始。例如:

fn:substring("www.it315.org", 4, 9) 的返回值爲字符串“it315”

(11)、fn:substringAfter

fn:substringAfter函數用於截取並返回一個字符串中的指定子字符串第一次出現之後的子字符串。

fn:substringAfter函數接收兩個字符串類型的參數,第一個參數表示要操作的源字符串,第二個參數表示指定的子字符串,例如:

fn:substringAfter(“www.it315.org”, “.”)的返回值爲字符串“it315.org”。

與之對應的EL函數爲:fn:substringBefore 

(12)、escapeXml

轉義函數。


常用例子:
<br/><br/>---------------使用el函數回顯數據(重要!!!)---------------------------<br/>
<% 
	User user = new User();
	String likes[] = {"sing","dance"};
	user.setLikes(likes);
	
	//數據回顯
	request.setAttribute("user",user);
%>

<input type="checkbox" name="like" vlaue="sing" ${fn:contains(fn:join(user.likes,","),"sing")?'checked':'' }>唱歌
<input type="checkbox" name="like" value="dance"  ${fn:contains(fn:join(user.likes,","),"dance")?'checked':'' }>跳舞
<input type="checkbox" name="like" value="basketball"  ${fn:contains(fn:join(user.likes,","),"basketball")?'checked':'' }>藍球
<input type="checkbox" name="like" value="football"  ${fn:contains(fn:join(user.likes,","),"football")?'checked':'' }>足球

${fn:escapeXml("<a href=''>點點點</a>")}

3、JSTL標籤庫

核心標籤庫:c.tld
國際化標籤:fmt.tld

數據庫標籤:sql.tld
XML標籤:x.tld

JSTL函數(EL函數):fn.tld

(1)、核心標籤庫

A、<c:out>標籤
<c:out> 標籤用於輸出一段文本內容到pageContext對象當前保存的“out”對象中。

屬性名 是否支持EL 屬性類型 屬性描述
Value true Object 指定要輸出的內容
escapeXml true Boolean 指定是否將>、<、&、'、" 等特殊字符進行HTML編碼
轉換後再進行輸出。默認值爲true
default true Object 指定如果value屬性的值爲null時所輸出的默認值

<br/>-----------------------c:out標籤--------------------------------------<br/>
<% 
	request.setAttribute("data",null);
%>
<c:out value="${data}" escapeXml="true" default="對不起,您要的數據找不着喲!!!"></c:out>


B、<c:set>標籤
<c:set>標籤用於把某一個對象存在指定的域範圍內,或者設置Web域中的java.util.Map類型的屬性對象或JavaBean類型的屬性對象的屬性。 
屬性名
是否支持EL
屬性類型
屬性描述
value true Object 用於指定屬性值
var false String 用於指定要設置的web域屬性的名稱
scope false String 用於指定屬性所在的web域
target true Object 用於指定要設置屬性的對象,這個對象必須是JavaBean
對象或java.util.Map對象
property true String 用於指定當前要爲對象設置的屬性名稱

<br/>-----------------------c:set標籤:向web存數據,向map或bean中存數據--------------------------------------<br/>
<c:set var="data" value="xxx" scope="page"/>
${pageScope.data }
<% 
	Map map = new HashMap();
	request.setAttribute("map",map);
%>
<c:set property="data" value="yyyyy" target="${map}"/>
${map.data }
<%--<c:set property="name" value="flx" target="${person}"></c:set>--%>

C、<c:remove>標籤 
<c:remove>標籤用於刪除各種Web域中的屬性。
其語法格式如下:
<c:remove var="varName"
[scope="{page|request|session|application}"] /> 


D、<c:catch>標籤
<c:catch>標籤用於捕獲嵌套在標籤體中的內容拋出的異常,其語法格式如下:<c:catch [var="varName"]>nested actions</c:catch>
var屬性用於標識<c:catch>標籤捕獲的異常對象,它將保存在page這個Web域中。 
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=gb2312" %>
<c:catch var="myex“ scope=“page”>
	<%
		10/0;
	%>
</c:catch>
異常:<c:out value="${myex}" /><br />
異常 myex.getMessage:<c:out value="${myex.message}" /><br />
異常 myex.getCause:<c:out value="${myex.cause}" /><br />
異常 myex.getStackTrace:<c:out value="${myex.stackTrace}" />

E、<c:if>標籤
<c:if test=“”>標籤可以構造簡單的“if-then”結構的條件表達式  
屬性名 是否支持EL 屬性類型 屬性描述
test true boolean 決定是否處理標籤體中的內容的條件表達式 
var false String 用於指定將test屬性的執行結果保存到某個Web域中
的某個屬性的名稱
scope false String 指定將test屬性的執行結果保存到哪個Web域中

<br/>-----------------------c:if標籤--------------------------------------<br/>

<c:if test="${user==null}" var="b" scope="page"></c:if>
${b }


F、<c:choose>標籤 
<c:choose>標籤用於指定多個條件選擇的組合邊界,它必須與<c:when>和<c:otherwise>標籤一起使用。使用<c:choose>,<c:when>和<c:otherwise>三個標籤,可以構造類似 “if-else if-else” 的複雜條件判斷結構。
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=gb2312" %>
<c:set value="${param.count}" var="count“  /> pageContext(count,2)
<c:choose>
	<c:when test="${count == 0}">
		對不起,沒有符合您要求的記錄。
	</c:when>
	<c:otherwise>
		符合您要求的記錄共有${count}條.
	</c:otherwise>
</c:choose>

G、<c:forEach>標籤

<c:forEach>標籤用於對一個集合對象中的元素進行循環迭代操作,或者按指定的次數重複迭代執行標籤體中的內容。 
屬性名 是否支持EL 屬性類型 屬性描述
var false String 指定將當前迭代到的元素保存到page這個Web域中的
屬性名稱
items true 任何支持的類型 將要迭代的集合對象
begin true int 如果指定items屬性,就從集合中的第begin個元素
開始進行迭代,begin的索引值從0開始編號;如果
沒有指定items屬性,就從begin指定的值開始迭代,
直到end值時結束迭代
end true int 參看begin屬性的描述
step true int 指定迭代的步長,即迭代因子的迭代增量
<br/>-----------------------foreach標籤--------------------------------------<br/>

<c:forEach var="num" begin="1" end="10" step="1">
	${num }
</c:forEach>

<% 
	List list = Arrays.asList("1","2");
	request.setAttribute("list",list);
%>

<c:forEach var="index"  begin="0" end="${fn:length(list)}">
	${list[index] }
</c:forEach>

H、<c:param>標籤 
  • 在JSP頁面進行URL的相關操作時,經常要在URL地址後面附加一些參數。<c:param>標籤可以嵌套在<c:import>、<c:url>或<c:redirect>標籤內,爲這些標籤所使用的URL地址附加參數。
  • <c:param>標籤在爲一個URL地址附加參數時,將自動對參數值進行URL編碼,例如,如果傳遞的參數值爲“中國”,則將其轉換爲“%d6%d0%b9%fa”後再附加到URL地址後面,這也就是使用<c:param>標籤的最大好處。 

示例:<c:param name="name" value="value" />

I、<c:url>標籤 

<c:url>標籤用於在JSP頁面中構造一個URL地址,其主要目的是實現URL重寫。URL重寫就是將會話標識號以參數形式附加在URL地址後面 

屬性名 是否支持EL 屬性類型 屬性描述
value true String 指定要構造的URL
var false String 指定將構造出的URL結果保存到Web域中的屬性名稱
scope false String 指定將構造出的URL結果保存到哪個Web域中

<br/>-----------------------c:url標籤(重點)--------------------------------------<br/>
<c:url value="/servlet/ServletDemo1" var="servletdemo1">
	<c:param name="name" value="中國"/>
	<c:param name="password" value="我是一個"/>
</c:url>
<a href="${servletdemo1 }">點點</a>

J、<c:redirect>標籤

<c:redirect>標籤用於實現請求重定向

屬性名 是否支持EL 屬性類型 屬性描述
url true String 指定要轉發或重定向到的目標資源的URL地址
context true String 當要使用相對路徑重定向到同一個服務器下的其他WEB應用程
序中的資源時,context屬性指定其他WEB應用程序的名稱

(2)、WEB國際化

軟件的國際化:軟件開發時,要使它能同時應對世界不同地區和國家的訪問,並針對不同地區和國家的訪問,提供相應的、符合來訪者閱讀習慣的頁面或數據。
國際化又稱爲 i18n:internationalization

軟件實現國際化,需具備哪些特徵:
  • 對於程序中固定使用的文本元素,例如菜單欄、導航條等中使用的文本元素、或錯誤提示信息,狀態信息等,需要根據來訪者的地區和國家,選擇不同語言的文本爲之服務。
  • 對於程序動態產生的數據,例如(日期,貨幣等),軟件應能根據當前所在的國家或地區的文化習慣進行顯示。
A、固定文本元素的國際化
對於軟件中的菜單欄、導航條、錯誤提示信息,狀態信息等這些固定不變的文本信息,可以把它們寫在一個properties文件中,並根據不同的國家編寫不同的properties文件。這一組properties文件稱之爲一個資源包。
在JavaAPI中提供了一個ResourceBundle 類用於描述一個資源包,並且 ResourceBundle類提供了相應的方法getBundle,這個方法可以根據來訪者的國家地區自動獲取與之對應的資源文件予以顯示。

a、創建資源包和資源文件
一個資源包中的每個資源文件都必須擁有共同的基名。除了基名,每個資源文件的名稱中還必須有標識其本地信息的附加部分。例如:一個資源包的基名是“myproperties”,則與中文、英文環境相對應的資源文件名則爲: 
“myproperites_zh.properties”  “myproperites_en.properties”


每個資源包都應有一個默認資源文件,這個文件不帶有標識本地信息的附加部分。若ResourceBundle對象在資源包中找不到與用戶匹配的資源文件,它將選擇該資源包中與用戶最相近的資源文件,如果再找不到,則使用默認資源文件。例如:
myproperites.properties

b、資源文件的書寫格式

資源文件的內容通常採用“關鍵字=值”的形式,軟件根據關鍵字檢索值顯示在頁面上。一個資源包中的所有資源文件的關鍵字必須相同,值則爲相應國家的文字。
並且資源文件中採用的是properties格式文件,所以文件中的所有字符都必須是ASCII字碼,對於像中文這樣的非ACSII字符,須先進行編碼。(java提供了一個native2ascII命令用於編碼)。例:
屬性文件是不能保存中文的


c、編程實現固定文本的國際化
ResourceBundle類提供了一個靜態方法getBundle,該方法用於裝載資源文件,並創建ResourceBundle實例:
                Locale currentLocale = Locale.getDefault();     //獲取當前java虛擬機默認的語言環境
                ResourceBundle myResources =ResourceBundle.getBundle(basename, currentLocale);
basename爲資源包基名(且必須爲完整路徑)。
如果與該locale對象匹配的資源包子類找不到。一般情況下,則選用默認資源文件予以顯示。 
加載資源文件後, 程序就可以調用ResourceBundle 實例對象的 getString 方法獲取指定的資源信息名稱所對應的值。
      String value =  myResources.getString(“key");
在WEB應用中實現固定文本的國際化

建立一個resource包,分別建立properties文件
demo1
public static void main(String[] args) {
	Locale locale = Locale.getDefault();
	ResourceBundle bundle = ResourceBundle.getBundle("cn.itcast.resource.myproperties",Locale.US);
	
	String username = bundle.getString("username");
	String password= bundle.getString("password");
	
	System.out.println(username);
	System.out.println(password);
}

JSP中實現靜態文本國際化:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>login</title>
  </head>  
  <body>  	
  	<fmt:setBundle var="bundle"  basename="cn.itcast.resource.myproperties" scope="page"/>    
    <form action="">
    	<fmt:message key="username" bundle="${bundle}"/><input type="text" name="username"><br/>
    	<fmt:message key="password" bundle="${bundle}"/><input type="password" name="password"><br/>
    	<input type="submit" value="<fmt:message key="submit" bundle="${bundle}"/>">
    </form>
    
    
  </body>
</html>

B、動態數據的國際化

數值,貨幣,時間,日期等數據由於可能在程序運行時動態產生,所以無法像文字一樣簡單地將它們從應用程序中分離出來,而是需要特殊處理。Java 中提供瞭解決這些問題的 API 類(位於 java.util 包和 java.text 包中)

Locale 類(沒有的利用構造函數構造)
Locale 實例對象代表一個特定的地理,政治、文化區域。
一個 Locale 對象本身不會驗證它代表的語言和國家地區信息是否正確,只是向本地敏感的類提供國家地區信息,與國際化相關的格式化和解析任務由本地敏感的類去完成。(若JDK中的某個類在運行時需要根據 Locale 對象來調整其功能,這個類就稱爲本地敏感類)

a、時間日期國際化——DateFormat類

DateFormat 類可以將一個日期/時間對象格式化爲表示某個國家地區的日期/時間字符串。

DateFormat 類除了可按國家地區格式化輸出日期外,它還定義了一些用於描述日期/時間的顯示模式的 int 型的常量,包括FULL, LONG, MEDIUM, DEFAULT, SHORT,實例化DateFormat對象時,可以使用這些常量,控制日期/時間的顯示長度。

例子:
例如,對於日期/時間“2005年9月15日下午4時41分20秒”,如設置了DateFormat的顯示模式,則日期/時間顯示樣式分別爲:
SHORT模式完全是數字的,在中文環境下顯示爲“05-9-15 下午4:41”;在英文環境下爲“9/15/05 4:41 PM”。

MEDIUM模式比SHORT模式長些,在中文環境顯示爲“2005-9-15 16:41:20”;在英文環境下顯示爲“Sep 15, 2005 4:41:20 PM”。

LONG模式比MEDIUM模式更長一些,在中文環境下顯示爲“2005年9月15日 下午04時41分20秒”;在英文環境下顯示爲“September 15, 2005 4:41:20 PM CST”。

FULL模式指定日期/時間的完整格式,在中文環境下顯示爲“2005年9月15日 星期四 下午04時41分20秒 CST”;在英文環境下,這個日期/時間顯示爲“Thursday, September 15, 2005 4:41:20 PM CST”。

實例化DateFormat類有九種方式,以下三種爲帶參形式,下面列出的三種方式也可以分別不帶參,或只帶顯示樣式的參數。
  • getDateInstance(int style, Locale aLocale):以指定的日期顯示模式和本地信息來獲得DateFormat實例對象,該實例對象不處理時間值部分。
  • getTimeInstance(int style, Locale aLocale):以指定的時間顯示模式和本地信息來獲得DateFormat實例對象,該實例對象不處理日期值部分。
  • getDateTimeInstance(int dateStyle, int timeStyle, Locale aLocale):以單獨指定的日期顯示模式、時間顯示模式和本地信息來獲得DateFormat實例對象。

DateFormat 對象的方法:
format: 將date對象格式化爲符合某個本地環境習慣的字符串。
parse:將字符串解析爲日期/時間對象
注意:parse和format完全相反,一個是把date時間轉化爲相應地區和國家的顯示樣式,一個是把相應地區的時間日期轉化成date對象,該方法在使用時,解析的時間或日期要符合指定的國家、地區格式,否則會拋異常。


DateFormat 對象通常不是線程安全的,每個線程都應該創建自己的 DateFormat  實例對象

public static void main(String[] args) throws ParseException {

Date date = new Date();  //當前這一刻的時間(日期、時間)

//輸出日期部分
DateFormat df = DateFormat.getDateInstance(DateFormat.FULL, Locale.GERMAN);
String result = df.format(date);
System.out.println(result);

//輸出時間部分
df = DateFormat.getTimeInstance(DateFormat.FULL, Locale.CHINA);
result = df.format(date);
System.out.println(result);


//輸出日期和時間
df = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.LONG, Locale.CHINA);
result = df.format(date);
System.out.println(result);


//把字符串反向解析成一個date對象
String s = "10-9-26 下午02時49分53秒";
df = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.LONG, Locale.CHINA);
Date d = df.parse(s);
System.out.println(d);
}

b、數字貨幣國際化——NumberFormat類

NumberFormat 可以將一個數值格式化爲符合某個國家地區習慣的數值字符串,也可以將符合某個國家地區習慣的數值字符串解析爲對應的數值
NumberFormat 類的方法:
  • format 方法:將一個數值格式化爲符合某個國家地區習慣的數值字符串
  • parse 方法:將符合某個國家地區習慣的數值字符串解析爲對應的數值。
實例化NumberFormat類時,可以使用locale對象作爲參數,也可以不使用,下面列出的是使用參數的。
  • getNumberInstance(Locale locale):以參數locale對象所標識的本地信息來獲得具有多種用途的NumberFormat實例對象
  • getIntegerInstance(Locale locale):以參數locale對象所標識的本地信息來獲得處理整數的NumberFormat實例對象
  • getCurrencyInstance(Locale locale):以參數locale對象所標識的本地信息來獲得處理貨幣的NumberFormat實例對象
  • getPercentInstance(Locale locale):以參數locale對象所標識的本地信息來獲得處理百分比數值的NumberFormat實例對象
int price = 89;

NumberFormat nf = NumberFormat.getCurrencyInstance(Locale.CHINA);
String result = nf.format(price);
System.out.println(result);

String s = "¥89.00";
nf = NumberFormat.getCurrencyInstance(Locale.CHINA);
Number n = nf.parse(s);
System.out.println(n.doubleValue()+1);

double num = 0.5;
nf = NumberFormat.getPercentInstance();
System.out.println(nf.format(num));

b、動態文本——MessageFormat

如果一個字符串中包含了多個與國際化相關的數據,可以使用MessageFormat類對這些數據進行批量處理。
例如:
At 12:30 pm on jul 3,1998, a hurricance destroyed 99 houses and caused $1000000 of damage
以上字符串中包含了時間、數字、貨幣等多個與國際化相關的數據,對於這種字符串,可以使用MessageFormat類對其國際化相關的數據進行批量處理。
MessageFormat 類如何進行批量處理呢?
  • MessageFormat類允許開發人員用佔位符替換掉字符串中的敏感數據(即國際化相關的數據)。
  • MessageFormat類在格式化輸出包含佔位符的文本時,messageFormat類可以接收一個參數數組,以替換文本中的每一個佔位符。

At 12:30 pm on jul 3,1998, a hurricance destroyed 99 houses and caused $1000000 of damage

模式字符串:
      At {0} on {1},a destroyed {2} houses and caused {3} of damage

模式字符串:
On {0}, a hurricance destroyed {1} houses and caused {2} of damage.

MessageFormat類
MessageFormat(String pattern)  
實例化MessageFormat對象,並裝載相應的模式字符串。

format(object obj[])
格式化輸出模式字符串,參數數組中指定佔位符相應的替換對象。
format(new Object[ ]{date, new Integer(99), new Double(1E7) })

String pattern = "On {0}, a hurricance destroyed {1} houses and caused "
			+ "{2} of damage.";
MessageFormat msgFmt = new MessageFormat(pattern,Locale.US);

//準備參數數組
String datetime = "Jul 3, 1998 12:30 PM";
Date date = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, 
			DateFormat.SHORT, Locale.US).parse(datetime);
Object [] msgArgs = {date, new Integer(99),new Double(1E7)};

//執行格式化操作
String result = msgFmt.format(msgArgs);
System.out.println(result);

佔位符有三種方式書寫方式:
  • {argumentIndex}: 0-9 之間的數字,表示要格式化對象數據在參數數組中的索引號
  • {argumentIndex,formatType}: 參數的格式化類型
  • {argumentIndex,formatType,FormatStyle}: 格式化的樣式,它的值必須是與格式化類型相匹配的合法模式、或表示合法模式的字符串。
String pattern = "At {0, time, short} on {0, date}, a destroyed'\n'"
		+ "{1} houses and caused {2, number, currency} of damage.";

MessageFormat msgFmt = new MessageFormat(pattern,Locale.US);

String datetimeString = "Jul 3, 1998 12:30 PM";
Date date = DateFormat.getDateTimeInstance(DateFormat.MEDIUM,
DateFormat.SHORT,Locale.US).parse(datetimeString);
String event = "a hurricance";
Object []msgArgs = {date, event, new Integer(99), new Double(1E7)};

String result = msgFmt.format(msgArgs);
System.out.println(result);


C、國際化標籤庫

a、<fmt:setLocale>標籤
<fmt:setLocale value="locale"
     [variant="variant"]
     [scope="{page|request|session|application}"]/>
<fmt:setLocale>

b、<fmt:setBundle>標籤
<fmt:setBundle basename="basename"
	[var="varName"]
	[scope="{page|request|session|application}"] />
<fmt:setBundle>
basename  指定創建ResourceBundle實例對象的基名

c、<fmt:message>標籤
<fmt:message key="username" bundle="${bundle}"/>
佔位符:
<fmt:param>標籤
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ page contentType="text/html;charset=gb2312" %>
<jsp:useBean id="now" class="java.util.Date" />
<%
	session.setAttribute("number", new Integer(8888888));
%>
<fmt:setBundle basename="org.it315.greetings" var="greetings" />
<fmt:message>標籤內嵌套<fmt:param>標籤的情況:<br />
<fmt:message key="okKey" bundle="${greetings}">
	<fmt:param value="${now}" />
	<fmt:param value="${number}" />
</fmt:message><br /><hr />
<fmt:message>標籤內沒有嵌套<fmt:param>標籤的情況:<br />
<fmt:bundle basename="org.it315.greetings" prefix="org.it315.">
	<fmt:message key="okKey" />
</fmt:bundle>	

4、文件的上傳與下載

(1)、文件的上傳

A、文件上傳概述
實現web開發中的文件上傳功能,需完成如下二步操作:
  • 在web頁面中添加上傳輸入項
  • 在servlet中讀取上傳文件的數據,並保存到本地硬盤中。
如何在web頁面中添加上傳輸入項?
<input type=“file”>標籤用於在web頁面中添加文件上傳輸入項,設置文件上傳輸入項時須注意:
  • 必須要設置input輸入項的name屬性,否則瀏覽器將不會發送上傳文件的數據。
  • 必須把form的enctype屬值設爲multipart/form-data.設置該值後,瀏覽器在上傳文件時,將把文件數據附帶在http請求消息體中,並使用MIME協議對上傳的文件進行描述,以方便接收方對上傳數據進行解析和處理
如果表單的提交類型爲multipart/form-data的話,在servlet方就不能採用傳統方式獲取表單數據

如何在Servlet中讀取文件上傳數據,並保存到本地硬盤中?
Request對象提供了一個getInputStream方法,通過這個方法可以讀取到客戶端提交過來的數據。但由於用戶可能會同時上傳多個文件,在servlet端編程直接讀取上傳數據,並分別解析出相應的文件數據是一項非常麻煩的工作,示例。
爲方便用戶處理文件上傳數據,Apache 開源組織提供了一個用來處理表單文件上傳的一個開源組件( Commons-fileupload ),該組件性能優異,並且其API使用極其簡單,可以讓開發人員輕鬆實現web文件上傳功能,因此在web開發中實現文件上傳功能,通常使用Commons-fileupload組件實現。
使用Commons-fileupload組件實現文件上傳,需要導入該組件相應的支撐jar包:Commons-fileupload和commons-io。commons-io 不屬於文件上傳組件的開發jar文件,但Commons-fileupload 組件從1.1 版本開始,它工作時需要commons-io包的支持。

maven引入:
<!-- 文件上傳下載-->
<dependency>
	<groupId>commons-io</groupId>
	<artifactId>commons-io</artifactId>
	<version>2.4</version>
</dependency>
<dependency>
	<groupId>commons-fileupload</groupId>
	<artifactId>commons-fileupload</artifactId>
	<version>1.3.1</version>
</dependency>




B、核心API—DiskFileItemFactory
DiskFileItemFactory 是創建 FileItem 對象的工廠,這個工廠類常用方法:

public void setSizeThreshold(int sizeThreshold) 
設置內存緩衝區的大小,默認值爲10K。當上傳文件大於緩衝區大小時, fileupload組件將使用臨時文件緩存上傳文件。

public void setRepository(java.io.File repository) 
指定臨時文件目錄,默認值爲System.getProperty("java.io.tmpdir").

public DiskFileItemFactory(int sizeThreshold, java.io.File repository) 
構造函數

C、核心API—ServletFileUpload
ServletFileUpload 負責處理上傳的文件數據,並將表單中每個輸入項封裝成一個 FileItem 對象中。常用方法有:

boolean isMultipartContent(HttpServletRequest request) 
判斷上傳表單是否爲multipart/form-data類型

List parseRequest(HttpServletRequest request)
解析request對象,並把表單中的每一個輸入項包裝成一個fileItem 對象,並返回一個保存了所有FileItem的list集合。 

setFileSizeMax(long fileSizeMax) 
設置上傳文件的最大值

setSizeMax(long sizeMax) 
設置上傳文件總量的最大值

setHeaderEncoding(java.lang.String encoding) 
設置編碼格式

setProgressListener(ProgressListener pListener) 
設置監聽器(常用於進度條)



示例:
package cn.itcast.web.contorller;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

public class UploadServlet3 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		try{
			
			//1.得到解析器工廠
			DiskFileItemFactory factory = new DiskFileItemFactory();
			
			//2.得到解析器
			ServletFileUpload upload = new ServletFileUpload(factory);
			
			//3.判斷上傳表單的類型
			if(!upload.isMultipartContent(request)){
				//上傳表單爲普通表單,則按照傳統方式獲取數據即可
				return;
			}
			
			//爲上傳表單,則調用解析器解析上傳數據
			List<FileItem> list = upload.parseRequest(request);  //FileItem
			
			//遍歷list,得到用於封裝第一個上傳輸入項數據fileItem對象
			for(FileItem item : list){
				
				if(item.isFormField()){
					//得到的是普通輸入項
					String name = item.getFieldName();  //得到輸入項的名稱
					String value = item.getString();
					System.out.println(name + "=" + value);
				}else{
					//得到上傳輸入項
					String filename = item.getName();  //得到上傳文件名  C:\Documents and Settings\ThinkPad\桌面\1.txt
					filename = filename.substring(filename.lastIndexOf("\\")+1);
					InputStream in = item.getInputStream();   //得到上傳數據
					int len = 0;
					byte buffer[]= new byte[1024];
					
					//用於保存上傳文件的目錄應該禁止外界直接訪問
					String savepath = this.getServletContext().getRealPath("/WEB-INF/upload");
					System.out.println(savepath);
					
					FileOutputStream out = new FileOutputStream(savepath + "\\" + filename);  //向upload目錄中寫入文件
					while((len=in.read(buffer))>0){
						out.write(buffer, 0, len);
					}
					
					in.close();
					out.close();
				}
			}		
		}catch (Exception e) {
			e.printStackTrace();
		}

		
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		doGet(request, response);
	}

}

文件上傳的注意事項
(1)、爲了保證服務器的安全,要把上傳文件放到WEB-INF目錄下面,禁止外界直接訪問。
(2)、中文亂碼問題
(3)、windows系統的一個文件夾下不能放超過10000個文件,不能只是用一個文件保存。哈希算法進行打散
(4)、文件重名問題,唯一的文件名保存






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章