Struts 1.x
来源:互联网 发布:藏头诗制作软件 编辑:程序博客网 时间:2024/05/30 12:30
--------------------------Struts 1.x理论介绍--------------------------
1. MVC设计模式
(1)模型-视图-控制器(Model-View-Controller)是80年代出现的一种软件设计模式,现在已经被广泛的使用。它强制的把应用程序的输入、处理、输出分开,三个核心模块M-V-C分别负担不同的任务。
(2)模型(Model)模型是应用程序的主体部分。模型表示业务数据和业务逻辑,一个模型可以为多个视图提供数据,提高了应用的可重用性。
(3)视图(View)用程序中用户界面相关的部分,视图向用户显示数据,并能接收用户的输入数据,但它并不进行任何实际的业务处理。
(4)控制器(controller)工作就是根据用户请求,调用相应的模型组件处理请求,然后调用相应的视图显示模型返回的数据。
(5)MVC 的出现不仅实现了功能模块和显示模块的分离,同时它还提高了应用系统的可维护性、可扩展性、可移植性和组件的可复用性。
2. 为什么要使用struts
首先,struts是建立在MVC这种公认的好的模式上的,Struts在M、V和C上都有涉及,但它主要是提供一个好的控制器和一套定制的标签库上,也就是说它的着力点在C 和V上,因此,它天生就有MVC所带来的一系列优点,如:结构层次分明,高可重用性,增加了程序的健壮性和可伸缩性,便于开发与设计分工,提供集中统一的 权限控制、校验、国际化、日志等等;
其次,它是个开源项目得到了包括它的发明者Craig R.McClanahan在内的一些程序大师和高手持续而细心 的呵护,并且经受了实战的检验,使其功能越来越强大,体系也日臻完善
最后,是它对其他技术和框架显示出很好的融合性,大大提高了开发速度
3. Framework的概念
人们用于解决相同或者相似类型问题的方案
特点:可重用性,可扩展性,可收缩性
基于请求响应(Request-Response)模式的应用Framework的逻辑结构
控制器(Controller)
业务逻辑层(Business Logic)
数据逻辑层(Data logic)
4. Struts的概念和体系结构
(1)Struts是Apache组织的一个开源项目,主要是采用Servlet和JSP技术来实现的,基于Sun Java EE平台的MVC框架,它采用MVC模式,将MVC模式”分离显示逻辑和业务逻辑”的能力发挥得淋漓尽致
Struts由一组相互协作的类、Serlvet以及丰富的标记库(jsp tag lib)和独立于该框架工作的实用程序类(Validator)组成。
(2)Struts有其自己的控制器(Controller),同时整合了其他的一些技术去实现模型层(Model)和视图层(View)。在模型 层,Struts可以很容易的与数据访问技术相结合,包括EJB,JDBC和Object RelationBridge。在视图层,Struts能够与JSP, VelocityTemplates,XSL等等这些表示层组件想结合。
(3)Struts framework是MVC模式的体现,下面我们就从分别从模型、视图、控制来看看struts的体系结构(Architecture)。下图显示了struts framework的体系结构响应客户请求时候,各个部分工作的原理。
从视图角度(View)
主要由JSP建立,struts自身包含了一组可扩展的自定义标签库(TagLib),可以简化创建用户界面的 过程。目前包括:Bean Tags,HTML Tags,Logic Tags,Nested Tags,Template Tags 这几个Taglib。有关它们的详细资料请参考struts用户手册
从模型角度(Model)
模型主要是表示一个系统的状态(有时候,改变系统状态的业务逻辑操作也也划分到模型中)。在 Struts中,系统的状态主要有ActiomForm Bean体现,一般情况下,这些状态是非持久性的。如果需要将这些状态转化为持久性数据存储,Struts本身也提供了Utitle包,可以方便的与数据 库操作
从控制器角度(Controller)
在Struts framework中, Controller主要是ActionServlet,但是对于业务逻辑的操作则主要由Action、ActionMapping、 ActionForward这几个组件协调完成(也许这几个组件,应该划分到模型中的业务逻辑一块)。其中,Action扮演了真正的业务逻辑的实现者, 而ActionMapping和ActionForward则指定了不同业务逻辑或流程的运行方向。
--------------------------Struts 1.x环境配置--------------------------
下载struts的jar包,从Apache 的官方网站 http://www.apache.org/ 中下载
选择 Download--Backup Sites下的http://www.apache.org/dist/--struts--binaries,可以找到有关struts 1.x的不同版本
1. 搭建环境
(1) 导入jar包
(2) 在WEB-INF下建立配置文件:struts-config.xml
(3) 在web.xml文件中注册struts中心控制器--ActionServlet,以及说明struts-config.xml配置文件的位置
(4) 超链接
struts-config.xml文件示例
web.xml文件示例
2. 配置FormBean
(1) 创建一个类,继承ActionForm
(2) 在struts-config.xml中注册该FormBean
<form-beans >
<form-bean name="userForm"type="com.yourcompany.struts.form.UserForm"/>
</form-beans>
属性name是变量名
属性type是类全名
3. 配置Action
(1) 创建一个类,继承Action
覆盖execute方法,该方法是Action中的缺省方法,调用Action的时候先寻找execute方法,其他的方法都会被无视掉
(2) 在struts-config.xml中注册该Action
<action-mappings >
<action path="/login"
type="com.Action.UserAction"
name="userForm"
<forward
name="success"
path="/success.jsp"
redirect="true" />
</action>
</action-mappings>
属性path指明(调用者)jsp能通过中心控制器ActionServlet找到该Action
属性type表示该Action类全名
Name表示该Action引用的FormBean的名称
在JSP或静态页面中
使用struts格式的html语言,表单中的action应该=/注册的Action名称
使用普通格式的html语言,表单中的action应该=/注册的Action名称.do
4. Struts-config.xml配置文件的元素格式规范
The content of element type“struts-config” must match
”(display-name?,description?,data-sources?,form-beans?,global-exceptions?,global-forwards?,action-mappings?,controller?,message-resources*,plug-in*)”
这是在MyEclipse环境下这样来定义的,所以使用此IDE时就必须遵守这个规范
5. 问题总结
(1) 谁来填充Form?什么时候填充?根据什么来填充
(2) ActionServlet怎样把请求派发给Action?
(3) Action运行完后怎样跳转?
------------------------Struts1.x的工作原理------------------------
Struts工作原理图示例
1. 读取配置
Struts框架总控制器ActionServlet本质上是一个Servlet,在web.xml中配置成自动启动的Servlet
读取配置文件struts-config.xml的配置信息,为不同的struts模块初始化相应的ModuleConfig对象:
ActionConfig、ControlConfig、FormBeanConfig、ForwardConfig、MessageResourcesConfig
2. 发送请求
用户提交表单或调用URL向WEB应用程序服务器提交一个请求,请求的数据用HTTP协议上传给web服务器
3. 填充FormBean
将*.do请求从ActionConfig中找出对应请求的Action子类,如没有对应的Action,控制器直接转发给JSP或静态页面。
如果有对应的Action且这个Action有一个相应的ActionForm,实例化该ActionForm并用JSP或静态页面中的HTTP请求的数据(例如注册信息,帐号、密码、姓名等)来填充ActionForm的属性,且保存在ServletContext中(request或session中),这样他们就可以被其他Action对象或者JSP调用
4. 派发请求
控制器根据配置信息ActionConfig将请求派发到具体的Action,并把相应的FormBean也传给该Action的execute()方法
5. 处理业务
Action一般只包含一个excecute()方法,它负责执行相应的业务逻辑(调用其他业务模块)。
完成后返回一个ActionForward对象,控制器通过该ActionForward对象来进行跳转工作
6. 返回响应
Action根据业务处理的不同结果返回一个目标响应对象给总控制器,该目标响应对象对应一个具体的JSP页面或另一个Action。
这个响应不是真正的响应目标,只是响应目标的一个关键字
7. 查找响应
总控制器根据执行业务功能由Action返回的目标响应对象,找到对应的资源对象,通常是一个具体的JSP页面。
8. 响应用户
目标响应对象(JSP)将结果页面展现给用户
--------------------------Action的研究与分析--------------------------
1. Action在发出该Action的请求时初始化,而不是在读取配置时初始化
2. 每个Action只会初始化一次
3. Action是线程不安全的,因为所有的请求共享一个Action实例
4. 怎样实现Action的安全性编程
(1) 注意不要用实例变量或者类变量共享只是针对某个请求的数据
(2) 注意资源操作的同步性
-----------------------ActionMapping的研究与分析-----------------------
1. struts-config.xml配置文件中的每一个<action>元素都与类org.apache.struts.action.ActionMapping的一个实例对应
2. 在Action中利用ActionMapping来获取struts-config.xml配置文件的信息
String name=mapping.getName();
String path=mapping.getPath();
String type=mapping.getType();
System.out.println("name="+name+"/tpath="+path+"/ttype="+type);
String[] forwardNames=mapping.findForwards();
for(String forwardName:forwardNames){
ActionForward forward=mapping.findForward(forwardName);
String forwardPath=forward.getPath();
System.out.println("forwardName="+forwardName+"/tforwardPath="+forwardPath);
}
3. 在struts-config.xml文件中的配置信息只能在该文件中做修改,而利用ActionMapping的setPath()方法来更改配置信息只会引起一个异常告诉用户该配置已经被冻结,这是一种保护思想,不想让用户更改从而用异常来封装它
4. 在struts-config.xml中
<action
attribute="userForm" input="/user.jsp" name="userForm"path="/user" type="com.user.UserAction"validate="true">
<forward name="suc" path="/sucess.jsp"redirect="true" />
</action>
Attribute属性用来存取form的关键字,缺省值与name一样
5. Validate属性用于控制是否校验表单,true—校验,false—不校验
默认为true
6. Input属性结合validate=true来使用,如果validate=false,不使用校验,则input属性无效,如果validate=true且表单校验失败则跳转到该input值所代表的目标模块
强制让validate()方法校验失败
public ActionErrorsvalidate(ActionMapping mapping,
HttpServletRequest request) {
ActionErrors errors=new ActionErrors();
ActionMessage message=new ActionMessage("error");
errors.add("error",message);
return errors;
}
Struts-config.xml文件
<action
attribute="userForm" input="/error.jsp" name="userForm"path="/user" type="com.user.UserAction"validate="true">
<forward name="suc" path="/sucess.jsp" redirect="true" />
</action>
7. 全局跳转
有两个或两个以上的Action都需要使用的Forward,可以配置为全局跳转
所有的Action都可以向一个页面进行跳转,减少了重复跳转操作的代码量
<global-forwards>
<forward name="index"path="/index.jsp"></forward>
</global-forwards>
-----------------------ActionForward的研究与分析-----------------------
1. ActionForward对象封装了跳转的URL路径且被请求处理器用于识别目标视图
2. ActionForward的名字是独一无二的
3. ActionForward的跳转方式
(1) 默认redirect=false,使用RequestDispatcher.forward方法跳转,是一种容器内跳转
(2) 如果在struts-config.xml配置文件中设置redirect=true,则使用HttpServletResponse.sendRedirect()方法跳转,该跳转方式也是一种容器外跳转,可以将path地址写为一个网址、例如path=”http://www.google.com”,当跳转的时候就会链接到该网站上
------------------------ActionForm的工作流程分析-----------------------
处理ActionForm的一般步骤
1. 检查Action的映射,确定Action中已经配置了对ActionForm的映射
2. 根据name属性,查找formbean的配置信息
3. 检查Action的formbean的使用范围,确定在此范围下(request,session),是否已经有次formbean的实例
4. 加入当前范围下,已经存在了此formbean的实例,而是对当前请求来说,是同一种类型的话,那么就重用
5. 否则,就重新构建一个formbean的实例(调用构造方法),并且保存在一定作用范围
6. Formbean的reset()方法被调用,可以设置每个属性在JSP或静态页面里对应的文本框等控件中的初始值
7. 调用对应的setter方法,对状态属性赋值
8. 如果validate的属性设置为true,那么就调用formbean的validate()方法
9. 如果validate()方法没有返回任何错误,控制器将ActionForm作为参数,传给Action实例的execute()方法并执行
注意:直接从ActionForm类继承的reset()和validate()方法,并不能实现什么处理功能,所以有必要自己重新覆盖
-------------------------ActionForm的研究与分析------------------------
1. Scope缺省值是session
(1) 从session中获取ActionForm
UserForm userForm=request.getSession().getAttribute("userForm");
(2) 从request中获取ActionForm
UserForm userForm=request.getAttribute("userForm");
2. JSP或静态页面表单中中注册信息项,例如我要注册ID、name和password,那么
<html:form action="/user">
id : <html:text property="id"/><br/>
name : <html:text property="name"/><br/>
password : <html:text property="password"/><br/>
<html:submit/><html:cancel/>
</html:form>
这三个属性的property属性对应的值就与ActionForm中的setXXX方法相对应,而不是与ActionForm中的属性名称对应,即使属性叫id1,name1,pwd也可以,只要方法名与property属性值相等即可。
-----------------------------Struts标签库-----------------------------
1. JSP视窗组件所使用的struts标签库由4类标签组成
Bean标记:在JSP页中管理bean,struts-bean.tld
逻辑标记:在JSP页中控制流程,struts-logic.tld
HTML标记:用来生成HTML标记,在表单中显示数据,使用会话ID对URL进行编程,
struts-html.tld
tiles标记:使用动态模板构造普通格式的网页,struts-tiles.tld
2. Struts标记的导入代码
<%@taglib uri="http://struts.apache.org/tags-bean"prefix="bean" %>
<%@taglib uri="http://struts.apache.org/tags-logic"prefix="logic" %>
<%@ taglib uri="http://struts.apache.org/tags-html"prefix="html" %>
<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
3. uri及prefix属性
(1) uri
如果没有背下来uri怎么写,那么可以将struts-taglib-1.3.10.jar包导入进myeclpse,然后查看其META-INF.tld目录下的标签文件信息,包含了4个文件:
Struts-bean.tld
Struts-html.tld
Struts-logic.tld
Struts-nested.tld
打开这几个文件,就可以各自的uri的信息,例如bean的uri:
<tlib-version>1.3</tlib-version>
<jsp-version>1.2</jsp-version>
<short-name>bean</short-name>
<uri>http://struts.apache.org/tags-bean</uri>
(2) prefix
要引用哪个标记,就写哪个标记的名称
-------------------------------bean标记------------------------------
1. define和write
在JSP页面中
先定义
<%
String username="Shiki";
request.setAttribute("username",username);
%>
在body中
<bean:define id="username1" name="username" scope="request"toScope="session"></bean:define>
标签获取username:<bean:write name="username1"/><br>
表达式获取username:${username1}
定义一个username字符串,值为”Shiki”,放入了request中,名称为username
username1代替了username的值,然后用标记和表达式分别输出
这段代表表示,define从已有的变量或者变量的属性定义一个新的变量,write用于输出该属性到JspWriter
define的scope属性定义获取值时的属性范围,而toScope属性定义输出值时的属性范围
2. message
配合ApplicationResources.properties资源文件来实现Struts的国际化功能
(1) 定义资源文件
相应语言的资源文件的名字
英语:ApplicationResources_en_US.properties
中文:ApplicationResources_zh_CN.properties
一定要注意语言的后缀,en_US、zh_CN,如果想用IE浏览器的语言切换来查看,就必须使用这些后缀名,名字不能改变
配置文件的格式为:
配置英文
Welcome=welcome
配置中文时,需要将中文转换成为Unicode编码,资源文件才可以通过转换而识别中文
Welcome= /u6b22/u8fce(中文的”欢迎”)
资源文件的格式都是以键值对的形式来填写的
(2) 修改struts-config.xml配置文件
<message-resources parameter="com.user.struts.ApplicationResources"key="MyKey"/>
(3) 在JSP页面中使用<bean:message>标记
用Struts实现国际化:<br>
<bean:message bundle="MyKey"key="language"/>语言:
<bean:message bundle="MyKey"key="welcome"/>
(4) 使用IE来查看网页文字国际化的效果
打开IE—工具—Internet选项—常规—语言,选择某一种当前浏览器使用的语言
Struts会找到相应语言后缀的资源文件的某个键并获取相应的值
-------------------------------logic标记-----------------------------
logic提供了一组在JSP页中处理流程控制的标记,这些标记封装在文件名为struts-logic.tld的标记包中。
该标记的主要三个功能是:条件逻辑,重复,转发/重定向响应
1. iterate
用于在对象集合中循环从而重复的产生输出文本,以及应用程序流程控制。
在JSP页面中
先定义
<%
String[] usernames={"黑桐干也","两仪式","苍崎橙子"};
request.setAttribute("user",usernames);
%>
在body中
用Struts实现iterator迭代器的功能:
<logic:iterate id="user" name="user"scope="request" indexId="id">
${id} <bean:write name="user"/>
</logic:iterate> Iterate标记的scope属性定义了获取值时的属性范围,name属性用于接收相应属性范围传递过来的值,id是该iterate标记定义一个新的对象,indexId可以为循环中的每个值指定一个编号,表达式${id}可以用来输出该编号
当要使用bean:write标记来输出时,将使用id所定义的值的名称
在logic:iterate标记中也可以再次嵌套logic:iterate标记,实现双重循环
2. notPresent和present
在一张页面可以充当两张页面,登录成功如何,不成功如何,都在一页中显示
例如我要判断我前台页面的name属性是否等于”Shiki”,
(1) 在Action中
if(name.equals("Shiki")){
HttpSession session=request.getSession();
session.setAttribute("user", name);
}
如果name等于”Shiki”,就把”Shiki”保存在session范围中
(2) 在jsp页面中
<logic:notPresent name="user" scope="session">
该用户不存在!
</logic:notPresent>
<logic:present name="user" scope="session">
${user} 登录成功
</logic:present>
Scope属性当前将值保存在哪个作用域范围中,Name属性表示传递过来的值
logic:notPresent当前页面的作用域范围内的值不存在时,显示什么
logic:present当该值存在时,显示什么
-------------------------------动态Form-----------------------------
1. Dynamic FormBean 动态Form,没有具体的物理文件,是在struts-config.xml文件中配置的
2. 配置动态Form格式:
<form-bean name="userDynaForm" type="org.apache.struts.action.DynaActionForm">
<form-property name="password"type="java.lang.String" />
<form-property name="name"type="java.lang.String" />
<form-property name="id"type="java.lang.String" />
</form-bean>
3. 配置Action:
<action
attribute="userDynaForm"
name="userDynaForm"
path="/userDyna"
scope="request"
type="com.user.Action.UserDynaAction"/>
4. 通过在JSP或静态页面的表单中输入数据,然后跳转到指定了userDynaForm的Action上
这样所有的数据就会放入动态Form中
JSP页面:
<form action="userDyna.do" method="post">
password <input type="text" name="password"> <br>
name <input type="text" name="name"> <br>
id <input type="text" name="id"> <br>
<input type="submit"value="提交">
<input type="reset"value="取消"> <br>
</form>
如果是用普通的html语法,action就要写成.do的形式
如果是采用struts的html标签语法,action就不需要写后缀名.do的形式
Action页面:
DynaActionForm DynaForm =(DynaActionForm) form;
PrintWriter out=response.getWriter();
out.print("This is userDyna");
String name=(String)DynaForm.get("name");
String password=(String)DynaForm.get("password");
String id=(String)DynaForm.get("id");
out.print("<br>"+id+" "+name+" "+password);
return null;
普通的formbean在Action获取表单中的值时,是使用set和get方法,而动态Form则在Action中使用get(“属性名”)的方式来取值
5. 使用普通的FormBean时,在Action的跳转页面上查看用户注册的信息,可以使用表达式${formbean.properties}
而使用动态Form时,想查看注册信息的表达式格式为${dynaform.map.properties}
普通的FormBean是使用set方法来保存,而动态Form是使用map集合来保存的
----------------------------Struts的异常处理-------------------------
1. 创建一个Exception类的子类,在构造方法中调用父类的构造方法,并传递一个错误信息
public class MyException extends Exception {
public MyException(String message){
super(message);
}
2. }配置struts-config.xml文件
<exception path="/errors.jsp"key="error" type="com.exception.MyException"></exception>
(1) Path出现异常后的跳转页面
(2) 用资源文件来存放异常信息,以键值对的形式,key是异常信息的键,通过key可以从 资源文件中获取到值,所以也要在struts-config.xml中配置资源文件
<message-resources parameter="com.user.struts.ApplicationResources"/>
该message-resources标记不能包含key属性,所以如果想与国际化功能同时实现,就要配置两个资源文件,一个带key,一个不带key
<message-resources parameter="com.user.struts.ApplicationResources"key="language"/>
<message-resources parameter="com.user.struts.ApplicationResources"/>
(3) Type是所要处理的异常,一般是自己定义一个Exception的子类
3. 在相应的Action中的execute方法中抛出异常
if(name.equals("java")){
throw new MyException("invalid");
}
4. 在异常处理页面(path所指定的页面)使用struts标记<html:errors>来输出资源文件中所包含的异常信息,该信息是由配置文件中exception标记的key属性来决定的
This is Exception page. <br>
<html:errors/>
------------------------ForwardAction 全局跳转------------------------
1. 将所有的*.jsp访问形式改变成统一访问模式*.do
2. 所有的jsp在WEB-INF下
3. 所有jsp的请求之前需要先访问Action
在struts-config.xml配置文件中设置Action
<action path="/fowardAction"forward="/user.jsp"></action>
4.该jsp将由定义的Action—forwardAction.do来访问
-----------------------------DispatchAction--------------------------
加入我要实现一个模块,需要对学生信息进行CURD操作
遵照Struts的MVC设计模式,Action作为控制器来使用
有以下4个Action:
AddStudentAction、DeleteStudentAction、UpdateStudentActio、QueryStudentAction
每个CURD操作就要对应一个Action,然后调用DAO方法来实现该功能,并作出跳转
但这样的缺点是:Action过多,所以需要合并相关的Action来简化操作
所以我们需要使用DispatchAction来实现带参数的一个Action包含多个可执行方法,多个提交组件针对一个Action,感觉像是同时包含个了多个Action,却实际减少了Action的数量,
1. 创建一个DispatchAction的子类,这里的方法必须与原来的execute方法同参数同返回值,但可以自定义方法名称,以此同时来包含多个这样的方法,实现多个Action
但是Action中的方法名称可以有多种,但是决不能是execute
2. 修改struts-config.xml配置
<action path="/studentAction"type="com.user.Action.StudentActionAction"parameter="operationType"/>
<html:link action="studentAction?operationType=AddStudentAction">
添加学生
</html:link>
根据parameter="operationType"参数所定义的内容去匹配Action中的方法名,分别调用不同的方法
------------------------------预处理类--------------------------------
实现对struts中各个网页的文字编码过滤转换
1. 创建com.en包,创建一个Encoding类,该类继承于RequestProcessor类,是一个预处理类,对struts里边所有的请求提前作出预处理
public class Encoding extends RequestProcessor {}
2. 覆盖父类方法processPreprocess
protected boolean processPreprocess(HttpServletRequest req,HttpServletResponse resp) {
req.setCharacterEncoding("gbk");
return true;
}
这个方法整合了过滤器和监听器,request和response都可以实现过滤功能
3. 修改struts-config.xml配置文件
在</struts-config>中作为单独的一个元素来配置
<controller processorClass="com.en.Encoding"></controller>
- Struts 1.x Vs Struts 2.x
- Struts 1.x 对比 Struts 2.x
- struts 1.x 2.x
- Struts 1.X入门
- Struts 1.x
- struts 1.x转换器
- struts 1.x 原理
- Struts 1.x
- 5.Struts 1.x 对比 Struts 2.x
- 5.Struts 1.x Vs Struts 2.x
- Struts 2.x 与 struts 1.x 比较
- Struts 1.x 异常总结
- struts 1.x spring 整合
- Struts 1.x | 标签库
- Struts 1.x FormFile UploadFile
- Struts 1.X工作原理
- 从struts 1.x升级到 struts 2(二) POJO
- 从struts 1.x升级到 struts 2(三) OGNL
- 深入分析request_irq的dev_id参数作用
- 把32位等任意格式图片灰度化并把图像数据保存为文本文件
- 使用 OProfile for Linux on POWER 识别性能瓶颈
- GB2312 编码和汉字相互转换
- android 学习笔记2011/06/16
- Struts 1.x
- 简单的 vs2008 web安装部署打包心得
- Ubuntu下JDK+Tomcat+MySql环境的搭建
- 框架整合
- 笔记:系统编程知识点恢复
- iPhone Object-c Base64编码
- 电子产品的防水等级JIS(IPX)
- 【转】Oracle数据库基本概念
- maven工作笔记