国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
導(dǎo)出文件

第 12 章 導(dǎo)出文件

注意

超越contentType="text/html",servlet不只可以生成text/html類(lèi)型的html文本,也可以生成image/jpeg類(lèi)型的圖片,http支持的所有文件格式都可以通過(guò)servlet生成。

如果你不滿(mǎn)足以下任一條件,請(qǐng)繼續(xù)閱讀,否則請(qǐng)?zhí)^(guò)此后的部分,進(jìn)入下一章:第 13 章 剖析el表達(dá)式。

  1. 了解如何使用servlet生成圖片。

  2. 了解設(shè)置contentType使servlet生成不同格式的文件。

12.1. 圖片校驗(yàn)碼

進(jìn)入首頁(yè),會(huì)顯示一個(gè)彩色圖形驗(yàn)證碼,用戶(hù)根據(jù)圖片上的文字輸入文本框。

如果輸入錯(cuò)誤,會(huì)提示輸入與圖片文字不同,并更新驗(yàn)證碼。

輸入正確會(huì)顯示成功信息。

彩色驗(yàn)證碼用來(lái)防止惡意程序自動(dòng)發(fā)送垃圾消息,或者是惡意程序循環(huán)嘗試登錄密碼。人眼可以根據(jù)圖片了解驗(yàn)證碼的內(nèi)容,但如果是程序就需要掃描圖片分析圖片中的內(nèi)容,為了加大程序分析破解的難度,我們還為圖片準(zhǔn)備了干擾用的背景顏色,并隨便修改文字的顏色。這些都是為了加大程序破解的難度。

現(xiàn)在所有的注意力都集中到如何動(dòng)態(tài)生成校驗(yàn)用的圖片,看一下index.jsp中的代碼。

<img src="captcha.jpg" />

大家可能感到奇怪了,這里img標(biāo)簽對(duì)應(yīng)的是一個(gè)靜態(tài)jpg圖片,為什么每次刷新顯示的圖片內(nèi)容都不同呢?仔細(xì)檢查12-01目錄下我們也看不到captcha.jpg這個(gè)圖片,這個(gè)圖片到底是從哪里得到的呢?

如我們之前所談到的第 3.4.2 節(jié) “forward導(dǎo)致找不到圖片”,在html里包含的圖片,css樣式表,js腳本,視頻等等外部資源,都需要瀏覽器再次向服務(wù)器發(fā)起請(qǐng)求。現(xiàn)在我們進(jìn)行的請(qǐng)求是一個(gè)名叫captcha.jpg的圖片,而服務(wù)器上并沒(méi)有這個(gè)圖片,從web.xml里的配置可以看到如下配置。

<servlet><servlet-name>CaptchaServlet</servlet-name><servlet-class>anni.CaptchaServlet</servlet-class></servlet><servlet-mapping><servlet-name>CaptchaServlet</servlet-name><url-pattern>/captcha.jpg</url-pattern></servlet-mapping>

在這里,名叫/captcha.jpg的請(qǐng)求會(huì)交給CaptchaServlet處理。雖然這個(gè)請(qǐng)求看起來(lái)很像一個(gè)實(shí)際存在的文件,可服務(wù)器接收到這個(gè)請(qǐng)求之后并沒(méi)有去磁盤(pán)上找這個(gè)文件,而是根據(jù)web.xml中配置把request發(fā)送給CaptchaServlet并等待它做出響應(yīng)。

請(qǐng)大家注意,jsp和servlet并不是只能返回html格式的數(shù)據(jù),實(shí)際上它們可以生成任意格式的數(shù)據(jù),比如這里我們就用servlet生成了一個(gè)圖片。正如我們之前討論forward時(shí)提到的,第 3.4.2 節(jié) “forward導(dǎo)致找不到圖片”,瀏覽器只是向服務(wù)器發(fā)送了一個(gè)請(qǐng)求,這個(gè)請(qǐng)求的地址是/captcha.jpg還是/index.jsp并沒(méi)有什么區(qū)別,在服務(wù)器看來(lái)他們僅僅是一個(gè)字符串而已,接收到請(qǐng)求后服務(wù)器先去按照web.xml中的配置做映射,將請(qǐng)求交給對(duì)應(yīng)的servlet處理,如果web.xml中沒(méi)有對(duì)應(yīng)這個(gè)請(qǐng)求的映射,才會(huì)去磁盤(pán)查找是否有這么一個(gè)文件,找到文件則輸出到響應(yīng)中傳回客戶(hù)端,如果找不到就返回經(jīng)典的404(找不到訪(fǎng)問(wèn)資源)。

其實(shí)我們使用的/check.do也是一樣的道理,你在服務(wù)器上找不到名叫check.do的文件,它只是一個(gè)指向CheckServlet的道標(biāo),告訴服務(wù)器調(diào)用CheckServlet處理這個(gè)請(qǐng)求,請(qǐng)記住,這些僅僅是請(qǐng)求,你永遠(yuǎn)不知道服務(wù)器會(huì)返回給你什么。

