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