理解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中对应的属性
来看代码:
- //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
理解Struts2的Action中的setter方法是怎么工作的的更多相关文章
- struts2:数据校验,通过Action中的validate()方法实现校验,图解
根据输入校验的处理场所的不同,可以将输入校验分为客户端校验和服务器端校验两种.服务器端验证目前有两种方式: 第一种 Struts2中提供了一个com.opensymphony.xwork2.Valid ...
- struts2:数据校验,通过Action中的validate()方法实现校验(续:多业务方法时的不同验证处理)
前文:struts2:数据校验,通过Action中的validate()方法实现校验,图解 如果定义的Action中存在多个逻辑处理方法,且不同的处理逻辑可能需要不同的校验规则,在这种情况下,就需要通 ...
- struts2的占位符*在action中的配置方法
转自:https://blog.csdn.net/u012546338/article/details/68946633 在配置<action> 时,可以在 name,class,meth ...
- JavaWeb_(Struts2框架)Action中struts-default下result的各种转发类型
此系列博文基于同一个项目已上传至github 传送门 JavaWeb_(Struts2框架)Struts创建Action的三种方式 传送门 JavaWeb_(Struts2框架)struts.xml核 ...
- struts2开发action 的三种方法以及通配符、路径匹配原则、常量
struts2开发action 的三种方法 1.继承ActionSupport public class UserAction extends ActionSupport { // Action中业务 ...
- 在struts2的action中操作域对象(request、session)
在struts2的Action中,操作域对象一共有三种方式: 1.ActionContext(与servelt API无关联): //相当于request ActionContext.getConte ...
- Struts2中使用execAndWait后,在 Action中调用getXXX()方法报告java.lang.NullPointerException异常的原因和解决方法
使用 Struts2 编写页面,遇到一个要长时间运行的接口,因此增加了一个execAndWait ,结果在 Action 中调用 getContext()的时候报告异常 ActionContext c ...
- struts2对action中的方法进行输入校验---xml配置方式(3)
上面两篇文章已经介绍了通过编码java代码的方式实现action方法校验,这里我们介绍第二种方式:xml配置文件 首先我们来看一个样例: ValidateAction.java: package co ...
- struts2对action中的方法进行输入校验(2)
struts2输入校验流程: 1.类型转换器对请求參数运行类型转换,并把转换后的值赋给aciton中的属性 2.假设在运行类型转换的过程中出现异常,系统会将异常信息保存到ActionContext, ...
随机推荐
- struts2 资源国际化
web.xml: <?xml version="1.0" encoding="UTF-8"?><web-app id="WebApp ...
- SQL查询效率where语句条件
有索引的列优先,都有索引的看查询出来的数据量,少的优先 in ,not in,<>,is null,is not null 等由于不会走索引,尽量不要使用. WHERE子句后面的条件顺序对 ...
- windows下多个文件合并成一个文件
如果你拿到的是一堆文件,那么你想把它合并成一个文件来使用,那么按下面的步骤,轻轻松松就可以搞定. 第一步:把所有要合并的文件放到同一个文件下面 第二步:在CMD里面进入到你的文件目录 第三步:输入如下 ...
- for循环计算阶乘
int x = 10; for(int y = x - 1; y >= 1; y--) { x = x * y; } System.out.println(x); 从10乘到1的阶乘写法. lo ...
- 第七章 二叉搜索树 (d2)AVL树:插入
- 常用修图工具的一些使用技巧及问题解决方法——ai
一.ai如何修改画布大小 一. ai如何修改画布大小: 1. 左上角菜单中的文件——文档设置(也可以直接点菜单栏下边的控制栏中的文档设置) 2. 文档设置界面中,点击右上角“编辑画板“ 3. 此时面板 ...
- [leetcode]636. Exclusive Time of Functions函数独占时间
Given the running logs of n functions that are executed in a nonpreemptive single threaded CPU, find ...
- php单点登陆简单实现 (iframe方式)
有四个网站分别为: www.a.com www.b.com www.c.com www.sso.com 需求是如果我们在sso登陆后,其他网站也会显示登陆中,不需要重复登陆,退出时,其他网站也会失效. ...
- PAT 1074 宇宙无敌加法器(20)(代码+思路+测试点分析)
1074 宇宙无敌加法器(20 分)提问 地球人习惯使用十进制数,并且默认一个数字的每一位都是十进制的.而在 PAT 星人开挂的世界里,每个数字的每一位都是不同进制的,这种神奇的数字称为"P ...
- 768A Oath of the Night's Watch
A. Oath of the Night's Watch time limit per test 2 seconds memory limit per test 256 megabytes input ...