">
Struts2
This presentation is the property of its rightful owner.
Sponsored Links
1 / 178

Struts2 PowerPoint PPT Presentation


  • 311 Views
  • Uploaded on
  • Presentation posted in: General

Struts2. MVC 模式 控制器 -FilterDispatcher 模型 -action 视图 -result. Struts2. 如何工作 拦截器 : 拦截器在 action 前 / 后调用 完成特定工作 , 实现低耦合 . 值栈和 OGNL: 值栈存储数据中心 OGNL 访问这些数据. Struts2 配置方式 (xml 和元数据 ). Struts.xml: <action name="HelloWorldAction" class="..HelloWorldAction">

Download Presentation

Struts2

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


Struts2

Struts2

MVC模式

控制器-FilterDispatcher

模型-action

视图-result

北京传智播客教育 www.itcast.cn


Struts21

Struts2

如何工作

拦截器:拦截器在action前/后调用

完成特定工作,实现低耦合.

值栈和OGNL:值栈存储数据中心

OGNL访问这些数据

北京传智播客教育 www.itcast.cn


Struts2 xml

Struts2配置方式(xml和元数据)

Struts.xml:

<action name="HelloWorldAction" class="..HelloWorldAction">

<result>/index.jsp</result>

</action>

<action name="MyAction" >

<result>/index.jsp</result>

</action>

注解:

@Results({

@Result(name="input", value="/RegistrationSuccess.jsp" )

@Result(value="/RegistrationSuccess.jsp" )

})

public class LoginAction implements Action {

public String execute() {

//Business logic for login

}

}

北京传智播客教育 www.itcast.cn


Struts22

Struts2配置方式(默认值以及模块化)

许多属性不需要显式设置,他们都有合理的默认值.

这些默认值基本上都定义在struts-default.xml/default.properties文档中.

<struts>

<constant name="struts.devMode" value="true" />

<package name="default" namespace="/" extends="struts-default">

<action name="Menu">

<result>/menu/Menu.jsp</result>

</action>

</package>

<include file="manning/chapterTwo/chapterTwo.xml"/>

<include file="manning/chapterThree/chapterThree.xml"/>

</struts>

北京传智播客教育 www.itcast.cn


Struts2 web xml

Struts2配置(web.xml)

注:struts2.1.3以后推荐使用org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter

Init():进行初始化。

北京传智播客教育 www.itcast.cn


Struts2 url

Struts2(url)

在struts1中,通过<action path="/test/helloworld">节点的path属性指定访问该action

的URL路径。

在struts2中,URL路径由两部份组成:包的命名空间+action的名称,例如

http://localhost:port/项目名称/test/helloworld.action

<package name="itcast" namespace="/test" extends="struts-default">

<action name="helloworld"

class="cn.itcast.action.HelloWorldAction" method="execute" >

<result name="success">/WEB-INF/page/hello.jsp</result>

</action>

</package>

北京传智播客教育 www.itcast.cn


Struts2 hello world

Struts2(hello world)

struts.xml

<struts>

<package name="HelloWorldPkg" namespace="/HelloWorld"

extends="struts-default">

<default-action-ref="HelloWorldAction" />

<default-action-class="...HelloWorldAction" />

<action name="NoClassAction">

<result>/helloworld/helloworld.jsp</result>

</action>

<action name="HelloWorldAction" class="..HelloWorldAction">

<result name="success">/helloWorld.jsp</result>

</action>

</package>

</struts>

注:http//localhost:8085/struts2/aaa/bbb/HelloWorldAction.action ?

北京传智播客教育 www.itcast.cn


Struts2 hello world1

Struts2(hello world)

index.jsp

<%@ page contentType="text/html; charset=UTF-8" %>

<%@ taglib prefix="s" uri="/struts-tags" %>

<html>

<head>

<title>helloWorld.jsp</title>

</head>

<body>

<h4>Enter your name </h4>

<s:form action="HelloWorldAction">

<s:textfield name="name" label="username"/>

<s:submit/>

</s:form>

</body>

</html>

北京传智播客教育 www.itcast.cn


Struts2 hello world2

Struts2(hello world)

HelloWorldAction.java

package cn.itcast.struts2.action;

public class HelloWorldAction {

private static final String GREETING = "Hello ";

public String execute() {

setCustomGreeting( GREETING + getName() );

return "SUCCESS";

}

private String name;

get/set

private String customGreeting;

get/set

}

北京传智播客教育 www.itcast.cn


Struts2 hello world3

Struts2(hello world)

helloWorld.jsp

<%@ page contentType="text/html; charset=UTF-8" %>

<%@ taglib prefix="s" uri="/struts-tags" %>

<html>

<head>

<title>HelloWorld</title>

</head>

<body>

<h3>Custom Greeting Page</h3>

<h4><s:property value="customGreeting"/></h4>

</body>

</html>

北京传智播客教育 www.itcast.cn


Struts2 hello world4

Struts2(hello world)

执行示意图:

北京传智播客教育 www.itcast.cn


Struts2 hello world5

Struts2(hello world-使用注解)

web.xml

<filter>

<filter-name>struts2</filter-name>

<filter-class>...FilterDispatcher</filter-class><!-- 不推荐使用 -->

<filter-class>...StrutsPrepareAndExecuteFilter</filter-class>

<init-param>

<param-name>actionPackages</param-name>

<param-value>manning</param-value>

</init-param>

</filter>

AnnotatedNameCollector.java

@Result( value="/chapterTwo/AnnotatedNameCollector.jsp" )

public class AnnotatedNameCollector extends ActionSupport {

/* EMPTY */

}

北京传智播客教育 www.itcast.cn


Struts2 action

Struts2(操纵action)

Aciton封装了工作单元并提供了数据传输中心

//工作单元

public string execute(){

}

//数据传输中心

Public string name ;//get/set

Public string greetingName ; //get/set

该应用中name参数被从表单转移到action的name属性(按照名称匹配的原则).除此以外action还

要把javabean属性暴露给结果.

在struts1中,每个action只有一个实例.如果struts2也是如此的话,我们就不能用action来携带

请求数据了,因为在多线程的情况下这是有问题的.struts2解决这一问题的办法是每次实例化新的

action实例.这也是和struts1不同的地方.

北京传智播客教育 www.itcast.cn


Struts2 action1

Struts2(操纵action)

Aciton的方法返回控制串用于结果路由

Struts1如何处理的?

返回的控制串表明哪个结果要被渲染.而且消除了代码中对路由对象的依赖,使得代码更简洁,达到了

解耦的目的.这些路由串必须和xml文档中配置的结果相匹配.

<action name="HelloWorld" class="manning.chapterOne.HelloWorld">

<result name="success">/chapterTwo/HelloWorld.jsp</result>

<result name="error">/chapterTwo/Error.jsp</result>

</action>

<action name="HelloWorld2" class=".." method="view">

<result name="input">/chapterTwo/Error.jsp</result>

</action>

注:开启动态方法调用.[struts.enable.DynamicMethodInvocation = true]

http://.../struts/HelloWorldAction!view.action?...

北京传智播客教育 www.itcast.cn


Struts2 action2

Struts2(操纵action)

打包action

Struts2中的包和java的包作用相当.逻辑上的容器,组织action和其他的组件.其中包的url中的

Namespace必须指定,而且包可以继承或抽象化.

<package name="chapterThreeSecure"

namespace="/chapterThree/secure"

extends="struts-default">

<action name="AdminPortfolio" >

<result>/chapterThree/AdminPortfolio.jsp</result>

</action>

<action name="AddImage" >

<result>/chapterThree/ImageAdded.jsp</result>

</action>

<action name="RemoveImage" >

<result>/chapterThree/ImageRemoved.jsp</result>

</action>

</package>

url:http://localhost:8080/manningHelloWorld/chapterThree/

secure/AddImage.action

北京传智播客教育 www.itcast.cn


Struts2 struts default

Struts2(使用struts-default下的组件)

只要扩展struts-default.xml,默认组件即可使用.默认拦截器栈即是

典型案例.

<package name="struts-default">

<interceptor-stack name="defaultStack">

<interceptor-ref name="exception"/>

<interceptor-ref name="alias"/>

<interceptor-ref name="servlet-config"/>

<interceptor-ref name="prepare"/>

<interceptor-ref name="i18n"/>

<interceptor-ref name="chain"/>

<interceptor-ref name="debugging"/>

<interceptor-ref name="profiling"/>

<interceptor-ref name="scoped-model-driven"/>

<interceptor-ref name="model-driven"/>

<interceptor-ref name="fileUpload"/>

<interceptor-ref name="checkbox"/>

北京传智播客教育 www.itcast.cn


Struts2 struts default1

Struts2(使用struts-default下的组件)

只要扩展struts-default.xml,默认组件即可使用.默认拦截器栈即是

典型案例.

<interceptor-ref name="params">

<param name="excludeParams">dojo\..*</param>

</interceptor-ref>

<interceptor-ref name="conversionError"/>

<interceptor-ref name="validation">

<param name="excludeMethods">input,back,cancel,browse</param>

</interceptor-ref>

<interceptor-ref name="workflow">

<param name="excludeMethods">input,back,cancel,browse</param>

</interceptor-ref>

</interceptor-stack>

. . .

<default-interceptor-ref name="defaultStack"/>

. . .

</package>

北京传智播客教育 www.itcast.cn


Struts2 struts default2

Struts2(使用struts-default下的组件)

只要扩展struts-default.xml,默认组件即可使用.默认拦截器栈即是

典型案例.

北京传智播客教育 www.itcast.cn


Struts2 action3

Struts2(实现action)

任何javabean都可以成为action,当action被执行时只要提供一个供框

架调用的入口方法即可.

Struts2中的action不是必须实现action接口,只要含有execute()方法

并且返回控制串即可.

北京传智播客教育 www.itcast.cn


Struts2 action4

Struts2(实现action)

可选action接口

com.opensymphony.xwork2.Action

该接口提供了执行方法和常量串供开发方便调用.

String execute() throws Exception

public static final String ERROR="error"

public static final String INPUT="input"

public static final String LOGIN="login"

public static final String NONE="none"

public static final String SUCCESS="success"

<action name="Name">

<result>/chapterOne/NameCollector.jsp</result>

</action>

北京传智播客教育 www.itcast.cn


Struts2 action5

Struts2(实现action)

actionSupport类

