Struts1总结
1、struts1 in Action
(1)到struts1官网上下载struts-1.3.10-all.zip。解压缩得到:
src目录:
apps目录:
lib目录:
docs目录:
具体设置参考:blank.war中的应用。
(2)Action
需要继承Action接口。
action的execute()方法会被struts1的入口程序ActionServlet调用。其中mapping参数代表struts-config.xml配置。ActionServlet从struts-config.xml文件读取配置信息,将其存放到ActionMapping对象中。
<action/>的input属性指定的页面,通过mapping.getInputForward()获取到。
Action访问封装在MessageResources中的本地化文本:
在Action中,定义了getResources(request)方法,返回当前默认的MessageResources对象,它封装了ResourceBundle中的文本内容。Action可通过此MessageResources对象访问文本内容。MessageResources对象存储在ServletContext中,MessageResources对象的getMessage()方法返回参数key对应的消息文本。
Java的ResourceBundle和Struts1的MessageResource类都允许使用静态和动态的文本。
对于动态消息文本,运行时,MessageFormat类的format()方法可把参数{0}替换为真正的动态文本内容。
(3)struts-config.xml
可修改web.xml中ActionServlet的初始化参数config的值来修改struts-config.xml文件的位置。
struts-config.xml中可配置数据源、全局异常处理、全局jsp页面、formbean、action以及国际化资源文件名称、插件(如配置数据校验插件)、第三方控制器等。
<controller/>配置第三方控制器,如配置spring,则所有的action由spring来管理。
<global-forwards/>配置全局jsp页面。
(4)多个struts-config.xml文件
struts1支持模块化开发,各个模块相互独立,配置在自己的struts配置文件里。系统集成时将这些struts配置文件配置在一起,中间用逗号隔开(即修改ActionServlet的初始化参数config的值)。
(5)struts可以配置命名空间(很少用,略)
(6)FormBean(连接视图和Action)
FormBean必须要继承ActionForm类。
在action中往FormBean里设置数据,struts标签会显示设置的数据。
FormBean能进行数据类型转换。struts在进行类型转换时,调用相关类型的valueOf()方法。若变量为int、double、float等变量,若格式不对,会当做0。若变量为Date、Time等复杂类型时,若格式不对,则会抛出异常。
FormBean的reset方法用于数据初始化(先reset,然后才赋值)。直接访问jsp时,会调用reset方法。
FormBean的validate方法用于提交数据时对数据进行校验。
ActionErrors类似一个HashMap,若有校验错误,则往ActionErrors里添加一条ActionMessage记录。若validate方法返回的ActionErrors为null或里面没有任何的ActionMessage记录,则认为通过了校验,并把FormBean提交给action运行。否则不会提交给action,也不会执行action的execute方法,而是直接返回输入页面,显示校验失败信息。ActionErrors里的信息由struts的<html:errors/>标签显示。<html:errors>标签处理类获得ActionErrors对象,从application.properties文件中读取相应的文本你,然后将文本信息显示在网页上。
从struts1.2与struts1.3开始,FormBean中可以使用POJO,提交数据后直接把数据赋给POJO对象。
a、在FormBean中需要自己new POJO对象。且要有setter、getter方法。
b、页面中name属性为user.name。
提交表单后会把输入框中的值设置到FormBean中的POJO对象,action直接引用该POJO对象即可。
注:此时在页面中可以使用<bean:write name="userform" property="user.name"/>输出结果。
FormBean中使用Map<String, Object> map接收参数。
a、在FormBean中自己new HashMap<String, Object>。map要有setter、getter方法,且要有
pubic void setValue(String key, Object value) {
map.put(key, value);
}
和public Object getValue(String key) {
return map.get(key);
}
b、页面中name属性为value(name)。
提交表单后,会把输入框中的值设置到FormBean中的Map对象,其中name为key,输入的值为value。action可以通过getValue()方法直接得到该Map对象中的值。
注:此时在页面中可以使用<html:text property="value(name)"/>取得数据。
FormBean的两种存在范围:request、session。默认是session。
输入的表单数据组装到FormBean中——>若<action>的validate属性为true,则调用FormBean的validate()方法。——>验证错误,请求转发给<action>的input属性指定的web组件,FormBean仍然存在;若验证正确,调用action的execute()方法,将FormBean实例传递给execute()方法。此后请求转发给其他web组件(如jsp),FormBean仍然存在。
(7)struts1标签(包括bean、html、logic三大标签库)
在struts1.2之前,使用标签库需要:
a、修改web.xml文件,添加<taglib>元素。
b、修改jsp文件。引入:<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>,此uri与web.xml中配置的<taglib-uri>要一致。
在struts1.3,可以不用修改web.xml文件,但需要修改jsp文件,其中的uri与tld文件中的uri要一致!
<bean:wirte>:用于输出JavaBean的属性值,并在网页中显示;
<bean:message>:用于输出本地化的文本内容。key属性指定消息key,与消息key匹配的文本内容来自于Resource Bundle。每个Resource Bundle都对应一个或多个本地化的消息资源文件,如application.properties。struts-config.xml文件通过<message-resources>元素定义一个Resource Bundle。如:<message-resources parameter="hello.application"/>,表示消息资源文件名为application.properties文件,存放路径为WEB-INF/classes/hello/application.properties。
<html:errors>:把request范围内的ActionErrors对象中包含的错误信息显示出来。
<logic:iterate id="" name="">:遍历name所表示的集合中的所有元素,检索到赋值给id所表示的变量,存在page范围内。 其中的indexId属性:定义一个变量,表示当前被遍历元素的序号。
struts1标签默认在session范围内查找FormBean,若存在这样的实例,就把FormBean中的属性赋值给HTML表单的文本框。
2、整合struts1和spring
Action的生命周期由sping进行管理。
(1)先复制spring需要的jar包,然后复制struts1需要的jar包。其中spring-webmvc-struts.jar是必须的。
(2)编写spring的配置文件applicationContext.xml。加入相应action的<bean />。
如:<bean name="/login" class="com.tao.usermgr.actions.LoginAction" scope="prototype">
<property name="userManager" ref="userManager"/>
</bean>
必须使用name属性,而不是id属性。name属性值必须和struts-config.xml文件中<action>标签 的path属性值一致;
建议将scope设置为prototype,这样就避免了struts Action的线程安全问题
spring会截获/login.do请求,将userManager通过setter方法注入给action,并调用action的execute()方法。
(3)在web.xml中引用spring配置文件。
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value> /WEB-INF/classes/applicationContext.xml </param-value>
</context-param>
<servlet>
<servlet-name>context</servlet-name>
<servlet-class> org.springframework.web.context.ContextLoaderServlet </servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
若Tomcat的版本较高,支持Listener。可以不使用servlet,而使用:
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
还有一种方法,可以在struts-config.xml文件中使用插件的方法加载spring,如:
<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">
<set-property property="contextConfigLocation" value="/WEB-INF/classes/applicationContext.xml" />
</plug-in>
(4)在struts-config.xml文件中配置
<controller processorClass="org.springframework.web.struts.DelegatingRequestProcessor"> </controller>,表示将action委托给spring管理。此时在每次配置action时,可以不用写type属性。
还有一种方法,即每次配置action时,<action>标签中的type属性需要修改为org.springframework.web.struts.DelegatingActionProxy。
DelegatingActionProxy是一个Action,主要作用是取得BeanFactory,然后根据<action>中的path属性值到IoC容器中取得本次请求对应的Action。
3、PS
(1)对于简单的没有业务逻辑的action,只显示一个jsp就够了。此时可以配置下,像访问action一样使用*.do的形式访问jsp页面。
如:<action path="/login" forward="/form/login.jsp"></action>
将Jsp配置为action可屏蔽jsp的真实位置,防止用户猜测破坏网站程序。出于安全考虑,可把jsp放到WEB-INF文件夹下,这样jsp文件只能通过.do或被action调用的形式访问。
(2)Person和PersonForm
Person中使用Date、Timestamp、List等类型,PersonForm中则使用String、String[]类型代替。Struts转换Date、List等类型不方便。能对数组属性进行类型转换,如转换成int[]、double[]等。
struts能通过request.getParameterValues(name)获取到String[]数组数据。
(3)struts1的action与servlet一样,线程不安全。由于action是线程不安全的,因此要避免写action的属性,最好的方法是把action的属性设为final,禁止对其进行写操作,彻底避免线程不安全的问题。
FormBean是线程安全的,每次请求都会产生一个新的FormBean。
struts1里的action的单一特性节省了服务器资源开支,但带来了的线程安全的问题。在struts2中,action被设计成为线程安全的了,每个请求都会产生一个新的action实例,请求处理完毕,action实例就销毁。
(4)struts1推荐在JSP中使用标签,可以使用任何的标签库,如JSTL标签库。struts1提供一套标签库。struts1标签库的特点是与struts1的action、FormBean等紧密结合在一起。
<bean:write>能输出request、page、session、application中能访问到的变量。有一个filter属性,默认是true,会对输出内容进行html转义。
<bean:write>与EL表达式不同的是,若变量不存在或访问不到,会抛出异常。
tiles标签库:
在处理网页布局以及布局的可重用性、可维护性上做的很好,能将页面或者部分页面组件化。tiles也可以独立于struts单独使用,单独使用时要配置tiles类库以及tld文件。
在Jsp层,struts1标签库能自动显示FormBean的数据。
(5)DispatchAction(是struts内置的分发器,通过反射来调用不同的方法,分发参数需要配置在struts-config.xml中)
因为一个action中会有很多不同的操作。这样,就不用在一个action中利用if...else...语句来判断业务类型,并执行不同的操作;
struts-config.xml中<action>元素中有一个parameter属性,用来设置使用哪个参数作为分发器的参数。
a、继承DispatchAction类;
b、指定由哪个参数进行分发;
c、action中execute()方法要执行super.execute();或者不写execute()方法。
此时方法名即为参数名,如dispatch.do?action=list会执行list()方法。
(6)文件上传
上传文件时form表单要指定enctype为multipart/form-data,method一定要设置为post。struts1.x的<html:form/>标签默认method为post。
strust1提供了<html:file>标签,集成了Apache的commons-upload工具包。
struts1把上传文件封装为FormFile对象,直接获取该对象,将文件数据保存即可。FormFile不是普通的文件,不能直接保存。FormFile提供getInputStream()接口获得它的输入流,将它的内容保存到指定文件中即可。还提供getFileName()等方法。(在formbean中定义FormFile类型的属性)
(7)异常处理
struts1利用ExceptionHandler类处理异常。若struts捕捉到了异常,会交给ExceptionHandler或其子类处理(调用Handler类的execute()方法)。ExceptionHandler也叫异常捕捉器。
a、继承ExceptionHandler类,重写execute()方法;
b、在struts-config.xml中配置ExceptionHandler。
<global-exceptions/>用来配置异常捕捉器,可以配置多种类型的异常捕捉器。其中key为错误信息,配置在资源文件中。type为异常类型,handler为异常处理的类。配置多个异常捕捉器时,最好把子类的捕捉器配置在前面,父类的放在后面。
(8)struts-config.xml中使用通配符
从struts1.2版本struts-config.xml中允许使用通配符。使用通配符,多个action可以共用一个配置。
若两个action配置基本一致,可以把不同的部分用通配符提取出来,使用一个配置。
*表示配置通配符,{1}代表第一个通配符表示的内容。
(9)添加源代码
如:Location path:D:/struts-1.2.7-src/src/share
(10)在jsp页面中,/表示整个web站点的根路径,如:http://localhost:8080/。
(11)getClass().getClassLoader().getResource("").getFile();
(12)框架都在追求低耦合率。接口是用来降低代码耦合率的。
(13)编码:
new String(data.getBytes("ISO-8859-1"), "gb2312");
(14)Struts1对国际化的支持
struts1配置文件的<controller>元素的Locale属性为true时(默认),struts1框架把用户的Locale实例保存在session范围内。
struts1配置文件中的每个<message-resources>元素定义了一个ResourceBundle。
当应用中有多个ResourceBundle时,通过<message-resources>元素的key属性区别。
web容器中Locale对象的来源:
JVM启动时会查询OS,为运行环境设置默认的Locale。web容器在其本地环境中通常会使用此默认的Locale。web客户端也有request(Locale)。
<bean:message>标签根据存储在session中的Locale实例,从默认的ResourceBundle中检索和Locale对应的资源文件。
(15)styleId:也就是id属性。在页面中,id是唯一的。