struts2 基础

http://struts.apache.org/

一、struts2初体验 ppt2

****************************************************************

第一个程序HelloWorld(导包,导配置文件struts.xml web.xml)
从apps\struts2-blank工程下copy
最少jar包:
javassit(同hibernate)、struts2-core、xwork-core、
commons-io、commons-lang3、commons-fileupload、freemarker、ognl

struts2.5 取消了xwork-core,添加log4j-api-2.x
注意:过滤器路径发生了改变

注意web.xml中的url-mapping
/* or *.action(请求的url必须也得写.action)

最简单程序:(index.action这里的action可以省略,2.3.20新增安全认证,默认只能通过action访问jsp)
<action name="index">
<result>/myindex.jsp</result>
</action>
等价于(如果存在index.suffix将按tomcat默认访问index.suffix而不执行该action方法)
<action name="index" class="com.opensymphony.xwork2.ActionSupport" method="execute">
<result name="success" type="dispatcher">myindex.jsp</result>
</action>


执行过程分析:tomcat->web.xml->filter->struts.xml->namespace->action->method
->result->jsp|html
结论:通过Action将请求和响应分开

namespace:(能自动向子路径下寻找action)
namespace决定action访问路径,默认为空"",通常写/(""和/都可以接收所有路径的action)
如果写/xxx就是映射/xxx/*.action,前台要action=xxx/*.action 或 xxx/yyy/*.action
注意:
写/xxx时有路径问题,默认所有的链接默认都会加/xxx,在struts.xml中可以使用绝对路径,页面中的href还可以采用myeclipse生成的basePath解决
前台form的action加了xxx/就只能访问xxx/、""、/


有时候修改struts.xml都要重启tomcat,解决方法:
<constant name="struts.configuration.xml.reload" value="true" />
修改为开发模式能打印详细错误信息:
<constant name="struts.devMode" value="true" />
指定action的后缀,默认为action:
<constant name="struts.action.extension" value="do" />

加载struts源码:
E:\xxx\struts-2.x.x\src\core\src\main\java

重新关联源代码:
现在已经关联过,add source那个按钮不存在了。
1、可以删除原来的源代码,重新选择
2、可以右键工程Builde Path -- Libraries 在这里找到需要关联源代码的jar包。然后点开这个jar包前的+号找到Source attachment,右键选择edit来改变源代码的关联。

设置xml提示:XML catalog->添加dtd->URI|SystemID
E:\xxx\struts-2.x.x\src\core\src\main\resources\*.dtd

一、Action
使用自定义Action
1、直接写个普通类,里面写个方法execute()或者任意方法(配置method)
2、实现Action接口,实现execute()方法
3、继承ActionSupport(用这种),因为里面有很多实用的方法可以直接调用
4、给Action注入参数值(属性注入)
5、Action默认解决post请求乱码(utf-8)

注意:
struts2中的action每个用户请求都会产生一个对象(多例),请求完毕销毁,struts1是基于servlet

action中没有配置class默认就是ActionSupport类
result中name没有配置默认就是success
result中type没有配置默认就是dispatcher
struts.xml文件改名或修改路径必须配置
<init-param>
<param-name>config</param-name>
<param-value>struts-default.xml,mystruts.xml</param-value>
</init-param>

****************************************************************

二、ppt2

访问Web元素:
1、使用内置类型获取(解耦合)
request = (Map<String,Object>)ActionContext.getContext().get("request");
session = ActionContext.getContext().getSession();
application = ActionContext.getContext().getApplication();
2、实现RequestAware、SessionAware、ApplicationAware接口,依赖容器注入DI(Dependency injection) (一般用这种)

3、使用和Servlet耦合的方式:ServletActionContext.....
4、实现ServletRequestAware、ServletResponseAware接口
注意:获得response并且取得out对象后不设置contentType到页面会出现乱码

struts标签:(注意页面使用标签必须在web.xml的过滤器映射中配置/*)
通用标签:
数据标签 <s:property /> 默认从ValueStact中取,ValueStact存储在request中
从Stack Context中取必须加#标记(#session.xxx)
逻辑标签<s:if>
UI标签:<s:form>

struts2默认主题:
<constant name="struts.ui.theme" value="xhtml"/>
value=simple|xhtml

简单数据验证:出错默认返回INPUT
validate() validateExecute()
addFieldError() addActionError()
<s:actionerror/>
<s:fielderror/>

方法调用:
1、配置class中method="方法名",不推荐用,因为它会产生太多的action
2、DMI: !方法名(users!execute.action) 不推荐用,因为会有安全隐患,默认是关闭状态
3、通配符(推荐使用):* (注意写多个"action name=*"的时候防止冲突,约定高于配置)
<action name="*-*" class="com.cssl.struts.{1}Action" method="{2}">
<result>/{1}-{2}_success.jsp</result>
<result name="error">/{1}-{2}_error.jsp</result>
</action>
注意:
1、2.5版本开始增加控制方法访问权限<allowed-methods>regist,doLogin...,但写死method可以不配
strict-method-invocation="false"取消方法验证
2、当配置了多个带通配符的action后,将优先匹配父包的action,同包则按配置文件先后顺序匹配
3、!!注意action的方法名不要取get... set...、否则有可能被拦截器当作属性调用


Result配置:type
dispatcher: 默认结果类型,后台使用RequestDispatcher() 转发请求
redirect: 后台使用的sendRedirect()将请求重定向至指定的URL
redirectAction:主要用于重定向到Action
chain: 主要用于转发到别的action,转到别的namespace下的action加参数param
stream: 下载方式

如果从一个包转发到另一包的Action需要配置
<param name="namespace">/admin</param>(注意'/')
<param name="actionName">...</param>


动态结果集:OGNL从ValueStack取值
<result name="success">${att}</result> //attr不能用

带参结果集:
<result>/success.jsp?name=${att}</result>

全局Result:<global-results><result name="">...</result></global-results>


**************************************************************

三、拦截器 ppt4

给action属性赋值:
1、直接在action定义属性和jsp页面name名称对应(属性较少的时候使用)
2、定义一个实体类Vo,类属性和jsp页面的name对应(jsp name:vo.属性名),action中拥有vo的引用及get(没有get方法会出现部分注入失败问题)和set方法,还需注意vo一定要有无参的构造(常用)
3、域模型驱动:实现ModelDriven<Vo>,必须自己手动new Vo()无须get和set, jsp页面直接用属性名称,不需要vo.属性名,而且不能在一个action注入两个vo对象


Struts架构图(文档)
Struts执行过程源码解析
自定义拦截器:实现Interceptor接口或继承AbstractInterceptor,配置xml

拦截器和过滤器的区别:都是责任链模式的典型应用
功能类似,原理类似,方法类似
拦截器是webwork和struts2的概念,在struts.xml中配置,只能拦截action请求
过滤器是Servlet中的概念,在web.xml配置,可以过滤所有请求

控制重复提交:使用post可以提示用户将重复提交
1、使用重定向
2、使用token拦截器控制重复提交

使用token:
1、表单必须包含标签<s:token/>
2、提交的Action必须继承ActionSupport
3、对应action中添加token的属性(可选)

配置xml:
token:在活动中检查合法令牌(token), 防止表单的重复提交
<interceptor-ref name="token"></interceptor-ref>
sessionToken:同上, 但是在接到非法令牌时将提交的数据保存在session中
<interceptor-ref name="tokenSession"></interceptor-ref>

注意:
defaultStack必须要有,不写系统不会自动加
使用token还需要加上名为 "invalid.token" 的 result,否则异常
tokenSession不需要加"invalid.token" 的 result
interceptor可以配全局<default-interceptor-ref/>,也可以单独为某一Action配置
使用通配符的时候如果配置了token那么所有页面都要<s:token/>

使用自定义权限控制拦截器:从session取值判断
Map session = invocation.getInvocationContext().getSession();
//截取请求URL
HttpServletRequest request = ServletActionContext.getRequest();
String targetURL = request.getServletPath().substring(1);
或者使用:
Action action = (Action)invocation.getAction();
if(action instanceof UsersAction){ ...}


**************************************************************

四、interceptor原理模拟实现

OGNL: ppt5
ValueStack:OGNLValueStack
push()、pop()、peek()
set()、setValue()、findValue()

如果Action中有同名属性页面取值默认只能取第一个(后进先出),为了取后面的同名元素先pop()再取
例如在两个Action中取下面Action的fielderror(也可以使用自定义属性存储的方式而不使用addFieldError())

OGNL:
struts2使用OGNL为默认表达式语言,同时扩展了OGNL,如值栈,并将值栈作为OGNL的根对象,可以直接访问,结合struts标签使用

访问值栈的元素不能用#

访问值栈中acton的普通属性的值
访问值栈中Model的属性值:<s:property value="userVo.username"/>
访问值栈中对象的对象中的属性值(对象导航):<s:property value="husband.wife.name"/>
访问值栈中对象的普通方法:<s:property value="user.username.length()"/>
访问值栈中action的普通方法:<s:property value="show()"/>
访问静态方法:(default.properties)
<constant name="struts.ognl.allowStaticMethodAccess" value="true"/>
<s:property value="@com.cssl.actions.OgnlTest@staticMethod()"/>
<s:property value="@java.lang.Integer@parseInt('12')"/>
访问静态属性:不需要配置
<s:property value="@com.cssl.actions.OgnlTest@staticField"/>

访问数组集合:(数组和List一样)(Set不能取某个元素)
<s:set var="users" value="{'aaa','bbb','ccc'}"/>
<s:set var="array" value="new int[]{1,2,3,4}"/>
<s:set var="a" value="aa" scope=""/>
scope:StackContext、page、request、session、application
不写默认直接存放在StackContext中var为key,取值直接使用#a

<s:iterater value="#users" status="st">(#st.even|#st.index)
<s:property />
</s:iterater>


访问集合中某个元素:<s:property value="users[1]"/><br/>
访问集合中某个元素的集合(users这个集合的每个元素都有username属性,得到username的List集合):
<s:property value="users.{username}"/><br/>
访问集合中某个属性的值:<s:property value="users[0].username"/><br/>

Map:
<s:set var="map" value="#{'id':1,'name':'admin','age':20}"></s:set>
<s:property value="map.key"/>
<s:property value="map.keys"/> | keySet()
<s:property value="map.values"/> | values()
<s:property value="map.size()"/>
Map.entry<key,value>:
<s:iterater value="#map">
<s:property value="key" /> | <s:property value="value"/>
</s:iterater>


#attr.count 依次从pageContext,request,session,application中取getAttribute()

过滤:? ^ $
返回符合条件的第一个:<s:property value="list.{^#this.age==20}[0].username"/><br/>
返回符合条件最后一个:<s:property value="list.{$#this.age==20}[0].username"/><br/>
返回符合条件所有对象:<s:property value="list.{?#this.age==20}"/><br/>

三元运算:<s:property value="1>0 ? 1:0"/>

$ # %的区别:
$用于i18n和struts配置文件
#取得Stack Context(非值栈)的值
%{}将原本的文本属性解析为ognl,对于本来就是ognl的不起作用,
如果要将原本是ognl的变成文本,加单引号
如:
<s:set var='http' value="'http://www.baidu.com'"/>
<s:url var="url" value="http"/>
<s:property value="http"/> | <s:property value="url"/>
http://www.baidu.com | http


OGNL中$号的使用
1..在国际化资源文件中,引用OGNL表达式
2..在struts.xml文件中,引用OGNL表达式

OGNL中%号的使用
1..使用%{}可以取出保存在值堆栈中的Action对象,直接调用它的方法
2..如果Action继承了ActionSupport,那么在页面标签中可以使用%{getText('key')}获取国际化信息

**************************************************************

五、声明式异常处理:
<action name="showTime" class="com.cssl.struts.ShowTimeAction">
<exception-mapping result="error" exception="java.lang.Exception"/>
<result name="error">/error.jsp</result>
</action>
全局异常映射:其他包继承此包
<package name="default" namespace="/" extends="struts-default">
<global-exception-mappings>
<exception-mapping result="error" exception="java.lang.Exception"></exception-mapping>
</global-exception-mappings>
</package>
全局结果:(必须放在<global-exception-mappings>前面)
<global-results>
<result name="error">/error.jsp</result>
</global-results>


验证框架:
struts2的验证分为分编程式验证、声明式验证、注解式验证

编程式验证:
重写validate()方法,所有请求该action(所有处理请求方法)都会调用
自定义validateXxx()方法,验证对应的处理请求方法xxx()!
调用顺序是先validateXxx()后validate()

声明式验证:
支持客户端验证
<s:form action="reg.action" validate="true">
验证文件命名:ActionName-validation.xml
假如你只想验证UserAction中的userAdd方法则改名:UserAction-action别名-validation.xml
<form action="doLogin.action" method="post"> -- UserAction-doLogin-validation.xml


field标签表示被验证的字段项
field-validator标签表示使用什么验证约束
short-circuit表示短路验证
message表示验证不通过时返回的错误消息
<!DOCTYPE validators PUBLIC
"-//Apache Struts//XWork Validator 1.0.3//EN"
"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<validators>
<field name="repass">
<field-validator type="fieldexpression">
<param name="expression">password==repass</param>
<message>两次密码不一致!</message>
</field-validator>
</field>
<field name="email">
<field-validator type="requiredstring">
<message>邮箱不能为空</message>
</field-validator>
<field-validator type="email">
<message>请输入有效的邮箱地址</message>
</field-validator>
</field>

详细配置见:
com.opensymphony.xwork2.validator.validators包下default.xml

注解式验证:直接注在Action上面
@Validations(
requiredStrings={
@RequiredStringValidator(fieldName="username",message="用户名不能为空!"),
@RequiredStringValidator(fieldName="telNum",message="电话号码不能为空!")
},
regexFields={@RegexFieldValidator(fieldName="telNum",expression="^(\\+86|0|1)\\d{10,11}$",
message="电话号码格式不正确!")}
)

或者get方法上面
@EmailValidator(message="Email is error!")

验证是先注解验证、xml的验证框架,再编码验证validateXxx(),在validate()

一般来说,简单验证用xml,复杂数据(查询数据库)验证用validate()
服务端验证也是必须的,即使有客户端验证!因为客户端验证是可以跳过的,
强健的web应用要有客户端和服务端验证!
action方法上添加注解@SkipValidation,能跳过所有的验证

struts2也支持客户端验证:
1、form的主题不能为simple
2、将form的validate属性设为true


国际化和本地化:native2ascii(转中文为ascii)
JDK使用国际化:ResourceBundle bundle=ResourceBundle.getBundle("message",Locale.ENGLISH);
<s:text name="title" />
<s:textfield key="users.username" name="users.username"/>
<s:submit value="%{getText('submit')}"/>
两种方式:%{getText('submit')} | key="submit"

Action级别:ActionName_zh_CN.properties
包级别: package_zh_CN.properties
全局: 全局名(struts2.xml中指定)_zh_CN.properties(一般用这种)
<constant name="struts.custom.i18n.resources" value="message"/>
资源文件中也可以带参数{0}
中文的资源文件MyEclipse直接使用设计视图编写,eclipse需要插件支持

动态语言切换:
<s:a href="locale.action?request_locale=en">English</s:a>|
<s:a href="locale.action?request_locale=zh_CN">中文</s:a>

*******************************************************************

六、类型转换:
struts2内置很多类型转换器
如String自动转int、double、Date...

注意:
1、转基本数据类型(如int)数组的时候给所有文本框输入value='0',否则拦截器出错返回INPUT,Integer注入null
2、转对象集合用List<T> list,不能用自定义对象数组,前端使用list[index].property
3、使用Map<String,Object>注入,前台使用map.key


日期类型也能自动转换:格式1:yyyy-MM-dd 格式2:yyyy年MM月dd日
<s:date name="birthday" format="yyyy-MM-dd HH:mm:ss"/>

自定义类型转换:
1、实现ognl.TypeConverter接口重写convertValue()
2、继承ognl.DefaultTypeConverter重写convertValue()
3、继承StrutsTypeConverter抽象类(DefaultTypeConverter子类)重写convertFromString和convertToString(常用)
前台注入action的时候调用,根据转换的类型调用对应的方法,如果后台类型就是String,则调用convertToString();
后台转换类型到前台String的时候也会调用convertToString();

参数含义:
Map<String, Object> context:OGNL上下文对象,通常用不上它;
String[] value:被转换的值;
Class toClass:要被转换成什么类型。

注册转换器:(action级别配置对于ModelDriven<T>注入的T无法使用,必须用全局配置)
a、src\配置全局属性文件xwork-conversion.properties(属性原始类名=转换器类)
com.cssl.Point=com.cssl.struts.MyConverter
b、package\配置指定action属性文件action名-conversion.properties(属性名=转换器类)

注意:
1、类型转换到页面输出要用struts标签才可以,使用el表达式无效!
2、全局的如果用(属性名=转换器类),只有属性名对的action有效!
3、修改所有类型的转换错误信息xwork.default.invalid.fieldvalue=字段"{0}"的值无效
4、定制特定字段的类型转换错误信息
在Action包下创建XxxAction.properties:invalid.fieldvalue.bornDate=生日转换错误


手动获取请求参数值:
第一种方法获取:(struts2.5不行)
ActionContext上下文包含parameters的Map集合,值得注意的是param.get("key")是一个String数组
(String[])ActionContext.getContext().getParameters().get("表单参数名");
struts2.5+:
(String[])ActionContext.getContext().getParameters().get("参数名").getMultipleValues();

第二种方法是直接把request引用进来:
ServletActionContext.getRequest().getParameter("表单参数名") option_24


struts标签:
<s:radio list="" listKey="" listValue="" key="" value=""/>
Freemarker异常加key="" value="" 或 name="" (其他标签也有类似情况)

二级级联标签:
<s:doubleselect />
标签必须嵌套在<s:form>标签中
form必须有name页面中不能有同名的name,action必须struts.xml中真实存在
name和doubleName不能为空

<s:doubleselect list="{'湖南','湖北'}" name="province"
doubleList="top == '湖南' ? {'长沙','株洲'} : {'武汉','襄阳'}" doubleName="city" />

<s:doubleselect list="map.keys" listKey="hid" listValue="hname" name="husband"
doubleName="wife" doubleList="map[top]|map.get(top)" doubleListKey="wid" doubleListValue="wname" />

ajax标签:<sx:div>


监听器:
ServletContext, HttpSession 和 ServletRequest 监听这三个域对象

*******************************************************************

七、上传下载:
commons-fileupload、commons-io
表单enctype="multipart/form-data"
method="post"
表单name=files
Action:
File[] files
String[] filesContentType
String[] filesFileName

上传路径:
realPath = ServletActionContext.getServletContext().getRealPath("/") + savePath +"\\";
或者使用File.separator代替"\\"
注意:Tomcat8.x 使用getRealPath获得绝对路径必须加"/",不能直接getRealPath(savePath)

上传文件:
File file = new File(realPath + filesFileName[i]);
FileUtils.copyFile(); //遍历所有上传文件,使用工具类上传

上传限制:action中拦截器配置
<interceptor-ref name="fileUpload">
<param name="allowedTypes"> image/bmp,image/png,image/gif,image/jpeg,image/jpg,image/x-png,image/pjpeg
</param>
<param name="maximumSize">10485760</param>
</interceptor-ref>

注意:
缺省拦截器栈中已经包含了fileUpload拦截器。那么这样配置就是做了两次拦截。所以我们必须把自己写的fileUpload放到default前面拦截!!!(default在前面的时候参数没有设置就会上传成功,之后拦截设置的参数就没用了)
或者使用如下配置也可以实现文件类型拦截
<interceptor-ref name="defaultStack">
<param name="fileUpload.allowedTypes">
image/bmp,image/png,image/gif,image/pjpeg,image/jpg,image/x-png
</param>
<param name="fileUpload.maximumSize">102400</param>
</interceptor-ref>

配置上传文件总大小:(maximumSize大于这个值无效除非在struts.xml中修改该常量大小)
<constant name="struts.multipart.maxSize" value="52428800"/>
注意:upload.action 不要和文件夹同名


下载action配置:
<result name="success" type="stream">
<!--默认为text/plain -->
<param name="contentType">application/x-msdownload;charset=ISO8859-1</param>

<!-- 默认就是inputStream,它将会指示StreamResult通过inputName属性值的getter方法, 比如这里就是
getInputStream()来获取下载文件的内容,意味着你的 Action要有这个方法 -->
<param name="inputName">inputStream</param>

<!-- 默认为inline(在线打开),设置为 attachment 将会告诉浏览器下载该文件,filename 指定下载文件时的文件名,若未指定将会是以浏览的页面名作为文件名,如以download.action作为文件名 -->
<param name="contentDisposition">attachment;filename="${fileName}"</param>

<!-- 输出时缓冲区的大小 -->
<param name="bufferSize">4096</param>
</result>

获得下载的文件名:
get或post提交中文文件名setFileName()方法都不需要进行编码转换
getFileName()方法设置请求头或直接对文件名进行转码:
getFileName():
ServletActionContext.getResponse().setHeader("Content-Disposition", "attachment;fileName=" + java.net.URLEncoder.encode(fileName,"UTF-8"));
或者
fileName = java.net.URLEncoder.encode(fileName,"UTF-8"));

在getInputStream()中得到需要下载的文件输入流:
File file = new File(realPath+getFileName());
InputStream is = new FileInputStream(file);


下载后报异常:BUG (2.3.16无此bug)
java.lang.IllegalStateException
at org.apache.catalina.connector.ResponseFacade.sendError(ResponseFacade.java:407)

stream对应的类是org.apache.struts2.dispatcher.StreamResult,该类的处理过程如下:
1。配置其中result标签下的各个参数
2。从服务器中获取输入流,并同时与客户端建立输出流(服务器与客户端链接通过Socket进行连接)
3。当点击“保存”或“打开”时,开始传输数据。如果点击“取消”,关闭所有的流。
这里要注意的是,但是实际发现Socket并没有断开!并且流也没有关闭!这一点非常重要!
所以在JSP容器通过Response获取输出流之前,前面的流并没有关闭,所以会造成该异常的报出。

解决:
1。获取struts2-sunspoter-stream-1.0.jar,并复制在/WEB-INF/lib下
2。在原有的struts.xml的基础上进行相应的配置
<result-types>
<result-type name="streamx" class="com.sunspoter.lib.web.struts2.dispatcher.StreamResultX"/>
</result-types>
使用type="streamx"


action中使用验证码也同下载的配置:
<action name="SecurityCodeImageAction"
class="com.dong.security.action.SecurityCodeImageAction">
<result name="success" type="stream">
<param name="contentType">image/jpeg</param>
<param name="inputName">imageStream</param>
<param name="bufferSize">2048</param>
</result>
</action>


*******************************************************************

八、jquery+struts2+json插件:

1、导入插件包:(不依赖json-lib包)
struts2-json-plugin-2.x.x.jar

json-lib包:(依赖ezmorph、commons-beanutils、commons-collection、commons-lang、commons-logging)
JSONObject.fromObject(Object);
JSONArray.fromObject(Collection);
使用json-lib手动转换双向关联有无限循环问题!

2、创建Action并配置:
<package name="json" extends="json-default" namespace="/test">
<action name="testByAction" class="cn.action.UserAction" method="testByAction">
<result type="json">
<!--这里指定将被Struts2序列化的属性,不配将序列化所有action属性-->
<param name="root">dataMap</param>
<!--这里指定序列化dataMap对象中某个属性,必须搭配root一起使用-->
<param name="includeProperties">users</param>
<!--这里指定将要从dataMap对象中排除的某个属性(对集合中属性无效)-->
<param name="excludeProperties">users</param>
</result>
</action>
</package>
root的值dataMap可以是对象、集合或者map!插件将自动转换其为json字符串,前台直接得到json对象,没有无限循环问题

我们也可以使用注解@JSON配置被序列化对象:
@JSON的属性分别是:
1. name 为属性起一个别名(序列化到JSON对象中的键默认是属性名称,使用了name属性那么键是name的名字)
2. serialize 默认为true 也就是可以被序列化,如果设为false那么该属性将不包含在JSON对象中
3. format 主要是对日期进行格式化


3、客户端:$.getJSON|$.post()

 

DWR:Direct Web Remoting
http://directwebremoting.org/dwr/index.html

1、导包:
dwr3.0需要commons-logging.jar

2、配置web.xml
<servlet>
<servlet-name>dwr</servlet-name>
<servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>true</param-value>
</init-param>
</servlet>

3、配置dwr.xml:默认WEB-INF\dwr.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dwr PUBLIC
"-//GetAhead Limited//DTD Direct Web Remoting 3.0//EN"
"http://directwebremoting.org/schema/dwr30.dtd">
<dwr>
<allow>
<create javascript="UsersDwr" creator="new" scope="session">
<param name="class" value="com.cssl.dwr.UsersDwr"></param>
<include method="getUsersSize"></include>
</create>
<!-- json与vo对象之间的转换,users可以在前台直接使用new Users()-->
<convert converter="bean" javascript="Users" match="com.cssl.vo.UsersVo"/>
</allow>
</dwr>

4、配置struts.xml
因为
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
将过滤掉dwr的请求,所以必须在struts.xml中去掉过滤
<constant name="struts.action.excludePattern" value="/dwr/.*,/dwr/test/.*" />


补充:
使用annotation配置strut2(注解和xml同时存在优先使用注解)
1、导包
struts2-convention-plugin-2.x.x和asm系列的3个jar包
struts2-config-browser-plugin-2.x.x.jar(可选,查看struts2的Action各种资源的映射)

插件会自动搜索action,actions,struts,struts2包

Convention插件会把如下两种java类当成Action处理:
1)所有实现了com.opensymphony.xwork2.Action的java类
2)所有类名以Action结尾的java类
3)将Action类名的驼峰写法(每个单词首字母大写、其他字母小写的写法)转成中画线写法(所有字母小写,单词与单词之间以中画线隔开) 映射execute()方法
OneTwoAction.java <--> one-two.action UsersAction <--> users.action

定位资源(result)的约定是:
actionURL-resultCODE.suffix或actionURL.suffix或resultCODE.suffix作为物理视图资源
物理资源默认路径WEB-INF/content/,可以在Action加注解@ResultPath("/")

com.cssl.actions.LoginAction 映射到 /
com.cssl.actions.myoffice.CarInfoAction 映射到 /myoffice 视图也将映射到目录/myoffice/

常用注解:
@ResultPath("/") //定位资源到WebRoot路径下
@Results(value={@Result(name="error",location="errors.jsp"),
@Result(name="invalid.token",location="token.jsp")}) //全局结果集
@InterceptorRefs({@InterceptorRef("token"),@InterceptorRef("defaultStack")}) //全局拦截器
@Action(value="abc",results={@Result(name="success", location="http://struts.apache.org", type="redirect")})
@Action(value="dologin",interceptorRefs={@InterceptorRef("token"),@InterceptorRef("defaultStack")},results={@Result(name="invalid.token",location="xishuashua.jsp"),@Result(name="success",location="/login-input.jsp")})
@Namespace("/my") //命名空间
@ParentPackage("default") //定义自定义拦截器包default,@InterceptorRef引用自定义拦截器


Action链的约定:
如果希望一个Action处理结束后不是进入一个视图页面,而是进行另一个Action形成的Action链。通过Convention插件则只需遵守如下三个约定即可。
1)第一个Action返回的逻辑视图字符串没有对应的视图资源
2)第二个Action与第一个Action处在同一个包下
3)第二个Action影射的URL为:firstActionURL+resultCODE(users+success=UsersSuccessAction)
4)跳转后值栈中只有第一个action

也可以通过类似xml的type=chain|redirectAction的方式实现
@Result(name="success",location="login-input",type="chain")

查看struts2的Action各种资源的映射(xml的也能查看,不能查看带*的)
http://localhost:8080/应用名字/config-browser/actionNames.action

查看异常有freemarker异常!!

几个重要的常量:
struts.convention.classes.reload ---自动重加载映射
struts.convention.package.locators ---Convention插件以该常量指定包作为根包
struts.convention.result.path ---设置Convention插件定位视图资源的根路径

转载于:https://www.cnblogs.com/yuan211/p/8334615.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值