该类实现了action接口和其他的几个有用的接口,比如数据校验、错误消息本

地化等.继承该类后,这些功能便自动获得.

一、基本校验

Struts2框架提供了丰富的高度可配的验证框架,同时也提供了基本的验证方法.这些任务主要是

通过拦截器和接口实现.actionSupport实现了两个接口和默认栈中的一个拦截器配合使用.

DefaultWorkflowInterceptor提供了基本的校验功能.若action使用了默认栈而且继承了该类,

则也具备了验证的功能.

<interceptor name="workflow"

class="com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor"/>

<interceptor-stack name="defaultStack">...

<interceptor-ref name="params"/>...

<interceptor-ref name="workflow">

<param name="excludeMethods">input,back,cancel,browse</param>

</interceptor-ref>...

</interceptor-stack name="defaultStack">

北京传智播客教育 www.itcast.cn


Struts2 action6

Struts2(实现action)

actionSupport类

一、基本校验(续)

该拦截器称为工作流拦截器是因为当验证错误发生时他会将请求的工作流转向导收入页面.注意

params拦截器在workflow之前,params拦截器把请求数据移动到action上,工作流拦截器再进行

校验,对于大多数的拦截器而言,顺序很重要.工作流拦截器启动时,首先寻找action中的validate()

方法来调用.该方法定义在com.opensymphony.xwork2.Validateable接口中.我们需要重写这

个方法的空实现.代码如下:

public class RegisterAction extends ActionSupport {

public String execute(){

...

return SUCCESS;

}

private String username;//get/set

private String password;//get/set

北京传智播客教育 www.itcast.cn


Struts2 action7

Struts2(实现action)

actionSupport类

一、基本校验(续)

public void validate(){

PortfolioService ps = getPortfolioService();

if ( getPassword().length() == 0 ){

addFieldError( "password", "Password is required.") );

}...

}

public String validateToRegView(){...}

验证方法执行完,控制权返回到工作流拦截器,该方法没有返回值,秘密就在于校验生成的错误消息.

工作流拦截器会查看是否有错误消息生成,如果有的话,他会更改请求的工作流,终止请求处理并立即

返回到用户的输入表单页面.在页面上会显示错误消息.

问题:消息存哪里了?如何检查有错误消息生成?

北京传智播客教育 www.itcast.cn


Struts2 action8

Struts2(实现action)

actionSupport类

一、基本校验(续)

com.opensymphony.xwork2.ValidationAware接口定义了存储和检索错误消息的方法,方法

及错误消息集合都已由actionSupport实现,只需通过如下访问.

addFieldError ( String fieldName, String errorMessage )---(1)

addActionError ( String errorMessage )--------------------(2)

方法1必须指定一个字段名,方法2时添加一个action范围的错误消息,不需要指定太多东西.

ValidationAware接口也定义了判断错误消息是否存在的方法,工作流拦截器会使用它们来决定

是否需要重定向工作流到input页面,若有错误发生,拦截器会寻找input结果.

<action name="Register" class="manning.chapterThree.Register">

<result>/chapterThree/RegistrationSuccess.jsp</result>

<result name="input">/chapterThree/Registration.jsp</result>

</action>

至于错误消息如何显示在页面上,那是UI标签的事情,我们以后介绍.

北京传智播客教育 www.itcast.cn


Struts2 action9

Struts2(实现action)

actionSupport类

二、为消息文本使用资源束

硬编码错误消息在action中不可想象的,好的方式是采用外部资源束文件.

ActionSupport提供了两个接口实现该功能.

com.opensymphony.xwork2.TextProvider提供了从资源束中提取消息的方法.

ActionSupport类给出了实现.使用这些方法都需要指定key值,然后返回和该action关联的属性

文件中key所对应的消息.

Register.properties:

user.exists=This user already exists.

username.required=Username is required.

password.required=Password is required.

portfolioName.required=Portfolio Name is required.

该文件需要Action放在一起.

然后即可通过getText()方法来访问消息了.

addFieldError("username", getText( "user.exists"));

北京传智播客教育 www.itcast.cn


Struts2 action10

Struts2(实现action)

actionSupport类

二、为消息文本使用资源束

ActionSupport为本地化消息文本也提供了国际化方案.

com.opensymphony.xwork2.LocaleProvider接口暴露了getLocale()方法.

ActionSupport实现了该接口检索用户设置在浏览器中的locale信息.

ActionSupport的TextProvider实现每次接受到消息文本时,也会检查locale信息,他是通过调

用LocaleProvider接口的getLocale()方法,然后定位到

相应的属性文件.

北京传智播客教育 www.itcast.cn


Struts23

Struts2(向对象传递数据)

我们可以暴露一个复杂的对象在action中,而不是定义基本的javabean属性.(struts1 form?)

有两种方案可以使用.

一、将javabean属性暴露成后台对象

每次手动收集数据信息再封装成domain对象是很繁琐的工作.

Action中:

Private User user ;//get/set

Public String execute(){

getPortfolioService().createAccount( user );

}

jsp中:

<s:textfield name="user.username" label="Username"/>

<h3>The <s:property value="user.portfolioName" /> Portfolio</h3>

北京传智播客教育 www.itcast.cn


Struts24

Struts2(向对象传递数据)

二、ModelDriven Action

模型驱动action通过getModel()方法暴露domain对象,由com.opensymphony.xwork2.

ModelDriven接口定义.这引入了另一个拦截器,该拦截器已经在默认栈中了.数据传输仍然是自动完

成的而且比以前更容易.

ActionSupport没有实现该接口,需要我们单独实现,他只有一个方法-getModel().

public class ModelDrivenRegister extends ActionSupport

implements ModelDriven {

public String execute(){

getPortfolioService().createAccount( user );

return SUCCESS;

}

private User user = new User();

public Object getModel() {

return user;

}

}}

北京传智播客教育 www.itcast.cn


Struts25

Struts2(向对象传递数据)

二、ModelDriven Action

private User user = new User();

我们必须初始化model对象,需要注意的是在action的execute()方法调用之前,框架已经获得了

Model对象的引用,通过getModel()完成,而且框架至始至终引用的就是这同一个model对象,所以

如果在action中改变model对象的引用,会造成数据的不一致.

以下代码阐述了这个问题:

public String execute(){

user = new User();

user.setSomething();

getPortfolioService().createAccount( user );

return SUCCESS;

}

private User user = new User();

public Object getModel() {

return user;

}

<s:textfield name="username" label="Username"/>

北京传智播客教育 www.itcast.cn


Struts26

Struts2(文件上传)

通过默认栈获得内置的上传支持.

<interceptor name="fileUpload"

class="org.apache.struts2.interceptor.FileUploadInterceptor"/>

<interceptor-stack name="defaultStack">

<interceptor-ref name="fileUpload"/>

</interceptor-stack>

<action name class>

<interceptor-ref name="defaultStack">

<param name="fileUpload.allowedTypes">text/plain,...

<param name="fileUpload.allowedExtensionTypes">.jpg,.jpeg

</interceptor-ref>

</action>

北京传智播客教育 www.itcast.cn


Struts27

Struts2(文件上传)

fileUpload拦截器运行机制:

fileUpload拦截器在params拦截器之前,文件上传拦截器执行时,处理multipart request来

传输文件,他使用servlet request包装类完成这一工作.

<s:file name="pic" label="Picture"/>

Action:

File pic;

String picContentType;

String picFileName;

若多个文件:File[]即可

北京传智播客教育 www.itcast.cn


Struts28

Struts2(用拦截器添加工作流)

通过拦截器的分离关注,使得框架更加整洁.即每个拦截器负责特定的工作,而不是都交给

某个组件/action完成.拦截器从我们的action中删除了横切的任务,我们通常所说的预处理/后处

理等.action的调用是被分层处理的,在action执行前后包括一系列拦截栈的执行.action被最后执

行,选择相应的结果,结果执行后,拦截器以相反的顺序进行后处理工作.

有些时候,拦截器决定action不能执行.那么就需要拦截器本身返回控制串.workflow拦截器就是

典型的案例.他做了两件事,首先validation拦截器调用validate()方法,再判断是否存在错误消

息,若存在错误消息,他返回控制串阻止action的进一步执行,action将不会启动,下一个拦截器也不

会调用.

北京传智播客教育 www.itcast.cn


Struts29

Struts2 (用拦截器添加工作流)

拦截器实战

一、ActionInvocation

该类封装了和特定action相关联所有的处理细节.

框架接受请求->决定url映射到哪个action->action实例添加到新建的ActionInvoc

ation对象中->框架询问xml启动哪个拦截器(以何顺序).除此以外,该对象还会持有对

重要信息的引用,比如Request对象和该action的Result Map.

二、拦截器如何启动

该类暴露的invoke方法供框架调用,来开始action的执行.,他负责追踪调用的执行步骤

并传递控制权给栈中相应的拦截器.主要通过调用拦截器的intercept()访方法来实现.

拦截启动顺序:

先从上到下执行->调用action->渲染页面->逆向调用拦截器(供后处理使用)

递归调用,维护状态(步骤)

北京传智播客教育 www.itcast.cn


Struts210

Struts2 (用拦截器添加工作流)

4.2.1ActionInvocation(续)

拦截器启动时可以做如下工作:

三个步骤:

预处理

传递控制权(到拦截器/action/控制串)

后处理

public String intercept(ActionInvocation invocation) throws Exception {

long startTime = System.currentTimeMillis();

String result = invocation.invoke();

long executionTime = System.currentTimeMillis() - startTime;

... log the time ...

return result;

}

Invoke()方法返回后,页面已经被渲染,即已经打开.

北京传智播客教育 www.itcast.cn


Struts211

Struts2 (用拦截器添加工作流)

考察内置拦截器

一、工具拦截器

Timer:

计时action执行

INFO: Executed action [/chapterFour/secure/ImageUpload!execute]

took 123 ms.

Logger:

预处理和退出后处理的日志记载.

INFO: Starting execution stack for action /chapterFour/secure/

INFO: Finishing execution stack for action /chapterF

北京传智播客教育 www.itcast.cn


Struts212

Struts2 (用拦截器添加工作流)

考察内置拦截器

三、数据传输拦截器

Params拦截器:

Static-params拦截器:移动静态参数到值栈属性中.

<action name="exampleAction" class="example.ExampleAction">

<param name="firstName">John</param>

<param name="lastName">Doe</param>

</action>

注意顺序,他在参数后面,会有覆盖问题.

