Struts原理与实践(2)
因为Struts是建立在MVC设计模式上的框架,你可以遵从标准的开发步骤来开发你的Struts Web应用程序,这些步骤大致可以描述如下:
1定义并生成所有代表应用程序的用户接口的Views,同时生成这些Views所用到的所有ActionForms并将它们添加到struts-config.xml文件中。
2在ApplicationResource.properties文件中添加必要的MessageResources项目
3生成应用程序的控制器。
4在struts-config.xml文件中定义Views与 Controller的关系。
5生成应用程序所需要的model组件
6编译、运行你的应用程序.
下面,我们就一步步按照上面所说的步骤来完成我们的应用程序:
第一步,我们的应用程序的Views部分包含两个.jsp页面:一个是登录页面logon.jsp,另一个是用户登录成功后的用户功能页main.jsp,暂时这个页面只是个简单的欢迎页面。
其中,logon.jsp的代码清单如下:
<%@ page contentType="text/html; charset=UTF-8" %> <%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %> <%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %> <HTML> <HEAD> <TITLE><bean:message key="logon.jsp.title"/></TITLE> <html:base/> </HEAD> <BODY> <h3><bean:message key="logon.jsp.page.heading"/></h3> <html:errors/> <html:form action="/logonAction.do" focus="username"> <TABLE border="0" width="100%"> <TR> <TH align="right"><bean:message key="logon.jsp.prompt.username"/></TH> <TD align="left"><html:text property="username"/></TD> </TR> <TR> <TH align="right"><bean:message key="logon.jsp.prompt.password"/></TH> <TD align="left"><html:password property="password"/></TD> </TR> <TR> <TD align="right"><html:submit><bean:message key="logon.jsp.prompt.submit"/></html:submit> </TD> <TD align="left"><html:reset><bean:message key="logon.jsp.prompt.reset"/></html:reset> </TD> </TR> </TABLE> </html:form> </BODY> </HTML> |
main.jsp的代码清单如下:
<%@ page contentType="text/html; charset=UTF-8" %> <%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %> <%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %><HTML> <HEAD> <TITLE><bean:message key="main.jsp.title"/></TITLE> <html:base/> </HEAD> <BODY> <logic:present name="userInfoForm"> <H3><bean:message key="main.jsp.welcome"/> <bean:write name="userInfoForm" property="username"/>! </H3> </logic:present> </BODY> </HTML> |
首先,我们看一下logon.jsp文件,会发现它有这么两个鲜明的特点:一是文件头部有诸如:
这样的指令代码,他们的作用就是指示页面要用到struts的自定义标签,标签库uri是一个逻辑引用,标签库的描述符(tld)的位置在web.xml文件中给出,见上篇文章的配置部分。struts的标签库主要由四组标签组成,它们分别是:
bean标签,作用是在jsp中操纵bean
logic标签,作用是在jsp中进行流程控制
html标签,作用是显示表单等组件
template标签,作用是生成动态模板
关于每类标签的具体作用及语法,因受篇幅限制,不在这里详细讨论,大家可参考struts手册之类的资料。只是心里要明白所谓标签其后面的东西就是一些类,这点与bean有些相似,它们在后端运行,生成标准的html标签返回给浏览器。
要使用它们显然要把它们的标签库描述文件引入到我们的系统中,这是些以.tld为扩展名的文件,我们要把它们放在/webapps/mystruts/WEB-INF/目录下。引入struts标签后原来普通的html标签如文本框的标签变成了这样的形式<?XML:NAMESPACE PREFIX = HTML />。
Jsp文件的第二个特点,就是页面上根本没有直接写用于显示的文字如:username,password等东西,而是用<?XML:NAMESPACE PREFIX = BEAN />这种形式出现。这个特点为国际化编程打下了坚实的基础,关于国际化编程后面的文章还会专门讨论。
这个简单的应用所用到的ActionForm为UserInfoForm,代码清单如下:
package entity; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionMapping; import javax.servlet.http.HttpServletRequest;public class UserInfoForm extends ActionForm{private String username;private String password;public String getUsername() {return (this.username);}public void setUsername(String username) {this.username = username;}public String getPassword() {return (this.password);}public void setPassword(String password) {this.password = password;} } |
在你的应用程序的WEB-INF目录下再建一个classes目录,在新建的这个classes目录下再建如下几个目录entity(用于存放ActionForm类)、action目录(用于存放Action类)、bussness目录(用于存放作为Model的业务对象类)。Classes目录下的子目录就是所谓的包,以后,还会根据需要增加相应的包。
现在,将UserInfoForm.java保存到entity目录中。
把如下代码添加到/webapps/mystruts/WEB-INF/struts-config.xml文件中
<form-beans><form-bean name="userInfoForm" type="entity.UserInfoForm" /></form-beans> |
特别要提醒一下的是:关于ActionForm的大小写,一定要按照上面的写,以免造成不必要的麻烦。
到此,我们完成了第一步工作。
第二步,我们建一个名为ApplicationResource.properties的文件,并把它放在/webapps/mystruts/WEB-INF/classes目录下。它在struts-config.xml的配置信息我们已在第一篇文章的末尾说了,就是:
目前我们在ApplicationResource.properties文件中加入的内容是:
#Application Resource for the logon.jsp logon.jsp.title=The logon page logon.jsp.page.heading=Welcome World! logon.jsp.prompt.username=Username: logon.jsp.prompt.password=Password: logon.jsp.prompt.submit=Submit logon.jsp.prompt.reset=Reset#Application Resource for the main.jsp main.jsp.title=The main page main.jsp.welcome=Welcome: |
到此,我们已完成了第二个步骤。
第三步,我们开始生成和配置Controller组件。
在前面我们已经提到,Struts应用程序的控制器由org.apache.struts.action.ActionServlet和org.apache.struts.action.Action类组成,其中,前者已由Struts准备好了,后者Struts只是为我们提供了个骨架,我们要做的是为实现应用程序的特定功能而扩展Action类,下面是实现我们登录程序的Action类的代码清单:
package action; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import javax.servlet.http.HttpServletResponse; import org.apache.struts.action.Action; import org.apache.struts.action.ActionError; import org.apache.struts.action.ActionErrors; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.apache.struts.action.ActionServlet; import bussness.UserInfoBo; import entity.UserInfoForm; public final class LogonAction extends Action {public ActionForward execute(ActionMapping mapping,ActionForm form,HttpServletRequest request,HttpServletResponse response)throws IOException, ServletException {UserInfoForm userInfoForm = (UserInfoForm) form; //从web层获得用户名和口令String username = userInfoForm.getUsername().trim();String password = userInfoForm.getPassword().trim();//声明错误集对象ActionErrors errors = new ActionErrors();//校验输入if(username.equals("")){ActionError error=new ActionError("error.missing.username");errors.add(ActionErrors.GLOBAL_ERROR,error);}if(password.equals("")){ActionError error=new ActionError("error.missing.password");errors.add(ActionErrors.GLOBAL_ERROR,error);}//调用业务逻辑if(errors.size()==0){String validated = "";try{UserInfoBo userInfoBo=new UserInfoBo();validated =userInfoBo.validatePwd(username,password);if(validated.equals("match")){//一切正常就保存用户信息并转向成功的页面 HttpSession session = request.getSession();session.setAttribute("userInfoForm", form); return mapping.findForward("success");} }catch(Throwable e){//处理可能出现的错误e.printStackTrace();ActionError error=new ActionError(e.getMessage());errors.add(ActionErrors.GLOBAL_ERROR,error);}} //如出错就转向输入页面,并显示相应的错误信息saveErrors(request, errors); return new ActionForward(mapping.getInput()); } } |
这个action类中有两个错误消息键要加到ApplicationResource.properties文件中,清单如下:
#Application Resource for the LogonAction.java error.missing.username=<li><font color="red">missing username</font></li> error.missing.password=<li><font color="red">missing password</font></li>> |
第四步:在struts-config.xml文件中定义Views与 Controller的关系,也就是配置所谓的ActionMapping。它们在struts-config.xml中的位置是排在… 标签后,我们的登录程序的配置清单如下:
<action-mappings><action input="/logon.jsp" name="userInfoForm" path="/logonAction" scope="session" type="action.LogonAction" validate="false"><forward name="success" path="/main.jsp" /> </action></action-mappings> |
第五步:生成应用程序所需要的model组件,该组件是完成应用程序业务逻辑的地方,现在我的登录程序的业务逻辑很简单,就是判断用户是不是lhb并且其口令是不是awave如果是就返回一个表示匹配的字符串"match",否则,就抛出出错信息。其代码清单如下:
package bussness;import entity.UserInfoForm;public class UserInfoBo {public UserInfoBo(){} public String validatePwd(String username,String password){String validateResult=""; if(username.equals("lhb")&&password.equals("awave")){validateResult="match";}else{throw new RuntimeException("error.noMatch");} return validateResult; } } |
将其放在bussness包中。
我们同样要将其表示错误信息的键值设置在ApplicationResource.properties文件中,清单如下:
#Application Resource for the UserInfoBo.java error.noMatch=<li><font color="red">no matched user</font></li> |
到此为止,我们已经完成了这个简单登录程序的所有组件。下面就可以享受我们的劳动成果了。
第六步、编译运行应用程序。
常规的做法是用Ant来装配和部署Struts应用程序,如果按这个套路,这篇文章就会显得十分冗长乏味,同时也没有太大的必要,因为,用一个IDE一般可以很方便地生成一个应用。因此,我们采用简便的方法,直接编译我们的.java文件。不过这里要注意一点的是:实践证明,要使得编译过程不出错,还必须将struts.jar文件放一份拷贝到/common/lib目录中,并在环境变量中设置CLASSPATH 其值是/common/lib/struts.jar;配置好后就可以分别编译entity、bussness及action目录下的.java文件了。编译完成后:打开/conf目录下的server.xml文件,在前加上如下语句为我们的应用程序建一个虚拟目录:
<Context path="/mystruts" docBase="mystruts" debug="0"reloadable="true"> </Context> |
启动,tomcat。在浏览器中输入:http://localhost:8080/mystruts/logon.jsp
如果前面的步骤没有纰漏的话,一个如图所示的登录画面就会出现在你的眼前。
如果,不输入任何内容直接点击Submit按钮,就会返回到logon.jsp并显示missing username和missing password错误信息;如果输入其他内容,则会返回no matched user的错误;如果输入的用户名是lhb且口令是awave则会显示表示登录成功的欢迎页面。
上面虽然是一个功能很简单的应用程序,但麻雀虽小,五脏俱全,基本涉及到了struts的主要组成部分。下面我们就来分析一下程序的特点和基本的工作原理。
首先,我们在浏览器中输入.jsp文件时,后台将struts的自定义标签"翻译"成普通的html标签返回给浏览器,而一些提示信息如作为输入框label的username、password还有按钮上提示信息还有错误信息等都来自MessageResources即ApplicationResource.properties文件中对应的键值。当我们点击Submit按钮时,从web.xml的配置可以看出,请求将被ActionServlet截获。它通过表单中提供的action参数在struts-config.xml文件中查找对应的项目,如果有对应的ActionForm,它就用表单中数据填充ActionForm的对应属性,本例中的ActionForm为userInfoForm,相应的属性是username和password,这就是所谓的实例化ActionForm。然后,将控制交给对应的Action,本例中是LogonAction,它做的主要工作是对ActionForm中取出的username和password做了一下校验,这里只是简单检验它们是否为空(这些简单的格式化方面的校验应该放在客户端进行,而且struts也为我们提供了一个很好的模式,后面如果有可能会详细介绍)。如果不为空则调用判断用户及口令是否正确的业务逻辑模块UserInfoBo,同时,它会捕获可能出现的错误,然后根据业务逻辑返回的结果将程序导向不同的页面,本例中如果业务逻辑返回的结果是"match"则依据中的返回main.jsp页面给浏览器同时在session对象中保存了用户的登录信息;否则,返回输入页面并显示相应的出错信息,完成了上篇文章所说的它的四个主要职责。
大家一定注意到了,在本例的业务逻辑模块UserInfoBo中,将用户与密码是写死在程序中的,在一个真实的应用程序中是不会这样做的,那些需要永久保存的信息如,username及口令等都会保存在数据库文件之类的永久介质中,下一篇文章我们将介绍在struts中如何访问数据库。
Struts原理与实践(2)相关推荐
- Struts原理与实践(5)
Struts原理与实践(5) 作者:罗会波 发文时间:2004.09.24 一个支持i18n的应用程序应该有如下一些特征: 1增加支持的语言时要求不更改程序代码 2字符元素.消息.和图象保存在原代码之 ...
- Struts原理与实践(文摘)
Struts原理与实践 摘自walle的blog word文档下载:http://www.chq.name/component/option,com_docman/task,doc_download/ ...
- Struts原理与实践
[@more@] Struts原理与实践 (第1部分) 一. 什么是Struts 框架(Framework)是可重用的,半完成的应用程序,可以用来产生专门的定制程序. 您只要细心地研究真实的应用程序, ...
- struts原理与实践(七)
第7部分 上一篇文章中介绍校验时提到客户边的校验用到了JavaScript,实际上用Struts配合JavaScript还可以实现许多有用的功能,比如,级联下拉菜单的实现就是一个典型的例子: 本例假设 ...
- Struts原理与实践(7)[转]
在上一篇文章中介绍校验时提到客户边的校验用到了JavaScript,实际上用Struts配合JavaScript还可以实现许多有用的功能,比如,级联下拉菜单的实现就是一个典型的例子: 本例假设要实现的 ...
- Struts原理与实践(7)
在上一篇文章中介绍校验时提到客户边的校验用到了JavaScript,实际上用Struts配合JavaScript还可以实现许多有用的功能,比如,级联下拉菜单的实现就是一个典型的例子: 本例假设要实现的 ...
- Atitit.java jna 调用c c++ dll的原理与实践 总结 v2 q27
Atitit.java jna 调用c c++ dll的原理与实践 总结 v2 q27 1. Jna简单介绍1 2. Jna范例halo owrld1 3. Jna概念2 3.1. (1)需 ...
- Atitit.软件兼容性原理与实践 v3 q326.docx
Atitit.软件兼容性原理与实践 v3 q326.docx 1. 架构兼容性1 2. Api兼容性1 2.1. 新api vs 修改旧的api1 3. Web方面的兼容性(js,html)1 3 ...
- 2018-2019-2 网络对抗技术 20165239Exp3 免杀原理与实践
2018-2019-2 网络对抗技术 20165239 Exp3 免杀原理与实践 win10 ip地址 192.168.18.1 fenix ip地址为 192.168.18.128 (1)杀软是如何 ...
最新文章
- kafka不使用自带zk_kafka 安装部署教程
- python图片二进制流转换成图片_微信如何将图片转换成word文字
- Java多线程中的Runnable和Thread
- HBase的hbase shell 详解
- css3中的background
- jQuery刻度尺滚动滑块插件
- uitableview 弹性_iOS UITableView/UICollectionView的嵌套和悬停的解决方案
- fscapture设置中文_Fscapture是什么软件?有没有功能介绍?
- 也来学学插件式开发续-利用MEF
- 易到高管被原百度外卖CEO巩振兵逼下跪:职场人到中年的无奈
- android gps 获取方位_Android GPS定位 获取经纬度
- 采集PLC数据转MQTT上报实现对PLC远程调试和远程程序上下载
- java--与君初相识之jdk的环境配置
- 《HelloGitHub》第 74 期
- VMware跨电脑移动Linux虚拟机
- 如何调整图片像素大小
- 如何在电脑端写qq看点文章?如何在电脑端找QQ看点
- SpringBoot项目打包成jar后读取包内文件报错问题解决方法
- Java小项目(一):桌球游戏(简单移动)
- Word~Word修改行间距磅值
热门文章
- Mybatis-Plus驼峰命名规则之Date类型字段返回值为null
- 闲来无事,就把lnmp的php升级到php-5.2.17最新稳定版本
- 通过代码生成机制实现强类型编程-CodeSimth版
- 基于 VS 2010 阐述C# 4个特性
- Linux Shell脚本入门教程系列之(四)Shell注释
- php输入流php://input的使用分析
- Intro.js轻松搞定页面引导流程
- MySQL5.7更改密码时出现ERROR 1054
- 非线性降维-核主成分分析KPCA
- IAR #pragma optimize 指令