The way and principle of Struts2 parameter assignment

parameter assignment method

1. Property driven

 

public class LoginAction {
    private String username;
    private String password;    
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }   
}

 

    <form action="login.action" method="post">
        姓名:<input type="text" name="username">
        密码:<input type="text" name="password">
        <input type="submit" value="提交">
    </form>

 

 

2. Define an object

 

public class LoginAction {
    private User user;  
    public User getUser() {
       return user;
    }
    public void setUser(User user) {
       this.user = user;
    }
}

 

    <form action="login.action" method="post">
        姓名:<input type="text" name="user.username">
        密码:<input type="text" name="user.password">
        <input type="submit" value="提交">
    </form>

 

 

3. Model-driven

 

public class LoginAction implements ModelDriven<User> {
    private User user=new User();
    public User getModel() {        
        return user;
    }
}

 

    <form action="login.action" method="post">
        姓名:<input type="text" name="username">
        密码:<input type="text" name="password">
        <input type="submit" value="提交">
    </form>

 

 

Value Stack

concept

ValueStack is an interface 
OgnlValueStack is the default implementation class of the ValueStack interface.

use

Can be used as a data transfer station. 
Used to pass data between foreground-background.

The life cycle

The life cycle of ValueStack is created with the creation of the request, and destroyed with the destruction of the request. 
It is created in the createActionContext of the PrepareOperations class, and cleaned up in the cleanupRequest.

 

     /**
     * Creates the action context and initializes the thread local
     */
    public ActionContext createActionContext(HttpServletRequest request, HttpServletResponse response) {
        ActionContext ctx;
        Integer counter = 1;
        Integer oldCounter = (Integer) request.getAttribute(CLEANUP_RECURSION_COUNTER);
        if (oldCounter != null) {
            counter = oldCounter + 1;
        }

        ActionContext oldContext = ActionContext.getContext();
        if (oldContext != null) {
            // detected existing context, so we are probably in a forward
            ctx = new ActionContext(new HashMap<String, Object>(oldContext.getContextMap()));
        } else {
            //------Create ValueStack-------
            ValueStack stack = dispatcher.getContainer().getInstance(ValueStackFactory.class).createValueStack();
            stack.getContext().putAll(dispatcher.createContextMap(request, response, null, servletContext));
            ctx = new ActionContext(stack.getContext());
        }
        request.setAttribute(CLEANUP_RECURSION_COUNTER, counter);
        ActionContext.setContext(ctx);
        return ctx;
    }

 

 

structure

There are two crucial things in OgnlValueStack, referred to as "object stack" and "Map stack". 

 

CompoundRoot root;
transient Map<String, Object> context;

 

The description of the object stack: 1. The properties of the object in the object stack can be directly accessed. 2. If there is an attribute with the same name in the object stack, search from the top of the stack until it is found. 3. In general, the echoed data should be placed in the object stack, which is more efficient. 4. Use Ognl expression to access the object stack, just use the property name directly without adding #.

Description of the map stack: 1. request, session, and application are all in the map stack. 2. You can put an object into the map. 3. Ognl expression accesses the contents of the map stack: if an object is in the map, then it is #request. The key value of the object. Attribute; if an object is directly put into the map, then it is the # object's key value. Attribute . Note: When you put an object on the map stack, you cannot directly access the properties of the object.

è¿ ™ é ‡ Œå † ™ å ›¾ç ‰ ‡ æ è¿ °

ModelDriven

The mechanism behind ModelDriven is ValueStack. The interface can be directly assigned to the user object through names such as username and password.

So, why is the user object in the ValueStack? When was it pushed into the ValueStack? 
The answer is: ModelDrivenInterceptor. 
ModelDrivenInterceptor is part of the default interceptor chain. When a request passes through ModelDrivenInterceptor, in this interceptor, it will be judged whether the Action object to be called currently implements the ModelDriven interface. If this interface is implemented, getModel() is called. method, and push the return value (in this case, the user object) into the ValueStack.

 

    public String intercept(ActionInvocation invocation) throws Exception {
        Object action = invocation.getAction();

        if (action instanceof ModelDriven) {
            ModelDriven modelDriven = (ModelDriven) action;
            ValueStack stack = invocation.getStack();
            Object model = modelDriven.getModel();
            if (model !=  null) {
                //放入栈中
                stack.push(model);
            }
            if (refreshModelBeforeResult) {
                invocation.addPreResultListener(new RefreshModelBeforeResult(modelDriven, model));
            }
        }
        return invocation.invoke();
    }

 

如何赋值

Struts2有个params拦截器(ParametersInterceptor),它是在调用你的LogonAction之前调用的,它会把request里面的参数(就是jsp页面上传递过来的那些值)取出来,去跟LogonAction里面的变量匹配,匹配到了就set进去,这里匹配是以setXXX方法为基准的。 
比如jsp页面上有个userName参数,拦截器就去LogonAction里面找setUserName()方法,找到了就把userName参数的值传递到setUserName()方法里面,setUserName()方法再把值赋给LogonAction里面的userName变量(这个名字随便是什么都行,因为拦截器只认setUserName()方法)。 
如果jsp页面上有个user.userName参数,拦截器就去LogonAction里面找setUser()方法,当然setUser()方法的参数就是一个User对象,所以拦截器会new一个User对象给这个setUser()方法,接着拦截器会到User对象中找setUserName()方法,并将user.userName参数的值传递给这个setUserName()方法。

流程图

赋值方法

(1)向map栈中存数据,即ValueStack中的context(OgnlContext)

ServletActionContext.getRequest().setAttribute("key","value");  
ServletActionContext.getSession().put("key","value");

    通过request,session等向map中存储数据

 

ActionContext.getContext().put("key","value");    

     直接向map栈中放数据,通过JSONResult返回json格式的数据时可以使用这种方式赋值

    @Action(value = "json", results = {@Result(type = "json", params = {"root", "result"})})
    public String queryFlowProject() {
        JSONArray result = new JSONArray();
        ServletActionContext.getContext().put("result", result);
        return "success";
    }

 

(2)向对象栈中存数据,即ValueStack中的root(CompoundRoot)对象

ValueStack valueStack = ActionContext.getContext().getValueStack();
valueStack.getRoot().add(new Object());

     先得到root,再把数据压入到root中,这中方式是放入到栈底.

 

ValueStack valueStack = ActionContext.getContext().getValueStack();
valueStack.getRoot().add(0,new Object());//这里0,表示压入栈顶.

     先得到root,利用add(index,Object)把一个对象压入到root中指定位置.

 

ValueStack valueStack = ActionContext.getContext().getValueStack();
valueStack.set("key","value");//先New一个Map,再调用push方法把Map放入到对象栈中,且放入栈顶.

     Store a map on the object stack

 

ValueStack valueStack = ActionContext.getContext().getValueStack();
valueStack.push(new Object());

     Use the push method of valueStack to push an object directly to the top of the stack

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326089523&siteId=291194637