AUTOWIRE拦截器:

整合spring

北京传智播客教育 www.itcast.cn


Struts213

Struts2 (用拦截器添加工作流)

考察内置拦截器

数据传输拦截器

SERVELET-CONFIG:

ServletContextAware—Sets the ServletContext

ServletRequestAware—Sets the HttpServletRequest

ServletResponseAware—Sets the HttpServletResponse

ParameterAware—Sets a map of the request parameters

RequestAware—Sets a map of the request attributes

SessionAware—Sets a map of the session attributes

ApplicationAware—Sets a map of application scope properties

PrincipalAware—Sets the Principal object (security)

FILEUPLOAD:文件上传拦截器

北京传智播客教育 www.itcast.cn


Struts214

Struts2 (用拦截器添加工作流)

考察内置拦截器

WorkflowInterceptor

public String intercept(ActionInvocation invocation)

throws Exception {

Action action = invocation.getAction();

if (action instanceof Validateable) {

Validateable validateable = (Validateable) action;

validateable.validate();

}

if (action instanceof ValidationAware) {

ValidationAware validationAwareAction =

ValidationAware) action;

if (validationAwareAction.hasErrors()) {

return Action.INPUT;

}

}

return invocation.invoke();

}

北京传智播客教育 www.itcast.cn


Struts215

Struts2 (用拦截器添加工作流)

考察内置拦截器

工作流拦截器

工作流拦截器携带以下几个参数:

alwaysInvokeValidate:总是调用校验方法.true|false true

inputResultName:输入结果名.校验失败后寻找结果的名称.默认为ACTION.INPUT.

excludeMethods:不执行校验的方法(排外)

<interceptor-ref name="workflow">

<param name="excludeMethods">input,back,cancel,browse</param>

</interceptor-ref>

北京传智播客教育 www.itcast.cn


Struts216

Struts2 (用拦截器添加工作流)

考察内置拦截器

VALIDATION拦截器

不同于workflow拦截器使用硬编码方式进行校验,该拦截器是struts2框架的一部分,用于验证框架.

也会使用ValidationAware方法存放错误信息,工作流验证错误消息时,并不知道消息由谁创建.这

不是什么问题,主要是验证拦截器先于工作流拦截器之前启动.

北京传智播客教育 www.itcast.cn


Struts217

Struts2 (用拦截器添加工作流)

考察内置拦截器

Prepare拦截器

调用action的prepare()方法[需要实现Preparable接口],在调用某些方法之前,执行某些准备工

作.还可为不同方法指定不同的预备方法.但prepare()方法始终都要执行.而且还可以关闭该拦截器

通过传递参数给该拦截器alwaysInvokePrepare – 默认值为true.

北京传智播客教育 www.itcast.cn


Struts218

Struts2 (用拦截器添加工作流)

考察内置拦截器

ModelDriven拦截器

模型驱动拦截器通过调用getModel()方法将model对象放置到valueStack顶端,用来接受请求

中的参数.该拦截器改变了工作流,不然params拦截器会将请求参数直接传递到action中.

北京传智播客教育 www.itcast.cn


Struts219

Struts2 (用拦截器添加工作流)

考察内置拦截器

各种拦截器

Exception

捕获异常并按类型映射他们到指定的错误页面,它位于栈顶以确保可以捕获到任何错误

面.

<global-results>

<result name="error">/chapterFour/Error.jsp</result>

</global-results>

<global-exception-mappings>

<exception-mapping exception="java.lang.Exception"

result="error"/>

</global-exception-mappings>

异常发生时,该拦截器会创建ExceptionHolder对象并放置到栈顶.该类是对栈

跟踪信息的异常包装.并作为javabean属性可通过标签访问.

Exception Name: <s:property value="exception" />

What you did wrong:<s:property value="exceptionStack" />

北京传智播客教育 www.itcast.cn


Struts220

Struts2 (用拦截器添加工作流)

考察内置拦截器

Tocken和Tocken-session

避免重复提交.tocken拦截器通过请求传递令牌值给拦截器,如果值重复出现则说明重复提交了.

两者不同之处是是否有更多的处理方式.

Scoped-ModelDriven

该拦截器支持跨越多个请求的向导方式的持久化处理.

ExeAndWait

请求耗时执行,给个页面作为反馈.防止用户变得焦躁.

<interceptor name="execAndWait" />

<result name="wait">/xxx.jsp</result>

<meta http-equiv="refresh" content="2;url=<s:url/>"/>

北京传智播客教育 www.itcast.cn


Struts221

Struts2 (用拦截器添加工作流)

考察内置拦截器

内置栈

除了默认栈以外,还有很多其它的栈可供使用.

北京传智播客教育 www.itcast.cn


Struts222

Struts2 (用拦截器添加工作流)

声明拦截器

Xml方式支持拦截器声明,注解方式目前还不支持.

声明单独的拦截器和拦截器栈

北京传智播客教育 www.itcast.cn


Struts223

Struts2 (用拦截器添加工作流)

声明拦截器

映射拦截器到action

<action name="MyAction" class="org.actions.myactions.MyAction">

<interceptor-ref name="timer"/>

<interceptor-ref name="logger"/>

<result>Success.jsp</result>

</action>

以上设置是不包含默认拦截器栈的,因此功能有限.

<action name="MyAction" class="org.actions.myactions.MyAction">

<interceptor-ref name="timer"/>

<interceptor-ref name="logger"/>

<interceptor-ref name="defaultStack"/>

<result>Success.jsp</result>

</action>

可以改变默认拦截器栈的设置:

<default-interceptor-ref name="defaultStack"/>

北京传智播客教育 www.itcast.cn


Struts224

Struts2 (用拦截器添加工作流)

声明拦截器

设置/重载参数

<interceptor-ref name="workflow">

<param name="excludeMethods">input,back,cancel,browse</param>

</interceptor-ref>

<action name="YourAction" class="org.actions.youractions.YourAction">

<interceptor-ref name="defaultStack">

<param name="validation.excludeMethods">doSomething</param>

</interceptor-ref>

<result>Success.jsp</result>

</action>

北京传智播客教育 www.itcast.cn


Struts225

Struts2 (用拦截器添加工作流)

构建自己的拦截器

实现拦截器接口

com.opensymphony.xwork2.interceptor.Interceptor

public interface Interceptor extends Serializable {

void destroy();

void init();

String intercept(ActionInvocation invocation) throws Exception;

}

前两个是生命周期方法.

如果你希望拦截器支持参数话类型(比如校验不包含某些方法),你可以继承一个该接口实现类.

com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.

北京传智播客教育 www.itcast.cn


Struts226

Struts2 (用拦截器添加工作流)

构建自己的拦截器

创建登录拦截器

public class Login extends ActionSupport implements SessionAware {

public String execute(){

User user = getPortfolioService().authenticateUser( getUsername(),

getPassword() );

if ( user == null ){

return INPUT;

}

else{

session.put( Struts2PortfolioConstants.USER, user );

}

return SUCCESS;

}

public void setSession(Map session) {

this.session = session;

}}

北京传智播客教育 www.itcast.cn


Struts227

Struts2 (用拦截器添加工作流)

创建认证拦截器

public class LoginInterceptor implements Interceptor {

public void destroy() {}

public void init() {}

public String intercept( ActionInvocation actionInvocation )

throws Exception{

Map session = actionInvocation.getInvocationContext().getSession();

User user = (User) session.get("user");

if (user == null)

return Action.LOGIN;

else {

return actionInvocation.invoke();

}}}

拦截器是无状态的,不要在拦截器对象内存放数据.

北京传智播客教育 www.itcast.cn


Struts228

Struts2 (用拦截器添加工作流)

构建自己的拦截器

声明拦截器并构造默认拦截器栈

<package name="interceptorPkg" namespace="/Integerceptor"

extends="struts-default">

<interceptors>

<interceptor name="loginInterceptor" class="..LoginInterceptor"/>

<interceptor-stack name="loginStack">

<interceptor-ref name="loginInterceptor"/>

<interceptor-ref name="defaultStack"/>

</interceptor-stack>

</interceptors>

<default-interceptor-ref name="loginStack"/>

. . .

</package>

北京传智播客教育 www.itcast.cn


Struts2 ognl

Struts2(数据传输:OGNL和类型转换)

OGNL和struts2

OGNL:Object-Graph Navigation Language.

OGNL是集成进struts框架中比较强大的技术有助于数据传输和类型转换.OGNL由表达式语言和类型

转换器组成.

表达式语言:

我们已经在jsp表单input名和jsp标签使用该语言了.他用来绑定java端的数据属性和基于字符串的

视图层表示.表达式语言甚至可以进行方法调用,目的就在于方便数据访问.大多数时候OGNL表达式不

需要转义,如需转义的话,需要用到%{表达式}符号.框架会把它按照表达式来处理而不是解释成字符

串语义.

北京传智播客教育 www.itcast.cn


Struts2 ognl1

Struts2 (数据传输:OGNL和类型转换)

如何工作

北京传智播客教育 www.itcast.cn


Struts2 ognl2

Struts2 (数据传输:OGNL和类型转换)

内置类型转换器

开箱即用的转换

String—Sometimes a string is just a string.

boolean/Boolean—true and false strings can be converted to both primitive

and object versions of Boolean.

char/Character—Primitive or object.

int/Integer, float/Float, long/Long, double/Double—Primitives or objects.

Date—String version will be in SHORT format of current Locale (for example,

12/10/97).

array—Each string element must be convertible to the array's type.

List—Populated with Strings by default.

Map—Populated with Strings by default.

北京传智播客教育 www.itcast.cn


Struts2 ognl3

Struts2 (数据传输:OGNL和类型转换)

内置类型转换器

用ognl表达式映射表单字段名到属性

<s:form action="Register">

<s:textfield name="user.username" label="Username"/>

<s:password name="user.password" label="Password"/>

<s:textfield name="user.portfolioName" label="Enter a name "/>

<s:textfield name="user.age" label="Enter your age as a double "/>

<s:textfield name="user.birthday" label="birthday. (mm/dd/yy)"/>

<s:submit/>

</s:form>

private User user;//get/set

User{

private String username;

private String password;

private String portfolioName;

private Double age;

private Date birthday;//get/set

}

北京传智播客教育 www.itcast.cn


Struts2 ognl4

Struts2 (数据传输:OGNL和类型转换)

内置类型转换器

