`

理解Struts2的Action中的setter方法是怎么工作的

    博客分类:
  • SSH
阅读更多

接触过webwork和Struts2的同行都应该知道,

提交表单的时候,只要Action中的属性有setter 方法,这些表单数据就可以正确赋值到Action中属性里;
另外对于Spring配置文件中声明的bean,也可以在Action中声明setter 方法将其注入到Action实例中。
那么现在要研究:这些是怎么工作的呢?


(1)提交表单时的参数
在struts2-core-2.3.1.2.jar压缩包内的struts-default.xml配置文件中有这个配置:
<interceptor name="params" class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>
这个拦截器是负责解析请求中的URL参数,并赋值给action中对应的属性

来看代码:

//com.opensymphony.xwork2.interceptor.ParametersInterceptor.java
//主要代码如下:
//...

    @Override
    public String doIntercept(ActionInvocation invocation) throws Exception {
        Object action = invocation.getAction();
        if (!(action instanceof NoParameters)) {
            ActionContext ac = invocation.getInvocationContext();
            final Map<String, Object> parameters = retrieveParameters(ac);

            if (LOG.isDebugEnabled()) {
                LOG.debug("Setting params " + getParameterLogMap(parameters));
            }

            if (parameters != null) {
                Map<String, Object> contextMap = ac.getContextMap();
                try {
                    ReflectionContextState.setCreatingNullObjects(contextMap, true);
                    ReflectionContextState.setDenyMethodExecution(contextMap, true);
                    ReflectionContextState.setReportingConversionErrors(contextMap, true);

                    ValueStack stack = ac.getValueStack();
                    setParameters(action, stack, parameters);
                } finally {
                    ReflectionContextState.setCreatingNullObjects(contextMap, false);
                    ReflectionContextState.setDenyMethodExecution(contextMap, false);
                    ReflectionContextState.setReportingConversionErrors(contextMap, false);
                }
            }
        }
        return invocation.invoke();
    }

    protected void setParameters(Object action, ValueStack stack, final Map<String, Object> parameters) {
        ParameterNameAware parameterNameAware = (action instanceof ParameterNameAware)
                ? (ParameterNameAware) action : null;

        Map<String, Object> params;
        Map<String, Object> acceptableParameters;
        if (ordered) {
            params = new TreeMap<String, Object>(getOrderedComparator());
            acceptableParameters = new TreeMap<String, Object>(getOrderedComparator());
            params.putAll(parameters);
        } else {
            params = new TreeMap<String, Object>(parameters);
            acceptableParameters = new TreeMap<String, Object>();
        }

        for (Map.Entry<String, Object> entry : params.entrySet()) {
            String name = entry.getKey();

            boolean acceptableName = acceptableName(name)
                    && (parameterNameAware == null
                    || parameterNameAware.acceptableParameterName(name));

            if (acceptableName) {
                acceptableParameters.put(name, entry.getValue());
            }
        }

        ValueStack newStack = valueStackFactory.createValueStack(stack);
        boolean clearableStack = newStack instanceof ClearableValueStack;
        if (clearableStack) {
            //if the stack's context can be cleared, do that to prevent OGNL
            //from having access to objects in the stack, see XW-641
            ((ClearableValueStack)newStack).clearContextValues();
            Map<String, Object> context = newStack.getContext();
            ReflectionContextState.setCreatingNullObjects(context, true);
            ReflectionContextState.setDenyMethodExecution(context, true);
            ReflectionContextState.setReportingConversionErrors(context, true);

            //keep locale from original context
            context.put(ActionContext.LOCALE, stack.getContext().get(ActionContext.LOCALE));
        }

        boolean memberAccessStack = newStack instanceof MemberAccessValueStack;
        if (memberAccessStack) {
            //block or allow access to properties
            //see WW-2761 for more details
            MemberAccessValueStack accessValueStack = (MemberAccessValueStack) newStack;
            accessValueStack.setAcceptProperties(acceptParams);
            accessValueStack.setExcludeProperties(excludeParams);
        }

        for (Map.Entry<String, Object> entry : acceptableParameters.entrySet()) {
            String name = entry.getKey();
            Object value = entry.getValue();
            try {
                newStack.setParameter(name, value);
            } catch (RuntimeException e) {
                if (devMode) {
                    String developerNotification = LocalizedTextUtil.findText(ParametersInterceptor.class, "devmode.notification", ActionContext.getContext().getLocale(), "Developer Notification:\n{0}", new Object[]{
                             "Unexpected Exception caught setting '" + name + "' on '" + action.getClass() + ": " + e.getMessage()
                    });
                    LOG.error(developerNotification);
                    if (action instanceof ValidationAware) {
                        ((ValidationAware) action).addActionMessage(developerNotification);
                    }
                }
            }
        }

        if (clearableStack && (stack.getContext() != null) && (newStack.getContext() != null))
            stack.getContext().put(ActionContext.CONVERSION_ERRORS, newStack.getContext().get(ActionContext.CONVERSION_ERRORS));

        addParametersToContext(ActionContext.getContext(), acceptableParameters);
    }
//...

 

上面的代码ValueStack stack = ac.getValueStack();
表明,它是从当前Action上下文获取值栈(其实就类似一个全局Map集合,用来存储参数值或struts上下文全局变量),
然后由判断如果是当前action可以接受的参数(Action中有setter方法)就过滤出来,
调用这句“newStack.setParameter(name, value); ”来保存到值栈中,
保存到了值栈中其实action实例的属性就能拿到值了。
最后一句“addParametersToContext(ActionContext.getContext(), acceptableParameters);
表明它还把这些过滤出来的参数保存到了ActionContext上下文中,
这样,如果跳转的类型是forward(服务器内部重定向),
目标url中就会带上上次请求的url的所有有用的参数。

 

(2) Spring配置bean注入到Action中
来看一个简单的Action类:

package com.liany.demo.pubs.org.employee.action;

import java.util.List;

import com.opensymphony.xwork2.ActionSupport;

import com.liany.demo.pubs.org.employee.model.Employee;
import com.liany.demo.pubs.org.employee.service.EmployeeService;

public class EmployeeAction extends ActionSupport{
	
	private EmployeeService employeeService;
	private List list; 
	private Employee employee = new Employee();  
	
	
	public StringReader getStringReader() {
		StringReader is = null;
		try {
			is = new StringReader(xmlBuf.toString());
		} catch (Exception e) {
			e.printStackTrace();
		}
		return is;
	}
	
	public Employee getEmployee() {
		return employee;
	}

	public void setEmployee(Employee employee) {
		this.employee = employee;
	} 

	public List getList() {
		return list;
	}

	public void setEmployeeService(EmployeeService employeeService) {
		this.employeeService = employeeService;
	}
	
	public String execute(){
		//列表
		list = this.employeeService.getEmployees();
		
		return "list";
	}
	
	public String view(){
		employee = this.employeeService.getEmployeeById(employee.getId());
		
		return "view";
	}
	
	public String edit(){
		if(employee.getId()!=null){
			//修改
			employee = this.employeeService.getEmployeeById(employee.getId());
		}else{
			//新增
			employee.setId(null);
		}
		
		return "input";
	}
	
	public String save(){
		this.employeeService.saveEmployee(employee);
		
		return "repage";
	}
	
	public String delete(){
		this.employeeService.deleteEmployeeById(employee.getId());
		
		return "repage";
	}
}

 

上面Action中的employeeService对象其实是在Spring配置文件中声明的bean,
代码中给它定义一个public的setEmployeeService()方法,这样就可以将bean实例注入到
Action中的实例中,这个功能是在Struts过虑器初始化的时候初始化了一个全局变量,
从而使得调用action时,从spring ioc容器中找到这个bean,再set给action对象。
配置文件是在struts.properties 文件中声明:
struts.objectFactory = spring
struts.objectFactory.spring.autoWire = name

 

好了先研究到这里, 有兴趣的朋友可以交流交流...

 

 

3
0
分享到:
评论
1 楼 tianzhihehe 2012-10-24  

先顶一个
SPRING与STRUTS2整合的时候,发现ACTION的参数总是没有赋值为NULL。
终于发现这张贴,忘了INTERCEPTOR这桩。
开始DEBUG。

相关推荐

    struts2 action 返回json方法(一)源码

    本篇将详细讲解如何在Struts2中配置Action来返回JSON响应。 首先,我们需要了解Struts2的Result类型。默认情况下,Action会返回一个JSP页面作为结果,但通过配置,我们可以让Action返回JSON数据。这需要使用到一个...

    struts2 action跳转action传参数

    ### Struts2中Action间的参数传递方法 在Struts2框架中,经常需要实现Action之间的跳转,并在跳转过程中传递必要的参数。这种需求在实际开发中非常常见,尤其是在需要根据用户的不同操作来调用不同的业务逻辑时。...

    Struts2 in action

    - **定义**:在Struts2框架中,**Action** 是用来处理客户端请求的核心类。当用户通过浏览器发送请求时,Struts2会将请求转发给相应的Action处理。 - **执行流程**: - 用户发起HTTP请求。 - 请求被Struts2的前端...

    Struts2--为Action的属性注入值

    在Struts2中,Action类是处理用户请求的核心组件,它封装了业务逻辑。为Action的属性注入值是Struts2的一个关键特性,使得我们可以方便地从请求参数中获取数据并绑定到Action实例上,以便后续的业务处理。 这个特性...

    Struts2_Action

    在Action类中,通常会有一个execute方法,该方法是Action的入口点,用于处理用户的请求并返回结果。例如: ```java public class LoginAction { private String userName; private String passWord; public ...

    struts2中Action获取参数的3种方式代码

    本文将详细介绍Struts2中Action获取参数的三种主要方式,并通过实际代码示例来阐述每种方法的使用。 1. **通过getter和setter方法获取参数** 这是最常见的方式,Struts2会自动将请求参数与Action类的属性进行匹配。...

    struts2.0之action

    表单数据直接包含在Action类中,通过getter和setter方法进行访问和设置。这样设计使得Action类更容易定制和扩展。 尽管Struts 2.0的Action可以不依赖任何特定类或接口,但通常为了利用框架提供的便利性,开发者会...

    struts2中action接收参数的方式

    本篇文章将深入探讨Struts2中Action接收参数的多种方式,以及相关源码解析。 首先,最常见的接收参数方式是通过方法签名直接接收。例如,如果在JSP页面上有这样一个表单: ```jsp &lt;form action="submit.action" ...

    struts2 中action的使用

    通过学习和理解上述知识点,你将能够有效地利用Struts2中的Action来组织和控制Web应用程序的流程,实现高效的开发。对于初学者来说,这是一个很好的起点,可以帮助你逐步掌握Struts2框架的核心概念和实践技巧。

    Struts2的Action中获得request response session几种方法

    在Struts2框架中,Action类是处理用户请求的核心组件,它负责业务逻辑的执行以及与视图层的交互。为了使Action能够访问到HTTP请求(HttpServletRequest)、响应(HttpServletResponse)、会话(HttpSession)等关键...

    马士兵Struts2笔记2013

    在Struts2中,你可以创建领域对象,通过setter和getter方法来接收和设置请求参数,这些对象可以在多个Action之间共享,提高了代码的复用性。 4. **Struts2_2.1.6版本的中文问题** 在某些版本的Struts2中,可能出现...

    struts2简单实例

    - Action类:在Struts2中,Action类是业务逻辑的载体,它处理用户请求并返回结果。在这个实例中,可能会有一个名为`StudentInfoAction`的类,包含查询学生信息的方法,如`queryStudents()`。 - 属性和getter/...

    struts1.x 和 struts2.x向Action里填充jsp参数原理

    3. Struts自动将请求参数值绑定到ActionForm的属性上,这得益于JavaBean规范中的getter和setter方法。 4. ActionServlet调用ActionForm的validate()方法进行表单验证。 5. 如果验证成功,ActionServlet将ActionForm...

    struts2标签使用方法

    在Struts2中,标签库是其核心特性之一,它提供了一系列预定义的JSP标签,用于简化视图层的编码,提高代码的可读性和可维护性。下面我们将详细探讨Struts2标签的使用方法以及EL(Expression Language)表达式。 1. *...

    struts2返回JSON数据的两种方式

    总结,Struts2中返回JSON数据有两种主要方式:一是通过`response.getWriter().print()`手动输出JSON字符串;二是利用Struts2的内置JSON插件,通过返回特定的属性和结果类型自动处理JSON。每种方法都有其适用场景,...

    Struts2实现的注册

    Action类通常继承自Struts2提供的`ActionSupport`类,并实现相应的getter和setter方法。此外,你还需要覆盖execute()方法,以处理用户提交的注册请求。 为了展示注册表单,创建一个JSP页面,使用Struts2的标签库...

    struts2 学习重点笔记

    - **原理**:Struts2 的拦截器会在 Action 执行完成后,调用 getter 方法并将结果存储到适当的范围对象中。 **3.4 请求转发与重定向** - **转发**:Action 的 execute 方法返回一个字符串,根据这个字符串找到对应...

    struts2 接收参数

    在Struts2中,Action类是业务逻辑的载体,每个Action类对应一个或多个用户操作。当用户提交表单或者触发某个URL时,相关的Action会被调用。 Struts2提供了多种方式来接收参数: 1. **使用setter方法**:这是最基础...

    struts2中的action.doc

    在Struts2中,Action类是核心组件,它负责处理用户的请求并协调应用逻辑。本文将深入探讨Struts2 Action中的数据处理机制,特别是关于数据来源和页面数据与Action的对应方式。 首先,Action中的数据主要来源于用户...

    struts in action

    《Struts in Action》一书深入探讨了Struts这一经典Java Web应用框架,旨在帮助开发者理解并熟练运用Struts来构建高效、可维护的Web应用程序。Struts是由Apache软件基金会开发的一个开源项目,它为Java开发者提供了...

Global site tag (gtag.js) - Google Analytics