1.图片校验码

<img  src="captcha.jpg"  />

web.xml配置

  1. <servlet> 
  2.     <servlet-name>CaptchaServlet</servlet-name>
  3.      <servlet-class>anni.CaptchaServlet</servlet-class>
  4.  </servlet> 
  5. <servlet-mapping> 
  6.     <servlet-name>CaptchaServlet</servlet-name>
  7.      <url-pattern>/captcha.jpg</url-pattern>
  8.  </servlet-mapping>

名叫/captcha.jpg的请求会交给CaptchaServlet处理

jsp和servlet并不是只能返回html格式的数据,实际上它们可以生成任意格式的数据,比如这里我们就用servlet生成了一个图片。

浏览器只是向服务器发送了一个请求,这个请求的地址是/captcha.jpg还是/index.jsp并没有什么区别,在服务器看来他们仅仅是一个字符串而已,接收到请求后服务器先去按照web.xml中的配置做映射,将请求交给对应的servlet处理,如果web.xml中没有对应这个请求的映射,才会去磁盘查找是否有这么一个文件,找到文件则输出到响应中传回客户端,如果找不到就返回经典的404(找不到访问资源)。

img只可能通过GET方式发送请求

  1. public void doGet(HttpServletRequest request, HttpServletResponse response)     throws ServletException, IOException {  
  2.     //设置页面不缓存 
  3.     response.setHeader("Pragma", "No-cache");     response.setHeader("Cache-Control", "no-cache");     response.setDateHeader("Expires", 0);  
  4.     // 在内存中创建图象 
  5.     int width = 60, height = 20; 
  6.     BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);  
  7.     // 获取图形上下文 
  8.     Graphics g = image.getGraphics();  
  9.     //生成随机类 
  10.     Random random = new Random();
  11.     // 设定背景色 
  12.     g.setColor(getRandColor(200, 250));     g.fillRect(0, 0, width, height);  
  13.     //设定字体 
  14.     g.setFont(new Font("Times New Roman", Font.PLAIN, 18));  
  15.     //画边框 
  16.     //g.setColor(new Color()); 
  17.     //g.drawRect(0, 0, width - 1, height - 1);
  18.  
  19. // 随机产生155条干扰线,使图象中的认证码不易被其它程序探测到     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);     }  
  20.     // 取随机产生的认证码(4位数字)     String sRand = ""; 
  21.     for (int i = 0;< 4; i++) { 
  22.         String rand = String.valueOf(random.nextInt(10)); 
  23. sRand += rand; 
  24.         // 将认证码显示到图象中 
  25.         // 调用函数出来的颜色相同,可能是因为种子太接近,所以只能直接生成 
  26.         g.setColor(new Color(20 + random.nextInt(110), 20 + random.nextInt(110), 20 + random.nextInt(110)));         g.drawString(rand, 13 * i + 6, 16);     }  
  27.     // 将认证码存入SESSION 
  28.     request.getSession().setAttribute("captcha", sRand);  
  29.     // 图象生效     g.dispose();  
  30.     // 输出图象到页面 
  31.     ImageIO.write(image, "JPEG", response.getOutputStream()); }

代码最先设置response(响应)中的头部配置,告诉浏览器不要缓存对/captcha.jpg的请求结果,这样才能保证每次刷新页面都看到最新生成的图片,要是设置了缓存很可能每次看到的都是最先请求看到的图片。

中间一大段代码实现动态生成图片的功能,我们先随机获得几个数字,然后写到BufferedImage中,最后就可以把图片数据写到response,因为图片是二进制数据,所以我们使用了response.getOutputStream()而不是response.getWriter()。

为了达到验证的功能,每次生成图片之后要记得讲随机得到的数字保存到session中,session中的变量可以跨越多个请求周期存在,等用户输入验证码提交后就能与session中的数据做比较了,这些是在CheckServlet中实现的。

  1. public void doPost(HttpServletRequest request, HttpServletResponse response)     throws ServletException, IOException {  
  2.     HttpSession session = request.getSession();  
  3.     String requestCaptcha = request.getParameter("captcha"); 
  4.     String sessionCaptcha = (String) session.getAttribute("captcha");  
  5.     if (sessionCaptcha != null && sessionCaptcha.equals(requestCaptcha)) {         session.removeAttribute("captcha"); 
  6.         request.getRequestDispatcher("/success.jsp").forward(request, response);     } else { 
  7.         request.setAttribute("message", "验证码输入错误"); 
  8.         request.getRequestDispatcher("/index.jsp").forward(request, response);     } }