数组

<s:textfield name="ages" label="Ages"/>

<s:textfield name="ages" label="Ages"/>

<s:textfield name="ages" label="Ages"/>

<s:textfield name="names[0]" label="names"/>

<s:textfield name="names[1]" label="names"/>

<s:textfield name="names[2]" label="names"/>

Private double[] ages ;

Private String[] names = new String[10];

北京传智播客教育 www.itcast.cn


Struts2 ognl5

Struts2 (数据传输:OGNL和类型转换)

内置类型转换器

List

private List lastNames ;

private List middleNames ;

不必预初始化集合.默认转换成字符串.

<s:textfield name="middleNames[0]" label="middleNames"/>

<s:textfield name="middleNames[1]" label="middleNames"/>

<s:textfield name="middleNames[2]" label="middleNames"/>

<s:textfield name="lastNames" label="lastNames"/>

<s:textfield name="lastNames" label="lastNames"/>

<s:textfield name="lastNames" label="lastNames"/>

北京传智播客教育 www.itcast.cn


Struts2 ognl6

Struts2 (数据传输:OGNL和类型转换)

内置类型转换器

指定List中的数据类型

若想显式指定数据类型,可通过属性文件的方式指定[XxxAction-conversion.properties].

属性文件和Action类放在一起.

[Element_weights=java.lang.Double]

<s:textfield name="weights[0]" label="weights"/>

<s:textfield name="weights[1]" label="weights"/>

<s:textfield name="weights[2]" label="weights"/>

private List weights;

如果使用java5的泛型,则可以省略属性文件的配置.

北京传智播客教育 www.itcast.cn


Struts2 ognl7

Struts2 (数据传输:OGNL和类型转换)

内置类型转换器

集合中是java对象

<s:textfield name="users[0].username" label="Usernames"/>

<s:textfield name="users[1].username" label="Usernames"/>

<s:textfield name="users[2].username" label="Usernames"/>

private List users ;

Element-users=manning.utils.User

<s:textfield name="users.username" label="Usernames"/>

<s:textfield name="users.username" label="Usernames"/>

<s:textfield name="users.username" label="Usernames"/>

北京传智播客教育 www.itcast.cn


Struts2 ognl8

Struts2 (数据传输:OGNL和类型转换)

内置类型转换器

Map<String,String>

<s:textfield name="maidenNames.mary" label="Maiden Name"/>

<s:textfield name="maidenNames.jane" label="Maiden Name"/>

<s:textfield name="maidenNames.hellen" label="Maiden Name"/>

<s:textfield name="maidenNames['beth']" label="Maiden Name"/>

<s:textfield name="maidenNames['sharon']" label="Maiden Name"/>

<s:textfield name="maidenNames['martha']" label="Maiden Name"/>

private Map maidenNames ;

Map<String,User>

Element_myUsers=manning.utils.User

<s:textfield name="myUsers['chad'].username" label="names"/>

<s:textfield name="myUsers.chad.birthday" label="birthday"/>

private Map myUsers ;

北京传智播客教育 www.itcast.cn


Struts2 ognl9

Struts2 (数据传输:OGNL和类型转换)

内置类型转换器

Map<Integer,User>

Key_myOrderedUsers=java.lang.Integer

Element_myOrderedUsers=manning.utils.User

<s:textfield name="myOrderedUsers[1].birthday" label="birthday"/>

<s:textfield name="myOrderedUsers[2].birthday" label="birthday"/>

<s:textfield name="myOrderedUsers[3].birthday" label="birthday"/>

private Map myOrderedUsers ;

北京传智播客教育 www.itcast.cn


Struts2 ognl10

Struts2 (数据传输:OGNL和类型转换)

自定义类型转换器

实现ognl.TypeConverter接口

继承类org.apache.struts2.util.StrutsTypeConverter.

public abstract Object convertFromString(Map context, String[] values,

Class toClass);

public abstract String convertToString(Map context, Object o);

北京传智播客教育 www.itcast.cn


Struts2 ognl11

Struts2 (数据传输:OGNL和类型转换)

在字符串和Date对象间转换(续)

public class DateTypeConverter extends StrutsTypeConverter {

public Object convertFromString(Map context, String[] values,

Class toClass) {

String date = values[0];

SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");

return sdf.parse(date);

}

public String convertToString(Map context, Object o) {

SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");

return sdf.format((Date)o);

}

}

北京传智播客教育 www.itcast.cn


Struts2 ognl12

Struts2 (数据传输:OGNL和类型转换)

配置自定义类型转换器

属性相关:

属性文件同action类放在一起

private Date birthday;

[CustomConverterTest-conversion.properties]

birthday=manning.utils.DateTypeConverter

全局类型转换:

[classpath]/xwork-conversion.properties

manning.utils.Circle=manning.utils.DateTypeConverter

北京传智播客教育 www.itcast.cn


Struts229

Struts2(构建视图:标签和结果)

tag

ActionContext和OGNL

OGNL表达式可以解析任何对象集合,值栈只是其中之一,而且是默认值.

ActionContext包含了所有范围的数据.每个ognl表达式解析时都需要一个根对象

北京传智播客教育 www.itcast.cn


Struts230

Struts2 (构建视图:标签和结果)

tag

ActionContext和OGNL

北京传智播客教育 www.itcast.cn


Struts231

Struts2 (构建视图:标签和结果)

tag

ActionContext和OGNL

选择根对象:

#session['user'],默认情况下,ValueStack是根对象.

#表示命名对象,OGNL上下文就是ActionContext.除了使用OGNL表达式语言外,你还可以使用

其他的EL语言.

北京传智播客教育 www.itcast.cn


Struts232

Struts2 (构建视图:标签和结果)

tag

ActionContext和OGNL

值栈-虚拟对象:

当struts2接受到请求后,马上创建一个ActionContext、一个ValueStack和一个

Action对象.Action对象立刻放到值栈上以用于ognl访问.

顶层对象覆盖低层对象

有多种方法可将数据放

到值栈上.比如push标

签.

OGNL不仅可以访问java

Bean属性,还可以访问

工具方法.(但不推荐

使用)

北京传智播客教育 www.itcast.cn


Struts233

Struts2 (构建视图:标签和结果)

tag

ActionContext和OGNL

标签API语法

Jsp语法:

<s:property value="name" />

<s:form action="Register">

<s:textfield name="username" label="Username"/>

<s:password name="password" label="Password"/> <s:submit value="Submit"/>

</s:form>

Velocity语法:

#sproperty( "value=name" )

#sform ("action=Register")

#stextfield ("label=Username" "name=username")

#spassword ( "label=Password" "name=password")

#ssubmit ("value=Submit")

#end

FreeMarker语法:

<@s.property value="name"/>

北京传智播客教育 www.itcast.cn


Struts234

Struts2 (构建视图:标签和结果)

ActionContext和OGNL

使用ognl设值属性值

String和非String属性

<s:property value="nonExistingProperty" />

<s:property value="nonExistingProperty" default="doesNotExist" />

没有通过#指定范围,默认是ValueStack.value属性指对象,不是String.OGNL会进行解析,

如果属性不存在,返回Null,null会转变成空串.default属性是String类型,不是OGNL表达式.

强制OGNL解析

<s:property value="nonExistingProperty" default="%{myDefaultString}" />

经测试,default属性强制应用ognl不好使,但label可以.??

<s:textfield name="username" label="your name" />

<s:textfield name="username" label="%{#session.user}" />

北京传智播客教育 www.itcast.cn


Struts235

Struts2 (构建视图:标签和结果)

ActionContext和OGNL

Data标签

该类标签用于从值栈中读写数据.

property, set, push, bean,action

北京传智播客教育 www.itcast.cn


Struts236

Struts2 (构建视图:标签和结果)

tag

Property

访问对象的属性.

北京传智播客教育 www.itcast.cn


Struts237

Struts2 (构建视图:标签和结果)

tag

Set

指定属性到另外一个名称,更方便引用.也可指定范围,默认在ActionContext[action]中的命名对

象.可直接通过#myObject访问.

id与name不推荐使用,推荐使用var属性.

<s:set name="username" value="user.username"/>

Hello, <s:property value="#username"/>. How are you?

<s:set name="username" scope="application" value="user.username"/>

<s:property value="#application['username']"/>. How are you?

北京传智播客教育 www.itcast.cn


Struts238

Struts2 (构建视图:标签和结果)

tag

push

set标签是创建值的新的引用,push是放置新的属性到值栈上.当你需要对一个对象进行大量操作时会

有用.标签结束后会从栈顶删除该属性.而且该对象只放到值栈中.而set标签可以放到任意范围中.

<s:push value="user">

This is the "<s:property value="portfolioName"/>" portfolio,

created by none other than <s:property value="username"/>

</s:push>

以上展示了push标签放置了一个叫user的属性到值栈,该属性是在action定义的javabean属性.引

用的时候不需要User.xxx来访问了.

北京传智播客教育 www.itcast.cn


Struts239

Struts2 (构建视图:标签和结果)

tag

bean

bean标签好像是set和push的混合,不同之处是他不操纵已有对象,而是创建新的对象实例

放置到值栈上也可在ActionContext设置对他的顶层引用.默认是放到值栈上,并且只在标签内部

可用,如果想标签外部可用,可通过使用var[struts2后期版本不建议id,改为var]属性来指定引

用名,该引用会作为命名的参数存在于ActionContext中,并且通过#访问.此类对象必须遵循标准

javabean规范.并可通过param标签初始化.

北京传智播客教育 www.itcast.cn


Struts240

Struts2 (构建视图:标签和结果)

tag

Bean

<s:bean name="org.apache.struts2.util.Counter" var="counter">

<s:param name="last" value="7"/>

</s:bean>

<s:iterator value="#counter">

<li><s:property/></li>

</s:iterator>

Counter:完全遵循javabean规范.

<s:bean name="manning.utils.JokeBean" >

<s:param name="jokeType">knockknock</s:param>

<s:property value="startAJoke()"/>

</s:bean>

以上代码把JokeBean对象放到了ValueStack上,而不是在ActionContext中,因此对象若在

栈中的化即可直接引用属性和方法了.

北京传智播客教育 www.itcast.cn


Struts241

Struts2 (构建视图:标签和结果)

tag

Action

该标签允许我们在视图层调用其他action,executeResult属性表明是否要将

action的执行结果写到当前的渲染页面.默认使用当前action名称空间.

