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類(lèi),用于部署該Servlet類(lèi)。
- @WebFilter:修飾Filter類(lèi),用于部署該Filter類(lèi)
- @WebInitParam:與@WebServlet或@WebFilter注解連用,為它們配置參數(shù)
- @MultipartConfig:修飾Servlet類(lèi),指定該Servlet類(lèi)負(fù)責(zé)處理multipart/form-data類(lèi)型的請(qǐng)求(主要用于處理上傳文件)
- @ServletSecurity:修飾Servlet類(lèi),與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è)配置文件的名稱(chēng)為 web-fragment.xml 。
制作一個(gè)Servlet模塊的步驟:
正常編寫(xiě)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>表示模塊名稱(chēng)(模塊的唯一標(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)目里的編寫(xiě)的servlet(或filter或listener)類(lèi)——>Export…——>JAR file——>NEXT——>(Browse)填寫(xiě)導(dǎo)出名字和存放位置——>finish 這樣就生成了我們需要的jar包了
示例 servlet類(lèi)代碼片:
@WebServlet(name="test",urlPatterns={"/basic.do"})
public class TestServlet extends HttpServlet{
?
? ?//使用該方法可響應(yīng)客戶(hù)端的所有請(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"> ? ? ? <!-- 指定模塊名稱(chēng) :唯一標(biāo)識(shí)--> ? ? <name>mySerModule</name> ? ? <!-- 加載順序 --> ? ? <ordering> ? ? ? ?<!-- 在其它模塊之前加載 --> ? ? ? ?<before> ? ? ? ? ? <others/> ? ? ? ?</before> ? ? </ordering> ? ? ? </web-fragment>
在web-fragment.xml里的配置和之前的web.xml里類(lèi)似,如果是注解實(shí)現(xiàn)的servlet的配置,則在web-fragment.xml里就將不再寫(xiě)配置了,如果不是,則還需要寫(xiě)配置。 打成jar包放在一個(gè)項(xiàng)目里面啟動(dòng)后,就可通過(guò)上面servlet注解配置的/basic.do路徑訪(fǎng)問(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è)線(xiàn)程單獨(dú)去調(diào)用耗時(shí)的業(yè)務(wù)方法。
配置servlet類(lèi)成為異步的servlet類(lèi)
- 通過(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)用的線(xiàn)程
? ? ? ?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ù)的線(xiàn)程類(lèi)
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ù)名稱(chēng)獲取文件上傳域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)文章
Java設(shè)計(jì)模式之Adapter適配器模式
這篇文章主要為大家詳細(xì)介紹了Java設(shè)計(jì)模式之Adapter適配器模式,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-03-03
IntelliJ IDEA 中配置 Spring MVC 環(huán)境的詳細(xì)步
這篇文章主要介紹了IntelliJ IDEA 中配置 Spring MVC 環(huán)境的詳細(xì)步驟及問(wèn)題解決,本文分步驟結(jié)合實(shí)例給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2025-04-04
Java實(shí)現(xiàn)HTML轉(zhuǎn)為Word的示例代碼
本文以Java代碼為例為大家詳細(xì)介紹如何實(shí)現(xiàn)將HTML文件轉(zhuǎn)為Word文檔(.docx、.doc)。在實(shí)際開(kāi)發(fā)場(chǎng)景中可參考此方法來(lái)轉(zhuǎn)換,感興趣的可以了解一下2022-06-06
淺談SpringCache與redis集成實(shí)現(xiàn)緩存解決方案
本篇文章主要介紹了淺談SpringCache與redis集成實(shí)現(xiàn)緩存解決方案,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-12-12
內(nèi)存屏障由來(lái)及實(shí)現(xiàn)思路
這篇文章主要為大家詳細(xì)介紹了內(nèi)存屏障由來(lái)及實(shí)現(xiàn)思路的詳細(xì)講解,讓大家徹底的理解內(nèi)存屏障,有需要的朋友可以借鑒參考下,希望能夠有所幫助2022-01-01
了解java中的Clojure如何抽象并發(fā)性和共享狀態(tài)
Clojure是一種運(yùn)行在Java平臺(tái)上的 Lisp 方言,Lisp是一種以表達(dá)性和功能強(qiáng)大著稱(chēng)的編程語(yǔ)言,但人們通常認(rèn)為它不太適合應(yīng)用于一般情況,而Clojure的出現(xiàn)徹底改變了這一現(xiàn)狀。,需要的朋友可以參考下2019-06-06
以實(shí)例講解Objective-C中的KVO與KVC機(jī)制
這篇文章主要介紹了以實(shí)例講解Objective-C中的KVO與KVC機(jī)制,即Key-Value-Observing與Key-Value-Coding,需要的朋友可以參考下2015-09-09
一文了解Java中record和lombok的使用對(duì)比
Java的 record 關(guān)鍵字是Java 14中引入的一個(gè)新的語(yǔ)義特性。Lombok 是一個(gè)Java庫(kù),可以自動(dòng)生成一些已知的模式為Java字節(jié)碼。本文我們將探討各種使用情況,包括java record 的一些限制。對(duì)于每個(gè)例子,我們將看到Lombok如何派上用場(chǎng),并比較這兩種解決方案2022-07-07

