文件上传下载及注解
文件上傳
一般情況下,我們?nèi)绻诒韱沃猩蟼魑募?#xff0c;一般會(huì)將form的enctype參數(shù)設(shè)置為multipart/form-data。通常文件上傳使用POST請(qǐng)求方式。
原始方法
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html><head><base href="<%=basePath%>"><title>My JSP 'index.jsp' starting page</title><meta http-equiv="pragma" content="no-cache"><meta http-equiv="cache-control" content="no-cache"><meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"><meta http-equiv="description" content="This is my page"><!--<link rel="stylesheet" type="text/css" href="styles.css">--></head><body><%--1.文件上傳,表單必須是post提交2.文件上傳,還需要在表單上加上enctype屬性(提交請(qǐng)求正文的類型)application/x-www-form-urlencoded(默認(rèn)取值,普通提交)multipart/form-data(多段式提交)3. 文件上傳,使用<input type="file" name="photo" /> 標(biāo)簽,并且必須有name屬性--%><form action="/fileupload/Aservlet" method="post" enctype="multipart/form-data">用戶名:<input type="text" name="name" /><br>個(gè)人近照:<input type="file" name="photo" /><br><input type="submit" value="上傳" /></form></body> </html>Aservlet
package fileupload;import java.io.IOException; import java.io.InputStream; import java.io.OutputStream;import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;@WebServlet("/Aservlet") public class Aservlet extends HttpServlet {// 文件上傳只能用POST提交,實(shí)現(xiàn)這個(gè)方法就好了protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//1.獲得瀏覽器提交上來的全部信息InputStream is = request.getInputStream();//2.提取流中的內(nèi)容,再根據(jù)分隔符OutputStream os = System.out;byte[] bytes = new byte[1024];int len = -1;while((len=is.read(bytes))!=-1){os.write(bytes, 0, len);os.flush();//3.手動(dòng)從請(qǐng)求頭中獲得分割線是什么//4.使用分隔線分隔請(qǐng)求正文//5. 從分隔的每一段中 提取信息.}}}使用工具類方便上傳
上面的方法復(fù)雜,使用第三方庫可以很方便的完成文件上傳。提交表達(dá)轉(zhuǎn)到Bservlet
package fileupload;import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.List;import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; 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.FileUploadException; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.apache.commons.io.IOUtils;@WebServlet("/Bservlet") public class Bservlet extends HttpServlet {// 需要用到commons-fileupload.jar, commons-io.jarprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 1. 創(chuàng)建配置工廠DiskFileItemFactory factory = new DiskFileItemFactory();// 2. 根據(jù)配置工廠創(chuàng)建解析請(qǐng)求中文件上傳內(nèi)容的解析器ServletFileUpload upload = new ServletFileUpload(factory);// 3. 判斷當(dāng)前請(qǐng)求是不是多段提交if (!upload.isMultipartContent(request)) {throw new RuntimeException("不是多段提交!");}try {// 4. 解析request對(duì)象,將已經(jīng)分割過的內(nèi)容放進(jìn)了ListList<FileItem> list = upload.parseRequest(request);if (list != null) {for (FileItem fileItem : list) {// 判斷當(dāng)前段是普通字段還是文件,這個(gè)方法是判斷普通段if (fileItem.isFormField()) {// 獲得jsp里name屬性對(duì)應(yīng)的值,這里是usernameString fname = fileItem.getFieldName();// 獲得用戶輸入的用戶名String value = fileItem.getString();System.out.println(fname + "=>"+value );// 否則就是文件了} else {// 獲得上傳文件的文件名String name = fileItem.getName();// 獲得文件上傳段中,文件的流InputStream in = fileItem.getInputStream();// 字節(jié)輸出流,用以保存文件FileOutputStream fos = new FileOutputStream("C:\\Users\\"+name);// 將輸入流復(fù)制到輸出流中IOUtils.copy(in, fos);fos.close();}}}} catch (FileUploadException e) {e.printStackTrace();}}}詳解DiskFileItemFactory
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 1 創(chuàng)建配置工廠=> 有參的構(gòu)造可以 直接設(shè)置下面兩個(gè)配置new DiskFileItemFactory(new File("d:/temp"), 10240);DiskFileItemFactory factory = new DiskFileItemFactory();// 1.1 設(shè)置文件上傳臨時(shí)目錄 => 默認(rèn)位置 => tomcat/tempfactory.setRepository(new File("d:/temp"));// 1.2 設(shè)置文件寫入硬盤的緩沖區(qū)大小=>默認(rèn)值=>10kfactory.setSizeThreshold(10240); }詳解ServletFileUpload
//2 根據(jù)配置工廠創(chuàng)建解析器(解析request對(duì)象) ServletFileUpload upload = new ServletFileUpload(factory); //2.1 判斷當(dāng)前請(qǐng)求是否是多段式提交 upload.isMultipartContent(request); //2.2 設(shè)置多段中每段 段頭 在解析時(shí),使用什么碼表解碼 => 當(dāng)段頭中出現(xiàn)中文時(shí),一定要調(diào)用該方式指定段頭碼表。Content-Disposition: form-data; name="username" // 這種就是段頭 upload.setHeaderEncoding("UTF-8"); //2.3 設(shè)置文件最大上傳大小 (單位:字節(jié)) upload.setSizeMax(1024*1024*10); // 單次請(qǐng)求,總上傳大小限制 10兆.因?yàn)槭嵌喽问教峤?#xff0c;所以可以一次上傳多個(gè)文件。對(duì)單個(gè)文件的限制可以使用下面的方法 upload.setFileSizeMax(1024*1024);// 每個(gè)文件上傳段,大小限制 1兆FileItem表示分割后的每一段的內(nèi)容,主要方法如下
boolean isFormField()。// isFormField方法用來判斷FileItem對(duì)象里面封裝的數(shù)據(jù)是一個(gè)普通文本表單字段,還是一個(gè)文件表單字段。如果是普通文本表單字段,返回一個(gè)true否則返回一個(gè)false。因此可以用該方法判斷是否是普通表單域還是文件上傳表單域。// 注意下面這兩個(gè)方法的區(qū)別String getName()// getName方法用來獲得文件上傳字段中的文件名。String getFieldName()// getFieldName方法用來返回表單標(biāo)簽的name屬性的值String getString("utf-8") // 空參或者傳入編碼方式如"UTF-8"。將FileItem對(duì)象中保存的數(shù)據(jù)流內(nèi)容以一個(gè)字符串返回。如果是普通表單字段,如登錄時(shí)候輸入用戶名。則返回用戶輸入的字段。如果是文件上傳則返回文件的內(nèi)容。boolean isInMemory() // 判斷FileItem對(duì)象封裝的數(shù)據(jù)是保存在內(nèi)存中還是硬盤中。void write(File file) // write方法將FileItem對(duì)象中的內(nèi)容保存到某個(gè)指定的文件中。如果FileItem對(duì)象中的內(nèi)容是保存在某個(gè)臨時(shí)文件中,該方法完成后,臨時(shí)文件可以會(huì)被刪除。該方法也可以將普通表單字段保存在一個(gè)文件中,但最主要的用途是把上傳的文件內(nèi)容保存在本地文件系統(tǒng)中。// 上例中也可以直接用fileItem.write(File file)來講數(shù)據(jù)寫到本地文件String getContentType() // 此方法用來獲得上傳文件的類型,即標(biāo)段字段元素描述頭屬性“content-type”的值,如image/jpeg。如果FileItem對(duì)象對(duì)應(yīng)的是普通的表單字段,將返回null。InputStream getInputStream() // 以流的形式返回上傳文件的主體內(nèi)容。 OutputStream getOutputStream() // 可以用此方法將輸入流寫到FileItem中void delete() // 此方法用來清空FileItem對(duì)象中封裝的主體內(nèi)容,如果內(nèi)容是被保存在臨時(shí)文件中,該方法會(huì)把臨時(shí)文件刪除。long getSize() // 返回上傳文件的大小。 List<FileItem> list = null;try {// 2.4 解析request,將每個(gè)分段中的內(nèi)容封裝到FileItem中l(wèi)ist = upload.parseRequest(request);} catch (FileUploadException e) {e.printStackTrace();}if (list != null) {for (FileItem item : list) {// 3.1 item 判斷當(dāng)前分段是否是普通表單段boolean flag = item.isFormField();// 3.2獲得 表單提交的鍵.(input元素,name屬性的值)// 普通段和文件上傳段都有String fname = item.getFieldName();// 3.3 返回文件名稱,普通段返回nullString name = item.getName();// 3.4 獲得文件上傳中的正文,如果是普通段,如用戶登錄則是用戶自己輸入的值。若是文件,則是文件內(nèi)容。以字符串形式返回段體中的內(nèi)容 注意:文件上傳段不建議使用該方法.使用item.getInputStream()更好String content = item.getString();System.out.println("是否是普通表單提交:" + flag + ",表單提交的鍵:" + fname + ",文件名稱:" + name + ",文件內(nèi)容:" + content);} }解決亂碼
文件上傳時(shí)候的文件名包含中文
ServletFileUpload的setHeaderEncoding("UTF-8");設(shè)置一下即可。
段體內(nèi)容亂碼
即getString()返回的內(nèi)容亂碼。fileItem.getString("UTF-8");即可。
上傳文件后應(yīng)該把文件保存到什么位置?
1. 上傳后如果需要其他用戶可以直接訪問,就放到webRoot下. 2. 上傳后其他用戶不能直接訪問, 不直接放在webRoot下。比如WEB-INF下或硬盤其他位置例如 D:\db\xxx.xxx保存用戶上傳的文件時(shí)的注意事項(xiàng)
使用用戶上傳的文件名來保存文件的話,文件名可能重復(fù)。所以保存文件之前,要保證文件名不會(huì)重復(fù)。
- 可以使用UUID生成隨機(jī)字符串
- 可以使用登錄用戶名+當(dāng)前系統(tǒng)毫秒數(shù)
在一個(gè)目錄下放所有用戶上傳的文件顯然不明智。可以用如下方法
- /upload/2017/04/15/xxxx 使用當(dāng)前日期作為子文件夾名稱
- 當(dāng)前登錄用戶的用戶名作為文件夾名稱
mkdir()和mkdirs()的區(qū)別
mkdirs()可以建立多級(jí)目錄。即使所有層級(jí)的目錄都不存在。這些文件夾都會(huì)創(chuàng)建。比如我們事先并沒有在D盤創(chuàng)建upload和2017等這些文件夾。
kdir只能用于父級(jí)目錄已經(jīng)存在的情況下使用,在已存在的父級(jí)目錄下再新建一級(jí)。只能一級(jí)!比如File("D:\upload\2017\04")。且D:\upload\2017是已經(jīng)存在的。父級(jí) 目錄存且只新建一級(jí)。故file.makedir()返回true成功創(chuàng)建。
但是File("D:\upload\2017\04\15")且D:\upload\2017存在,但不存在15文件夾。所以這里是想新建兩級(jí)目錄。因?yàn)楦讣?jí)目錄不存在所以創(chuàng)建失敗返回false。
多文件同時(shí)上傳
同時(shí)上傳多個(gè)文件,無非是多寫幾個(gè)<input type="file" name="photo">這樣的標(biāo)簽,提交的時(shí)候一并上傳,同時(shí)上傳的文件不過是被分成了幾段而已。由于List<FileItem> list = upload.parseRequest(request);返回的是全部的FileItem的,所以后臺(tái)處理的代碼不用變。這里用js來處理添加和刪除的邏輯。
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%String path = request.getContextPath();String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()+ path + "/"; %><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"><title>My JSP 'index.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!--<link rel="stylesheet" type="text/css" href="styles.css">--> </head><body><script type="text/javascript">function fun1() {//1 創(chuàng)建出想要添加的行var tr = document.createElement("tr");// this表示當(dāng)前標(biāo)簽,這里是buttontr.innerHTML = "<td><input type='file' name='photo' /></td><td><input type='button' value='刪除' onclick='fun2(this)' /></td>";//2 找到表格var table = document.getElementById("one");//3 找到表格最后一行var lastRow = table.rows[table.rows.length-1];//4 insertBefore,由于瀏覽器解析table的原因。tr的父節(jié)點(diǎn)可能并不是table,所以下面的寫法兼容了兩種情況lastRow.parentNode.insertBefore(tr, lastRow);}//參數(shù): 要?jiǎng)h除行中的刪除按鈕對(duì)象,button的父節(jié)點(diǎn)是td,td父節(jié)點(diǎn)是tr,tr的父節(jié)點(diǎn)不一定是table。不過沒關(guān)系,用tr的父節(jié)點(diǎn)去刪除tr就行(obj.parentNode.parentNode)function fun2(obj){obj.parentNode.parentNode.parentNode.removeChild(obj.parentNode.parentNode);}</script><form action="/fileupload/Dservlet" method="post" encType="multipart/form-data"><table border="1" id="one"><tr><th colspan="2">照片上傳</th></tr><tr><td><input type="file" name="photo" /></td><td><input type="button" value="添加"onclick="fun1()" /></td></tr><tr><td colspan="2" align="center"><inputtype="submit" value="上傳" /></td></tr></table></form></body> </html>文件下載
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html><head><base href="<%=basePath%>"><title>My JSP 'index.jsp' starting page</title><meta http-equiv="pragma" content="no-cache"><meta http-equiv="cache-control" content="no-cache"><meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"><meta http-equiv="description" content="This is my page"><!--<link rel="stylesheet" type="text/css" href="styles.css">--></head><%-- get提交,?name="name" 表示參數(shù)--%><body><a href="/filedownload/Aservlet?name=西電.zip">西電.zip</a> <br><a href="/filedownload/Aservlet?name=課.png">課.png</a> <br><a href="/filedownload/Aservlet?name=Android基礎(chǔ)(四).md">Android基礎(chǔ)(四).md</a> <br></body> </html> package filedownload;import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URLEncoder;import javax.print.URIException; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;import org.apache.commons.io.IOUtils;@WebServlet("/Aservlet") public class Aservlet extends HttpServlet {// 點(diǎn)擊超鏈接屬于GET提交protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 原則: 凡是響應(yīng)正文中需要輸出內(nèi)容, 一定要設(shè)置content-type頭String fileName = request.getParameter("name");System.out.println(fileName);ServletContext sc = getServletContext();// 只會(huì)截取文件后綴名String type = sc.getMimeType(fileName);response.setContentType(type);// 設(shè)置這里讓瀏覽器知道我們下載的文件名,要不默認(rèn)使用Aservlet這個(gè)名稱,且沒有后綴名.注意這里加了attachment;filename=// 文件名可能是中文的,下載時(shí)候可能出現(xiàn)亂碼。要轉(zhuǎn)碼成UTF-8response.setHeader("Content-Disposition", "attachment;filename="+URLEncoder.encode(fileName, "UTF-8"));// 獲得資源輸入流InputStream inputStream = sc.getResourceAsStream("/WEB-INF/resource/"+fileName);OutputStream outputStream = response.getOutputStream();IOUtils.copy(inputStream, outputStream);} }注解
什么是注解?它有什么作用?
注解就是 @xxx 這種就是注解.
- 注釋:給程序員看的.
- 注解:給程序看。
使用注解的目的: 其實(shí)將來使用注解目的就是為了代替?zhèn)鹘y(tǒng)配置文件。
比如下面三個(gè)注解
自定義注解
package annoation;public @interface MyAnnotation {}上面的內(nèi)容被編譯成.class再反編譯過來就是這樣
interface MyAnnotation extends Annotation { }注解本質(zhì)上就是一個(gè)接口。它擴(kuò)展了java.lang.annotation.Annotation接口;在java中所有注解都是Annotation接口的子接口。
package annoation;public @interface MyAnnotation {//聲明屬性=> 用抽象方法//聲明一個(gè)名為name的屬性 類型是StringString name();}自定義注解的使用
package annoation;public class Demo {// 注意一定要鍵name@MyAnnotation(name = "hello")public void test() {} }注解支持的類型
常見的比如
八大基本數(shù)據(jù)類型
- String
- Array
- Enum枚舉
注意
如果注解中,必填屬性只有一個(gè). 這個(gè)屬性的名字是"value".那么在賦值時(shí)不需要加屬性的鍵.
package annoation;import java.lang.annotation.ElementType; public @interface MyAnnotation {String value();// 或者String[] value();} package annoation;public class Demo {// 沒加value="good",直接下面這樣就行@MyAnnotation("good")public void test() {} }可以使用default關(guān)鍵字,添加屬性的默認(rèn)值。就不用寫 a=了
int a() default 10;
元注解
package annoation;import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;//元注解 (4個(gè)) //修飾注解的注解 //RetentionPolicy.SOURCE 注解會(huì)保留到Java源文件這一階段 ,編譯成class文件后就不存在了 //RetentionPolicy.CLASS 注解在源文件和編譯成class文件后也還存在 //RetentionPolicy.RUNTIME 注解在源文件、編譯后的class文件、以及運(yùn)行時(shí)期都存在 // @Retention(RetentionPolicy.RUNTIME) //@Target 注解支持加在什么位置 //ElementType.CONSTRUCTOR 構(gòu)造方法 //ElementType.METHOD 方法 // 比如下面,注解可以加、在構(gòu)造函數(shù),方法和類上 @Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.TYPE})//@Inherited 所加的注解可否被繼承 @Inherited //@Documented 生成java文檔時(shí)候也保留注解 @Documented public @interface MyAnnotation2 {}注解小例子
package annoation;import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface MyAnnotation3 {double value(); }模擬銀行轉(zhuǎn)賬,注解的作用是:單筆轉(zhuǎn)賬不得超過1000
package annoation;import java.lang.reflect.Method;public class BankTransfer {@MyAnnotation3(10000)public static void trans(String person, String another, double money) throws ClassNotFoundException, NoSuchMethodException {// Method m = BankService.class.getMethod("zz",String.class,String.class,double.class); // 也可以上面的寫法// 1. 獲得注解所在的反射對(duì)象 Method m = Class.forName("annoation.BankTransfer").getMethod("trans", String.class, String.class, double.class);//2 判斷方法是否被注解修飾if (m.isAnnotationPresent(MyAnnotation3.class)) {//3 獲得注解的屬性值MyAnnotation3 myAnnotation = m.getAnnotation(MyAnnotation3.class);double maxmoney = myAnnotation.value();if (money > maxmoney) {throw new RuntimeException("單次轉(zhuǎn)賬不能超過" + maxmoney + "元!");}System.out.println(person + "給" + another + "轉(zhuǎn)了" + money + "元!");} else {//沒被注解修飾throw new RuntimeException("系統(tǒng)異常,不能轉(zhuǎn)賬!");}}public static void main(String[] args) throws NoSuchMethodException, ClassNotFoundException {trans("我", "你", 100000);} }重寫JDBCUtils
代替配置文件,使用注解
package annoation;import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;@Retention(RetentionPolicy.RUNTIME) // 加到類上 @Target(ElementType.TYPE) public @interface JDBCInfo {String className();String url();String user();String password();} package annoation;import java.sql.*;@JDBCInfo(className = "com.mysql.jdbc.Driver", url = "jdbc:mysql://localhost:3306/example", user = "root", password ="admin") public class JDBCUtils {private static String driver;private static String url;private static String user;private static String password;// 靜態(tài)代碼塊,隨著類的加載而加載,只加載一次static {try {//獲得注解中配置的屬性//1 獲得注解所在的反射對(duì)象//2 獲得注解的實(shí)現(xiàn)類JDBCInfo info = Class.forName("annoation.JDBCUtils").getAnnotation(JDBCInfo.class);//3 獲得4個(gè)屬性值driver = info.className();url=info.url();user=info.user();password=info.password();} catch (ClassNotFoundException e) {e.printStackTrace();}}public static Connection getConnection() {Connection connection = null;try {connection = DriverManager.getConnection(url, user, password);} catch (Exception e) {e.printStackTrace();throw new RuntimeException("創(chuàng)建連接失敗!");}return connection;}// 釋放資源// 參數(shù)可能為空// 調(diào)用close要拋出異常,即使出現(xiàn)異常也能關(guān)閉 public void close(Connection conn, Statement state, ResultSet result) {try {if (result != null) { result.close();}} catch (SQLException e) {e.printStackTrace();} finally {try {if (state != null) {state.close();}} catch (SQLException e) {e.printStackTrace();} finally {try {if (conn != null) {conn.close();}} catch (SQLException e) {e.printStackTrace();}}}}public static void main(String[] args) {System.out.println(getConnection());} }以前寫的使用properties來保存并讀取配置文件。對(duì)比一下
package jdbc;import java.io.FileInputStream; import java.io.InputStream; import java.sql.*; import java.util.Properties;public class JDBCUtil {private static String driver;private static String url;private static String user;private static String password;// 靜態(tài)代碼塊,隨著類的加載而加載,只加載一次static {try {Properties prop = new Properties();// load()接收InputStream,所以向上轉(zhuǎn)型InputStream is = new FileInputStream("src/jdbc/jdbc_setting.properties");prop.load(is);driver = prop.getProperty("ClassName");url = prop.getProperty("url");user = prop.getProperty("user");password = prop.getProperty("password");Class.forName(driver);is.close();} catch (Exception e) {e.printStackTrace();}}public static Connection getConnection() {Connection connection = null;try {connection = DriverManager.getConnection(url, user, password);} catch (Exception e) {e.printStackTrace();throw new RuntimeException("創(chuàng)建連接失敗!");}return connection;}// 釋放資源// 參數(shù)可能為空// 調(diào)用close要拋出異常,即使出現(xiàn)異常也能關(guān)閉public static void close(Connection conn, Statement state, ResultSet result) {if (result != null) {try {result.close();} catch (SQLException e) {e.printStackTrace();} finally {if (state != null) {try {state.close();} catch (SQLException e) {e.printStackTrace();} finally {if (conn != null) {try {conn.close();} catch (SQLException e) {e.printStackTrace();}}}}}}}public static void main(String[] args) {System.out.println(getConnection());} }枚舉簡介
通常描述數(shù)量固定的屬性。比如性別,一周從周一到周日,這些都是固定的 。為了定義這些量,我們可以這樣寫。
public class Sex { // 靜態(tài)代碼塊最先執(zhí)行,所以這里定義的時(shí)候不初始化也不會(huì)報(bào)錯(cuò)public static final Sex MALE;public static final Sex FEMALE;static {MALE = new Sex();FEMALE = new Sex();}// 或者不用靜態(tài)代碼塊的方法,直接下面這樣// public static final Sex MALE = new Sex();// public static final Sex FEMALE = new Sex();public static void main(String[] args) {//男性Sex male = Sex.MALE;//女性Sex female = Sex.FEMALE;} }如果使用枚舉就很省事
package annoation;public enum Sex2 {MALE, FEMALE; }測(cè)試一下
public static void main(String[] args) {//男性Sex2 male = Sex2.MALE;//女性Sex2 female = Sex2.FEMALE; }by @sunhaiyu
2017.4.15
轉(zhuǎn)載于:https://www.cnblogs.com/sun-haiyu/p/7027024.html
總結(jié)
- 上一篇: Ajax中有关readyState(状态
- 下一篇: 编程理解