北京传智播客教育 www.itcast.cn


Struts242

Struts2 (构建视图:标签和结果)

tag

Action

<h3>Action Tag</h3>

<h4>This line is from the ActionTag action's result.</h4>

<s:action name="TargetAction" executeResult="true"/>

<h4>This line is before the ActionTag invokes the secondary action.</h4>

<s:action name="TargetAction"/>

<h4>Secondary action has fired now.</h4>

<h5>Request attribute set by secondary action = </h5>

<pre> <s:property value="#request.dataFromSecondAction"/></pre>

北京传智播客教育 www.itcast.cn


Struts243

Struts2 (构建视图:标签和结果)

tag

Iterator

<s:iterator value="users" status="itStatus">

<li>

<s:property value="#itStatus.count" />

<s:property value="portfolioName"/>

</li>

</s:iterator>

标签体内部循环中的每个对象依次放入栈顶,这样方便我们引用.而且也提供了对基本信息的访问,

通过定义变量到ActionContext中.比如当前循环是奇数/偶数,等等.

北京传智播客教育 www.itcast.cn


Struts244

Struts2 (构建视图:标签和结果)

tag

If else

<s:if test="user.age > 35">This user is too old.</s:if>

<s:elseif test="user.age < 35">This user is too young</s:elseif>

<s:else>This user is just right</s:else>

北京传智播客教育 www.itcast.cn


Struts245

Struts2 (构建视图:标签和结果)

tag

include

在当前页面包含另外资源的渲染.而且还可以传递请求参数给该资源.action标

签只能包含action,而该标签可包含任何servlet资源.同<jsp:include>标签很相似.

Value属性是字符串类型,如想包含由变量定义的动态资源[路径]的话,需要使用%{表达式}.

该标签和struts2框架结合更加紧密.而且支持URL重写.

北京传智播客教育 www.itcast.cn


Struts246

Struts2 (构建视图:标签和结果)

tag

url

管理url,控制参数和自动持久化session.

action属性:只能指向action.

vlaue可以指向任何有效web资源.如果也想指向action的话,需要加.action后缀.

URL = <s:url value="IteratorTag.action"/>

<a href='<s:url value="IteratorTag.action" />'> Click Me </a>

输出:

URL = IteratorTag.action

<a href='IteratorTag.action'> Click Me </a>

----------------------------------------------

URL = <s:url action="IteratorTag" var="myUrl">

<s:param name="id" value="2"/>

</s:url>

<a href='<s:property value="#myUrl" />'> Click Me </a>

输出:

URL =<a href='/manningHelloWorld/chapterSix/IteratorTag.action?id=2'>

Click Me</a>

北京传智播客教育 www.itcast.cn


Struts247

Struts2 (构建视图:标签和结果)

tag

url

北京传智播客教育 www.itcast.cn


Struts248

Struts2 (构建视图:标签和结果)

tag

i18n text

text 标签用于从资源束中检索消息显示语言相关的文本.

i18n 标签用于指定资源束.

<s:i18n name="manning.chapterSix.myResourceBundle_tr">

In <s:text name="language"/>,

<s:text name="girl" var="foreignWord"/>

</s:i18n>

"<s:property value="#foreignWord"/>" means girl.

北京传智播客教育 www.itcast.cn


Struts249

Struts2 (构建视图:标签和结果)

tag

param

传递参数.

北京传智播客教育 www.itcast.cn


Struts250

Struts2 (构建视图:标签和结果)

tag

ognl

使用ognl表达式语言引用java环境中的数据属性,使用OGNL的类型转换器管理http的字符

串和java中的类型的转换工作.

引用javabean属性

Person.father.father.firstName:属性链

Getting/setting:

<s:form action="Register">

<s:textfield name="username" label="Username"/>

<s:password name="password" label="Password"/>

<s:textfield name="portfolioName" label="Enter a portfolio name."/>

<s:submit/>

</s:form>

user.portfolio.name:以上OGNL表达式都是要通过set方法完成字符串属性知道java类型值得

转换.而且框架会为我们处理null的情况.

北京传智播客教育 www.itcast.cn


Struts251

Struts2 (构建视图:标签和结果)

tag

ognl

操纵List和Array

北京传智播客教育 www.itcast.cn


Struts252

Struts2 (构建视图:标签和结果)

tag

ognl

操纵List和Array

ognl也可直接创建集合对象.比如我们想直接在视图层为下拉列表框创建选项:

北京传智播客教育 www.itcast.cn


Struts253

Struts2 (构建视图:标签和结果)

tag

Ognl

ognl操纵map.

ognl用多种方式使用#号,每种是不同的.动态map对于动态单选按扭组很有用.

创建map与创建list语法很相似,不同的是map前需要加"#"号.

北京传智播客教育 www.itcast.cn


Struts254

Struts2 (构建视图:标签和结果)

tag

Ognl

过滤和投影集合

Collectionname.{expression}:投影[子集]

Collectionname.{?expression}:过滤

北京传智播客教育 www.itcast.cn


Struts255

Struts2 (构建视图:标签和结果)

tag

Ognl

高级表达式语言特征

北京传智播客教育 www.itcast.cn


Struts256

Struts2 (构建视图:标签和结果)

tag

Ognl

高级表达式语言特征

OGNL还允许在一个表达式里通过","号分隔连接多个子表达式

User.age=10,user.name="chad",user.username

最后一个表达式返回的值是该表达式的值.

北京传智播客教育 www.itcast.cn


Struts257

Struts2 (构建视图:标签和结果)

tag

Ognl

调用方法:

上图假设utilityBean事先被放到ValueStack上,因此在OGNL表达式就可以忽略对象名.

因为默认情况下,直接对ValueStack进行解析.我们先调用makeRandomNumber()方法,然

后再访问属性或方法.这两中方案没有什么不同.其实我们以前直接访问javabean属性也是

要通过get方法.

北京传智播客教育 www.itcast.cn


Struts258

Struts2 (构建视图:标签和结果)

tag

Ognl

访问静态方法和字段:

两种方法访问静态属性与方法.一种要求完整类名,另一个直接解析ValueStack.

语法如下:

@[FullClassName]@[property or methodCall]

@[email protected]

@[email protected]()

@[email protected]

@[email protected]()

Vs:ValueStack

北京传智播客教育 www.itcast.cn


Struts2 ui

Struts2(UI组件标签)

不单是表单元素

生成html标记

<s:textfield name="username" label="Username"/>

html:

<td class="tdLabel">

<label for="Register_username" class="label">Username:</label>

</td>

<td>

<input type="text" name="username" value="" id="Register_username"/>

</td>

绑定表单字段到值栈属性

继承类型转换 校验 国际化

北京传智播客教育 www.itcast.cn


Struts2 ui1

Struts2(UI组件标签)

Tag tempate theme

北京传智播客教育 www.itcast.cn


Struts2 ui2

Struts2(UI组件标签)

Tag tempate theme

Tag

标签API可用任何技术实现,默认struts2给出了jsp velociy freemarker实现.不

论哪种实现, 本地标签都会代理处理过程.框架管理模型数据和业务逻辑 收集数据

这些数据可以来自属性 参数 actioncontxt valuestack.

tempate

模板携带数据模型混合一些静态数据部分,最终生成html代码

theme

每个标签都有模板不同的版本,每个版本属于不同的主题.主题是模板组,使用使用一致的风格和行为

进行渲染.例如某个主题用table进行渲染,而令一个用css进行渲染.主题由框架分成几束,可以从中

选择.有几种方式指定主题,默认所有标签都用xhtml主题进行渲染.可以为整个应用/某个页面/某个

标签应用不同主题.struts给出了四个主题可供选择.

北京传智播客教育 www.itcast.cn


Struts2 ui3

Struts2(UI组件标签)

Tag tempate theme

改变主题

需要改框架的默认值,所有的默认值都定义在org.apache.struts2.defaut.properties文件中.

若想覆盖的话,定义自己的属性文件

struts.properties

struts.ui.theme=css_xhtml

同样也可以通过指定组件自身的theme属性来使用特定的主题.或者给form

组件指定主题,则表单内的所有组件都会使用该主题.

<s:textfield theme="" />

<s:form theme="" />

北京传智播客教育 www.itcast.cn


Struts2 ui4

Struts2(UI组件标签)

Tag tempate theme

常规属性

常规属性区分string类型和非串类型.是否需要%{}强制执行.

北京传智播客教育 www.itcast.cn


Struts259

Struts2

北京传智播客教育 www.itcast.cn


Struts2 ui5

Struts2(UI组件标签)

Tag tempate theme

简单组件

<s:head/>

该标签必须放在head标记内.通常生成css的link和js连接.

<head>

<title>Portfolio Registration</title>

</head>

<link rel="stylesheet" href=" . . . styles.css" type="text/css"/>

<script language="JavaScript" type="text/javascript" src=". . .dojo.js"/>

<script language="JavaScript" type="text/javascript" src="dojoRequire.js"/>

北京传智播客教育 www.itcast.cn


Struts2 ui6

Struts2(UI组件标签)

Tag tempate theme

textfield

Key用于抽取资源束文件值, global-resources.properties

Value属性可不写,和name保持一致.设key以后,lable可不写.

需要配置struts.xml文件指定资源束位置

struts.custom.i18n.resources=global-messages

北京传智播客教育 www.itcast.cn


Struts2 ui7

Struts2(UI组件标签)

Tag tempate theme

textarea

北京传智播客教育 www.itcast.cn


Struts2 ui8

Struts2(UI组件标签)

Tag tempate theme

checkbox

可选框,绑定的javabean属性需要是boolean类型

fieldValue:提交之后实际的值.

北京传智播客教育 www.itcast.cn


Struts2 ui9

Struts2(UI组件标签)

Tag tempate theme

Select:name属性用于javabean属性绑定.

<s:select name="user.name" list="{'tom','jerry'}" />

<select name="user.name" id="formname_user_name">

<option value="tom">tom</option>

<option value="jerry">jerry</option>

</select>

北京传智播客教育 www.itcast.cn


Struts2 ui10

Struts2(UI组件标签)

Tag tempate theme

Select

[list]

<s:select name="username" list='users' listKey="username"

listValue="username" label="Select an artist" />

<select name="username" id="SelectPortfolio_username">

<option value="Jimmy">Jimmy</option>

<option value="Chad">Chad</option>

<option value="Mary">Mary</option>

