- 浏览: 72905 次
- 性别:
- 来自: 杭州
最新评论
-
zhaojian770627:
...
B+树的Java实现 -
kevindude:
包含在了clyde库里
Clyde学习笔记三(Config) -
silverys:
能否提供demo下载学习一下,谢谢
3D MMO Demo -
silverys:
请问下,这个Three Rings Resource Edit ...
Clyde学习笔记三(Config) -
Bactryki:
要用什么包呢?
基于Struts2+Spring+iBatis的web应用最佳实践系列之二(访问控制篇上)
本篇主要讨论下如何使用Struts2实现一个通用的验证码(checkcode)功能。
首先我们要有一个CheckCodeSession类,用来保存我们生成好的checkcode。这个类很简单,主要就是保存了验证码本身,创建时间以及是否有效的标志。
public class CheckCodeSession { private String checkCode;//验证码 private long createTime;//创建时间 private boolean validate = false;//是否有效(默认无效) public String getCheckCode() { return checkCode; } public void setCheckCode(String checkCode) { this.checkCode = checkCode; } public long getCreateTime() { return createTime; } public void setCreateTime(long createTime) { this.createTime = createTime; } public boolean isValidate() { return validate; } public void setValidate(boolean validate) { this.validate = validate; } }
我们再来看一下checkcode aciton。它从0-9十个数字中随机选取4个作为一个checkcode,即验证码本身,并把生成的验证码赋值给checkCodeSession,并设置成有效。同时还实现了CheckCodeSessionAware 这个接口。
public class CheckCodeAction implements Action, CheckCodeSessionAware { private static final long serialVersionUID = 1L; private String checkCode; private CheckCodeSession checkCodeSession; private int codeLenght = 4; private static char[] codes={'0','1','2','3','4','5','6','7','8','9'}; public String execute() throws Exception { Random random = new Random(); char[] checkCodeChararray = new char[codeLenght]; for(int i=0;i<codeLenght;i++){ checkCodeChararray[i] = codes[random.nextInt(codes.length)]; } checkCode = String.valueOf(checkCodeChararray); checkCodeSession.setCheckCode(checkCode); checkCodeSession.setCreateTime(System.currentTimeMillis()); checkCodeSession.setValidate(true); return SUCCESS; } public String getCheckCode() { return checkCode; } public void setCheckCodeSession(CheckCodeSession checkCodeSession) { this.checkCodeSession = checkCodeSession; } public void setCodeLenght(int codeLenght) { this.codeLenght = codeLenght; } public CheckCodeSession getCheckCodeSession() { return checkCodeSession; } }
CheckCodeSessionAware接口,这个接口很简单,只有两个getter、setter方法。
public interface CheckCodeSessionAware { public void setCheckCodeSession(CheckCodeSession checkCodeSession); public CheckCodeSession getCheckCodeSession(); }
现在我们已经有了checkcode和生成checkcode的aciton,那么具体如何实现验证功能呢?这就要涉及到Struts2的验证框架,我们还是来看代码,结合CheckCodeSessionAware接口,CheckCodeValidator实现对checkcode的验证功能。
public class CheckCodeValidator extends FieldValidatorSupport { private static Logger logger = Logger.getLogger(CheckCodeValidator.class); public void validate(Object object) throws ValidationException { Object obj = getFieldValue(getFieldName(), object); CheckCodeSession checkCodeSession = null; if(object instanceof CheckCodeSessionAware){ checkCodeSession = ((CheckCodeSessionAware)object).getCheckCodeSession(); if(checkCodeSession == null){ logger.error("action: "+ object +" not implements CheckCodeSessionAware.class"); } } String checkCode = (String) obj; if(StringUtil.isEmpty(checkCode) || checkCodeSession == null || !checkCodeSession.isValidate()){ this.addFieldError(getFieldName(), object); }else{ if(checkCode.equalsIgnoreCase(checkCodeSession.getCheckCode())){ checkCodeSession.setValidate(false); }else{ this.addFieldError(getFieldName(), object); } } }
Struts2框架设计的非常灵活,验证本身就可以成为一个框架,我们的CheckCodeValidator只要简单的继承FieldValidatorSupport就能成为一个validator,在应用中只需要简单的配置就可以使用。
下面我们再来看一下如何在页面上显示验证码,在这里又是对框架的扩展,我们的CheckCodeResultType继承了StrutsResultSupport从而变成了一个新的result type。在这里,我们使用java 2d的api根据checkcode的值生成图片后直接写入到httpResponse中。值得注意的是我们在http header中设置了No-cache的方式,这是为了不让浏览器缓存checkcode图片。
public class CheckCodeResultType extends StrutsResultSupport{ protected String contentType = "image/jpeg"; protected int contentLength; private String checkCode; /** * @return Returns the contentType. */ public String getContentType() { return (contentType); } /** * @param contentType The contentType to set. */ public void setContentType(String contentType) { this.contentType = contentType; } /** * @return Returns the contentLength. */ public int getContentLength() { return contentLength; } /** * @param contentLength The contentLength to set. */ public void setContentLength(int contentLength) { this.contentLength = contentLength; } /** * @see com.opensymphony.xwork.Result#execute(com.opensymphony.xwork.ActionInvocation) */ protected void doExecute(String finalLocation, ActionInvocation invocation) throws Exception { try { // Find the Response in context HttpServletResponse oResponse = (HttpServletResponse) invocation.getInvocationContext().get(HTTP_RESPONSE); oResponse.setHeader("Pragma","No-cache"); oResponse.setHeader("Cache-Control","no-cache"); oResponse.setDateHeader("Expires", 0); // Set the content type oResponse.setContentType(conditionalParse(contentType, invocation)); // Set the content length if (contentLength != 0) { oResponse.setContentLength(contentLength); } // Get the outputstream OutputStream oOutput = oResponse.getOutputStream(); //取随机产生的认证码(4位数字) String rand=conditionalParse(checkCode, invocation); // 在内存中创建图象 int width=60, height=24; if(rand!= null){ width = 17 * rand.length(); } BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); // 获取图形上下文 Graphics g = image.getGraphics(); // 生成随机类 Random random = new Random(); // 设定背景色 g.setColor(getRandColor(200,250)); g.fillRect(0, 0, width, height); // 设定字体 Font font = new Font("Times New Roman",Font.BOLD,20); g.setFont(font); // 画边框 g.setColor(getRandColor(20,50)); g.drawRect(0,0,width-1,height-1); // 随机产生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); } if(rand != null){ for (int i=0;i<rand.length();i++){ // 将认证码显示到图象中 g.setColor(new Color(20+random.nextInt(110),20+random.nextInt(110),20+random.nextInt(110)));//调用函数出来的颜色相同,可能是因为种子太接近,所以只能直接生成 g.drawString(String.valueOf(rand.charAt(i)),15 * i + 7,17); } } // 图象生效 g.dispose(); // 输出图象到页面 ImageIO.write(image, "JPEG", oResponse.getOutputStream()); // Flush oOutput.flush(); } finally { } } private 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); } public String getCheckCode() { return checkCode; } public void setCheckCode(String checkCode) { this.checkCode = checkCode; } }
现在,我们所需要的代码全部都有了,那么,在具体的应用中应该如何使用呢?
首先,在struts.xml中,配置好checkcode aciton。注意,这里的result type使用的是我们自己定义的checkCode类型。
<result-types> <result-type name="checkCode" class="com.meidusa.toolkit.web.common.resulttype.CheckCodeResultType" /> </result-types> <action name="checkCode" class="com.meidusa.toolkit.web.common.action.CheckCodeAction"> <result name="success" type="checkCode"> <param name="contentType">image/jpeg</param> <param name="checkCode">${checkCode}</param> </result> </action>
其次,在需要使用验证码验证的aciton中同样实现CheckCodeSessionAware接口,比如我们的login aciton
public class LoginAction extends ActionSupport implements ClientCookieAware<Cookie>, ClientCookieNotCare, CheckCodeSessionAware{ private Cookie cookie; private String loginId; private CheckCodeSession checkCodeSession; private String checkcode; public String getCheckcode() { return checkcode; } public void setCheckcode(String checkcode) { this.checkcode = checkcode; } public String getLoginId() { return loginId; } public void setLoginId(String loginId) { this.loginId = loginId; } public Cookie getCookie() { return cookie; } public void setClientCookie(Cookie cookie) { this.cookie = cookie; } public String execute() throws Exception { cookie.setLoginId(loginId); cookie.save(); return SUCCESS; } public CheckCodeSession getCheckCodeSession() { return checkCodeSession; } public void setCheckCodeSession(CheckCodeSession checkCodeSession) { this.checkCodeSession = checkCodeSession; } }
这里,还有非常关键的一步。大家是否还记得在本文开头介绍的那个CheckCodeSession类和CheckCodeSessionAware接口呢?CheckCodeSessionAware接口的功能除了让struts2的validation框架在调用validate方法验证的时候可以从aciton中获得CheckCodeSession对象外,还有一个很重要的功能是让spring来注入这个CheckCodeSession对象。也就是说CheckCodeSession需要作为一个bean由spring来配置。注意,这里非常关键的一步是把scope设置成session,使得checkcode aciton中的CheckCodeSession与需要对checkcode验证的action(比如这里的login aciton)中的CheckCodeSession保持一致。如果不是设置成session的话,验证框架在验证的时候读取的checkcode值会与用户看到输入的值不同。
<bean id="checkCodeSession" class="com.meidusa.toolkit.web.common.components.CheckCodeSession" scope="session" />
这需要使用spring2.0的配置文件,老版本的spring配置文件不支持scope这个属性。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
最后,我们还需要编写一个validators.xml,告诉struts2框架我们自己定义的额外的validator,并把这个文件放在与struts.xml相同的目录中。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator Config 1.0//EN" "http://www.opensymphony.com/xwork/xwork-validator-config-1.0.dtd"> <validators> <validator name="checkcode" class="com.meidusa.toolkit.web.common.validators.CheckCodeValidator"/> </validators>
在所有都配置好的情况下,我们再来看一下在页面上如何使用checkcode
<label>请输入验证码</label><input type="text" name="checkcode" /><img src="/demo/checkCode.action"/></br><s:fielderror/>
最后,再把我们的checkcode validator配置给我们的loginAction
<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd"> <validators> <field name="checkcode"> <field-validator type="requiredstring"> <message>验证码必须填写</message> </field-validator> <field-validator type="checkcode"> <message>验证码不正确!</message> </field-validator> </field> </validators>
至此,对于验证码的实现就全部介绍完了,这已经是本系列的第六篇了,笔者会在下一篇中放出一个demo供大家下载体验,并结束整个系列。
评论
我也做了和您demo相似的工程,但是这里没能成功。
发表评论
-
基于Struts2+Spring+iBatis的web应用最佳实践系列之七(Demo篇)
2010-02-08 15:01 3124终于来到了本系列的最 ... -
基于Struts2+Spring+iBatis的web应用最佳实践系列之五(分页篇)
2010-02-05 17:13 2475分页也是一个大家经常讨论的话题,网上也有过很多的分页方法的介绍 ... -
基于Struts2+Spring+iBatis的web应用最佳实践系列之四(CRUDL篇)
2010-02-04 23:08 3146让我们首先来看一下什 ... -
基于Struts2+Spring+iBatis的web应用最佳实践系列之三(访问控制篇下)
2010-02-03 18:47 2289在本系列的上一篇中我 ... -
基于Struts2+Spring+iBatis的web应用最佳实践系列之二(访问控制篇上)
2010-02-03 15:40 2474访问控制对于一个web应用来说几乎是不可或缺的。当访问web应 ... -
基于Struts2+Spring+iBatis的web应用最佳实践系列之一(自动配置篇)
2010-02-02 00:13 3733由于最近有点时间,便 ...
相关推荐
这个“struts2+spring+iBatis框架包”集成了这三个框架,使得开发者能够快速构建基于MVC(Model-View-Controller)模式的Web应用。 Struts2作为MVC框架,负责处理应用程序的控制逻辑。它通过Action类和配置文件定义...
Struts2、Spring3和iBATIS是Java Web开发中常用的三大框架,它们各自负责不同的职责,协同工作可以构建出高效、松耦合的Web应用。在这个“struts2+spring3+ibatis项目整合案例”中,我们将深入探讨这三个框架如何...
Struts2、Spring和iBatis是Java Web开发中三个非常重要的开源框架,它们的集成应用可以构建出高效、灵活的后端系统。Struts2作为MVC(Model-View-Controller)架构的一部分,主要负责处理HTTP请求和展示视图;Spring...
Struts2、Spring和iBatis是Java Web开发中三个非常重要的框架,它们分别负责表现层、业务层和数据访问层。将这三个框架整合在一起,可以实现MVC(Model-View-Controller)架构,提高应用的灵活性和可维护性。 **...
Struts2+Spring+Hibernate和Struts2+Spring+Ibatis是两种常见的Java Web应用程序集成框架,它们分别基于ORM框架Hibernate和轻量级数据访问框架Ibatis。这两种框架结合Spring,旨在提供一个强大的、可扩展的、易于...
"Struts2+Spring+Ibatis+MySQL" 是一个经典的Java Web开发框架组合,用于构建高效、可扩展的企业级应用程序。这个组合集成了强大的MVC(Model-View-Controller)框架Struts2、依赖注入与面向切面编程的Spring框架、...
开发环境说明 ...本示例完整地结合Struts2+Spring2+iBatis2+MySQL5,演示了一个用户表的增、删、改、查。 想完整学习Struts2+Spring+iBatis的同仁,可以在这个例子中学习或模仿最基本也是最核心的技术要点。
Struts2、Spring和iBatis是Java Web开发中经典的三大框架,它们分别负责MVC模式中的Action层、业务逻辑层和服务数据访问层。这个"Struts2+Spring2.5+iBatis完整增删改查Demo"提供了一个完整的集成示例,包括所有必要...
在Java Web开发中,Spring、Struts2和iBatis是三个非常重要的框架,它们各自在不同的层面上提供了强大的功能。Spring是一个全面的后端应用框架,提供了依赖注入(DI)、面向切面编程(AOP)、事务管理等功能;Struts...
Struts2、Spring和iBatis是Java Web开发中常用的三大框架,它们分别负责MVC模式中的Action层、业务逻辑层和服务数据访问层。本文将详细介绍这三个框架如何整合,以及在实际项目中如何运用。 首先,Struts2作为表现...
Struts2、Spring2 和 iBatis 是三个在Java Web开发中广泛应用的开源框架,它们分别负责MVC架构中的控制层、服务层和数据访问层。这个集成项目,"SSITest",是为了帮助初学者理解和实践这三大框架的协同工作。 **...
struts2 + spring + ibatis 实例 struts2 + spring + ibatis 实例 struts2 + spring + ibatis 实例 struts2 + spring + ibatis 实例 struts2 + spring + ibatis 实例
Struts2、Spring和iBatis是Java Web开发中经典的三大框架,它们组合起来可以构建出高效、可维护的企业级应用程序。在这个“struts2+spring+ibatis”的小demo中,我们将深入探讨这三个框架的核心功能以及它们如何协同...
Struts2、Spring和iBatis是Java Web开发中经典的三大框架,它们组合起来可以构建出高效、可维护的企业级应用程序。在这个项目实例中,我们将深入探讨这三个框架如何协同工作,以及它们各自的核心功能。 首先,...
Struts2、Spring和iBatis是Java Web开发中常用的三个开源框架,它们各自负责不同的职责,协同工作可以构建出高效、松耦合的Web应用。这个整合项目实例旨在展示如何将这三个框架集成到一起,以实现更强大的功能。 1....
struts2+hibernate+spring+ibatis 小实例struts2+hibernate+spring+ibatis 小实例struts2+hibernate+spring+ibatis 小实例struts2+hibernate+spring+ibatis 小实例struts2+hibernate+spring+ibatis 小实例struts2+...
Struts2+Spring+Ibatis整合的简单人事管理系统 没分了,转载过来的,有需要的看看吧,我觉得不错~~
Struts2、Spring2和iBatis是Java Web开发中常用的三大框架,它们结合使用可以构建高效、可扩展的企业级应用程序。在这个简单的登录例子中,我们将深入探讨这三个框架如何协同工作来实现用户身份验证。 首先,Struts...
Struts2、Spring和iBatis是Java Web开发中常用的三大框架,它们分别负责MVC模式中的Action层、业务逻辑层以及数据访问层。将这三个框架整合在一起,可以构建出高效、灵活且易于维护的Web应用程序。下面我们将详细...
Struts2、Spring、iBatis以及Oracle是Java Web开发中的四大核心组件,它们共同构建了一个强大且灵活的后端架构。在这个实例中,我们将会深入探讨这些技术如何协同工作,实现分页搜索功能和上传附件操作。 1. **...