zoukankan      html  css  js  c++  java
  • 理解Struts2的Action中的setter方法是怎么工作的

    接触过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中对应的属性

    来看代码:

    Java代码  收藏代码
    1. //com.opensymphony.xwork2.interceptor.ParametersInterceptor.java  
    2. //主要代码如下:  
    3. //...  
    4.   
    5.     @Override  
    6.     public String doIntercept(ActionInvocation invocation) throws Exception {  
    7.         Object action = invocation.getAction();  
    8.         if (!(action instanceof NoParameters)) {  
    9.             ActionContext ac = invocation.getInvocationContext();  
    10.             final Map<String, Object> parameters = retrieveParameters(ac);  
    11.   
    12.             if (LOG.isDebugEnabled()) {  
    13.                 LOG.debug("Setting params " + getParameterLogMap(parameters));  
    14.             }  
    15.   
    16.             if (parameters != null) {  
    17.                 Map<String, Object> contextMap = ac.getContextMap();  
    18.                 try {  
    19.                     ReflectionContextState.setCreatingNullObjects(contextMap, true);  
    20.                     ReflectionContextState.setDenyMethodExecution(contextMap, true);  
    21.                     ReflectionContextState.setReportingConversionErrors(contextMap, true);  
    22.   
    23.                     ValueStack stack = ac.getValueStack();  
    24.                     setParameters(action, stack, parameters);  
    25.                 } finally {  
    26.                     ReflectionContextState.setCreatingNullObjects(contextMap, false);  
    27.                     ReflectionContextState.setDenyMethodExecution(contextMap, false);  
    28.                     ReflectionContextState.setReportingConversionErrors(contextMap, false);  
    29.                 }  
    30.             }  
    31.         }  
    32.         return invocation.invoke();  
    33.     }  
    34.   
    35.     protected void setParameters(Object action, ValueStack stack, final Map<String, Object> parameters) {  
    36.         ParameterNameAware parameterNameAware = (action instanceof ParameterNameAware)  
    37.                 ? (ParameterNameAware) action : null;  
    38.   
    39.         Map<String, Object> params;  
    40.         Map<String, Object> acceptableParameters;  
    41.         if (ordered) {  
    42.             params = new TreeMap<String, Object>(getOrderedComparator());  
    43.             acceptableParameters = new TreeMap<String, Object>(getOrderedComparator());  
    44.             params.putAll(parameters);  
    45.         } else {  
    46.             params = new TreeMap<String, Object>(parameters);  
    47.             acceptableParameters = new TreeMap<String, Object>();  
    48.         }  
    49.   
    50.         for (Map.Entry<String, Object> entry : params.entrySet()) {  
    51.             String name = entry.getKey();  
    52.   
    53.             boolean acceptableName = acceptableName(name)  
    54.                     && (parameterNameAware == null  
    55.                     || parameterNameAware.acceptableParameterName(name));  
    56.   
    57.             if (acceptableName) {  
    58.                 acceptableParameters.put(name, entry.getValue());  
    59.             }  
    60.         }  
    61.   
    62.         ValueStack newStack = valueStackFactory.createValueStack(stack);  
    63.         boolean clearableStack = newStack instanceof ClearableValueStack;  
    64.         if (clearableStack) {  
    65.             //if the stack's context can be cleared, do that to prevent OGNL  
    66.             //from having access to objects in the stack, see XW-641  
    67.             ((ClearableValueStack)newStack).clearContextValues();  
    68.             Map<String, Object> context = newStack.getContext();  
    69.             ReflectionContextState.setCreatingNullObjects(context, true);  
    70.             ReflectionContextState.setDenyMethodExecution(context, true);  
    71.             ReflectionContextState.setReportingConversionErrors(context, true);  
    72.   
    73.             //keep locale from original context  
    74.             context.put(ActionContext.LOCALE, stack.getContext().get(ActionContext.LOCALE));  
    75.         }  
    76.   
    77.         boolean memberAccessStack = newStack instanceof MemberAccessValueStack;  
    78.         if (memberAccessStack) {  
    79.             //block or allow access to properties  
    80.             //see WW-2761 for more details  
    81.             MemberAccessValueStack accessValueStack = (MemberAccessValueStack) newStack;  
    82.             accessValueStack.setAcceptProperties(acceptParams);  
    83.             accessValueStack.setExcludeProperties(excludeParams);  
    84.         }  
    85.   
    86.         for (Map.Entry<String, Object> entry : acceptableParameters.entrySet()) {  
    87.             String name = entry.getKey();  
    88.             Object value = entry.getValue();  
    89.             try {  
    90.                 newStack.setParameter(name, value);  
    91.             } catch (RuntimeException e) {  
    92.                 if (devMode) {  
    93.                     String developerNotification = LocalizedTextUtil.findText(ParametersInterceptor.class, "devmode.notification", ActionContext.getContext().getLocale(), "Developer Notification: {0}", new Object[]{  
    94.                              "Unexpected Exception caught setting '" + name + "' on '" + action.getClass() + ": " + e.getMessage()  
    95.                     });  
    96.                     LOG.error(developerNotification);  
    97.                     if (action instanceof ValidationAware) {  
    98.                         ((ValidationAware) action).addActionMessage(developerNotification);  
    99.                     }  
    100.                 }  
    101.             }  
    102.         }  
    103.   
    104.         if (clearableStack && (stack.getContext() != null) && (newStack.getContext() != null))  
    105.             stack.getContext().put(ActionContext.CONVERSION_ERRORS, newStack.getContext().get(ActionContext.CONVERSION_ERRORS));  
    106.   
    107.         addParametersToContext(ActionContext.getContext(), acceptableParameters);  
    108.     }  
    109. //...  

    上面的代码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类:

    Java代码  收藏代码
    1. package com.liany.demo.pubs.org.employee.action;  
    2.   
    3. import java.util.List;  
    4.   
    5. import com.opensymphony.xwork2.ActionSupport;  
    6.   
    7. import com.liany.demo.pubs.org.employee.model.Employee;  
    8. import com.liany.demo.pubs.org.employee.service.EmployeeService;  
    9.   
    10. public class EmployeeAction extends ActionSupport{  
    11.       
    12.     private EmployeeService employeeService;  
    13.     private List list;   
    14.     private Employee employee = new Employee();    
    15.       
    16.       
    17.     public StringReader getStringReader() {  
    18.         StringReader is = null;  
    19.         try {  
    20.             is = new StringReader(xmlBuf.toString());  
    21.         } catch (Exception e) {  
    22.             e.printStackTrace();  
    23.         }  
    24.         return is;  
    25.     }  
    26.       
    27.     public Employee getEmployee() {  
    28.         return employee;  
    29.     }  
    30.   
    31.     public void setEmployee(Employee employee) {  
    32.         this.employee = employee;  
    33.     }   
    34.   
    35.     public List getList() {  
    36.         return list;  
    37.     }  
    38.   
    39.     public void setEmployeeService(EmployeeService employeeService) {  
    40.         this.employeeService = employeeService;  
    41.     }  
    42.       
    43.     public String execute(){  
    44.         //列表  
    45.         list = this.employeeService.getEmployees();  
    46.           
    47.         return "list";  
    48.     }  
    49.       
    50.     public String view(){  
    51.         employee = this.employeeService.getEmployeeById(employee.getId());  
    52.           
    53.         return "view";  
    54.     }  
    55.       
    56.     public String edit(){  
    57.         if(employee.getId()!=null){  
    58.             //修改  
    59.             employee = this.employeeService.getEmployeeById(employee.getId());  
    60.         }else{  
    61.             //新增  
    62.             employee.setId(null);  
    63.         }  
    64.           
    65.         return "input";  
    66.     }  
    67.       
    68.     public String save(){  
    69.         this.employeeService.saveEmployee(employee);  
    70.           
    71.         return "repage";  
    72.     }  
    73.       
    74.     public String delete(){  
    75.         this.employeeService.deleteEmployeeById(employee.getId());  
    76.           
    77.         return "repage";  
    78.     }  
    79. }  

    上面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

  • 相关阅读:
    UIWebView显示乱码问题
    Masonry控制台打印约束冲突问题解决
    iOS正则表达式之验证问题总结
    Cannot assign to 'self' outside of a method in the init family
    iOS模拟器设置输入中文
    python递归中的return"陷阱"
    自己动手写一个U盘拷贝小工具
    selenium对富文本框的处理
    selenium webdriver如何添加cookie
    利用ChromeOptions()加载用户配置
  • 原文地址:https://www.cnblogs.com/zhangshitong/p/5225752.html
Copyright © 2011-2022 走看看