</select>

[map]

<s:select name="username" list='users' listKey="username"

listValue="value.username" label="Select an artist" />

北京传智播客教育 www.itcast.cn


Struts2 ui11

Struts2(UI组件标签)

Tag tempate theme

Radio/checkboxlist

北京传智播客教育 www.itcast.cn


Struts2 ui12

Struts2(UI组件标签)

集合化的组件

预先初始化集合组件

public String execute(){

List users = ..;

return SUCCESS;

}

<s:radio name="username" list='users' value="defaultUsername"

listKey="username" listValue="username" label="Select an artist" />

<input type="radio" name="username" value="Jimmy"/>

<input type="radio" name="username" value="Charlie Joe"/>

<input type="radio" name="username" checked="checked" value="Chad"/>

<input type="radio" name="username" value="Mary"/>

北京传智播客教育 www.itcast.cn


Struts2 ui13

Struts2(UI组件标签)

集合化的组件

额外标签

label创建只读标签

<s:label name="username" label="Username" />

hidden

<s:hidden name="username" />

双选框[联动]

北京传智播客教育 www.itcast.cn


Struts2 ui14

Struts2(UI组件标签)

集合化的组件

双选框[联动]

<s:doubleselect name="username" list='users' listKey="username"

listValue="username" doubleName="portfolioName"

doubleList="portfolios" doubleListValue="name" />

Users是值栈中的User集合,每个User有username属性和

Portfolios集合,该集合每个元素是portfolios对象.

北京传智播客教育 www.itcast.cn


Struts2 result

Struts2(Result细化)

action之后的活动

action之行完成后,返回控制串,他是mvc中v的部分.通常为jsp,如果是freemarker或者重定向到

任意URL该如何处理呢?

使用自定义结果类型构建ajax应用

传统的web应用和ajax应用比较

北京传智播客教育 www.itcast.cn


Struts2 result1

Struts2(Result细化)

常用结果类型

<result-type name="freemarker"

class="org.apache.struts2.views.freemarker.FreemarkerResult"/>

[struts-default.xml]

北京传智播客教育 www.itcast.cn


Struts2 result2

Struts2(Result细化)

RequestDispatcher又称Dispatcher

<result-type name="dispatcher"

class=" . . . ServletDispatcherResult" default="true"/>

<action name="PortfolioHomePage" class=".chapEight.PortfolioHomePage">

<result>/chapterEight/PortfolioHomePage.jsp</result>

</action>

作为include分发

<s:action name="" executeResult="true" />

安装RequestDispatcherResult

<result-type name="dispatcher"

class="org.apache.struts2.dispatcher.ServletDispatcherResult"

default="true"/>

北京传智播客教育 www.itcast.cn


Struts2 result3

Struts2(Result细化)

RequestDispatcher又称Dispatcher

<action name="SelectPortfolio"

class="manning.chapterSeven.SelectPortfolio">

<result type="dispatcher">/chapterSeven/SelectPortfolio.jsp</result>

</action>

<action name="SelectPortfolio"

class="manning.chapterSeven.SelectPortfolio">

<result type="dispatcher" >

<param name="location">/chapterSeven/SelectPortfolio.jsp</param>

<param name="parse">true</param>

</result>

</action>

北京传智播客教育 www.itcast.cn


Struts2 result4

Struts2(Result细化)

ServletRedirectResult又称 redirect

安装结果类型

<result-type name="redirect"

class="org.apache.struts2.dispatcher.ServletRedirectResult"/>

<action name="SendUserToSearchEngineAction" class="myActionClass">

<result type='redirect'>http://www.google.com</result>

</action>

嵌入ognl创建动态位置[配置文件中引用ognl表达式用$而不是%]

<action name="SendUserToSearchEngineAction" class="myActionClass">

<result type='redirect' >

http://www.google.com/?myParam=${defaultUsername}

</result>

</action>

北京传智播客教育 www.itcast.cn


Struts2 result5

Struts2(Result细化)

ServletActionRedirectResult又称 redirectAction

<action name="Login" class="manning.chapterSeven.Login">

<result type="redirect">/secure/AdminPortfolio.action</result>

</action>

<action name="Login" class="manning.chapterEight.Login">

<result type="redirectAction">

<param name="actionName">AdminPortfolio</param>

<param name="namespace">/chapterEight/secure</param>

</result>

</action>

<action name="Login" class="manning.chapterEight.Login">

<result type="redirectAction">

<param name="actionName">AdminPortfolio</param>

<param name="namespace">/chapterEight/secure</param>

<param name="param1">hardCodedValue</param>

<param name="param2">${testProperty}</param>

</result>

</action>

北京传智播客教育 www.itcast.cn


Struts2 result6

Struts2(Result细化)

Jsp的替代

freemarker和velocity

VelocityResult又称velocity

[安装velocityResult]

<result-type name="velocity"

class="org.apache.struts2.dispatcher.VelocityResult"/>

<result-types>

[设置默认值]

<result-type name="velocity"

class="org.apache.struts2.dispatcher.VelocityResult"

default="true"/>

</result-types>

[使用Velocity结果]

<action name="ViewPortfolioVM" class="...ViewPortfolio" >

<result type="velocity">/chapterEight/ViewPortfolio.vm</result>

</action>

北京传智播客教育 www.itcast.cn


Struts2 result7

Struts2(Result细化)

Velocity模板

<html>

<head>

<title>Viewing Portfolio</title>

</head>

<body>

<h5>

This is the #sproperty ("value=portfolioName") portfolio of the

artist currently known as #sproperty ("value=username")

</h5>

<a href='#surl ("action=PortfolioHomePage")'>Home</a>

</body>

</html>

北京传智播客教育 www.itcast.cn


Struts2 result8

Struts2(Result细化)

FreemarkerResult又称 freemarker

安装结果

<result-type name="freemarker"

class="org.apache.struts2.views.freemarker.FreemarkerResult"/>

设置默认值

<result-types>

<result-type name="freemarker"

class="org.apache.struts2.views.freemarker.FreemarkerResult"

default="true"/>

</result-types>

使用结果

<action name="ViewPortfolioFM"

class="manning.chapterEight.ViewPortfolio" >

<result type="freemarker">/chapterEight/ViewPortfolio.ftl</result>

</action>

北京传智播客教育 www.itcast.cn


Struts2 result9

Struts2(Result细化)

FreemarkerResult又称 freemarker

<html>

<head>

<title>Viewing Portfolio</title>

</head>

<body>

<h5>

This is the <@s.property value="portfolioName" /> portfolio of

the artist currently known as <@s.property value="username" />

</h5>

<a href="<@s.url action='PortfolioHomePage'/>">Home</a>

</body>

</html>

北京传智播客教育 www.itcast.cn


Struts2 result10

Struts2(Result细化)

全局结果

<global-results>

<result name="error">/chapterFour/Error.jsp</result>

</global-results>

北京传智播客教育 www.itcast.cn


Struts260

Struts2(提升应用程序)

同Spring hibernate/JPA整合

添加spring到struts2

下载安装spring plug-in.该插件提供了对象工厂的扩展,有机会管理创建的所有的

对象,[spring-plug-in.jar和spring.jar放到WEB-INF/lib下]

需要创建spring容器.

<listener>

<listener-class>org.springframework.web.context.ContextLoaderListener

</listener-class>

</listener>

[显式声明struts2的objectFactory为spring(可选)]

struts.objectFactory=spring

北京传智播客教育 www.itcast.cn


Struts261

Struts2(提升应用程序)

同Spring hibernate/JPA整合

让spring管理aciton的创建

[spring context.xml]

<bean id="springManagedLoginAction" class="manning.chapterNine.Login"

scope="prototype">

<property name="portfolioService" ref="portfolioService"/>

</bean>

[struts.xml]

<action name="Login" class="springManagedLoginAction">

<result type="redirectAction">

<param name="actionName">AdminPortfolio</param>

<param name="namespace">/chapterEight/secure</param>

</result>

<result name="input">/chapterEight/Login.jsp</result>

</action>

北京传智播客教育 www.itcast.cn


Struts262

Struts2(提升应用程序)

同Spring hibernate/JPA整合

平衡自动装配action

name type construct autodetect

action不需配置在上下文中,即spring不负责action实例化.默认按照名称自动装配所有的对

象.[属性名必须和bean的id一致,setXXX]

struts.objectFactory.spring.autoWire=type

<constant name="struts.objectFactory.spring.autoWire" value="type"/>

北京传智播客教育 www.itcast.cn


Struts263

Struts2(体验验证框架)

验证框架结构

北京传智播客教育 www.itcast.cn


Struts264

Struts2(体验验证框架)

struts2的流程中的验证框架

基本验证回顾

ActionSupport实现了Validateable和ValidationAware接口.由workflow拦截器按顺序调用.

前者的validate()方法进行校验,后者负责将错误信息保存起来.判断是否错误信息.

引入验证框架工作流

验证框架同以前的基本校验共享一些功能,都是用validationAware接口存储错误信息,用workfl

Ow拦截器导向input页面.实际上,唯独需要改变的是validation本身,而且很明显.该拦截器是验证

框架的入口,

需要引入validation拦截器,该拦截器工作时,会寻找所有的验证资源文件.

<interceptor-ref name="params"/>

<interceptor-ref name="conversionError"/>

<interceptor-ref name="validation"/>

<interceptor-ref name="workflow"/>

北京传智播客教育 www.itcast.cn


Struts265

Struts2(体验验证框架)

验证框架工作流

北京传智播客教育 www.itcast.cn


Struts266

Struts2(体验验证框架)

验证框架工作流

validation拦截器工作workflow之前,workflow拦截器由两步构成,先调用validate()方

法,这也是基本验证的入口点.既然我们使用了验证框架,就可以不实现该方法.

改造action支持验证框架

以前基本验证代码:

public void validate(){

PortfolioService ps = getPortfolioService();

if ( getPassword().length() == 0 ){

addFieldError( "password", getText("password.required") );

}

if ( getUsername().length() == 0 ){

addFieldError( "username", getText("username.required") );

}

. . .

}

北京传智播客教育 www.itcast.cn


Struts267

Struts2(体验验证框架)

声明验证元数据文件ActionClass-validation.xml

该文件和action类放在一起

北京传智播客教育 www.itcast.cn


Struts268

Struts2(体验验证框架)

声明验证元数据文件ActionClass-validations.xml

