Servlet3.0新特性全解
Servlet3.0新特性全解
tomcat 7以上的版本都支持Servlet 3.0
Servlet 3.0 新增特性
- 注解支持;Servlet、Filter、Listener無(wú)需在web.xml中進(jìn)行配置,可以通過(guò)對(duì)應(yīng)注解進(jìn)行配置;
- 支持Web模塊;
- Servlet異步處理;
- 文件上傳API簡(jiǎn)化;
Servlet3.0的注解
- @WebServlet :修飾Servlet類,用于部署該Servlet類。
- @WebFilter:修飾Filter類,用于部署該Filter類
- @WebInitParam:與@WebServlet或@WebFilter注解連用,為它們配置參數(shù)
- @MultipartConfig:修飾Servlet類,指定該Servlet類負(fù)責(zé)處理multipart/form-data類型的請(qǐng)求(主要用于處理上傳文件)
- @ServletSecurity:修飾Servlet類,與JAAS(Java驗(yàn)證和授權(quán)API)有關(guān)的注解
- @HttpConstrait:與@ServletSecurity連用
- @HttpMethodConstrait:與@ServletSecurity連用
示例代碼片: 修飾過(guò)濾器Filter:
@WebFilter( ? ? ? ?filterName="log", ? ? ? ?urlPatterns={"/*"}, ? ? ? ?initParams={ ? ? ? ?@WebInitParam(name="encoding",value="GBK"), ? ? ? ?@WebInitParam(name="loginPage",value="/login.jsp") ? ? ? }) public class MyFilter implements Filter { ? ?//內(nèi)容省略...... }
修飾Servlet
@WebServlet(name="test", ? ?urlPatterns={"/basic.do"}, ? ?initParams={ ? ? ? ?@WebInitParam(name="userName",value="peter"), ? ? ? ?@WebInitParam(name="age",value="100") ? ? ? }) public class TestServlet extends HttpServlet{ ? ?//內(nèi)容省略.... }
修飾監(jiān)聽(tīng)器Listener:
@WebListener public class MyRequestListener implements ServletRequestListener{ ? ?//內(nèi)容省略... }
Servlet3.0的Web模塊支持
原來(lái)一個(gè)web應(yīng)用的任何配置都需要在web.xml中進(jìn)行,因此會(huì)使得web.xml變得很混亂,而且靈活性差?,F(xiàn)在可通過(guò)Web模塊來(lái)部署管理它們。
Web模塊對(duì)應(yīng)一個(gè)Jar包,即Servlet 3.0可以將每個(gè)Servlet、Filter、Listener打成jar包,然后放在WEB-INF\lib中。
每個(gè)模塊都有自己的配置文件,這個(gè)配置文件的名稱為 web-fragment.xml 。
制作一個(gè)Servlet模塊的步驟:
正常編寫Servlet,并編譯;
將此編譯class文件及所在包通過(guò)jar包命令打成jar包;
將此jar包用winrar打開(kāi),將META-INF中的manifest刪除后添加 web-fragment.xml;
將此jar包放入WEB-INF\lib中即可;
web-fragment.xml說(shuō)明:
<web-fragment>
為根元素;<name></name>
表示模塊名稱(模塊的唯一標(biāo)識(shí));<ordering></ordering>
定義模塊加載順序的標(biāo)簽,當(dāng)然可以不設(shè)置模塊加載順序;<before><others/></before>
表示在所有模塊前面加載(第一個(gè)加載);<after><name>A</name></after>
表示在A模塊后面加載;可以在里面部署listener、filter、servlet
值得注意的是,web.xml中用
<absolute-ordering>
標(biāo)簽指定的模塊加載順序?qū)?huì)覆蓋web模塊的web-fragment.xml文件中指定的加載順序。如何用myEclipse打jar包(有些人不知道) 右鍵你web項(xiàng)目里的編寫的servlet(或filter或listener)類——>Export…——>JAR file——>NEXT——>(Browse)填寫導(dǎo)出名字和存放位置——>finish 這樣就生成了我們需要的jar包了
示例 servlet類代碼片:
@WebServlet(name="test",urlPatterns={"/basic.do"}) public class TestServlet extends HttpServlet{ ? ? ?//使用該方法可響應(yīng)客戶端的所有請(qǐng)求 ? ?public void service(HttpServletRequest req, HttpServletResponse resp)throws IOException{ ? ? ? ?System.out.println("進(jìn)servlet了"); ? ? ? ?PrintStream out = new PrintStream(resp.getOutputStream()); ? ? ? ?//向頁(yè)面輸入下面字符串 ? ? ? ?out.print("1234567890"); ? } ? }
web-fragment.xml代碼片
<web-fragment version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" ? ? xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ? ? xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd"> ? ? ? <!-- 指定模塊名稱 :唯一標(biāo)識(shí)--> ? ? <name>mySerModule</name> ? ? <!-- 加載順序 --> ? ? <ordering> ? ? ? ?<!-- 在其它模塊之前加載 --> ? ? ? ?<before> ? ? ? ? ? <others/> ? ? ? ?</before> ? ? </ordering> ? ? ? </web-fragment>
在web-fragment.xml里的配置和之前的web.xml里類似,如果是注解實(shí)現(xiàn)的servlet的配置,則在web-fragment.xml里就將不再寫配置了,如果不是,則還需要寫配置。 打成jar包放在一個(gè)項(xiàng)目里面啟動(dòng)后,就可通過(guò)上面servlet注解配置的/basic.do路徑訪問(wèn)上面的servle了。
servlet3.0提供的異步處理
提供異步原因
在以前的servlet中,如果作為控制器的servlet調(diào)用了一個(gè)較為耗時(shí)的業(yè)務(wù)方法,則servlet必須等到業(yè)務(wù)執(zhí)行完后才會(huì)生成響應(yīng),這使得這次調(diào)用成了阻塞式調(diào)用,效率比較差
實(shí)現(xiàn)異步原理
重新開(kāi)一個(gè)線程單獨(dú)去調(diào)用耗時(shí)的業(yè)務(wù)方法。
配置servlet類成為異步的servlet類
- 通過(guò)注解asyncSupported=true實(shí)現(xiàn)
- 通過(guò)web.xml配置
<servlet> ? ? ? ?<servlet-name>test1</servlet-name> ? ? ? ?<servlet-class>com.zrgk.servlet.AsyncServlet</servlet-class> ? ? ? ?<async-suppored>true</async-suppored> ? ? ? ? ?</servlet> ? ?<servlet-mapping> ? ? ? ?<servlet-name>test1</servlet-name> ? ? ? ?<url-pattern>/basic.do</url-pattern> ? ?</servlet-mapping>
具體實(shí)現(xiàn)
java代碼:
@WebServlet(name="AsyncServlet",urlPatterns={"/testAsyn.do"},asyncSupported=true) ? public class AsyncServlet extends HttpServlet{ ? ? public void service(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{ ? ? ? //解決亂碼 ? ? ? request.setCharacterEncoding("GBK"); ? ? ? ? response.setContentType("text/html;charset=GBK"); ? ? ? ? //通過(guò)request獲得AsyncContent對(duì)象 ? ? ? AsyncContext actx = request.startAsync(); //重點(diǎn)方法** ? ? ? //設(shè)置異步調(diào)用超時(shí)時(shí)長(zhǎng) ? ? ? ?actx.setTimeout(30*3000); ? ? ? ? ?//啟動(dòng)異步調(diào)用的線程 ? ? ? ?actx.start(new MyThread(actx));//重點(diǎn)方法** ? ? ? ? // 直接輸出到頁(yè)面的內(nèi)容(不等異步完成就直接給頁(yè)面) ? ? ? ?//但這些內(nèi)容必須放在標(biāo)簽內(nèi),否則會(huì)在頁(yè)面輸出錯(cuò)誤內(nèi)容,這兒反正我測(cè)試是這樣,具體不知對(duì)不對(duì)?? ? ? ? PrintWriter out = response.getWriter(); ? ? ? out.println("<h1>不等異步返回結(jié)果就直接返到頁(yè)面的內(nèi)容</h1>"); ? ? ? ? out.flush(); ? } ? } ? ? //異步處理業(yè)務(wù)的線程類 public class MyThread implements Runnable { ? ? private AsyncContext actx; ? ? ? //構(gòu)造 ? ? public MyThread(AsyncContext actx){ ? ? ? ? ? ? ?this.actx = actx; ? ? ? } ? ? ? public void run(){ ? ? ? ? ?try{ ? ? ? ? ? ? ?//等待5秒,模擬處理耗時(shí)的業(yè)務(wù) ? ? ? ? ? Thread.sleep(4*1000); ? ? ? ? ? //獲得request對(duì)象,添加數(shù)據(jù)給頁(yè)面 ? ? ? ? ? ServletRequest req = actx.getRequest(); ? ? ? ? ? req.setAttribute("content","異步獲得的數(shù)據(jù)"); ? ? ? ? ? //將請(qǐng)求dispath到index.jsp頁(yè)面,該頁(yè)面的session必須設(shè)為false ? ? ? ? ? actx.dispatch("/index.jsp"); ? ? ? ? }catch(Exception e){ ? ? ? ? ? ?e.printStackTrace(); ? ? ? } ? ? ? } ? }
頁(yè)面代碼(頁(yè)頭里session設(shè)為false,表時(shí)該頁(yè)面不會(huì)再創(chuàng)建session):
<%@ page language="java" import="java.util.*" pageEncoding="utf-8" session="false"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <html> ? ?<body> ? ?<a href="<%=basePath%>/testAsyn.do">測(cè)試異步調(diào)用</a> ? ?異步結(jié)果:${content} ?</body> </html>
異步監(jiān)聽(tīng)器
異步監(jiān)聽(tīng)器用來(lái)監(jiān)聽(tīng)異步Servlet的異步處理事件,通過(guò)實(shí)現(xiàn)AsyncListener接口實(shí)現(xiàn),代碼如下:
public class MyAsyncListener implements AsyncListener{ ? ? ?//異步調(diào)用完成時(shí)觸發(fā) ? ?@Override ? ?public void onComplete(AsyncEvent event) throws IOException { ? ? ? ?// 省略.... ? ? ? ? } ? ? ?//異步調(diào)用出錯(cuò)時(shí)觸發(fā) ? ?@Override ? ?public void onError(AsyncEvent event) throws IOException { ? ? ? ?// 省略.... ? ? ? ? } ? ? ?//異步調(diào)用開(kāi)始觸發(fā) ? ?@Override ? ?public void onStartAsync(AsyncEvent event) throws IOException { ? ? ? ?// 省略.... ? ? ? ? } ? ? ?//異步調(diào)用超時(shí)觸發(fā) ? ?@Override ? ?public void onTimeout(AsyncEvent event) throws IOException { ? ? ? ?// 省略.... ? ? ? ? } ? }
還需要在異步Servlet里注冊(cè)異步監(jiān)聽(tīng)器,即添加如下代碼即可:
actx.addListener(new MyAsyncListener());
Filter異步調(diào)用與Servlet一樣。
改進(jìn)的ServletAPI(上傳文件)
改進(jìn)內(nèi)容
HttpServletRequest增加了對(duì)上傳文件的支持
ServletContext允許通過(guò)編程的方式動(dòng)態(tài)注冊(cè)Servlet、Filter
HttpServletRequest提供了如下兩個(gè)方法處理文件的上傳
Part getPart(String name)
根據(jù)名稱獲取文件上傳域Collection<Part> getParts()
獲取所有文件上傳域上傳文件時(shí)一定要為表單域設(shè)置enctype屬性,它表示表單數(shù)據(jù)的編碼方式,有如下三個(gè)值:
application/x-www-form-urlencoded (默認(rèn)),它只處理表單里的value屬性值,它會(huì)將value值處理成URL編碼方式。如果此時(shí)表單域里有上傳文件的域(type=”file”),則只會(huì)獲取該文件在上傳者電腦里的絕對(duì)路徑串,該串沒(méi)什么實(shí)際意義。
multipart/form-data 此處編碼方式會(huì)以二制流的方式來(lái)處理表單數(shù)據(jù),此時(shí)會(huì)將文件內(nèi)容也封裝到請(qǐng)求參數(shù)里。
texst/plain 當(dāng)表單的action屬性為mailto:URL的形式時(shí)比較方便,主要適用于直接通過(guò)表單發(fā)送郵件的方式
上傳文件的Servlet需要加上@MultipartConfig注解
通過(guò)request獲取的Part對(duì)象就可以操作文件域了
示例
@WebServlet(name="uploadServlet",urlPatterns="/upload.do") @MultipartConfig public class UploaderServlet extends HttpServlet { ? ? ?public void service(HttpServletRequest request,HttpServletResponse response) throws IOException, ServletException{ ? ? ? ?//獲得Par對(duì)象(每個(gè)Part對(duì)象對(duì)應(yīng)一個(gè)文件域) ? ? ? ?Part part = request.getPart("file"); ? ? ? ?long size = part.getSize(); //獲取上傳文件大小 ? ? ? ?String info = part.getHeader("content-disposition");//獲得包含原始文件名的字符串 ? ? ? ?//獲取原始文件名 ? ? ? ?String fileName = info.substring(info.indexOf("filename="")+10,info.length()-1); ? ? ? ?//將文件上傳到某個(gè)位置 ? ? ? ?part.write(getServletContext().getRealPath("/uploadFiles")+"/"+fileName); ? } }
ServletContext提供了如下方法動(dòng)態(tài)注冊(cè)Servlet、Filter addServlet(); 動(dòng)態(tài)注冊(cè)Servlet addFilter(); 動(dòng)態(tài)注冊(cè)Filter addListener(); 動(dòng)態(tài)注冊(cè)Listener setInitParameter(String name ,String value); 為Web應(yīng)用設(shè)置初始化參數(shù)。
以上就是Servlet3.0新特性全解的詳細(xì)內(nèi)容,更多關(guān)于Servlet3.0新特性的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Springboot中使用Filter實(shí)現(xiàn)Header認(rèn)證詳解
這篇文章主要介紹了Springboot中使用Filter實(shí)現(xiàn)Header認(rèn)證詳解,當(dāng)在?web.xml?注冊(cè)了一個(gè)?Filter?來(lái)對(duì)某個(gè)?Servlet?程序進(jìn)行攔截處理時(shí),它可以決定是否將請(qǐng)求繼續(xù)傳遞給?Servlet?程序,以及對(duì)請(qǐng)求和響應(yīng)消息是否進(jìn)行修改,需要的朋友可以參考下2023-08-08Java中POST、GET、@RequestBody和@RequestParam區(qū)別詳析
在前后端傳json數(shù)據(jù)進(jìn)行交互的時(shí)候,同學(xué)們會(huì)經(jīng)常用到的兩個(gè)注解,@RequestBody和@RequestParam主要是用來(lái)接收前端傳給后端的json數(shù)據(jù),下面這篇文章主要給大家介紹了關(guān)于Java中POST、GET、@RequestBody和@RequestParam區(qū)別的相關(guān)資料,需要的朋友可以參考下2022-10-10基于JTable的列寬與內(nèi)容自適應(yīng)的實(shí)現(xiàn)方法
本篇文章是對(duì)JTable的列寬與內(nèi)容自適應(yīng)的實(shí)現(xiàn)方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05使用java實(shí)現(xiàn)百萬(wàn)級(jí)別數(shù)據(jù)導(dǎo)出excel的三種方式
這篇文章主要介紹了使用java實(shí)現(xiàn)百萬(wàn)級(jí)別數(shù)據(jù)導(dǎo)出excel的三種方式,有些業(yè)務(wù)系統(tǒng)可能動(dòng)輒涉及到百萬(wàn)上千萬(wàn)的數(shù)據(jù),用正常的方法效率就變得很低,今天我們來(lái)看看這幾種實(shí)現(xiàn)思路2023-03-03Java ArrayList擴(kuò)容問(wèn)題實(shí)例詳解
這篇文章主要介紹了Java ArrayList擴(kuò)容問(wèn)題實(shí)例詳解,分享了相關(guān)代碼示例,小編覺(jué)得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下2018-02-02Java實(shí)現(xiàn)文件上傳的兩種方法(uploadify和Spring)
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)文件上傳的兩種方法,uploadify和Spring實(shí)現(xiàn)文件上傳,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-11-11