struts2的Struts2中显示图片验证码
Struts2中显示图片验证码
现在很多网站在进行注册、登录甚至发表文章都要求输入验证码,只有用户输入的验证码和验证码输入框旁边的小图片中显示的文字相同时,相关的操作(注册、登录等)才可以继续进行。这其实是网站用于防犯用户使用注册机进行恶意攻击的一种必手段。
其实前面在学习struts基本原理的时候,偶在脑子里就曾经冒出过这个问题:用struts2如何输出一个验证码?
然后又google和baidu了一下,发现网上资源的确不少,但把原理讲透了的不多。而其中有一篇被转了很多次的帖子最可恨,它号称支持中文的验证码,但是里面用到了几个自定义的类,而帖子里根本没有公布这些类的源代码,也没有告诉你类到哪里可以下载到。
不过还好,struts2里提供了一些demo和源代码,通过阅读这些demo源代码,可以找到解决这个问题的方法。
回顾一下struts2的基本流程:
1.客户端发出请求
2.struts2过滤器拦截请求
3.过滤器创建Action对象
4.调用Action对象的相应方法
5.根据方法返回的字符串值跳到相应的资源(jsp, html等)
从这几个步骤看,似乎无从下手。Struts2最终都会把资源重定向到一个jsp或html页面,难道我们只能在jsp里做手脚吗?
其实在struts的配置文件中,result元素还有一个名为type的属性。缺省情况下,它表示一个result是用于跳转到一个指定的url,如果给它指定一个值,则输出到客户端的可以是其它的类型。思路就从这里打开。
Result元素可以将类型指定为实现了com.opensymphony.xwork2.Result;接口的类。这个接口中定义了一个方法:
execute(ActionInvocation invocation)
struts2就是在这个方法中完成展示给客户端内容的工作。
OK,其实说白了,原理也就是这么简单,要想完成输出图片验证码的操作,与一般的struts2不同的地方有:
1、在Action中创建要显示的字符串,然后在内存中创建Image对象,并把字符串打印到这个Image对象中,再把Image对象放到一个字节数组中。当然别忘了把字符串的值放到Session中
2、编写一个类并实现com.opensymphony.xwork2.Result接口,在这个类中将Action对象创建的字节数组写到输出流中。
3、在配置文件中把result 的类型指定为前面编写的Result类型。
源代码如下:
1、Action代码:
package stu.struts2.image;
import com.opensymphony.xwork2.ActionSupport;
import java.util.Random;
import java.awt.*;
import java.awt.image.*;
import java.io.ByteArrayOutputStream;
import org.apache.struts2.ServletActionContext;
public class ImageAction extends ActionSupport {
/**
*验证码对应的Session名
*/
private static final String SessionName = "CheckCodeImageAction";
/**
*用于随机生成验证码的数据源
*/
private static final char[] source = new char[]{
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
'U', 'V', 'W', 'X', 'Y', 'Z',
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0'
};
/**
*用于随机打印验证码的字符颜色
*/
private static final Color[] colors = new Color[]{
Color.RED, Color.BLUE, Color.BLACK
};
/**
*用于打印验证码的字体
*/
private static final Font font = new Font("宋体", Font.PLAIN, 13);
/**
*用于生成随机数的随机数生成器
*/
private static final Random rdm = new Random();
private String text = "";
private byte[] bytes = null;
private String contentType = "image/png";
public byte[] getImageBytes(){
return this.bytes;
}
public String getContentType(){
return this.contentType;
}
public void setContentType(String value){
this.contentType = value;
}
public int getContentLength(){
return bytes.length;
}
/**
*生成长度为4的随机字符串
*/
private void generateText(){
char[] source = new char[4];
for(int i=0; i source[i] = ImageAction.source[rdm.nextInt(ImageAction.source.length)]; } this.text = new String(source); // 设置Session ServletActionContext.getRequest().getSession().setAttribute(SessionName,this.text); } /** *在内存中生成打印了随机字符串的图片 *@return在内存中创建的打印了字符串的图片 */ private BufferedImage createImage(){ int width = 35; int height = 14; BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics g = image.getGraphics(); g.setColor(Color.LIGHT_GRAY); g.fillRect(0, 0, width, height); g.setFont(font); for(int i=0; i g.setColor(colors[rdm.nextInt(colors.length)]); g.drawString(this.text.substring(i, i+1), 2 + i * 8, 12); } g.dispose(); return image; } /** *根据图片创建字节数组 *@param image用于创建字节数组的图片 */ private void generatorImageBytes(BufferedImage image){ ByteArrayOutputStream bos = new ByteArrayOutputStream(); try{ javax.imageio.ImageIO.write(image, "jpg", bos); this.bytes = bos.toByteArray(); }catch(Exception ex){ }finally{ try{ bos.close(); }catch(Exception ex1){ } } } /** *被struts2过滤器调用的方法 *@return永远返回字符串"image" */ public String doDefault(){ this.generateText(); BufferedImage image = this.createImage(); this.generatorImageBytes(image); return"image"; } } 2、Result 类 package stu.struts2.image; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.Result; import javax.servlet.http.HttpServletResponse; import org.apache.struts2.ServletActionContext; public class ImageResult implements Result { public void execute(ActionInvocation ai) throws Exception { ImageAction action = (ImageAction)ai.getAction(); HttpServletResponse response = ServletActionContext.getResponse(); response.setHeader("Cash", "no cash"); response.setContentType(action.getContentType()); response.setContentLength(action.getContentLength()); response.getOutputStream().write(action.getImageBytes()); response.getOutputStream().flush(); } } 3、struts.xml 配置文件 总结一下 顺着Result的type属性这个思路往下想,result其实应该还有很多种类型可以指定(实现了com.opensymphony.xwork2.Result接口),那么缺省时会是哪种类型呢? 用解压缩软件打开struts2-core-2.1.6.jar,提取里面的struts-default.xml文件,我们会发现其中有一段 这是struts-default中预定义的result类型,我估计缺省的应该就是ServletRedirectResult或者ServletActionRedirectResult。如果想进一步研究,我们还可以去阅读这两个类的源代码。 分享到: jstl标签| struts2的s:token标签 ?2012-04-10 10:53 ?浏览997 ?评论(1) ?分类:Web前端 ?相关推荐 评论 1 楼iChanarley 2012-11-14 支持原创,必须踩一下 发表评论 您还没有登录,请您登录后再发表评论 2012年第11卷第6期 产业与科技论坛2012.(11).6 Industrial &Science Tribune Struts2框架工作原理及应用体会 □宋 君 张家爱 【摘要】通过针对特定用户的分析,搭建以Struts2为技术核心的旅行社管理系统。本文简单的介绍了MVC 、 Struts2的工作原理,同时总结了在项目制作过程中所得到的心得。 【关键词】 Struts2;MVC ;FilterDispatcher ;Action 【基金项目】本文为大学生科技创新院级基金项目(编号:2011070)成果 【作者单位】宋君,吉林农业科技学院信息工程学院;张家爱,吉林农业科技学院信息工程学院教师 本着锻炼自我与积极参与到实用性技术的目标,以发掘自身创新意识为前提。利用空闲时间,在老师的指导下,进行了一次大学生创新项目的实践性活动。本着实用原则,以某中小旅行社为客户(根据用户需求,匿名),以Struts2框架为基点,进行了一次旅行社管理系统的开发。在项目结束之余, 特将在项目过程中经历的种种认识进行了简单的总结,希望让阅读本文的朋友们,更多的参与到此类活动中。 一、基础思想— ——MVC 简述作为时下经典框架之一, MVC 具有其独特的价值。MVC 框架简单的说,就是将数据模型与用户视图进行分离。通过控制器进行协调处理的一种结构是框架。同时,也是本文中要讨论的Sturts2框架的基础思想。 M 是指模型层(Model ),V 是指用户视图(View ),C 则是指控制器 (Controller )。这种划分方式是以将模型层与视图层进行代码分离,从而降低两者之间的耦合性,使同一程序可以使用不同形式进行表现。不同层之间的修改不会或尽量少的印象到其他层功能的史前为前提。有效的提高的代码的维护性和设计难度。 图1 二、 Struts2工作原理(一)Struts2框架组成。Struts2框架由三个主要部分组成:核心控制器、业务控制器,以及由用户实现的业务逻辑组件。这里我们将侧重于核心控制器与业务控制器的理解与说明。 (二)核心控制器:FilterDispatcher 。FilterDispatcher 是Struts2框架的核心控制器,在此,我们可以将FilterDispatcher 看作一个类似于过滤网的过滤器。当用户发出请求,并到达Web 硬哟那种时,该过滤器会过滤用户请求。如果用户请求的结尾为action ,则将该请求转入Struts2框架进行处理。当Struts2框架获得了*.actio 请求后,会根据请求前面“*”的那部分内容,决定调用哪个业务逻辑组件作为响应单位。这里需要说明的是Struts2用来处理用户请求的Action 实例并不是业务控制器,而是作为Action 的代理———正因为Struts2的一大特点,与Servlet API 的非耦合性,使得用户实现的业务控制器无法直接处理用户请求。有效的提高了后期调试维护的效率。而Struts2框架再次提供了了一系列的拦截器。这些拦截器负责将HttpServletRequest 请求的参数解析出来,传入Action 中,并毁掉Action 的Execute 方法来处理用户请求。用户实现的Action 类仅作为Struts2的Action 代理的代理目标。用户实现的业务控制器则包含了对用户请求的处理。用户的请求数据包含在HttpServletRequest 对象中,而用户的Action 类无需访问HttpServletRequest 对象。拦截器负责将HttpServletRequest 里的请求数据解析出来,并传给业务逻辑组件Action 实例。 (三)业务控制器。业务控制器就是前文提到的用来实现用户Action 的实力,这里的每个Action 类通常包含有一个execute 方法,当业务控制器处理完用户的请求后,该方法将会针对此次处理返回一个字符串— ——该字符串就是一个逻辑树图名。当程序开发人员开发出系统所需要的业务控制器后,还需要针对性的配置Struts2的Action ,即需要配置Ac- tion 的以下三个部分:(1)Action 所处理的URl 。(2)Action 组件所对应的实现类。(3)Action 里包含的逻辑试图和物理资源之间的对应关系。每个Action 都要处理一个用户请求,而用户请求则总是包含有指定的URL 。当核心控制器过滤用户请求,并调用后,根据请求的URL 和Action 处理URL 之间的对应关系来处理转发。 · 342· 1、自定义拦截器,实现对注册页面上的文字信息进行过滤拦截,不允许出现字符集合中{“佛法”,”集会”,”党派”}的文字信息。如出现,则返回到注册页面,重新填写。 2、定义拦截器,实现登录检查。由于在项目开发时,需要对大多数的页面进行登录检查。当没有登录就无法进行操作,并返回到登录页面。为减少代码量利用Struts2中自定义拦截器的功能,实现登录检查。(避免不登录直接访问某个Action) Web.xml Struts 2作业 1.简述什么是MVC? 答:MVC 的全称为model-view-controller(模型-视图-控制器)。MVC 是一种开发应用程序的模式,这个模式已经具有了很好的框架架构,并且十分容易维护。使用MVC 开发出来的应用程序一般包括以下几块内容:·控制器(Controller):控制器类处理客户端向Web 应用程序发出的请求,获取数据,并指定返回给客户端,用来显示处理结果的视图。·模型(Model):模型类代表了应用程序的数据,这些数据通常具有一个数据验证逻辑,用来使得这些数据必须符合业务逻辑。·视图(View):视图类是Web 应用程序中用来生成并显示HTML 格式的服务器端对客户端请求的响应结果的模板文件 2.Struts 2以(WebWork)为核心,采用(拦截器)的机制来处理用户的 请求。 3.简述一个请求在Struts 2框架中的处理流程,请按自己对框架的理解叙述。答:1-用户提交自己的请求;2-由web.xml拦截,转发到action进行处理;3- Struts.xml根据相应的action配置,调用相应的方法来处理,并根据结果转发到不同的页面。 4.不属于Action接口中定义的字符串常量是( B )? A)SUCCESS B)FAILURE C)ERROR D)INPUT 5.资源文件的后缀名为(D)? A)txt B)doc C)property D)properties 6.在JSP页面中可以通过Struts 2提供的(D)标签来输出国际化信息。 A) Struts2项目的构建与配置 1.配置struts.xml (1)配置struts.xml可以参考下载的struts-2.3.14.1-all.zip解压后的apps文件夹下的 参考项目的struts.xml文件。 (2)主要的配置如下: Struts2+Spring3+Hibernate4+Maven整合 目录 1.建立Maven工程 2.搭建Spring3 3.搭建Struts2并整合Spring3 4.搭建Hibernate4并整合Spring3 内容 1.建立Maven工程 第一步: 第二步: 第三步: 第四步: 注意:这里的JDK要选择默认的,这样别人在使用的时候,如何JDk不一致的话也不会出错,如下图所示: 第五步: Maven标准目录 src/main/java src/main/resources src/test/java src/test/resources 第六步: 发布项目:Maven install 清除编译过的项目:Maven clean OK,Mean 工程创建成功! 2. 搭建 Spring3 (1)下载Spring3需要的jar包 1.spring-core 2.spring-context 3.spring-jdbc 4.spring-beans 5.spring-web 6.spring-expression 7.spring-orm 在pom.xml中编写Spring3需要的包,maven会自动下载这些包。 Struts2拦截器详细配置过程 1:所有拦截器的超级接口Interceptor,拦截器去实现这个接口; Interceptor它其中有三个方法 (init(),destroy(),interceptor()):Init()方法:在服务器起动的时候加载一次,并且只加载一次; Destroy()方法:当拦截器销毁时执行的方法; Interceptor()方法:其中里边有一个参数invocation public String intercept(ActionInvocation invocation)throws xception { System.out.println("interceptor!!"); String result=invocation.invoke(); return result; }Invocation.invoke()是如果只有一个拦截器执行完这个方法后,会返回给视图,如果有多 个拦截器,它顺序的执行完所有的拦截器,才返回给视图. 2:可以在系统初始化中给拦截器指定默认的参数(也包括了定义拦截器方式)如下:在拦截器类中把hello当做属性set/get方式注入到拦截器类中; Struts2框架工作原理及应用体会
实验六 利用Struts2实现自定义拦截器
Struts2练习题说课讲解
Struts2学习笔记
Struts2+Spring3+Hibernate4+Maven整合
struts2拦截器配置详解
Action Tag 示例