北京传智播客教育 www.itcast.cn


Struts269

Struts2(体验验证框架)

声明验证元数据文件ActionClass-validations.xml

Field校验器

该校验器作用在字段上,定义完field元素后,就可以定义field-validator元素来表明哪个校验

器对该数据进行校验.如果校验没通过,会产生错误消息,并有workflow拦截器发送到input页.me

Ssage元素包含错误消息.每个field不只限于一个field-validator,可同时使用多个.

非字段校验器

可对多个字段进行校验,内置的校验器中只提供了一个非字段校验器-expression校验器.他允许你

嵌入一个包含验证逻辑的OGNL表达式.

<validator type="expression">

<param name="expression">password==rePassword</param>

<message>password is not the same to rePassword!</message>

</validator>

北京传智播客教育 www.itcast.cn


Struts270

Struts2(体验验证框架)

声明验证元数据文件ActionClass-validations.xml

消息元素选项

<field name="username">

<field-validator type="stringlength">

<param name="maxLength">8</param>

<param name="minLength">5</param>

<message>While ${username} is a nice name, a valid username

must be between ${minLength} and ${maxLength}

characters long.

</message>

</field-validator>

</field>

<field name="portfolioName">

<field-validator type="requiredstring">

<message key="portfolioName.required"/>

</field-validator>

</field>

user.exists=This user ${username} already exists.

北京传智播客教育 www.itcast.cn


Struts271

Struts2 (体验验证框架)

考察内置校验器(略)

北京传智播客教育 www.itcast.cn


Struts272

Struts2 (体验验证框架)

自定义校验器

com.opensymphony.xwork2.validator(接口)

com.opensymphony.xwork2.validator.validators.ValidatorSupport(非字段验证)

com.opensymphony.xwork2.validator.validators.FieldValidatorSupport(字段验证)

