对于Struts2应用中的开发者来说,Action才是整个应用系统的核心,开发者需要提供大量的Action类,并且在struts.xml文件中对Action类进行配置,Action中包含了对用户请求的处理逻辑,因此,我们也称Action为业务控制器.
1) 实现Action实现类
相对于Struts1而言,Struts2采用的低侵入式的设计,Struts2不要求Action类继承任何的Struts2基类,或者实现任何的Struts2的接口,在这种设计方式下,Struts2的Action类是一个非常普通的POJO(但是通常会包含一个没有参数的execute()方法),从而,有很好的代码复用性.
Struts2通常直接使用Action来封装HTTP请求参数,因此,Action类里面还应该包含与请求参数相对应的属性,并且为这些属性提供getter和setter方法.
比如说,用户请求包含user和password两个请求参数,那么Action就应该提供user和两个属性来封装用户的请求参数,并且为user和password提供对应的getter和setter方法,西面是处理该请求的Action的代码片段:
package com.supermos.app.Action;
//处理用户请求的Action类,这个只是一个POJO类
//不需要继承任何的基类,不需要实现任何的接口
public class LoginAction {
//提供两个属性来封装HTTP请求的参数
private String user;
private String password;
public String getUser() {
return user;
}
public void setUser(String user) {
https://www.doczj.com/doc/a74125673.html,er = user;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
//Action类默认来处理用户请求的方法,execute
public String execute(){
//处理结束,返回一个字符串,这个字符串将对应视图物理资源
return "success";
}
}
上面的Action类只是一个普通的Java类,这个Java类提供了两个属性,user和password,这个两个属性分别对应两个HTTP请求参数.
(即使Action需要处理的请求包含user和password两个HTTP请求参数,Action类也是可以不包含user和password两个属性的,因为系统是通过对应的getter和setter方法来处理请求参数的,而不是通过属性的名字来处理请求参数的,也就是说,如果包含user的HTTP请求参数,Action类里面是否包含user属性并不重要,重要的是要包含void setUser(String user)和String getUser()这两个方法)
Action类的属性,不仅可以用于封装请求参数,还可以用于封装处理结果.比如在前面的Action 代码中看到的,如果希望将服务器提示的”登录成功”在下一个页面中输出,那么,我们可以在Action类中增加一个tip属性,并且为该属性提供对应的getter和setter方法,也就是为Action 类增加如下的代码片段:
//封装服务器提示的tip属性
private String tip;
public String getTip() {
return tip;
}
public void setTip(String tip) {
this.tip = tip;
}
一旦在Action中设置了tip属性的值,我们就可以在下一个页面当中使用struts2标签来输出该属性的值,在jSP页面当中输出tip属性值的代码片段如下:
系统不会严格区分Actino里面的那个属性是用来封装请求参数的属性,那个事用来封装结果的属性,对于系统来说,封装请求参数和封装处理结果的属性石完全平等的.如果用户的HTTP 请求里面包含了tip的请求参数,系统就会调用Action的void setTip(String tip)方法,通过这种方式,名为tip的请求参数就可以传给Action实例,如果Action类里面没有包含对应的方法,那么名字为tip的请求参数也就无法传入该Action.
同样,在JSP页面中输出的Action属性的时候,它也不会区分该属性是用来封装请求参数的还是用于封装处理结果的属性,所以说,使用Struts2的标签既可以输出Action的处理结果,也可以输出Http请求参数值.
从上面的代码可以看到,需要在JSP页面中输出的处理结果是一个非常简单的字符串,可以使用
为了让用户开发的Action来更加的规范,Struts2提供了一个Action接口,这个接口定义了Struts2的Action处理类应该实现的规范,下面是Action接口的代码:
public interface Action {
public static final String SUCCESS="success";
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 String execute()throws Exception;
}
上面的Action接口里面只定义了一个execute方法,该接口的规范规定了Action类应该包含一个execute方法,该方法的作用是返回一个字符串,除此之外,该接口还定义了5个字符串常量,他们的作用是统一execute方法的返回值.
比如说,当Action处理完用户的请求成功之后,有人喜欢返回welcome这种字符串,有的人喜欢返回success字符串…这样不利于项目的统一管理.Struts2的Action定义上面的5个字符串:error,none,input,longin和success等等分别代表了特定的含义,当然,如果开发者依然希望使用特定的字符串做为逻辑视图的名字,开发者依然可以返回自己的视图.
另外,Struts2还提供了Action类的一个实现类:ActionSupport,下面是Action类的代码:
package com.opensymphony.xwork2;
import com.opensymphony.xwork2.util.ValueStack;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import java.io.Serializable;
import java.util.*;
/**
* Provides a default implementation for the most common actions.
*/
//系统提供的ActionSupport类
public class ActionSupport implements Action, Validateable, ValidationAware, TextProvider,
LocaleProvider, Serializable {
protected static Logger LOG = LoggerFactory.getLogger(ActionSupport.class);
private final transient TextProvider textProvider = new TextProviderFactory().createInstance(getClass(), this);
private final ValidationAwareSupport validationAware = new ValidationAwareSupport();
//收集校验错误的方法
public void setActionErrors(Collection
validationAware.setActionErrors(errorMessages);
}
//返回校验错误的方法
public Collection
return validationAware.getActionErrors();
}
public void setActionMessages(Collection
validationAware.setActionMessages(messages);
}
public Collection
return validationAware.getActionMessages();
}
/**
* @deprecated Use {@link #getActionErrors()}.
*/
@Deprecated public Collection
}
/**
* @deprecated Use {@link #getFieldErrors()}.
*/
@Deprecated public Map
}
//设置表单域校验错误信息
public void setFieldErrors(Map
}
//返回表单域校验错误信息
public Map
return validationAware.getFieldErrors();
}
//控制locale的相关信息
public Locale getLocale() {
ActionContext ctx = ActionContext.getContext();
if (ctx != null) {
return ctx.getLocale();
} else {
LOG.debug("Action context not initialized");
return null;
}
}
public boolean hasKey(String key) {
return textProvider.hasKey(key);
}
//返回国际化信息的方法
public String getText(String aTextName) {
return textProvider.getText(aTextName);
}
public String getText(String aTextName, String defaultValue) {
return textProvider.getText(aTextName, defaultValue);
}
public String getText(String aTextName, String defaultValue, String obj) { return textProvider.getText(aTextName, defaultValue, obj);
}
public String getText(String aTextName, List
return textProvider.getText(aTextName, args);
}
public String getText(String key, String[] args) {
return textProvider.getText(key, args);
}
public String getText(String aTextName, String defaultValue, List
}
public String getText(String key, String defaultValue, String[] args) { return textProvider.getText(key, defaultValue, args);
}
public String getText(String key, String defaultValue, List
}
public String getText(String key, String defaultValue, String[] args, ValueStack stack) { return textProvider.getText(key, defaultValue, args, stack);
}
public ResourceBundle getTexts() {
return textProvider.getTexts();
}
public ResourceBundle getTexts(String aBundleName) {
return textProvider.getTexts(aBundleName);
}
public void addActionError(String anErrorMessage) {
validationAware.addActionError(anErrorMessage);
}
public void addActionMessage(String aMessage) {
validationAware.addActionMessage(aMessage);
}
public void addFieldError(String fieldName, String errorMessage) { validationAware.addFieldError(fieldName, errorMessage);
}
public String input() throws Exception {
return INPUT;
}
public String doDefault() throws Exception {
return SUCCESS;
}
/**
* A default implementation that does nothing an returns "success".
*
* Subclasses should override this method to provide their business logic. *
* See also {@link com.opensymphony.xwork2.Action#execute()}.
*
* @return returns {@link #SUCCESS}
* @throws Exception can be thrown by subclasses.
*/
//默认的处理用户请求的方法,直接返回success字符串public String execute() throws Exception {
return SUCCESS;
}
public boolean hasActionErrors() {
return validationAware.hasActionErrors();
}
public boolean hasActionMessages() {
return validationAware.hasActionMessages();
}
public boolean hasErrors() {
return validationAware.hasErrors();
}
public boolean hasFieldErrors() {
return validationAware.hasFieldErrors();
}
/**
* Clears field errors. Useful for Continuations and other situations
* where you might want to clear parts of the state on the same action. */
public void clearFieldErrors() {
validationAware.clearFieldErrors();
}
/**
* Clears action errors. Useful for Continuations and other situations * where you might want to clear parts of the state on the same action. */
public void clearActionErrors() {
validationAware.clearActionErrors();
}
/**
* Clears messages. Useful for Continuations and other situations
* where you might want to clear parts of the state on the same action. */
public void clearMessages() {
validationAware.clearMessages();
}
/**
* Clears all errors. Useful for Continuations and other situations
* where you might want to clear parts of the state on the same action.
*/
public void clearErrors() {
validationAware.clearErrors();
}
/**
* Clears all errors and messages. Useful for Continuations and other situations * where you might want to clear parts of the state on the same action.
*/
public void clearErrorsAndMessages() {
validationAware.clearErrorsAndMessages();
}
/**
* A default implementation that validates nothing.
* Subclasses should override this method to provide validations.
*/
//包含空的输入校验方法
public void validate() {
}
@Override public Object clone() throws CloneNotSupportedException {
return super.clone();
}
public void pause(String result) {
}
}
正如上面的代码看到的,该Action是一个默认的Action类,该类里面已经提供了很多默认的方法,这些默认的方法包括获取国际化信息的方法,数据校验的方法,默认的处理用户请求的方法等等,实际上,ActionSupport类是Struts2默认的Action处理类,如果让开发者的Action类继承该ActionSupport来,就会大大的简化Action的开发.
(当用户配置的Action类没有指定class属性的时候,系统会自动使用ActionSupport类作为默认的Action处理类)
2) Action访问Servlet API
Struts2的Action并没有直接和任何的Servlet API进行耦合,这是Struts2的一个改良之处,因为Action类不再和Servlet API耦合,就可以更加轻松的去测试该Action,就不用mock去模拟数据测试了.
但是对于web应用的控制器而言,不访问Servlet API几乎是不可能的,比如说跟踪HTTP
Session的状态等等.Struts2框架提供了一种更加轻松的方式来访问Servlet API,Web应用中通常需要访问的Servlet API就是HttpServletRequest,HttpSession和HttpContext,这三个类分别代表JSP内置对象里面的request,session和application.
Struts2提供了一个ActionContext类,Struts2的Action可以通过该类来访问Servlet API,下面是ActionContext类中包含的几个常用的方法:
l Object get(Object key):该方法类似于调用HttpServletRequest的getAttribute(String name)方法.
l Map getApplication():返回一个Map对象,该对象模拟了该应用的ServletContext 实例.
l static ActionContext getContext():静态方法,获取系统的ActionContext实例.
l Map getParameters():获取所有的请求参数,类似于调用HttpServletRequest对象的getParameterMap方法.
l Map getSession():返回一个Map对象,这个Map对象模拟了HttpSession实例.
l void setApplication(Map application):直接传入一个Map实例,将该Map实例里面的key-value对转换成application的属性名属性值.
l void setSession(Map session):直接传入一个Map实例,将该Map实例里面的key-value对转换成session的属性名和属性值.
下面的一个应用将在Action类中通过ActionContext访问ServletAPI:
①系统提交请求到LoginAction,LoginAction的代码如下:
package com.supermos.app.Action;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionContext;
public class LoginAction implements Action{
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
https://www.doczj.com/doc/a74125673.html,ername = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String execute(){
//获取ActionContext实例,通过该实例访问Servlet API
ActionContext ctx=ActionContext.getContext();
//获取ServletContext里面的counter属性
Integer counter=(Integer)ctx.getApplication().get("counter");
//如果counter的属性为空,就设置该counter的属性为1 if(counter==null){
counter=1;
}
//否则,将counter加1
else{
counter=counter+1;
}
//将增加1之后的counter的值设置为counter属性
ctx.getApplication().put("counter", counter);
//将登陆用的username属性设置为一个HttpSession属性
ctx.getSession().put("user",this.getUsername());
if("supermos".equalsIgnoreCase(this.getUsername())&&"ziwen".equalsIgnoreCase(this.getPassw ord())){
//直接设置HttpServletRequest属性,下面的代码的作用类似于设置HttpServletRequest属性
//request.setAttribute("tip","服务器提示,您已经成功登陆");
ctx.put("tip", "服务器提示,您已经成功登陆");
return this.SUCCESS;
}else{
//直接设置HttpServletRequest属性
ctx.put("tip","服务器提示,您登陆失败,请检查您的用户名和密码");
return this.ERROR;
}
}
}
②上面的Action访问了HttpServletRequest的属性,也访问了HttpSession的属性,还让问
了HttpContext的属性,将该Action配置在struts.xml文件中,struts.xml文件的代码如下:
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"https://www.doczj.com/doc/a74125673.html,/dtds/struts-2.0.dtd">
③如果浏览者在页面中输入用户名supermos密码ziwen的时候,将提交给LoginAction 来进行处理,该Action的execute方法分别设置了HttpServletRequest属性,HttpSession属性和ServletContext属性,为了验证是否成功设置了这三个属性,我们在success.jsp页面中访问这三个对象的属性:代码如下:
<%@ page language="java" pageEncoding="utf-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
本站的访问次数为:${applicationScope.counter}
${https://www.doczj.com/doc/a74125673.html,er },您已经登录!
${requestScope.tip }
显然,相比Struts1中直接访问ServletAPI,Strut2通过ActionContext访问ServletAPI更加的优雅,让Action彻底从ServletAPI中分离出来,从而可以允许该Action脱离web容器.最大的好处就是可以脱离web容器测试Action.
3) Action直接访问ServletAPI
虽然Struts2提供了ActionContext来访问ServletAPI,但是这种方式毕竟不能够直接获得ServletAPI的实例,为了在Action中直接访问ServletAPI,Struts2还提供了如下的几个接口:
l ServletContextAware:实现该接口的Action可以直接访问Web应用的ServletContext实例.(aware[??w??]意识到的,知道的)
l ServletRequestAware:实现该接口的Action可以直接访问服务器相应的HttpServletRequest实例
l ServletResponseAware:实现该接口的Action可以直接访问服务器相应的HttpServletResponse实例.
下面以ServletResponseAware为例子,介绍如何在Action中访问HttpServletResponse对象,本应用通过HttpServletResponse为系统添加Cookie对象.下面是该上面例子的Action的修改:
package com.supermos.app.Action;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.interceptor.ServletResponseAware;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionContext;
public class LoginAction implements Action,ServletResponseAware{ //需要访问的HttpServletResponse对象
private HttpServletResponse response;
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
https://www.doczj.com/doc/a74125673.html,ername = username;
}
public String getPassword() {
2012年第11卷第6期 产业与科技论坛2012.(11).6 Industrial &Science Tribune Struts2框架工作原理及应用体会 □宋 君 张家爱 【摘要】通过针对特定用户的分析,搭建以Struts2为技术核心的旅行社管理系统。本文简单的介绍了MVC 、 Struts2的工作原理,同时总结了在项目制作过程中所得到的心得。 【关键词】 Struts2;MVC ;FilterDispatcher ;Action 【基金项目】本文为大学生科技创新院级基金项目(编号:2011070)成果 【作者单位】宋君,吉林农业科技学院信息工程学院;张家爱,吉林农业科技学院信息工程学院教师 本着锻炼自我与积极参与到实用性技术的目标,以发掘自身创新意识为前提。利用空闲时间,在老师的指导下,进行了一次大学生创新项目的实践性活动。本着实用原则,以某中小旅行社为客户(根据用户需求,匿名),以Struts2框架为基点,进行了一次旅行社管理系统的开发。在项目结束之余, 特将在项目过程中经历的种种认识进行了简单的总结,希望让阅读本文的朋友们,更多的参与到此类活动中。 一、基础思想— ——MVC 简述作为时下经典框架之一, MVC 具有其独特的价值。MVC 框架简单的说,就是将数据模型与用户视图进行分离。通过控制器进行协调处理的一种结构是框架。同时,也是本文中要讨论的Sturts2框架的基础思想。 M 是指模型层(Model ),V 是指用户视图(View ),C 则是指控制器 (Controller )。这种划分方式是以将模型层与视图层进行代码分离,从而降低两者之间的耦合性,使同一程序可以使用不同形式进行表现。不同层之间的修改不会或尽量少的印象到其他层功能的史前为前提。有效的提高的代码的维护性和设计难度。 图1 二、 Struts2工作原理(一)Struts2框架组成。Struts2框架由三个主要部分组成:核心控制器、业务控制器,以及由用户实现的业务逻辑组件。这里我们将侧重于核心控制器与业务控制器的理解与说明。 (二)核心控制器:FilterDispatcher 。FilterDispatcher 是Struts2框架的核心控制器,在此,我们可以将FilterDispatcher 看作一个类似于过滤网的过滤器。当用户发出请求,并到达Web 硬哟那种时,该过滤器会过滤用户请求。如果用户请求的结尾为action ,则将该请求转入Struts2框架进行处理。当Struts2框架获得了*.actio 请求后,会根据请求前面“*”的那部分内容,决定调用哪个业务逻辑组件作为响应单位。这里需要说明的是Struts2用来处理用户请求的Action 实例并不是业务控制器,而是作为Action 的代理———正因为Struts2的一大特点,与Servlet API 的非耦合性,使得用户实现的业务控制器无法直接处理用户请求。有效的提高了后期调试维护的效率。而Struts2框架再次提供了了一系列的拦截器。这些拦截器负责将HttpServletRequest 请求的参数解析出来,传入Action 中,并毁掉Action 的Execute 方法来处理用户请求。用户实现的Action 类仅作为Struts2的Action 代理的代理目标。用户实现的业务控制器则包含了对用户请求的处理。用户的请求数据包含在HttpServletRequest 对象中,而用户的Action 类无需访问HttpServletRequest 对象。拦截器负责将HttpServletRequest 里的请求数据解析出来,并传给业务逻辑组件Action 实例。 (三)业务控制器。业务控制器就是前文提到的用来实现用户Action 的实力,这里的每个Action 类通常包含有一个execute 方法,当业务控制器处理完用户的请求后,该方法将会针对此次处理返回一个字符串— ——该字符串就是一个逻辑树图名。当程序开发人员开发出系统所需要的业务控制器后,还需要针对性的配置Struts2的Action ,即需要配置Ac- tion 的以下三个部分:(1)Action 所处理的URl 。(2)Action 组件所对应的实现类。(3)Action 里包含的逻辑试图和物理资源之间的对应关系。每个Action 都要处理一个用户请求,而用户请求则总是包含有指定的URL 。当核心控制器过滤用户请求,并调用后,根据请求的URL 和Action 处理URL 之间的对应关系来处理转发。 · 342·
Struts 2作业 1.简述什么是MVC? 答:MVC 的全称为model-view-controller(模型-视图-控制器)。MVC 是一种开发应用程序的模式,这个模式已经具有了很好的框架架构,并且十分容易维护。使用MVC 开发出来的应用程序一般包括以下几块内容:·控制器(Controller):控制器类处理客户端向Web 应用程序发出的请求,获取数据,并指定返回给客户端,用来显示处理结果的视图。·模型(Model):模型类代表了应用程序的数据,这些数据通常具有一个数据验证逻辑,用来使得这些数据必须符合业务逻辑。·视图(View):视图类是Web 应用程序中用来生成并显示HTML 格式的服务器端对客户端请求的响应结果的模板文件 2.Struts 2以(WebWork)为核心,采用(拦截器)的机制来处理用户的 请求。 3.简述一个请求在Struts 2框架中的处理流程,请按自己对框架的理解叙述。答:1-用户提交自己的请求;2-由web.xml拦截,转发到action进行处理;3- Struts.xml根据相应的action配置,调用相应的方法来处理,并根据结果转发到不同的页面。 4.不属于Action接口中定义的字符串常量是( B )? A)SUCCESS B)FAILURE C)ERROR D)INPUT 5.资源文件的后缀名为(D)? A)txt B)doc C)property D)properties 6.在JSP页面中可以通过Struts 2提供的(D)标签来输出国际化信息。 A)
Struts2Validator Struts2验证框架 Updated Jun 18, 2010 by cm2...@https://www.doczj.com/doc/a74125673.html, Action配置中一定要设置input返回页面 添加验证只要创建验证的xml文件 1.创建xml文件名 验证Action中全部方法 在Action同包下,创建:Action类名-validation.xml 如:ValidateAction创建ValidateAction-validation.xml 验证Action中单个方法 Struts2复习题 1.以下属于struts2的控制器组件是: A.Action B.ActionForm C.ActionServlet D.dispatchAction 2.以下属于struts2的体系结构的是:(多选) A.struts2控制器组件 B.struts2配置文件 C.FilterDispathcer D.Action 3.以下属于struts2配置文件中的配置元素是:(多选) A. Struts2中数据标签使用示例 S truts2提供了大量丰富的标签供使用,它不再像S truts1中一样,将种类标签进行分门列别,但可以根据其使用的用途用以区别。本文通过对S truts2中数据标签的学习,来对S truts2中标签的学习起到一个抛砖引玉的作用。 文中将介绍Action标签、Bean标签、Data标签、Include标签、P aram标签、Set标签、T ext标签、P roperty 标签等标签。 代码下载:https://www.doczj.com/doc/a74125673.html,/y1ps2Mjpc3NiLKuetMOpCsZOOypD6KSdo8-46Zy2wpoMcABeo4vOC NJXtWDEO93-TXgZogwAF YxSOni5BEG2EoN65OFwHdG71v-/St ruts2DataTags.rar?download 一、java-struts2复习题
struts2标签使用实例
Action Tag 示例