2.图片验证码 JSP版本

  1. <%@ page contentType="image/jpeg" import="java.awt.*,java.awt.image.*,java.util.*,javax.imageio.*" %> <%! 
  2. // 给定范围获得随机颜色 
  3. Color getRandColor(int fc,int bc) {     Random random = new Random();     if(fc > 255) {         fc = 255;     } 
  4.     if(bc > 255) {         bc = 255;     } 
  5.     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); } %> <% 
  6. //设置页面不缓存 
  7. response.setHeader("Pragma", "No-cache"); response.setHeader("Cache-Control", "no-cache"); response.setDateHeader("Expires", 0);  
  8. // 在内存中创建图象 
  9. int width = 60, height = 20; 
  10. BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);  
  11. // 获取图形上下文 
  12. Graphics g = image.getGraphics();  
  13. //生成随机类 
  14. Random random = new Random();  
  15.  
  16. // 设定背景色 
  17. g.setColor(getRandColor(200,250)); g.fillRect(0, 0, width, height);  
  18. //设定字体 
  19. g.setFont(new Font("Times New Roman", Font.PLAIN, 18));  
  20. //画边框 
  21. //g.setColor(new Color()); 
  22. //g.drawRect(0,0,width-1,height-1); 
  23.   
  24. // 随机产生155条干扰线,使图象中的认证码不易被其它程序探测到 
  25. 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); }  
  26. // 取随机产生的认证码(4位数字) 
  27. String sRand = ""; 
  28. for (int i = 0;< 4; i++) { 
  29.     String rand = String.valueOf(random.nextInt(10));     sRand += rand; 
  30.     // 将认证码显示到图象中 
  31.     // 调用函数出来的颜色相同,可能是因为种子太接近,所以只能直接生成 
  32.     g.setColor(new Color(20 + random.nextInt(110), 20 + random.nextInt(110), 20 + random.nextInt(110)));     g.drawString(rand, 13 * i + 6, 16); }  
  33. // 将认证码存入SESSION 
  34. session.setAttribute("captcha", sRand);  
  35. // 图象生效 
  36. g.dispose();  
  37. // 输出图象到页面 
  38. ImageIO.write(image, "JPEG", response.getOutputStream());  
  39. out.clear(); 
  40. out = pageContext.pushBody(); 

在jsp中使用response.getOutputStream()很可能引起一个问题。

getOutputStream() has already been called for this response

在tomcat5下jsp中出现此错误,一般都是在jsp中使用了输出流(如输出图片验证码,文件下载等)后没有妥善处理好。

具体的原因就是在tomcat中,jsp转换成servlet之后在函数_jspService(HttpServletRequest request, 
HttpServletResponse response)的最后有一段这样的代码

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

这里是在释放在jsp中使用的对象,会调用response.getWriter(),因为这个方法是和
response.getOutputStream()相冲突的,所以会出现以上这个异常。 
然后当然是要提出解决的办法,其实挺简单的(并不是和某些朋友说的那样--将jsp内的所有空格和回车符号所有都删除掉),在使用完输出流以后调用以下两行代码即可:

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