publicclass DatePatternValidator extends FieldValidatorSupport {

private String datePattern = "yyyy-MM-dd";

publicvoid validate(Object object) throws ValidationException {

String field = getFieldName();

String value = (String) getFieldValue(field, object);

try {

SimpleDateFormat sdf = new SimpleDateFormat(datePattern);

sdf.parse(value);

} catch (Exception e) {

addFieldError(field, object);

}

}

北京传智播客教育 www.itcast.cn


Struts273

Struts2 (体验验证框架)

自定义校验器

校验器带参数,xml向属性传参如下:

<field-validator type="passwordintegrity">

<param name="datePattern">yyyy/MM/dd</param>

<message>date format is wrong </message>

</field-validator>

内置校验器

com/opensymphony/xwork2/validator/validators/default.xml

使用自定义验证器

Classpath:src/validators.xml

<validators>

<validator name="passwordintegrity"

class="manning.utils.PasswordIntegrityValidator"/>

</validators>

北京传智播客教育 www.itcast.cn


Struts274

Struts2 (体验验证框架)

验证框架高级主题

域对象级别校验

定义域对象相关的验证元数据User-validation.xml内容与前边定义的验证元数据相同.只是暴露

的范围不同.为了使用User级别的验证,需要在使用User的action和这些验证之间做个连接.该工作

由visitor校验器完成.他在action相关的验证文件中.message是错误消息的前缀.

北京传智播客教育 www.itcast.cn


Struts275

Struts2 (体验验证框架)

域对象级别校验

对模型驱动action使用校验框架

action级别验证元数据字段名变为model.

appendPrefix参数告诉visitor校验器不再需要对字段名预加前缀.设置为false允许校验器寻找

顶级的字段名.

北京传智播客教育 www.itcast.cn


Struts276

Struts2 (体验验证框架)

使用校验上下文提炼校验

何时进行哪些校验—context,除了execute方法作为校验入口点外,希望定义更多的校

验入口点.

[不同方法有不同的验证规则]

<action name="BubbleSort" class="manning.sort.SortAction"

method="bubbleSort">

<result>/sort/SortResults.jsp</result>

</action>

<action name="HeapSort" class="manning.sort.SortAction" method="heapSort">

<result>/sort/SortResults.jsp</result>

</action>

需要用两个验证文件替换原来的文件即可.

SortAction-BubbleSort-validation.xml和

SortAction-HeapSort-validation.xml

[ActionClassName-aliasName-validation.xml]

注:若原文件未删除,则同样被加载,而且不会阻止其执行,所以可在原文件中定义公共的验证逻辑.

北京传智播客教育 www.itcast.cn


Struts277

Struts2 (体验验证框架)

使用校验上下文提炼校验

对visitor和域对象使用context

同一域对象对于action的不同方法有不同的验证要求.

[ClassName-aliasName-validation.xml]

User-BubbleSort-validation.xml

User-HeapSort-validation.xml

框架会自动侦测哪个action被调用,并寻找对应的文件.

如果上下文很多[12],还采用域模型相关的上下文的话,会有好多元数据.

User-thisAlias[thatAlias]-validation.xml…

visitor校验器允许开发人员通过context属性指定用户定义的上下文.我们只需要定义两个文件

即可.admin和public

User-admin-validation.xml和User-public-validation.xml

需要为别名配置visitor.

[UpdateUserAction-UpdateUserAdmin-validation.xml]

北京传智播客教育 www.itcast.cn


Struts278

Struts2 (体验验证框架)

继承

北京传智播客教育 www.itcast.cn


Struts279

Struts2 (体验验证框架)

短路

北京传智播客教育 www.itcast.cn


Struts280

Struts2 (体验验证框架)

使用注释声明验证

@Validation

public class RegisterValidationAnnotated extends ActionSupport

implements SessionAware {

@ExpressionValidator(expression = "username != password",

message = "Username and password can't be the same.")

public String execute(){...}

@RequiredStringValidator(type = ValidatorType.FIELD,

message="Email is required.")

@EmailValidator(type = ValidatorType.FIELD, key="email.invalid",

message="Email no good.")

public void setEmail(String email) {

this.email = email;

}

@StringLengthFieldValidator(type = ValidatorType.FIELD, minLength="5" ,

maxLength = "8", message = "Password must be between

${minLength} and ${maxLength} characters.")

@RequiredStringValidator(type = ValidatorType.FIELD,

message = "Password is required.")

public String getPassword() {

北京传智播客教育 www.itcast.cn


Struts281

Struts2(国际化)

使用资源束和locale检索本地文本

用资源束存储资源[PropertyResourceBundle常见实现]

[BundleName_languageCode.properties]

北京传智播客教育 www.itcast.cn


Struts282

Struts2(国际化)

使用资源束和locale检索本地文本

用资源束存储资源[PropertyResourceBundle常见实现]

用本地javaRESOURCEBUNDLES操作

Locale currentLocale = new Locale( "tr");

ResourceBundle myMessages = ResourceBundle.getBundle("EmailClientMessages",

currentLocale);

String greetingLabel = myMessages.getString( "greeting");

struts2简化国际化

struts2去哪里寻找属性文件

指定框架去哪寻找属性文件[共存]

使用i18n来完成工作.

北京传智播客教育 www.itcast.cn


Struts283

Struts2(国际化)

I18n demo

资源束名[ActionClassname_bundlename.properties]

<h4><s:text name="homepage.greeting"/></h4>

<hr>

<h5><s:text name="site.entrance.text"/></h5>

<h5><a href="<s:url action='VisitorHomePage'/>">

<s:text name="visitor"/>

</a></h5>

<h5><a href="<s:url action='ArtistHomePage'/>"><s:text name="user"/></a>

</h5>

<hr>

com.opensymphony.xwork2.TextProvider.getText()

<s:text name="homepage.greeting"/>

<s:property value="getText('homepage.greeting')"/>

北京传智播客教育 www.itcast.cn


Struts284

Struts2(国际化)

寻找位置顺序

1. ActionClass

2. MyInterface

3. MySuperClass

4. ModelDriven

5. package.properties[名称固定]

6. Domain model object exposed on the ValueStack referenced by key

7. Default ResourceBundles

北京传智播客教育 www.itcast.cn


Struts285

Struts2(国际化)

北京传智播客教育 www.itcast.cn


Struts286

Struts2(国际化)

定义默认的资源束

<constant name="struts.custom.i18n.resources" value="global-messages" />

struts.custom.i18n.resources=global-messages

struts.custom.i18n.resources=global-messages,manning.utils.otherBundle

检索资源束消息文本

<s:label key="user.username" />

user.username=Username

本地化验证错误消息文本

<field-validator type="email">

<message key="email.invalid"/>

</field-validator>

本地化类型转换错误消息文本

[Register.properties]

invalid.fieldvalue.age=Please enter a numerical value for your age.

[global-messages]

xwork.default.invalid.fieldvalue=We can not convert that to a Java type.

北京传智播客教育 www.itcast.cn


Struts287

Struts2(国际化)

通过i18n指定资源束名

<s:i18n name="manning.chapterEleven.SpecialMessages">

<s:text name="greeting"/>

</s:i18n>

参数化本地文本

1.使用ognl表达式

portfolio.view.greeting=Welcome to the ${portfolio.name} Portfolio

2.使用占位符传递参数[按顺序]

portfolio.view.tagline=Created by {0} {1}

<s:text name="portfolio.view.tagline">

<s:param value="portfolio.owner.firstName"/>

<s:param value="portfolio.owner.lastName"/>

</s:text>

<s:param>Lando</s:param>

北京传智播客教育 www.itcast.cn


Struts288

Struts2(国际化)

格式化日期和数字

timestamp=Today is {0,date,long}

<s:text name="timestamp">

<s:param value="currentDate"/>

</s:text>

item.price={0,number,currency}

北京传智播客教育 www.itcast.cn


Struts289

Struts2(国际化)

重载框架locale检测

http header[locale]若想指定locale?

指定locale

i18n拦截器

检查request是否包含request_locale参数.若有,则将该值设置到ActionContext中.

<s:form>

<s:radio name="request_locale" list="locales" value="locale"/>

<s:submit key="chooseLanguage"/>

</s:form>

[Action]

static public final Map locales = new HashMap();

static {

locales.put("en_US", "English");

locales.put("es_SP", "Spanish");

}

public Map getLocales (){

return locales;

}

北京传智播客教育 www.itcast.cn


Struts290

Struts2(国际化)

i18n拦截器

LocaleProvider.该拦截器除了放置locale信息在当前的actionContext以外,还会将其放到

session范围内[WW_TRANS_I18N_LOCALE].处理每个请求时都会进行相同的的处理.

编程设置locale

getLocale()缺省实现:

return ActionContext.getContext().getLocale();

北京传智播客教育 www.itcast.cn


Struts291

Struts2(最佳实践)

使用插件扩展struts2

struts-default.xml (bundled in the struts2-core-x.y.z.jar)

struts-plugin.xml (as many as can be found in plug-in JARs)

struts.xml (provided by your application)

sitemesh(web.xml)

北京传智播客教育 www.itcast.cn


Struts292

Struts2(最佳实践)

使用插件扩展struts2

sitemesh(web.xml)[续]

北京传智播客教育 www.itcast.cn


Struts293

Struts2流程图

北京传智播客教育 www.itcast.cn


Struts294

Struts2(最佳实践)

使用插件扩展struts2

tiles(web.xml)

<context-param>

<param-name>

org.apache.tiles.impl.BasicTilesContainer.DEFINITIONS_CONFIG

</param-name>

<param-value>/tiles/myTiles.xml</param-value>

</context-param>

...

<listener>

<listener-class>

org.apache.struts2.tiles.StrutsTilesListener

</listener-class>

</listener>

北京传智播客教育 www.itcast.cn


Struts295

Struts2(最佳实践)

使用插件扩展struts2

struts2-tiles-plugin-2.x.jar[struts-plugin.xml]

<struts>

<package name="tiles-default" extends="struts-default">

<result-types>

<result-type name="tiles"

class="org.apache.struts2.views.tiles.TilesResult"/>

</result-types>

</package>

</struts>

Our's struts.xml

<struts>

<package name="members" namespace="/members" extends="tiles-default">

<result-types>

<result-typ name="tiles class="org.apache.struts2.views.tiles.TilesResult"

default="true"/>

</result-types>

<action name="list"><result>membersPage</result></action>

</package>

</struts>

北京传智播客教育 www.itcast.cn


Struts296

Struts2(最佳实践)

Jfreechart

struts2-jfreechart-plugin-2.x.jar[struts-plugin.xml]

<struts>

<package name="jfreechart-default">

<result-types>

<result-type name="chart"

class="org.apache.struts2.dispatcher.ChartResult">

<param name="height">150</param>

<param name="width">200</param>

</result-type>

</result-types>

</package>

</struts>

our's struts.xml

<package name="struts-default.xml,jfreechart-default">

<action name="chart" class="com.strutsschool.action.CreateChart">

<result type="chart">

<param name="width">400</param>

<param name="height">300</param>

</result>

</action>

</package>

北京传智播客教育 www.itcast.cn


Struts297

Struts2 (最佳实践)

内部组件系统

beans

北京传智播客教育 www.itcast.cn


Struts298

Struts2 (最佳实践)

constant

1 web.xml init parameters for the Struts filter

2 default.properties in the Struts JAR

3 struts.properties in WEB-INF/classes (deprecated in Struts 2.1)

4 struts-plugin.xml in each plug-in JAR

5 struts.xml in WEB-INF/classes

injection

北京传智播客教育 www.itcast.cn


Struts299

Struts2(最佳实践)

  • 13最佳实践

  • 13.1.2重新加载资源

  • 13.1.3单元测试action

  • 13.2.2junit和测试

北京传智播客教育 www.itcast.cn


Struts2100

Struts2(最佳实践)

  • 13最佳实践

  • 13.2.2junit和测试

    简单的单元测试[作为pojo]

    使用代理

北京传智播客教育 www.itcast.cn


Struts2101

Struts2(最佳实践)

  • 13最佳实践

  • 13.2.3测试验证文件

北京传智播客教育 www.itcast.cn


Struts2102

Struts2(高级主题)

动态方法调用

通配符

<action name="CoinAction_*" method="{1}" class="CoinAction">

<result name="show">/pages/member/show.jsp</result>

<result name="add">/pages/member/add.jsp</result>

<result name="edit">/pages/member/edit.jsp</result>

<result name="destroy">/pages/member/destroy.jsp</result>

<result name="list">/pages/member/list.jsp</result>

</action>

动态工作流

<action name="CoinAction_*" method="{1}" class="CoinAction">

<result name="destroy">${nextPage}</result>--action的属性

</action>

北京传智播客教育 www.itcast.cn


Struts2103

Struts2(高级主题)

使用令牌防止重复提交

<s:token/>

Prepare the web page with a unique token embedded as a hidden field.

Stash this unique token in the user session.

Return the page to user browser.

When the form is submitted, the two tokens are compared.

If the tokens do not match, invalid.token result is returned.

tockenstack包含了token拦截器,用于重复检查,若重复提交的话,会返回invalid.token

<s:form>

<s:token/>

<s:textfield key="coinToss"/>

<s:submit action="flipCoin"/>

</s:form>

<action name="flipCoin" method="flipCoin" class="CoinAction">

<interceptor-ref name="tokenStack"/>

<result name="success">samplesPage</result>

<result name="invalid.token">duplicatePage</result>

</action>

北京传智播客教育 www.itcast.cn


Struts2104

Struts2(高级主题)

使用令牌防止重复提交

<action name="flipCoin" method="flipCoin" class="CoinAction">

<interceptor-ref name="tokenStack"/>

<result name="success">samplesPage</result>

<result name="invalid.token">duplicatePage</result>

</action>

[基本令牌支持]

<interceptor-stack name="myTokenStack">

<interceptor-ref name="token"/>

<interceptor-ref name="defaultStack"/>

</interceptor-stack>

[高级令牌支持]

<interceptor-stack name="myTokenStack">

<interceptor-ref name="tokenSession"/>

<interceptor-ref name="defaultStack"/>

</interceptor-stack>

北京传智播客教育 www.itcast.cn


Struts2105

Struts2(高级主题)

使用令牌防止重复提交

[拦截器栈拦截敏感方法]

<interceptor-stack name="myTokenStack">

<interceptor-ref name="tokenSession"><!—指定防止重复提交的方法-->

<param name="includeMethods">save,proceed,whateverElse</param>

</interceptor-ref>

<interceptor-ref name="defaultStack"/>

</interceptor-stack>

<interceptor-stack name="mySensitiveStack">

<interceptor-ref name="myTokenStack">

<param name="tokenSession.includeMethods">save</param>

<param name="validation.excludeMethods">someMethod</param>

</interceptor-ref>

</interceptor-stack>

注意:不论是token还是tokenSession都需要显式指定包含的方法(includeMethods).否则不好

使,token拦截器需要配置invalid.token参数指定响应页面.tokenSession不需要,直接退回到

点击后退的页面.

北京传智播客教育 www.itcast.cn


Struts2106

Struts2(高级主题)

自动显示等待页

声明等待栈

<action name="search" class="SearchAction">

<interceptor-ref name="waitStack"/>

<result name="success">/resultsPage.jsp</result>

<result name="wait">/waitPage.jsp</result>

</action>

<interceptor-stack name="waitStack">

<interceptor-ref name="defaultStack" />

<interceptor-ref name="execAndWait" />

</interceptor-stack>

Wait.jsp

<html>

<head><title>Please wait</title>

<meta http-equiv="refresh" content="2;url=<s:url/>"/>

</head>

注意:execAndWait必须放在最后声明.因为他会终止程序运行,不会有后续的拦截器被调用了!

北京传智播客教育 www.itcast.cn


Struts2107

Struts2(高级主题)

自动显示等待页

先等待/后等待顺序很重要?

try {

Thread.sleep(5000);

} catch (InterruptedException e) {

e.printStackTrace();

}

Collection<User> list =

(Collection<User>)InMemoryDB.getAllUsers().values();

ActionContext.getContext().getContextMap().put("list", list);

北京传智播客教育 www.itcast.cn


Struts2108

Struts2(高级主题)

传统web外观

北京传智播客教育 www.itcast.cn


Struts2109

Struts2(高级主题)

tiles

北京传智播客教育 www.itcast.cn


Struts2110

Struts2(高级主题)

tiles

北京传智播客教育 www.itcast.cn


Struts2111

Struts2(高级主题)

tiles

struts2-tiles-plugin-2.0.9.jar

tiles-core.jar

tiles-API.jar

tiles-jsp.jar

web.xml

<context-param>

<param-name>org.apache.tiles.impl.BasicTilesContainer.DEFINITIONS_CONFIG

</param-name>

<param-value>/tiles/tiles.xml</param-value>

</context-param>

<listener>

<listener-class>

org.apache.tiles.web.startup.TilesListener

</listener-class>

</listener>

北京传智播客教育 www.itcast.cn


Struts2112

Struts2(高级主题)

Tiles

struts2-tiles-plugin-2.0.9[struts-plugin.xml]

添加新的结果类型

<struts>

<package name="tiles-default" extends="struts-default">

<result-types>

<result-type name="tiles"

class="org.apache.struts2.views.tiles.TilesResult"/>

</result-types>

</package>

</struts>

Our struts.xml

<struts>

<package name="strutsSchool" extends="tiles-default">

<result-types>

<result-type name="tiles"

class="org.apache.struts2.views.tiles.TilesResult"

default="true"/>

</result-types>

</package>

<include file="home.xml"/>

<include file="member.xml"/>

</struts>

北京传智播客教育 www.itcast.cn


Struts2113

Struts2(高级主题)

Tiles

struts2-tiles-plugin-2.0.9[struts-plugin.xml]

添加新的结果类型

public class ListMembers extends BaseController {

public void execute(TilesRequestContext tilesContext,

AttributeContext attributeContext) {

tilesContext.getRequestScope().put("list", getMembers());

}

<s:property value="password" />

<s:date name="created" format="M/d/yyyy" />

<s:url id="url" action="%{actionClass}_show">

<s:param name="requestId" value="id"/>

</s:url>

<s:a href="%{url}">Show</s:a>

<s:url id="url" action="%{actionClass}_edit">

<s:param name="requestId" value="id"/>

</s:url>

<s:a href="%{url}">Edit</s:a>

<s:url id="url" action="%{actionClass}_destroy">

<s:param name="requestId" value="id"/>

</s:url>

<s:a href="%{url}">Destroy</s:a>

北京传智播客教育 www.itcast.cn


Struts2114

Struts2(高级主题)

Tiles

struts.xml

北京传智播客教育 www.itcast.cn


Struts2115

Struts2(高级主题)

Tiles

struts.xml

北京传智播客教育 www.itcast.cn


  • Login