Java-Web 基础加强之泛型、注解和Servlet3.0新特性
目錄
?
一、泛型
1.泛型類
2.泛型方法
3.繼承(實現)泛型類(接口)
4.通配符
????? ? (1)通配符概述
????? ? (2)通配符的缺點
????? ? (3)通配符的限制
????? ? (4)帶有下邊界的通配符
????? ? (5)帶有下邊界的通配符
????? ? (6)通配符小結
二、注解
1.注解的概述
2.java中的注解
3.定義注解類
4.使用注解
5.注解的屬性
6.注解的作用目標
7.注釋的保留策略
8.通過反射讀取注解
三、Servlet3.0新特性
1.Servlet3.0新特性概述
2.@WebServlet、@WebFilter、@WebListener
3.Servlet異步處理
4.文件上傳
一、泛型
1.泛型類
????????具有一個或多個泛型變量的類被稱之為泛型類。
public class A<T> {private T t;public A(T t) {this.t = t; } public T get() {return t; } }2.泛型方法
????????泛型方法的特點:
????????????????方法的參數中會使用泛型變量;
????????????????方法的返回值中會使用泛型變量。
public <T> T get(T[] ts) {return ts[ts.lengt / 2]; }3.繼承(實現)泛型類(接口)
????????繼承泛型類需要為父類的泛型變量賦值!就好比創建泛型類的對象時需要給泛型變量賦值一樣。
????????? * 子類不是泛型類:需要給父類傳遞類型常量
? ????????????? > 當給父類傳遞的類型常量為String時,那么在父類中所有T都會被String替換!
????????? * 子類是泛型類:可以給父類傳遞類型常量,也可以傳遞類型變量
// 繼承泛型類1:子類也是泛型類public class MyList<T> extends ArrayList<T> {}// 繼承泛型類2:子類也是泛型類public class MyList2<T> extends ArrayList<T> {}// 繼承泛型類3:子類不是泛型類public class MyList3 extends ArrayList<String> {}4.通配符
????? ? (1)通配符概述
public static void fun(List<?> list) {…}????????上面代碼中的“?”就是一個通配符,它只能在“<>”中使用。造成不能把它從“<>”中拿出來。
????????這時你可以向fun()方法傳遞List<String>、List<Integer>類型的參數了。當傳遞List<String>類型的參數時,表示給“?”賦值為String;當傳遞List<Integer>類型的參數給fun()方法時,表示給“?”賦值為Integer。
????? ? (2)通配符的缺點
????????帶有通配符的參數不能使用與泛型相關的方法,例如:list.add(“hello”)編譯不通過。
????????在上面例子中,List<?> list參數中的通配符可以被賦任何值,但同時你也不知道通配符被賦了什么值。
????????當你不知道“?”是什么時,會使你不能使用任何與泛型相關的方法。也就是說fun()方法的參數list不能再使用它的與泛型相關的方法了。例如:list.add(“hello”)是錯誤的,因為List類的add()方法的參數是T類型,而現在你不知道T是什么類型,你怎么去添加String的東西給list呢?如果使用者在調用fun()方法時傳遞的不是List<String>,而是List<Integer>時,你添加String當然是不可以的。
????????當然,還可以調用list的get()方法。就算你不知道“?”是什么類型,但它肯定是Object類型的。所以你可以:Object o = list.get(0);
????? ? (3)通配符的限制
????????通配符只能出現在引用的定義中,而不能出現在創建對象中。例如:new ArrayList<?>(),這是不可以的。ArrayList<?> list = null,這是可以的。
????? ? (4)帶有下邊界的通配符
????????List<? extends Number> list;
????????????其中<? extends Number>表示通配符的下邊界,即“?”只能被賦值為Number或其子類型。
當fun()方法的參數為List<? extends Number>后,說明你只能賦值給“?”Number或Number的子類型。
????????雖然這多了一個限制,但也有好處,因為你可以list的get()方法了。就算你不知道“?”是什么類型,但你知道它一定是Number或Number的子類型。所以:Number num = list.get(0)是可以的。
????????但是,還是不能調用list.add()方法!
????? ? (5)帶有下邊界的通配符
????????List<? super Integer> list;
????????????????其中<? super Integer>表示通配符的下邊界,即“?”只能被賦值為Integer或其父類型。
????????這時再去調用list.get()方法還是只能使用Object類型來接收:Object o = list.get(0)。因為你不知道“?”到底是Integer的哪個父類。
????????但是你可以調用list.add()方法了,例如:list.add(new Integer(100))是正確的。因為無論“?”是Integer、Number、Object,list.add(new Integer(100))都是正確的。
????? ? (6)通配符小結
????????????????1. 方法參數帶有通配符會更加通用;
????????????????2. 帶有通配符類型的對象,被限制了與泛型相關方法的使用;
????????????????3. 下邊界通配符:可以使用返回值為泛型變量的方法;
????????????????4. 上邊界通配符:可以使用參數為泛型變量的方法。
? ? 5.泛型父類獲取子類傳遞的類型參數
public class A<T> {}public class B extends A<String> {}public class C extends A<Integer> {}????????如果你需要在A類中得到子類給T賦值的類型,那么可以使用下面的方法:
public class A<T> {public A() {ParameterizedType pType = (ParameterizedType) this.getClass().getGenericSuperclass();Class clazz = (Class) pType.getActualTypeArguments()[0];System.out.println(clazz.getName());} }二、注解
1.注解的概述
????????注釋是用來替代配置文件的!我們以前總是要寫一些配置文件,例如web.xml你還記得么?里面要寫<servlet>和<servlet-mapping>!誰來讀配置文件呢?當然是Tomcat!誰來寫配置文件呢?當然是我們來寫了!
????????在Servlet3.0中就可以使用使用注解來代替配置文件,開發者就不用再寫配置文件了,而是寫注解,然后Tomcat來讀取注解。
????????注解也是類,需要定義了才能使用!
????????在Servlet3.0中有一個注解類為@WebServlet,然后我們就可以在Servlet中使用@WebServlet中使用這個注解了。這個注解就是用來替代<servlet>了。然后Tomcat會通過反射來讀取注解中的信息!
2.java中的注解
????????@Override:作用在方法上的注解。當方法不是重寫父類的方法時會報錯;
????????@Deprecated:作用在方法上。標記該方法為作廢方法(已過時);
????????@SuppressWarnings:作用在方法上,壓制警告。
3.定義注解類
????????定義注解類不能使用class、enum,也不能使用interface,而是使用@interface。
????????????@interface myAnn1{}
4.使用注解
????????注解可以作用在:類(接口或枚舉)、屬性、方法、構造器、包、參數、局部變量
@MyAnn public class Demo1 {@MyAnnprivate int a;@MyAnnpublic Demo1() {}@MyAnnpublic void fun1() {}@MyAnnpublic void fun2(@MyAnn String s) {@MyAnnint n = 10;} }@interface MyAnn{}5.注解的屬性
????????定義注解時也可以給出屬性
//定義了兩個屬性 value和value1 @interface MyAnn1{String value();int value1(); }????????當為注解指定屬性后,那么在使用注解時就必須要給屬性賦值了:
@MyAnn(value1=100,value="hello")????????注解的屬性還可以有默認值,使用default關鍵字。在使用注解時就可以不給帶有默認值的屬性賦值了。但沒有給出默認值的屬性還是要賦值的。在使用注解時需要給屬性賦值。
@interface MyAnn3 {String value1() default "hello world";String value(); }????? ? 賦值的時候可以不給有默認值的的value1屬性賦值。當只給名為value的屬性賦值時,還可以不給出屬性的名稱直接給值。
@MyAnn3("hello")????? ? 注意事項:
????????? ? (1)注解的屬性后面要有一對圓括號,而且圓括號內不能給出東西。就像是無參的方法一樣;
????????? ? (2)注解的屬性類型只能是:基本類型、String、Enum、Class、注解類型、以上類型的一維數組類型;
????????? ? (3)注解的屬性可以有默認值,例如:int a() default 100;
????????? ? (4)數組的屬性默認值:int[] arr() default {1,2,3},這里不能使用new int[]{1,2,3}
????????? ? (5)使用注解時,在給數組屬性賦值時的格式:@MyAnn(arr={1,2,3});
6.注解的作用目標
????????在定義注解時可以限制注解的作用目錄!例如讓注解只能作用在類和方法上。
????????在定義注解時,可以使用@Target注解來限制注解的作用目標:
@Target({ElementType.TYPE,ElementType.METHOD}) @interface MyAnn4 {}????????這樣MyAnn就只能作用在類和方法上的!其中ElementType.TYPE表示類和接口。
7.注釋的保留策略
????????注解的保留策略是指,注解是只保留在源代碼上,還是保留到class文件上,再或者是類在運行時,可以被類加載器加載到內存中。
????????如果希望注解被反射,那么注解就要保留到運行時,而不是源代碼或類文件上。
????????指定注解的保留策略需要使用元注解@Retention,它有一個value屬性,類型為RetentionPolicy類型,RetentionPolicy是枚舉類型:
public enum RetentionPolicy {SOURCE, CLASS, RUNTIME } //注解保留到運行時 @Retention(RetentionPolicy.RUNTIME) //注解可以作用在類或方法上 @Target({ElementType.TYPE, ElementType.METHOD}) @interface MyAnn5{//String類型的value屬性,默認值為helloString value() default "hello";//int類型的value1屬性,默認值為100int value1() default 100; }8.通過反射讀取注解
創建注解類
@Retention(RetentionPolicy.RUNTIME)@Target({ ElementType.TYPE, ElementType.METHOD })public @interface MyAnn {String value() default "hello";int value1() default 100;} }給類和方法添加注解
@MyAnn(value = "hello world", value1 = 200)public class MyClass {private int a;@MyAnn("myMethod")public void fun() {}}通過反射讀取注解
@Testpublic void Demo1() throws Exception {Class clazz = MyClass.class;MyAnn myAnn = (MyAnn) clazz.getAnnotation(MyAnn.class);// 獲取類上的MyAnn類型的注解System.out.println(myAnn.value());// 獲取value()屬性值System.out.println(myAnn.value1());// 獲取value1屬性值Method method = clazz.getMethod("fun");MyAnn myAnn1 = method.getAnnotation(MyAnn.class);// 獲取方法上的MyAnn類型的注解System.out.println(myAnn1.value());System.out.println(myAnn1.value1());}三、Servlet3.0新特性
1.Servlet3.0新特性概述
????????Servlete3.0的主要新特性如下三部分:
????????????????使用@WebServlet、@WebFilter、@WebListener三個注解來替代web.xml文件中的Servlet、Filter、Listener的配置;
????????????????Servlet異步處理:當Servlet處理比較費時的問題時,這會讓客戶感覺到很卡。當使用異常處理時可以把已經處理好的內容先一步響應給客戶端瀏覽器,然后使用另一個線程來完成費時的操作,也就是把內容一部分一部分的顯示出來;
????????????????上傳組件:不用再使用fileupload等第三方的上傳組件,使用Servlet3.0的上傳組件會更方便。
2.@WebServlet、@WebFilter、@WebListener
@WebServlet(urlPatterns={"/AServlet"}, initParams={@WebInitParam(name="paramName",value="paramValue")},loadOnStartup=1 ) public class AServlet extends HttpServlet {public void init(ServletConfig config) throws ServletException {System.out.println(config.getInitParameter("paramName"));}public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {request.setCharacterEncoding("utf-8");response.setContentType("text/html;charset=utf-8");response.getWriter().print("Hello World!");} @WebFilter(urlPatterns={"/*"}, dispatcherTypes={DispatcherType.REQUEST, DispatcherType.FORWARD}) public class AFilter implements Filter {public void destroy() {}public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {System.out.println("start filter");chain.doFilter(request, response);System.out.println("end filter");}public void init(FilterConfig fConfig) throws ServletException {} } @WebListener() public class AListener implements ServletContextListener {public void contextDestroyed(ServletContextEvent arg0) {System.out.println("服務器關閉了");}public void contextInitialized(ServletContextEvent arg0) {System.out.println("服務器啟動了");} }3.Servlet異步處理
????????Servlet異步處理就是讓Servlet在處理費時的請求時不要阻塞,而是一部分一部分的顯示。
????????也就是說,在使用Servlet異步處理之后,頁面可以一部分一部分的顯示數據,而不是一直卡,等到請求響應結束后一起顯示。
????????在使用異步處理之前,一定要在@WebServlet注解中給出asyncSupported=true,不然默認Servlet是不支持異步處理的。如果存在過濾器,也要設置@WebFilter的asyncSupported=true。
@WebServlet(urlPatterns = {"/MyServlet"}, asyncSupported=true)????????注意,響應類型必須是text/html,所以:response.setContentType(“text/html;charset=utf-8”);
????????使用異步處理大致可以分為兩步:
????????????? ? (1)Servlet正常響應數據;
????????????? ? (2)Servlet異常響應數據。
????????在Servlet正常響應數據時,沒什么可說的,可通知response.getWriter().print()來向客戶端輸出,但輸出后要使用response.getWriter().flush()刷新,不然數據只是在緩沖區中,不能向客戶端發送數據的。
????????異步響應數據需要使用request.startAsync()方法獲取AsyncContext對象。然后調用AsyncContext對象的start()方法啟動異步響應,start()方法需要一個Runnable類型的參數。在Runnable的run()方法中給出異步響應的代碼。
asyncContext.start(new Runnable() {public void run() {for(char i = 'a'; i <= 'z'; i++) {try {Thread.sleep(100);asyncContext.getResponse().getWriter().print(i + "?");asyncContext.getResponse().getWriter().flush();} catch (Exception e) {e.printStackTrace();}}asyncContext.complete();}});?
????????Tomcat需要知道異步響應是否結束,如果響應不結束,雖然客戶端瀏覽器會看到響應的數據,但是鼠標上只是有個圈圈的不行的轉啊轉的,表示還沒有結束響應。Tomcat會等待到超時為止,這個超時的時間可以通過AsyncContext類的getTimeout()方法獲取,Tomcat默認為20000毫秒。當然也可以通過setTimeOut()方法設置,以毫秒為單位。ac.setTimeout(1000*10)。
????????如果異步線程已經結束了響應,那么可以在異步線程中調用AsyncContext.complete()方法,這樣Tomcat就知道異步線程已經完成了工作了。
4.文件上傳
????????Servlet3.0提供了文件上傳的處理方案。只需要在Servlet上添加@MultipartConfig注解即可。
????????當然也可以為@MultipartConfig注解指定屬性值,它有四個屬性:
????????????????int filesizeThreshold:指定緩存的大小,當超出這個大小后,文件會保存到磁盤上;
????????????????String location:指定臨時文件的目錄;
????????????????long maxFilesize:指定上傳單個文件的大小限制,如果上傳的誰的超出了這個大小,那么就會拋出異常;
????????????????long maxRequestSize:指定整個表單的大小限制。
????????當在Servlet上使用了@MultipartConfig注解后,那么就可以使用request.getPart(“fieldName”)來獲取<input:file>的內容,其中Part表示一個文件表單項。
<form action="/a1/UploadServlet" method="post" enctype="multipart/form-data">用戶名:<input type="text" name="username"/><br/>照 片:<input type="file" name="file1" /><br/><input type="submit" value="提交"/> </form> @WebServlet(urlPatterns={"/UploadServlet"}) @MultipartConfig(maxFileSize=1024 * 1024) public class UploadServlet extends HttpServlet {public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {request.setCharacterEncoding("utf-8");response.setContentType("text/html;charset=utf-8");String username = request.getParameter("username");//還是用原來方法來獲取普通表單項的內容response.getWriter().print("size: " + username + "<br/>");Part part = request.getPart("file1");//獲取文件表單項的內容,返回值為Partresponse.getWriter().print("size: " + part.getSize() + "<br/>");//打印文件的大小response.getWriter().print("type: " + part.getContentType() + "<br/>");//打印文件的類型response.getWriter().print("name: " + part.getName() + "<br/>");//打印文件表單項的filedName,而不是fileName。String name = part.getHeader("content-disposition");//獲取當前文件表單項的指定頭信息String fileNameTmp = name.substring(name.indexOf("filename=")+10); //獲取上傳文件的名稱!因為Part沒有提供獲取fileName的方法,所以需要自己來寫方法處理這一問題String fileName = fileNameTmp.substring(0,fileNameTmp.indexOf("\"")); System.out.println("fileName: " + fileName);String savepath = this.getServletContext().getRealPath("/uploads");part.write(savepath + "/" + fileName);//把文件保存到指定路徑} }?
總結
以上是生活随笔為你收集整理的Java-Web 基础加强之泛型、注解和Servlet3.0新特性的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java-Web 监听器和过滤器
- 下一篇: java美元兑换,(Java实现) 美元