Java的Struts框架中登陆功能的实现和表单处理器的使用
实现struts登录
1、jar包拷贝
首先是建立java web项目,之后打开我们我们下载好strtus框架,struts-1.2.9-bin文件夹和struts-1.2.9.src源文件文件夹。在bin文件夹中的lib文件中拷贝struts的jar包,拷贝到我们自己项目struts_login –>lib文件夹下。
2、web.xml文件配置
找到struts-1.2.9-bin中struts-1.2.9-bin-->webapps下的struts实例struts-blank中的struts-1.2.9-bin\webapps\struts-blank\web-inf下的web.xml文件,复制配置对actionservlet的配置,粘贴到我们的项目struts_login的web-inf下的web.xml中,代码如下所示。主要是对struts自带的actionservlet进行配置。
<servlet> <servlet-name>action</servlet-name> <servlet-class>org.apache.struts.action.actionservlet</servlet-class> <init-param> <param-name>config</param-name> <param-value>/web-inf/struts-config.xml</param-value> </init-param> <init-param> <param-name>debug</param-name> <param-value>2</param-value> </init-param> <init-param> <param-name>detail</param-name> <param-value>2</param-value> </init-param> <load-on-startup>2</load-on-startup> </servlet> <!--standard action servlet mapping --> <servlet-mapping> <servlet-name>action</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping>
3、在项目中建立自己的actionform
在项目中建立自己的actionform,继承struts框架中已经写好的actionform,在actionform设置用到的数据,并且要和我们界面上设置的名称一致。因为我们在提交表单的时候,所有的请求都会放到actionform中。建立登录的actionform,loginactionform.java代码如下所示。
package com.bjpowernode.struts; import org.apache.struts.action.actionform; /** * 登录actionform,负责表单收集数据. * 表单的属性必须和actionform中的get和set的属性一致. * @author summer * */ public classloginactionform extends actionform { //用户名。 private stringusername; //密码。 private string password; //设置密码。 public voidsetpassword(stringpassword) { this.password = password; } //得到用户名。 public stringgetusername() { return username; } //设置用户名。 public voidsetusername(stringusername) { this.username = username; } //得到密码。 public stringgetpassword() { return password; } }
4、建立自己的action
建立自己的action,同时继承struts框架中的org.apache.struts.action.action,重载父类的execute方法。在这里完成取出表单中的数据。通过calactionformcalform= (calactionform)(calactionform)form;(struts框架中已经帮我们封装好了,我们去使用就可以了)来取得表单中的值。经过判断后,进行相应的操作,跳转到相应的页面。action的功能是负责拿到表单数据和调用业务逻辑后进行页面跳转。建立登陆的action类,loginaction.java类,调用业务逻辑类usermanager的login方法。代码如下所示。
packagecom.bjpowernode.struts; importjavax.servlet.http.httpservletrequest; importjavax.servlet.http.httpservletresponse; importorg.apache.struts.action.action; importorg.apache.struts.action.actionform; importorg.apache.struts.action.actionforward; importorg.apache.struts.action.actionmapping; /** *登录action *负责取得表单数据,调用业务逻辑,返回转向信息. * * @author summer * */ public classloginaction extendsaction { @override public actionforward execute(actionmappingmapping,actionform form, httpservletrequest request, httpservletresponseresponse) throws exception { loginactionform laf = (loginactionform)form; stringusername = laf.getusername(); stringpassword = laf.getpassword(); usermanager usermanager = newusermanager(); //传递用户名和密码 try { usermanager.login(username, password); request.setattribute("username", username); return mapping.findforward("success"); }catch(usernotfoundexception e) { e.printstacktrace(); request.setattribute("msg","用户不能找到,用户名称=[" +username +"+]"); }catch(passworderrorexception e) { e.printstacktrace(); request.setattribute("msg","密码错误"); } return mapping.findforward("error"); } }
5、 建立struts-config.xml
作为struts框架的核心描述,struts-config.xml可以说“一切尽在掌握”。它不但描述了mvc模型,定义所有视图层和控制层之间的接口(actionform),与控制层和模型层的接口(action)进行结合,而且可以定义一些附加组件,如国际化信息资源排至文件,标签库信息等。
仍然是站在巨人的肩膀上,将我们下载的struts bin文件夹中的struts-config.xml文件复制到我们的项目的web-inf中,删除struts-config.xml中的注释部分。把action和actionform配置起来。actionform放到<form-beans></form-beans>中,action配置放到<action-mappings></action-mappings>中,struts-config.xml配置代码如下所示。
<?xml version="1.0" encoding="iso-8859-1" ?> <!doctype struts-config public "-//apache software foundation//dtd struts configuration1.2//en" "http://jakarta.apache.org/struts/dtds/struts-config_1_2.dtd"> <struts-config> <form-beans> <form-bean name="loginform" type="com.bjpowernode.struts.loginactionform"/> </form-beans> <action-mappings> <action path="/login" type="com.bjpowernode.struts.loginaction" name="loginform" scope="request" > <forward name="success" path="/login_success.jsp"/> <forward name="error" path="/login_error.jsp"/> </action> </action-mappings> </struts-config>
其中form-beans元素中可以定义0个或1个以上的form-bean元素,每个form-bean被认为是一个actionform对象,name属性表示form-bean元素的名称,type属性指定其类名和路径。
action-mappings元素用来包含零到多个action,其子元素action负责具体映射的详细信息。在action-mapping元素中可以定义0个或1个以上的action元素。每个action元素接受path属性定义的请求,并映射到type属性所定义的具体action对象。在映射过程中,将name属性定义的actionform一并传过去,它有如下属性:
parameter,scope两个属性指定了传送方式和范围,scope常用的值有两个“session”和“request”。
validate属性指定了是否需要actionform的验证。
forward元素,将请求success转发到”/login_success.jsp”页面。
6、业务逻辑类usermanager和自定义异常类
代码如下所示:
packagecom.bjpowernode.struts; publicclassusermanager { publicvoid login(stringusername,stringpassword) { if(!"admin".equals(username)) { thrownewusernotfoundexception(); } if(!"admin".equals(password)) { thrownewpassworderrorexception(); } } }
自定义异常类usernotfoundexception和passworderrorexception代码如下所示。
packagecom.bjpowernode.struts; public class usernotfoundexceptionextends runtimeexception { public usernotfoundexception() { } public usernotfoundexception(stringmessage) { super(message); } public usernotfoundexception(throwable cause) { super(cause); } public usernotfoundexception(stringmessage,throwable cause) { super(message, cause); } } packagecom.bjpowernode.struts; public class passworderrorexceptionextends runtimeexception { public passworderrorexception() { } public passworderrorexception(stringmessage) { super(message); } public passworderrorexception(throwable cause) { super(cause); } public passworderrorexception(stringmessage,throwable cause) { super(message, cause); } }
7、视图jsp页面调用。
登录界面login.jsp,错误显示界面login_error.jsp,登录成功界面login_success.jsp。代码如下所示。
<%@pagelanguage="java" contenttype="text/html; charset=gb18030" pageencoding="gb18030"%> <!doctypehtml public "-//w3c//dtdhtml 4.01 transitional//en" "http://www.w3.org/tr/html4/loose.dtd"> <html> <head> <meta http-equiv="content-type" content="text/html; charset=gb18030"> <title>inserttitle here</title> </head> <body> <form action="login.do" method="post"> 用户:<inputtypeinputtype="text" name="username"><br> 密码:<inputtypeinputtype="password" name="password"></br> <input type="submit" value="登录"> </form> </body> </html>
login_success.jsp.
<%@page language="java"contenttype="text/html;charset=gb18030" pageencoding="gb18030"%> <!doctype html public "-//w3c//dtdhtml 4.01 transitional//en" "http://www.w3.org/tr/html4/loose.dtd"> <html> <head> <meta http-equiv="content-type" content="text/html; charset=gb18030"> <title>insert title here</title> </head> <body> ${username},登录成功! </body> </html>
login_error.jsp界面。
<%@page language="java" contenttype="text/html; charset=gb18030" pageencoding="gb18030"%> <!doctype html public "-//w3c//dtdhtml 4.01 transitional//en" "http://www.w3.org/tr/html4/loose.dtd"> <html> <head> <meta http-equiv="content-type" content="text/html; charset=gb18030"> <title>insert title here</title> </head> <body> <%-- <%=request.getattribute("msg") %> --%> ${msg } </body> </html>
就这样我们实现了运用struts框架完成用户登录。就这样从初步学习到简单应用,随着应用的次数增多,我们会对struts理解越来越深刻,并且感受struts框架给我们带来的便捷。
表单处理器actionform(静态动态)
上面讲解了struts配置,实现了使用struts框架进行登录的示例。一些名词已经在脑海中飘荡了。
actionservlet:struts的控制器,负责截取url或分发。提供model(模型层)和view(视图层)使用,因此可将它看作是模型和视图之间的中介。
actionform:用于封装用户的请求参数,而请求参数是通过jsp页面的表单域传递过来的。
action:用户请求和和业务逻辑的桥梁,每个action作为业务逻辑的代理,可以调用业务逻辑。
一些问题是有必要再次提起的。
使用基本的mvc和使用struts框架区别,使用struts好处在哪里?
我们知道我们不适用框架的时候,在mvc中典型的控制器是servlet,servlet可以获取参数和逻辑模型的调用和转向功能。而struts对它做了封装,为什么要进行封装?当我们请求到一个servlet,我们在这个servlet中取得参数、调用业务逻辑、转向,我们在servlet中写死了转向页面,当我们想要换一个转向页面的时候就需要改动代码了,改动代码后还要重新进行编译。
而且从表单中传递过来的数据全是字符串形式,我们还需要根据实际的需求把字符串转换为我们需要的类型,如果很多地方需要转换,并且每次使用每次都要进行转换,有没有一种机制,把表单中的字符串拿过来自动转换为相应的类型呢?不需要我们再进行手动转换呢?
基于上述的不便,转向不灵活,表单中的字符串每次都要进行转换等一系列的原因,struts把这些做了封装。提取出重复的操作,转向信息放到了配置文件中,这样更加灵活了。
在上述问题中,阐述了struts对表单的封装,在web应用程序开发过程中,开发人员需要大量的时间来处理表单问题,有的时候是通过表单提交一些新的问题,有的是通过表单修改数据,所有这些表单在处的处理在传统web开发中是非常复杂的。本篇重点说说struts中的表单处理器actionform。
actionform
问题的提出
在传统的web应用程序开发中,繁杂的表单处理给开发工作人员带来了巨大的困难,在传统的开发语言中,没有组建可以自动收集用户输入的表单内容,开发人员不得不在程序中手动提取表单的值。例如在表单中有这样的一个文本输入域:<inputtype=”text” name=”password”> 要在程序中取得这个文本输入域的值,只能用这样的方法:request.getparameter(“password”);这样的处理方法在表单比较小的时候是可以使用的,但是当表单输入项较多的时候就不得不大量重复类似上面的处理。
问题的解决
在struts中就是使用actionform来解决这个问题,对于每一个用户的表单,需要提供一个actionform,这个actionform自动把客户提交的表单保存在这个actionform中,然后把这个actionform传递给action,从而在action中可以通过这个actionform取出用户信息,然后根据这些信息完成对应的业务逻辑处理。
例如在struts中用struts的html标签表述成下述形式:
<html:text property=”password”/>
在这种情况下表单提交后,struts框架会自动把表单中的这个输入项赋值到actionform中的password属性中,从而把表单中的内容保存在actionform中,整个过程由struts自动完成,不需要开发人员干涉。我们在创建actionform时要遵循以下规范:
(1)每个actionform都要继承org.apache.struts.action.actionform类,而且需要为每一个表单提供一个actionform。
(2)actionform中每个属性要与表单中的输入项一一对应。
(3)acitonform每个属性都要提供的getter方法和setter方法。struts框架就是通过这些方法来保存表单的值,然后在action中通过这些方法取得表单的值。
(4)如果表单需要验证,就需要在actionform中提供validate方法,这个方法中提供对表单的具体验证逻辑。这个方法不仅实现了数据验证同时实现了数据缓冲的作用,在validate方法中验证用户提交表单的有效性,当表单验证失败时会自动返回用户输入页面,这时候用户输入的值都保存在actionform中,返回页面时struts框架会取出acitonform中的数据并输出到对应的用户输入项中,保证了用户开始输入的表单信息。
问题的提出
以上所说的是静态actionform,当我们为每个表单都创建一个acitonform的时候,会导致actionform数量过多。每个actionform过强的聚合性也会使代码难以维护和重用。怎么样不用去创建过多的actionform?而且当提交表单的属性名字相同时,不用再重复创建acitonform(例如登录和注册)?
问题的解决
struts中可以使用动态actionform来解决上述问题。动态actionform不需要创建自己的actionform,需要在创建自己action的时候直接把execute方法中传递过来的form对象转化为dynaactionform。
我们需要更改struts-config.xml中form-beans配置:
<form-beans> <form-bean name="dynaform" type="org.apache.struts.action.dynaactionform"> <form-property name="username" type="java.lang.string" /> <form-property name="age" type="java.lang.integer"/> </form-bean> </form-beans>
action中使用get方法取得表单中的值。
/** * 测试动态actionform. * @author summer * */ public classdynaactionformtestaction extends action { @override publicactionforward execute(actionmapping mapping, actionform form, httpservletrequestrequest, httpservletresponse response) throwsexception { dynaactionformdaf = (dynaactionform)form; //取出map中key值为name,value为类名. stringusername = (string)daf.get("username"); integerage = (integer)daf.get("age"); system.out.println("username"+username); system.out.println("username"+age); returnmapping.findforward("success"); } }
静态actionform方式,使用get/set方法,而动态actionform方式,使用map的getkey方式,其中key就是标签name的值。
使用动态actionform优点:若更改表单和actionform时不需要重新编译,而静态的需要更改静态的actionform.java文件,必须重新编译。缺点:静态返回的是对应的值,动态actionform返回的是对象,我们还要把这个对象进行强制转换。