[计算机软件及应用]struts笔记
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Struts学习笔记
xml描述数据本身
xsl修饰xml
DOM
SAX
stup 通过协议骨架远程对象
典型的proxy代理
struts:
学j2ee应该朝domain model,FrameWork,Parttern,架构模式方向发展,才能深入了解掌握。
一、Domain Model
领域模型:是对现实世界的对象模型
是从现实世界抽取出来的
一般是先把领域模型设计出来
DDD领域驱动设计
不像以前,上来先设计数据库,数据库是面向关系的,而java是面向对象的,先面向关系再面向对象,有点别扭
ORM自动的把实例类自动转换成数据表
实体对象概念,user就是实体概念,有标识
值对象概念,属于实体对象的一部分,不是跟数据库的对应
二、Parttern模式遇到什么事情用什么方案解决?
1、设计模式,GOF设计模式,对象思维,就是把现实中的实体抽象成对象
工厂,策略,代理
很重要,掌握了设计模式,就有了对象的概念
2、架构模式
MVC架构模式
3、分析模式
RBAC(Roles Base Access Control)基于角色的访问控制,对权限设计的处理模型
who谁用这些权限
what针对哪些资源设计权限
how授权给谁,怎么样授权
三、FrameWork 框架
框架不是一个成熟的产品,是个半成品,struts spring是给开发人员用的,是基础性的服务,就是提供基础组件,封装的是基础性的服务,才可以在各个行业通用。
是大师级的人物写出来的框架,如果我们不用框架,自己就得先写框架,然后再开发具体业务,那就太费时,用框架,我们就只考虑具体业务设计开发,struts就是一个mvc框架。
领域模型对象
表现层-业务层-持久层
struts spring hibernate
以前:jsp -实体bean
现在:jsp -采用DTO 或者VO
宜于扩展:OCP,只增加相应的实现类,不用修改以前的类
两层的一般是:C/S
以前大量的存储都用存储过程,不适合跨平台思想
B/S:呈现层,业务层,持久层,数据库层
可以把界面交给界面组做
业务层交给业务开发做
数据库交给数据库开发做
分层好处,jsp就是显示用的,不参与业务实现,javabean实现业务,分层可以复用,客户端可以是pc,也可以是手机,只是前端采用不同的html,wml实现,业务层不变
JDO有收费的也有开源的,但是开源的不太好
hibernate 是开源的,用的比较多
spring
struts 我们用struts1.2是非常经典的mvc框架
webwork
分析struts的源代码,深入了解mvc
在javaProject下建struts目录
切换 workspace 到struts
建一个test_servlet项目
servlet特性:
前面必须有“/”
<url-pattern>/servlet/TestServlet</url-pattern>
<url-pattern>/TestServlet</url-pattern>
<url-pattern>*.action</url-pattern>
敲任意字符.action,如果有*了前面不用加“/”
<url-pattern>*.do</url-pattern>
敲任意字符.do,如果有*了前面不用加“/”
<url-pattern>/servlet/*</url-pattern>
servlet/后面跟什么都可以访问
servlet充当一个控制的角色,mvc中的c角色
配置成*.do,通过request.getRequestURI判断请求的user.do,item.do,与配置文件里配置的参数比较,通过策略模式,派发到相应的servlet类(UserServlet,ItemServlet)
servlet根据请求转到对应的manager类处理,然后转到实体类,dao层统称为model层,处理的结果转到jsp页面显示
MVC:
jsp 充当一个显示的界面mvc中的V(view)
servlet mvc中的C(control)
业务逻辑层 mvc中的M(Model)
structs就是实现mvc
面向请求的驱动
Struts1.x struts2.x webwork
面向事件的驱动
M2就是MVC模式
drp采用的是M1,业务逻辑和表示逻辑混合,jsp充当的角色太重,不适合多于10人开发M2适合大型项目开发,MVC,jsp(v)+servlet(c)+model(m)分层的概念servlet:接受业务参数,调用model层完成操作,然后转到jsp显示结果
UserManager就是一个模型,如果UserManager封装的好哪怕改成swing也可以照用,那样才体现分层的思想
实体类:贫血模型,vo,pojo
设置模型:UserManager就是模型层的概念,增删改查
最主要区别:
M1没有分层
M2是细粒度分层
M1适合小型项目开发
M2适合大型项目开发
M model ,业务逻辑
view jsp,显示层,呈现层UI Layer
controller servlet
swing:也是分层概念,mvc
观察者模式
tree,model
通过浏览器访问某一个servlet接受参数,把参数组织打包,形成用户对象,调用model层处理完成后,返回给servlet层,servlet传递给jsp视图层,返回给浏览器,那样用户可以看到结果。
struts就是实现了这样一个mvc
浏览器发送给Servlet接收到参数,分析uri,(截获到uri与struts-config.xml文件匹配转到相应的model控制)转到相应的actionServlet,调用model处理,返回给controller,转到jsp
返回给浏览器生成动态页面给浏览器显示
浏览器发一个请求到web容器,web容器会创建两个对象request,response,这两个对象包装了用户请求内容,容器回调两个对象把封装的内容传给你继续传递下去
actionServlet分析struts-config.xml
struts执行流程:
孙卫琴写的struts书比较不错
《深入浅出hibernate》书
servlet:
提交表单请求- http协议(封装了用户端的信息ip,数据等)- web容器生成request,response对象,所以我们可以通过request,response获取到用户信息及提交的表单内容
struts如何收集数据呢?
actionForm概:是收集数据的
ActionServlet会把表单数据拿到放到一个ActionForm类里,我们写一个UserActionFrom.java 继承ActionForm并且配置到struts-config.xml文件里,在Action里通过ActionFrom来获取
struts对象:
ActionServlet是struts特有的类,控制器
Action
ActionForm封装数据
ActionForward是一个对象,包装了要转发的jsp路径,Action要返回一个ActionForward,这样ActionServlet才能解析要转到哪个jsp。
ActionMapping
webwork,jsf比struts复杂,功能强大
通常开源项目,build文件ant脚本
stuts源码:
struts-1.2.9-src\struts-1.2.9-src\src\share\org\apache\struts\action\
ActionServlet.java
ActionForm.java
Action.java
ActionForward.java
ActionMapping.java
mvc是架构上的模式
任何一种语言都可以实现mvc,主要是思路上的体现
可以体现在大的方面,也可以体现在小的方面
在ie输入*.do,ActionServlet就会通过struts-config.xml找到对应的Action,Action调用Model
层,Action返回一个ActionForward对象给ActionServlet,转到jsp页面
1、建一个struts_login普通项目,把struts相应的包(struts-1.2.9-bin\lib\)加入web-inf下的lib 下
2、通过winzip把truts-1.2.9-bin\webapps\struts-blank.war(这是一个struts提供的一个空例子项目)解压,把里面的struts-config.xml拷贝到项目的web-inf下,把xml文件里的注释都去掉:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.2//EN"
"/struts/dtds/struts-config_1_2.dtd">
<struts-config>
</struts-config>
接着拷贝里面的web.xml文件中的配置ActionServlet,放到项目的web.xml里:
<!-- Standard Action Servlet Configuration (with debugging) -->
<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>//配置第三方包读取xml的级别,不要也可以
<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、创建一个几个:login.jsp页面
4、建一个LoginActionForm(封装客户提交的数据),注意里面的属性要跟表单中的各个表
单name要相同,不然获取不到数据;
创建LoginAction.java(对model操作的类)
5、如何让struts知道我们要怎么做呢?配置struts-config.xml
<form-beans>
<form-bean name=”loginActionForm” type=”com.bjsxt.struts.LoginActionForm”/>
</form-beans>
//为什么叫type而不是class呢?struts就是那么定义的
(ctrl+shif+< 出提示)
<action-mappings>
path=”/login”//配置uri,struts根据uri进行匹配,类似于servlet配置的url-pattern <action
type=”com.bjsxt.struts.LoginAction”//配置Action
name=”loginActionForm”//根据上面配置的ActionForm
scope=”request”//配置请求范围,默认是session
>
path=”/login_success.jsp”/>//请求成功后转到的页面
name=”success”
<forward
<forward name=”error” path=”/login_error.jsp”/>//请求失败后转到的页面</action>
</action-mappings>
要配置:
ActionServlet,在web.xml配置
Struts-config.xml,配置每个请求的Action,ActionForm,请求的资源路径
为什么叫.do?
因为在web.xml配置了*.do
用户提交用户密码后,login.jsp post login.do ActionServlet 找到<action-mappings>的path 有没有/login,先找ActionFrom name=”loginActionForm”(可以不配置,如果配置就传递数据过来),然后通过Action找到type="com.bjsxt.struts.LoginAction",处理完成后返回给ActionServlet解析forward
struts在启动时候就把struts-config.xml里的相应配置都加载了,把他们放到map里面,key 就是Action的name,value就是Action
存< action-mapping>是采用map方式map的值是path,value是ActionForm对象
通过map的getMap()得到相应的mapping
每个<action>对应一个actionmapping
每个<action>可以有多个<forward>,有个成员map存储他们:
存<forward>又是采用map方式:key值是forwardName ,value值是actionForward值
UI layer :struts属于UI Layer
model layer: spring hibernate
为什么要分层?主要是为了复用,便于维护
Model 1:传统的方式,jsp+javaBean,jsp承担太重
Model 2:适合做大型项目,开发周期比较长,MVC(如果指的是j2ee开发:model业务逻辑层,c是servlet(获取v层数据调用Model方法,负责转向jsp),v是jsp)
browser请求,controller接收数据调用Model方法
strutes就是首先model2
browse输入*.do,ActionServlet查询struts=config.xml的path,找到相应的action之后,封装ActionForm并分派到Action,Action调用Model方法之后,返回一个ActionForward对象给ActionServlet,分析forward并跳转到jsp页面,并返回到客户端
提交到struts的中央控制器ActionServlet,因为我们在web.xml里配置了ActionServle,Struts-config.xml,servlet截取部分URI与配置文件的path对比找到相应的action标签,找到actionForm,action完成相应的处理
struts-config.xml是通过struts.jar下的org/apache/struts/resources/struts-config_1_2.dtd来控制格式的
通过哪个类读取struts-config.xml?
在tomcat启动的时候,ActionServlet的init方法就加载了Struts-config.xml了,是通过org.apache.struts.config.impl.ModuleConfigImpl
实现接口
org.apache.struts.config.ModuleConfig
来加载Struts-config.xml的.
fidFormBean()
ModuleConfigImpl来实现的
ActionServlet初始化的时候做了很多事情(在web.xml里配置了启动的时候就初始化),其中有一个是读了Struts-config.xml文件,把里面的每个标签都读到对象里了,一个<action>标签对应一个实例(ActionMapping)对象,所以可以有多个<action>,每个<action>里有多个属性,把每个<action>放到Map里
Map map = new HashMap();
map.put(“/login”,new ActionMapping());
map.put(“/itemAction”,new ActionMapping());
<action>是通过path来标识,所以path的值是唯一的不能重复,
ActionConfig findActionConfig(String path)读的Map
ActionMapping继承了ActionConfig
返回一个父类
ActionConfig 里有forward
一个<action>对应多个<forward>,用Map来表示
ActionConfig.class ActionMapping
key 是 name
value 是
public class ActionMapping {
name;
String
private
path;
private
String
….
protected HashMap forwards = new HashMap();
forwards.put(“success”, new ActionForward());
forwards.put(“error”, new ActionForward());
//提供了一个查找方法
public ActionForward findForward (String name) {
(ActionForward)foreards.get(name);
return
}
}
ForwardConfig.class
有很多属性,其中有name,path,redirect重定向
多个<action>又放到一个Map里了。
<form-bean>标签
key是name
value是ActionForm
多个<form-bean>放到Map里
通过get(key)找到具体<form-bean>
ActionServlet接收请求
一个action对应一个actionMapping,截取URL,返回一个actionMapping对象,看path属性里有没对应的请求路径,如果有找name对应的actionform对应的key,封装actionform,同时把request,response分派到action,action接收到后处理相应请求后返回一个actionForward对象给ActionServlet,ActionServlet通过ActionForward.getforward(name)读到跳转的路径,转发到相应的jsp页面,返回给浏览器。
ActionServlet.java
doPost process
RequestProcessor
processMultipart(request);//这个是上传实现
Stirng path = //截取path
ActionMapping mapping = processMapping()//截取path
通过ModelConfig接口来访问,查询Mapping
ActionMapping mapping = (ActionMapping)moduleConfig.findActionConfig(String path)//查actionMapping
怎么处理ActionForm?
ActionForm form = processActionForm();
创建createActionForm
String name = mapping.getName();//拿到配置ActionForm的name
moduleConfig.findformBeanConfig(name)//get ActionForm的配置信息,
还没实例化
lookupActionForm查之前所配置的scope的范围内(request,session)有没有ActionFrom,如果有返回一个ActionFrom instance(ActionForm实例),如果没有就createActionForm创建一个ActionFrom(通过反射创建的),创建完成后,放到相应的scope范围内
request.setAttribute();
request.setAttribute(“loginActionForm”);
或者session.setAttribute(“loginActionForm”);
ActionForm怎样收集数据?RequestUtils.class
先判断actionMaping里的name是否配置,如果配置了
form.reset();//重置ActionForm
我们在写loginActionForm继承ActionForm的时候可以重写reset方法重置,目地是清理一下,清理成默认值,比如用户密码都初始化成admin
populate方法具体收集页面数据
name = request.getParameterNames()//取得页面上的所有的name
parameterValue = request.getParameterValues(name);//取得页面上的所有控件的值
Map properties.put(parameterValue);//把值都放到Map里
BeanUtils.populate(bean.properites)//通过第三方BeanUtils包,循环map,一个一个放到对象里
request.getAttribute(“loginActionForm”);
session.getAttribute(“loginActionForm”);
createActionForm;//
actionForm.reset();//清理初始化
Object obj = request.getParameterValues(“username”)
map.put(“username”, obj);
Object obj = request.getParameterValues(“password”)
map.put(“password”, obj);
创建ActionForm完成后,要检查,通过重写validate检查传过来的数据是否合法。
RequestProcessor.class
最后调用ActionForward。
ie 点击登录发送请求 login.do actionServlet 找到actionMapping实例,到Map里找到actionMaping 到name里取到相应的ActionForm,判断scope范围内是否有改ActionForm实例,如果有返回一个实例,没有就新创建一个实例并且放到scope范围内,开始收集数据,在收集之前,reset清理一下,先获取所有的name值,再取得value值,放到map里,遍历map值放到ActionForm里,调用validate方法判断值是否合法,如果在<action validate=”true”>会调用我们复写ActionForm的validate方法检查数据,然后调用action的execute方法执行,返回一个ActionForward,
struts流程.pag有点不对的地方
创建或复用ActionForm实例应该在actionForm.reset()之后
ActionForm的值可以在jsp页面得到,因为在scope设置了request,在jsp页面得导入ActionForm
Konfiguration 支持第三方插件 validator(validator)这个插件能动态验证,配置在struts-config.xml
<plug-in >标签
validation.xml
通过正则表达式验证页面的输入
validator-rules.xml
Action, ActionForm不完全属于模型层,有部分关系验证分为:
表单上的验证
数据库里的验证
UserNotFoundException extends RuntimeException PasswordErrorException extends RuntimeException
UserManager类{
单例模式实现
public void validate(String userName, String password) {
{
if(!”admin”.equals(userName))
throw new UserNotFoundException(“username错误”);
}
if(!”admin”.equals(password)) {
throw new PasswordErrorException(“password错误”);
}
}
}
在LoginAction.java
try {
password); UserManager.getInstance().validate(userName,
mapping.findForward(“success”);
return
} catch(UserNotFoundException unfe) {
request.setAttribute(“errorinof”,userName + “不能找到”);
} catch(PasswordErrorException pee) {
“错误”);
+
request.setAttribute(“errorinof”,password
}
return mapping.findForward(“error”);
使用Taglib是为了重用。
尽量少使用jsp脚本
<logic:empty>集合是否为空
empty(是否为空), notEmpty(是否不为空), present(是否存在)和notPresent(是否不存
在)
taglib帮助文档:struts-1.2.9-bin\webapps \struts-documentation.war解压出来
index.html → Documentation → User and Developer Guides →
Bean Tags → Bean Taglib API Reference
logic Tags → Bean Taglib API Reference
由于struts的tag跟自身的耦合度特别紧密,要把他的国际化配上,所以用的不广泛。
jstl(是sun的标准)
jsp2.0重要标志是加入了taglib
建一个项目:struts_taglib
把struts的包,文件拷贝到项目里,配置web.xml(ActionServlet)
配置国际化:
从struts空项目里的struts-config.xml拷贝:<message-resources parameter=”MessageResources”>放到struts-conifig.xml最后面
拷贝struts-1.2.9-bin\webapps\struts-blank\WEB-INF\src\java下的MessageResources.properties 文件放到项目的src下
新建一个测试标签类
com.bjsxt.structs
BeanWriteTestAction
Action
extends
World”);
request.setAttribute(“hello”,”Hello
color=’red’>北京欢迎您!</font>”);
request.setAttribute(“bj”,”<font
//日期
request.setAttribute(“today”,new Date());
//数字
request.setAttribute(“n”,12345657.99);
//新建后面的两个类后,做如下操作:
//结构
new
=
Group();
Group
group
group.setName("IBM");
User user = new User();
user.setUserName("张三");
user.setAge(22);
user.setRelatedGroup(group);
request.setAttribute("user",
user);
实现tag方式两种:
1、一种可以在web-inf下建立tld文件并在web.xml里配置
2、在jsp页面引入
<% taglib prefix=”bean” uri=”/tags-bean”%>
(参考struts.jar/META-INF/tlds/struts-bean.tld)
jsp写法:
标签写法:
hello标签<bean:write name=”hello”/>
bj(default)标签:<bean:write name=”bj”/>
bj(filter=true 缺省值是true)标签:<bean:write name=”bj”/>原样输出
bj(filter=false)标签:<bean:write name=”bj” filter=”false”/>输出是红色
filter对html进行过虑,默认是true表示原样输出,设置为false表示按照html效果输出
日期标签:<bean:write name=”today” format=”yyyy-MM-dd HH:mm:ss” />
format对日期格式化
数字标签:<bean:write name=”n” format=”###,###.##” />//这种方式位数不够不补0
<bean:write name=”n” format=”###,###.00” />//这种方式位数不够补0
format对数字格式化
结构输出
property可以取指定名称的属性的值
姓名:<bean:write name=”user” property=”userName”>
年龄:<bean:write name=”user” property=”age”>
所属组:<bean:write name=”user” property=””>
新建两个类:
Group.java
private String name;
User.java
String
userName;
private
age;
int
private
relatedGruop;//关联的关系
private
Group
empty(是否为空), notEmpty(是否不为空), present(是否存在)和notPresent(是否不存在)测试:
com.bjsxt.struts
EmptyPresentTestAction.java
request.setAttribute(“attr2”,null);结果一样
request.setAttribute(“attr2”,);//
request.setAttribute("attr3", new ArrayList());
return
mapping.findForward(“success”);
配置struts-config.xml
emptypresent.jsp
<@ taglib prefix=”logic” uri=”/tags-logic”> //在struts包里的struts.jar/META-INF/tlds/struts-logic.tld
标签写法:
<logic:empty name=”attr1”>
attr1为空<br>
</logic:empty>
<logic:notEmpty name=”attr1”>
attr1不为空<br>
</logic:empty>
<logic:present name=”attr1”>
attr1存在<br>
</logic:empty>
<logic:notPresent name=”attr1”>
attr1不存在<br>
</logic:empty>
<logic:empty name=”attr2”>
attr2为空<br>
</logic:empty>
<logic:notEmpty name=”attr2”>
attr2不为空<br>
</logic:empty>
<logic:present name=”attr2”>
attr2存在<br>
</logic:empty>
<logic:notPresent name=”attr2”>
attr2不存在<br>
</logic:empty>
输出:
attr1为空
attr1不存在
attr2为空
attr2存在
测试标签跌代:
IterateTestAction extends Action
复写execute方法
List userList = new ArrayList();
Group relatedGroup = new Group();
relatedGroup.setName(“尚学堂”);
for(int i=0; i<5; i++) {
User user = new User();
i);
user.setUserName(“user_”+
i);
user.setAge(22
+
user.setRelatedGroup(relatedGroup);
uerList.add(user);
}
request.setAttribute(“userList”,userList);
mapping.findForward(“success”);
return
配置struts-config.xml
iterate.jsp
//-----------传统方式输出-----------
List userList = (List)request.getAttribute(“userList”);
if(userList == null || userList.size() ==0) {
out.println(“没有符合条件的数据”);
} else {
for(Iterator iter = userList.iterator(); iter.hasNext();) {
User user = (User)iter.next();
out.println(user.getUserName());
out.println(user.getAge());
out.println(user.getRelatedGroup());
}
}
//---------标签输出方式----------
引入标签:bean标签,logic标签
name=”userList”>//判断是否为空
<logic:empty
//没有符合数据
out.pirntln(“没有数据”);
</logic:empty>
<logic:notEmpty
name=”userList”>//判断是否为空
//有符合数据
id=”user”
name=”userList”>//id指的是对象的引用,变量名称 <logic:iterate
name=”user”
property=”userName”>
<bean:write
property=”age”>
<bean:write
name=”user”
<bean:write
property=””>
name=”user”
</logic:iterate>
</logic:empty>
struts实现mvc流程:
model1:jsp+javabean,jsp承担角色太重,适合小项目
model2:分层实现,有利于复用,减少耦合
struts核心的ActionServlet,实现转发
粗分析:浏览器发送请求,ActionServlet收到请求,根据struts-config.xml找到相应的Action,并找到相应的ActionForm,封装数据传到Action,Action调用model层完成操作,返回一个ActionForward给ActionServlet,转到jsp页面,返回客户端
细分析:看struts-config.xml里的action-mapping配置,看web.xml配置ActionServlet
ie发送请求,ActionServlet接收,得到ActionMapping,先到scop的范围里找ActionForm 有没有,有就传给Action,如果没有就创建一个,reset一下,根据action配置里看有没viledate,检查数据合法性,收集数据给ActionForm,Action调用model层完成相应操作,返回一个ActionForward给ActionServlet,ActionServlet分析返回对象,转到jsp,返回给客户端。
JSTL:(sun的标准,在jsp1.2已经提出来了,真正是在jsp2.0使用比较广泛)
jstl.jar sun定义的接口(规范)
standar apache对jstl的实现
注意:jstl和struts没有任何关系
新建一个项目struts_jstl:(配置jstl环境)
1、把jstl.jar,standard.jar拷贝到项目的lib下,如果只使用EL表达式,不用引用这两个包
2、配置struts包
el有隐式对象:
EL标识式隐式对象,pageScope,requestScope,sessionScope,applicationScope,如果未指定scope,它的搜索顺序是page,request,session,application
自定义函数库:
MyFunctions
1、定义类和方法(方法必须是静态的public的)
2、编写的自定义的tld文件,并且将自定义的tld文件拷贝到WEB-INF,或其子目录下
3、在jsp中通过taglib指令,引入自定义函数库
4、直接调用即可
package com.bjsxt.struts;
/**
*自定义函数库
*@author Administrator
*
*/
public class MyFunctions {
/**
*方法必须是静态的public的
*@param name
*@return
*/
public static String sayHello(String name) { return"Hello " + name;
}
}
myfunctions.tld
struts的控制器ActionServlet
在struts-config.xml配置文件里的每个action对应一个actionMapping实例,而每个action可以对应多个forward;
在web.xml里配置了ActionServlet访问的*.do方式,用户端发起请求,web容器根据接收到请求,生成request,response对象传递给ActionServlet控制器,控制器截取到的URL与对应的actionMapping对象的path(根据struts-config.xml生成的actionMapping对象查找每个action对应的actionMapping对象),然后根据scope的范围查找对应的ActionForm对象,如果没有就新创建一个,如果没有就直接调用内存中的ActionForm对象,在封装对象之前还要利用validate对数据进行判断是否合法,如果合法就把传过来的数据进行封装并分派(dispatch)给对应的Action对象,Action把接收到的ActionForm传递给model并进行相应处理,处理完成后生成一个ActionForward对象传递回给控制器…。
在struts中,为了不太依赖与stuts的ActionForm,需要另外建一个实体类与ActionForm对应,把ActionForm数据设置给实体类,在设置过程中可以对每个属性进行赋值,但是这样写比较费时,在实际项目开发中一般利用BeanUtils.copyProperties(目标对象,源对象)进行对象拷贝比较方便,如下:
AddUserAction.java
//获取从页面表单中提交过来的值
UserActionForm uaf = (UserActionForm)form;
//减少与struts依赖,创建User实体对象,并将ActionForm中的内容设置到User对象中// User user = new User();
// user.setUserId(uaf.getUserId());
// user.setUserName(uaf.getUserName());
// user.setPassword(uaf.getPassword());
// user.setEmail(uaf.getEmail());
// user.setContactTel(uaf.getContactTel());
Date());
// user.setCreateDate(new
User user = new User();
//BeanUtils.copyProperties(目标对象,源对象)
uaf);
BeanUtils.copyProperties(user,
Date());
user.setCreateDate(new
相同实体类拷贝:(UserActionForm对象拷贝到User对象里)
BeanUtils.copyProperties(目标对象,源对象)
如果没有的属性需要另外写上:
user.setCreateDate(new Date());//目标对象,源对象里都没有需要自己写
jsp里的写的basePath(基础路径)
对html可以起作用,所有的路径都是基于他
但是javascript不起作用,得加上
<%@ page language="java" import="java.util.*" pageEncoding="GB18030"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
如果action配置了actionForm,查找scope有没有,如果有直接返回一个对象,然后收集页
面的数据,通过遍历把name,value放到map里,调用beanUtil复制,ActionForm可以用
validate对值进行验证(配置action的属性validate为true才会调用validate),如果要初始化
必须实现reset方法。
动态actionForm:就是不用写相应的ActionForm继承ActionForm,自动生成的,只要在配置文件里设置一下就可以了,避免ActionForm膨胀而涉及的,使用ActionForm可以获得静态ActionForm的所有功能:
新建一个struts_actionform项目
配置:
//这个配置相当于写了一个ActionForm类
<form-bean name=” dynaActionForm” type=” org.apache.struts.action. DynaActionForm”>
type=”ng.String”/>//这个跟页面的属性一致,相当于name=”name”
<form-property
以前写的ActionForm的属性
<form-property name=” age” type=”ng.Integer”/>
</ form-bean >
struts.jar → org.apache.struts.action → DynaActionForm就是实现了动态actionForm DynaActionForm extends ActionForm
写一个Action类:
DynaUserActionFormTestAction extends Action
DynaActionForm daf = (DynaActionForm)form;//强制转换成动态的,因为ActionForm form也是继承了DynaActionForm
String name= (String)daf.get(“name”);// DynaActionForm里有个get方法,其实是把页面收集的值放到map中,然后咱们调用他的get方法取相应的值。
String name= (String)daf.get(“age”);
跳转页面:dyna_user_actionform_success.jsp
<h1>测试动态ActionForm</h1>
<hr>
<!--在struts-config.xml里配置action,没有设置attribute="dynaForm"
姓名:${ }<br>
年龄:${dynaUserActionForm.map.age }<br>
-->
<!--在struts-config.xml里配置action,设置attribute="dynaForm" -->
姓名:${}<br>
年龄:${dynaForm.map.age}<br>
姓名:${}// dynaUserActionForm是在scope范围内传递过来的,map是DynaUserActionForm里面有个getMap()方法返回页面属性值的map集合,(javabean取属性是根据读取器的get后面的名称来取的),name是集合里的属性
action里配置的attribute="dynaform",forward跳转的页面里取值方式就是attribute方式,写成跟attribute设置的名称一样(如下的dynaform)而不是原来的名称(dynaUserActionForm)path="/dynaactionformtest"
<action
type="com.bjsxt.struts.DynaUserActionFormTestAction"
name="dynaUserActionForm"
scope="request"
attribute="dynaform"
>
path="/dyna_user_actionform_success.jsp"/>
name="success"
<forward
</action>
采用struts进行文件上传:
commons-beanutils.jar
commons-fileupload.jar
实际上是struts对commons fileupload封装
页面的<form>需要配置
enctype=multipart/form-data
method=post
<form action= method=post enctype=multipart/form-data>
name=title>
type=text
<input
<input type=file name=myfile>//struts对file进行特殊处理,必须使用FormFile实例对象如:FormFile myfile;
<input type=submit value=上传>
</form>
建立一个UploadActionForm extends ActionForm
String
title;
private
private FormFile myfile;// struts对file进行特殊处理,必须使用FormFile实例对象
建一个UploadAction extends Action
UploadActionForm uaf = (UploadActionForm)form;
uaf.getTitle();
String
=
FormFile myfile = uaf.getMyfile();//在FormFile.class里提供了很多方法,其中有取得文件名的方法:
if(myfile != null) {//因为返回是一个对象,所以可以判断是否为空
//myfile.getFileName();//取得文件名
//将文件流保存到磁盘
//拿到输出流
FileOutputStream fos = new FileOutputStream(“c:/”+myfile.getFileName());
//写出
fos.write(myfile.getFileData());
//输出到磁盘
fos.flush();
fos.close();
}
建一个upload_success.jsp
标题:${uploadActionForm.title}
文件:${uploadActionForm.myfile.fileName}//myfile是FormFile.class的FormFile引用,就是他的对象,里面有个getFileName的方法
配置action,form-bean
<form-bean name=”uploadActionform” type=”com.bjsxt.struts.UploadActionForm”/>
<action path=”/upload” type=”com.bjsxt.struts.UploadAction” name=” uploadActionform” scope=”rquest”>
<forward name=”success” path=”/upload_success.jsp”/>
</action>
<li>测试空字段</li><br>
<form action="" method="post">
姓名:<input type="text" name="name"><br>
<input type="submit" value="保存"><br> </form>
建一个BlankfieldActionForm extends ActionForm
private
name;
String
password;
private
String
private
int
age;
建一个BlankfieldAction extends Action
mapping.findForward(“success”);
return
配置action,actionForm
<form-bean name=”blankfieldAction” type=””/>
<action >
建一个blankfield_success.jsp
jsp脚本输出:
<%@page import=”com.bjsxt.struts.*”%>
<%
BlankfieldActionForm form = (BlankfieldActionForm)request.getAttribute (“blankfieldActionForm”); %>
姓名:<%=form.getName()%>//在页面表单里有,但是没有输入内容,则输出是空串“”;
密码:<%=form.getPassword()%>//在页面表单里没有,如果没给值,jsp脚本输出是null,因为password是ActionForm的成员变量,默认是null,age是int成员变量是默认值是
0,所以输出是0;
年龄:<%=form.getAge()%>//在页面表单里没有,如果没给值,jsp脚本输出是0,因为age 是ActionForm的成员变量,int成员变量是默认值是0,所以输出是0;
EL表达式:
姓名:${ }输出空串””
姓名:${ }输出空串””
姓名:${blankfieldActionForm.age }输出0
转换器:对表单提交数据自动转换
ActionServlet.class里有很多转换器
initOther();
布尔转换:BooleanConverter 实现了Converter接口
看你写的ActionForm定义的属性是什么,如果是布尔类型他就到map(map里有各种类型
转换器)里找布尔转换器
map的key对应转换器类,value对应转换器
转换器需要注册ConvertUtils.register,是放到map里,BooleanConverter里实现转换
转换器的实现源码在:
D:\share\09_Struts\beanutils-1.5-src\commons-beanutils-1.5-src\beanutils\src\java
对java.util.Date类型不能自动转换,需要自己转换才行:
要自己写一个转换器:UtilDateConverter.class
或者改成String类型来实现
对java.sql.Date可以自动转换,但是输入的格式必须为yyyy-mm-dd如:2007-10-18。
提交页面内容:
<li>测试ActionForm类型的自动转换</li><br>
<form action="">
intvalue=<input type="text" name="intValue"><br>
doublevalue=<input type="text" name="doubleValue"><br>
booleanvalue=<input type="text" name="booleanValue"><br>
<input type="submit" value="测试"><br>
</form>
TypeConvertActionForm extends ActionForm
intValue;
private
int
doubleValue;
double
private
booleanValue;
private
boolean
TypeConvertAction extends Action
mapping.findForward(“success”);
return
配置action,ActionFrom
<form-bean name=”typeConvertActionForm” type=” com.bjsxt.struts.TypeConvertActionForm”/>
<action path=”/typeconvert”
type=”com.bjsxt.struts.TypeConvertAction”
name=”typeConvertAction”
scope=”request”
>
<forward name=”success” path=”/ typeConvert_success.jsp”/>
</action>
typeConvert_success.jsp
<h1>测试ActionForm类型的自动转换</h1>
<hr>
}<br>
intValue=${typeConvertActionForm.intValue
}<br>
doubleValue=${typeConvertActionForm.doubleValue
}<br>
booleanValue=${typeConvertActionForm.booleanValue
private static FastHashMap converters = new FastHashMap();
自定义ActionForm的转换器步骤:
1、定义一个类,实现Converter接口,实现convert方法
UtilDateConverter implements Converter:
convert(Class type, Object value) {
object
public
if(value == null) {
value;
return
}
//如果是java.util.Date就返回
if(value instanceof Date) {
value;
return
}
if(value instanceof String) {
SimpleDateFormat format = new SimpleDateFormat(“yyyy-MM-dd”);
{
try
format.parse((String)value)
return
} catch(ParseException e) {
e.printStackTrace();
}
}
}
2、用servlet实现注册:实现converter注册,通常采用servlet注册UtilConverterInitServlet extends HttpServlet
覆盖init方法
ConvertUtils.register(new UtilDateConverter(),Date.class);
在web.xml配置该servlet:
<servlet>
<servlet-name>UtilConverterInitServlet</servlet-name>
<servlet-class>com.bjsxt.struts.UtilConverterInitServlet</servlet-class>
<load-on-startup>3</load-on-startup>
</servlet>
(servlet可以不配置mapping,因为我们不需要路径来执行他,而是要tomcat启动的时候初始化他)。