代碼請(qǐng)大家參考12-01/WEB-INF/src/CaptchaServlet.java,因?yàn)閕mg只可能通過(guò)GET方式發(fā)送請(qǐng)求,所以我們僅僅定義了doGet()方法。

public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {//設(shè)置頁(yè)面不緩存response.setHeader("Pragma", "No-cache");response.setHeader("Cache-Control", "no-cache");response.setDateHeader("Expires", 0);// 在內(nèi)存中創(chuàng)建圖象int width = 60, height = 20;BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);// 獲取圖形上下文Graphics g = image.getGraphics();//生成隨機(jī)類(lèi)Random random = new Random();// 設(shè)定背景色g.setColor(getRandColor(200, 250));g.fillRect(0, 0, width, height);//設(shè)定字體g.setFont(new Font("Times New Roman", Font.PLAIN, 18));//畫(huà)邊框//g.setColor(new Color());//g.drawRect(0, 0, width - 1, height - 1);// 隨機(jī)產(chǎn)生155條干擾線(xiàn),使圖象中的認(rèn)證碼不易被其它程序探測(cè)到g.setColor(getRandColor(160, 200));for (int i = 0; i < 155; i++) {int x = random.nextInt(width);int y = random.nextInt(height);int xl = random.nextInt(12);int yl = random.nextInt(12);g.drawLine(x,y,x+xl,y+yl);}// 取隨機(jī)產(chǎn)生的認(rèn)證碼(4位數(shù)字)String sRand = "";for (int i = 0;i < 4; i++) {String rand = String.valueOf(random.nextInt(10));sRand += rand;// 將認(rèn)證碼顯示到圖象中// 調(diào)用函數(shù)出來(lái)的顏色相同,可能是因?yàn)榉N子太接近,所以只能直接生成g.setColor(new Color(20 + random.nextInt(110), 20 + random.nextInt(110), 20 + random.nextInt(110)));g.drawString(rand, 13 * i + 6, 16);}// 將認(rèn)證碼存入SESSIONrequest.getSession().setAttribute("captcha", sRand);// 圖象生效g.dispose();// 輸出圖象到頁(yè)面ImageIO.write(image, "JPEG", response.getOutputStream());}

代碼最先設(shè)置response(響應(yīng))中的頭部配置,告訴瀏覽器不要緩存對(duì)/captcha.jpg的請(qǐng)求結(jié)果,這樣才能保證每次刷新頁(yè)面都看到最新生成的圖片,要是設(shè)置了緩存很可能每次看到的都是最先請(qǐng)求看到的圖片。

中間一大段代碼實(shí)現(xiàn)動(dòng)態(tài)生成圖片的功能,我們先隨機(jī)獲得幾個(gè)數(shù)字,然后寫(xiě)到BufferedImage中,最后就可以把圖片數(shù)據(jù)寫(xiě)到response,因?yàn)閳D片是二進(jìn)制數(shù)據(jù),所以我們使用了response.getOutputStream()而不是response.getWriter()。

為了達(dá)到驗(yàn)證的功能,每次生成圖片之后要記得講隨機(jī)得到的數(shù)字保存到session中,session中的變量可以跨越多個(gè)請(qǐng)求周期存在,等用戶(hù)輸入驗(yàn)證碼提交后就能與session中的數(shù)據(jù)做比較了,這些是在CheckServlet中實(shí)現(xiàn)的。

public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {HttpSession session = request.getSession();String requestCaptcha = request.getParameter("captcha");String sessionCaptcha = (String) session.getAttribute("captcha");if (sessionCaptcha != null && sessionCaptcha.equals(requestCaptcha)) {session.removeAttribute("captcha");request.getRequestDispatcher("/success.jsp").forward(request, response);} else {request.setAttribute("message", "驗(yàn)證碼輸入錯(cuò)誤");request.getRequestDispatcher("/index.jsp").forward(request, response);}}

這樣我們便獲得了彩色圖性校驗(yàn)碼的功能,例子在12-01目錄下。

12.2. 圖片校驗(yàn)碼 - jsp版

使用servlet既需要編譯源代碼,又要在web.xml加入對(duì)應(yīng)的請(qǐng)求映射。如果只是需要簡(jiǎn)單的驗(yàn)證碼功能,我們也可以使用jsp實(shí)現(xiàn)。

我們已經(jīng)知道jsp就是servlet的另一種形式,servlet能做的事情jsp也可以實(shí)現(xiàn),下面就是實(shí)現(xiàn)CaptchaServlet功能的captcha.jsp。