JSP入门 导出文件的更多相关文章

  1. Jsp入门学习笔记

    #Jsp入门 一.JSP基础语法 1.JSP指令: page inlcude taglib 2.JSP注释: a.html注释: <!-- abcdefghijklmn --> b.jsp ...

  2. JSP入门:介绍什么是JSP和Servlet(转)

    转自:http://developer.51cto.com/art/200907/134506.htm JSP入门:什么是jsp? JSP(Java Server Pages)是由Sun Micros ...

  3. JSP入门必读

    JSP基础知识:转自老师上课梳理的笔记,希望对大家有所帮助.有什么不妥当的地方还望大家批评指正. 特别适用于JSP入门的人员使用.1.JSP [1] 简介1.1 HTML    HTML擅长显示一个静 ...

  4. 九、JSP入门(1)

    JSP入门 1 JSP概述 1.1 什么是JSP JSP(Java Server Pages)是JavaWeb服务器端的动态资源.它与html页面的作用是相同的,显示数据和获取数据. 1.2 JSP的 ...

  5. day11(jsp入门&Cookie&HttpSession&一次性图片校验码)

    day11 JSP入门   1 JSP概述 1.1 什么是JSP JSP(Java Server Pages)是JavaWeb服务器端的动态资源.它与html页面的作用是相同的,显示数据和获取数据. ...

  6. JSP入门之自定义标签

    第二部分简单讲解:主要讲解el表达式,核心标签库.本章主要讲解:自定义标签库:404页面,505页面,错误页面配置方法 全部代码下载:链接 1.JSP自定义标签: 自定义标签是用户定义的JSP语言元素 ...

  7. Jsp入门实战上

    前面讲了servlet入门实践现在开始介绍jsp入门实践,开发环境的搭建请参考我前面的tomcat的文章,jsp入门教程分为上下两部分,第一部分简单讲解:jsp语法的规范,以及三大编译指令,七个动作指 ...

  8. Cookie&&Session&&jsp入门

    会话技术 会话:一次会话中包含多次请求和响应. 一次会话:浏览器第一次给服务器资源发送请求,会话建立,直到有一方断开为止 功能:在一次会话的范围内的多次请求间,共享数据 方式: 客户端会话技术:Coo ...

  9. JSP入门

    JSP简介 所谓JSP就是在网页文件中嵌入Java代码或JSP定义的一些标记.JSP是建立在Servlet上的,在执行时JSP容器会先将JSP文件转换成Servlet文件以及class 文件,然后再执 ...

随机推荐

  1. C# 反射、与dynamic最佳组合

    在 C# 中反射技术应用广泛,至于什么是反射.........你如果不了解的话,请看下段说明,否则请跳过下段.广告一下:希望我文章的朋友请关注一下我的blog,这也有助于提高本人写作的动力. 反射:当 ...

  2. 有哪些关于 Python 的技术博客?

    Python是一种动态解释型的编程语言,它可以在Windows.UNIX.MAC等多种操作系统以及Java..NET开发平台上使用.不过包含的内容很多,加上各种标准库.拓展库,乱花渐欲迷人眼.因此如何 ...

  3. java Io流中FileInputStream和BufferedInputStream的速度比较

    首先是对FileInputStream 加上 FileOutputStream 对文件拷贝的应用 我这里拷贝的是一个视频.当然,你们拷贝什么都可以,当文件越大时效果越明显 下面是对BufferedIn ...

  4. CentOS7.3虚拟机扩展数据磁盘

    操作之前需要重点查看: 由于扩容磁盘的操作非同小可,一旦哪一步出现问题,就会导致分区损坏,数据丢失等一系列严重的问题,因此建议:在进行虚拟机分区扩容之前,一定要备份重要数据文件,并且先在测试机上验证以 ...

  5. JSP入门必读

    JSP基础知识:转自老师上课梳理的笔记,希望对大家有所帮助.有什么不妥当的地方还望大家批评指正. 特别适用于JSP入门的人员使用.1.JSP [1] 简介1.1 HTML    HTML擅长显示一个静 ...

  6. C++ operator bool

    雕虫小技: #include <iostream> struct A{ operator bool(){ return false; } }; int main() { A a{}; if ...

  7. JAVA实用案例之邮件发送

    最近有朋友问邮件怎么发送,就简单写了个demo,因为懒得找jar包,所以项目是创建的maven工程,具体的maven引用的jar如下: <dependency> <groupId&g ...

  8. java程序的内存分配

    java程序的内存分配 JAVA 文件编译执行与虚拟机(JVM)介绍 Java 虚拟机(JVM)是可运行Java代码的假想计算机.只要根据JVM规格描述将解释器移植到特定的计算机上,就能保证经过编译的 ...

  9. 记一次wiki数据爬取过程

    最近有个爬取各国领导人信息的奇怪需求,要求百度和维基两种版本的数据,最要命的还要保持数据的结构不变.正好印象中隐约记得维基有专门的领导人列表页,不考虑爬取下来的格式不变的话应该很好爬的样子. 首先思路 ...

  10. dubbo+zookeeper伪集群配置

    zookeeper作为注册中心,服务器和客户端都要访问,如果有大量的并发,肯定会有等待.所以可以通过zookeeper集群解决. 一.为什么需要zookeeper呢? 大部分分布式应用需要一个主控.协 ...