<%@ page contentType="image/jpeg" import="java.awt.*,java.awt.image.*,java.util.*,javax.imageio.*" %><%!// 給定范圍獲得隨機(jī)顏色Color getRandColor(int fc,int bc) {Random random = new Random();if(fc > 255) {fc = 255;}if(bc > 255) {bc = 255;}int r = fc + random.nextInt(bc - fc);int g = fc + random.nextInt(bc - fc);int b = fc + random.nextInt(bc - fc);return new Color(r, g, b);}%><%//設(shè)置頁(yè)面不緩存response.setHeader("Pragma", "No-cache");response.setHeader("Cache-Control", "no-cache");response.setDateHeader("Expires", 0);// 在內(nèi)存中創(chuàng)建圖象int width = 60, height = 20;BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);// 獲取圖形上下文Graphics g = image.getGraphics();//生成隨機(jī)類(lèi)Random random = new Random();// 設(shè)定背景色g.setColor(getRandColor(200,250));g.fillRect(0, 0, width, height);//設(shè)定字體g.setFont(new Font("Times New Roman", Font.PLAIN, 18));//畫(huà)邊框//g.setColor(new Color());//g.drawRect(0,0,width-1,height-1);// 隨機(jī)產(chǎn)生155條干擾線(xiàn),使圖象中的認(rèn)證碼不易被其它程序探測(cè)到g.setColor(getRandColor(160, 200));for (int i = 0; i < 155; i++) {int x = random.nextInt(width);int y = random.nextInt(height);int xl = random.nextInt(12);int yl = random.nextInt(12);g.drawLine(x,y,x+xl,y+yl);}// 取隨機(jī)產(chǎn)生的認(rèn)證碼(4位數(shù)字)String sRand = "";for (int i = 0;i < 4; i++) {String rand = String.valueOf(random.nextInt(10));sRand += rand;// 將認(rèn)證碼顯示到圖象中// 調(diào)用函數(shù)出來(lái)的顏色相同,可能是因?yàn)榉N子太接近,所以只能直接生成g.setColor(new Color(20 + random.nextInt(110), 20 + random.nextInt(110), 20 + random.nextInt(110)));g.drawString(rand, 13 * i + 6, 16);}// 將認(rèn)證碼存入SESSIONsession.setAttribute("captcha", sRand);// 圖象生效g.dispose();// 輸出圖象到頁(yè)面ImageIO.write(image, "JPEG", response.getOutputStream());out.clear();out = pageContext.pushBody();%>

captcha.jsp中的代碼與servlet基本相同,不過(guò)需要注意兩點(diǎn)。

  1. 在定義Color getRandColor(int fc,int bc)的時(shí)候用到了<%!%>的寫(xiě)法,比普通<%%>多了一個(gè)嘆號(hào),這是在jsp中定義方法時(shí)必要的步驟,方法必須寫(xiě)到<%!%>中才能正常執(zhí)行,感興趣的話(huà)可以去tomcat的work下找對(duì)應(yīng)生成的java代碼來(lái)研究,看看<%!%>和<%%>的代碼分別生成到哪里。

  2. 在jsp中使用response.getOutputStream()很可能引起一個(gè)問(wèn)題。

    getOutputStream() has already been called for this response    

    在tomcat5下jsp中出現(xiàn)此錯(cuò)誤,一般都是在jsp中使用了輸出流(如輸出圖片驗(yàn)證碼,文件下載等)后沒(méi)有妥善處理好。

    具體的原因就是在tomcat中,jsp轉(zhuǎn)換成servlet之后在函數(shù)_jspService(HttpServletRequest request, HttpServletResponse response)的最后有一段這樣的代碼

    finally {    if (_jspxFactory != null) _jspxFactory.releasePageContext(_jspx_page_context);    }    

    這里是在釋放在jsp中使用的對(duì)象,會(huì)調(diào)用response.getWriter(),因?yàn)檫@個(gè)方法是和response.getOutputStream()相沖突的,所以會(huì)出現(xiàn)以上這個(gè)異常。

    然后當(dāng)然是要提出解決的辦法,其實(shí)挺簡(jiǎn)單的(并不是和某些朋友說(shuō)的那樣--將jsp內(nèi)的所有空格和回車(chē)符號(hào)所有都刪除掉),在使用完輸出流以后調(diào)用以下兩行代碼即可:

    out.clear();    out = pageContext.pushBody();    

我們還需要修改index.jsp,讓其中的img標(biāo)簽請(qǐng)求captcha.jsp。

<img src="include/captcha.jsp">

這里又一次證明了html寫(xiě)的僅僅是請(qǐng)求而已,src="include/captcha.jsp"怎么看都不像一個(gè)圖片的名稱(chēng),但是它確實(shí)可以正確顯示圖片,因?yàn)榉?wù)器將請(qǐng)求交給captcha.jsp,處理后得到是一個(gè)圖片的數(shù)據(jù),可以在瀏覽器里正常顯示。

captcha.jsp放在12-02/include目錄下,小項(xiàng)目中可以直接用它了。

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶(hù)發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
Jsp頁(yè)面中關(guān)于客戶(hù)端圖片緩存的解決
SpringMVC雜記(十) 驗(yàn)證碼生成
驗(yàn)證碼生成 沒(méi)有保存功能,直接顯示 成功2018-7-31
生成登錄頁(yè)面隨機(jī)數(shù)圖片的代碼范例
FusionCharts在服務(wù)器端導(dǎo)出圖片(J2EE版)
java輸出扭曲驗(yàn)證碼 (效果很好)
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服