Struts2之处理请求参数

时间:2022-01-22 15:08:14

时间:2017-1-11 11:05

——Struts2中获取请求参数(重点)

1、Struts2是一个MVC框架,那么分别表示什么?
    View:JSP
    Model:Action
    Controller:Action、StrutsPrepareAndExecuteFilter

2、为什么Action既是Model又是Controller?
    因为Action本身可以作为一个JavaBean。

3、在Struts2中获取请求参数有两大种(三小种)方式可以获取:
    1)属性驱动(在Action中添加属性,对Action的属性进行操作)
        *   直接将Action作为一个Model,就可以得到请求参数,也就是将Action作为一个JavaBean,提供get/set方法。
            这种方式底层是通过反射来实现的。
            >   问题1:使用Action封装请求参数,会不会存在线程安全问题?
                不会,每一次请求都会生成一个Action对象。
            >   问题2:使用该方式封装数据,将数据封装到Action属性中,不可能将Action对象传递给业务层。
                需要单独定义JavaBean,将Action属性封装到JavaBean

            示例代码:
                    //属性驱动的第一种方式获取请求参数,直接将Action做为Model
                    public class Login1Action extends ActionSupport {
                        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;
                        }
                        @Override
                        public String execute() throws Exception {
                            HttpServletRequest request = ServletActionContext.getRequest();
                            if ("tom".equals(username) && "123".equals(password)) {
                                request.getSession().setAttribute("username", username);
                              return SUCCESS;
                            } else {
                                request.setAttribute("login.message", "用户名或密码错误");
                                return "failer";
                            }
                        }
                    }

            实现原理:
                1、首先为Action类提供JavaBean属性,并提供get / set方法
                2、在过滤器中添加如下代码,将请求参数封装到JavaBean中:
                    /*
                     * 在调用invoke()方法前,处理请求参数的封装
                     */
                    Object actionObject = c.newInstance();
                    // 将请求参数封装到Action中(底层也是反射实现的)
                    BeanUtils.populate(actionObject, request.getParameterMap());
                3、在Action中使用属性 

------------------------------------------------------------------------------------------------------------------

        *   创建独立的Model对象,页面通过ognl表达式封装
            >   在Action中声明一个JavaBean对象
            >   private User user;
            >   提供get/set方法:public User getUser()....
            >   在页面中使用ognl表达式:<input type="text" name="user.username" />
            优点:简单,解决了第一种封装的问题。
            缺点:在页面中使用了ognl表达式,与Struts2框架耦合度高。

            示例代码:

                /*

                 * 属性驱动的第二种方式获取请求参数,在Action中声明一个JavaBean
                 * 在表单中的name值需要修改为:
                 *  * name="user.username" name="user.password"
                 *  * <input type="text" name="user.username" />
                 * user表示Action内部封装JavaBean对象的名称
                 * 这是Struts2中提供的一个默认表达式语言:ognl
                 */
                public class Login2Action extends ActionSupport {
                    private User user;
                    public User getUser() {
                        return user;
                    }
                    public void setUser(User user) {
                        this.user = user;
                    }
                    @Override
                    public String execute() throws Exception {
                        HttpServletRequest request = ServletActionContext.getRequest();
                        if ("tom".equals(user.getUsername()) && "123".equals(user.getPassword())) {
                            request.getSession().setAttribute("username", user.getUsername());
                            return SUCCESS;
                        } else {
                            request.setAttribute("login.message", "用户名或密码错误");
                            return "failer";
                        }
                    }
                }

------------------------------------------------------------------------------------------------------------------

            这种方式底层通过Struts2中的一个interceptor进行了封装:
                <interceptor name="params" class="com.opensymphony.xwork2.interceptor.ParametersInterceptor" />
                    @Override

                    public String doIntercept(ActionInvocation invocation) throws Exception {
                        Object action = invocation.getAction();
                        if (!(action instanceof NoParameters)) {
                            ActionContext ac = invocation.getInvocationContext();
                            // 相当于request.getParameters(); 
                            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();
                                    // 将参数赋值给Action中的JavaBean 
                                    setParameters(action, stack, parameters);
                                } finally {
                                    ReflectionContextState.setCreatingNullObjects(contextMap, false);
                                    ReflectionContextState.setDenyMethodExecution(contextMap, false);
                                    ReflectionContextState.setReportingConversionErrors(contextMap, false);
                                }
                            }
                        }
                        return invocation.invoke();
                    }

------------------------------------------------------------------------------------------------------------------

    2)模型驱动(在开发中应用比较多)
        使用ModelDriven接口,对请求数据进行封装。
        步骤:
            *   声明一个JavaBean对象并且必须实例化对象。
                >   private User user = new User();
            *   Action类实现ModelDriven接口
                >   public class Login3Action extends ActionSupport implements ModelDriven

            *   重写getModel()方法
                >   public Object getModel() { return this.user; }

        优点:解决了属性驱动存在的问题
            *   不需要将Action封装成JavaBean
            *   解决了在页面中使用ognl表达式的问题
        缺点:一次只能封装一个JavaBean对象,getModel()方法只能返回一个Bean。

        很多关于模型驱动的拦截器都是ModelDriven拦截器操作的:
            com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor

        示例代码:

            /*
             * 使用模型驱动获取请求参数
             */
            public class Login3Action extends ActionSupport implements ModelDriven {
                private User user = new User();
                public Object getModel() {
                    return this.user;
                }
 
                public String login() throws Exception {
                    HttpServletRequest request = ServletActionContext.getRequest();
                    System.out.println(user.getUsername() + ": " + user.getPassword());
                    if ("tom".equals(user.getUsername()) && "123".equals(user.getPassword())) {
                        request.getSession().setAttribute("username", user.getUsername());
                        return "success.jsp";
                    } else {
                        request.setAttribute("msg", "用户名或密码错误");
                        return "login.jsp";
                    }
                }
            }

        实现原理:
            1、在Action中声明一个初始化的JavaBean对象。
            2、实现ModelDriven接口
            3、重写getModel()方法
            4、在拦截器中实现如下代码:
                /*
                 * 模型驱动
                 */
                // 得到HelloAction类中声明的User对象
                Object actionObject = c.newInstance();
 
                // 判断HelloAction是否实现了MyModelDriven接口
                if(actionObject instanceof MyModelDriven){
                    // 将子类强转成父类
                    MyModelDriven model = (MyModelDriven)actionObject;
 
                    // 获取HelloAction内部的User对象,然后把请求参数封装到User对象中
                    BeanUtils.populate(model.getModel(), request.getParameterMap());
                } else {
                    // 1、属性驱动
                    actionObject = c.newInstance();
                    // 将请求参数封装到Action中(底层也是反射实现的)
                    BeanUtils.populate(actionObject, request.getParameterMap());
                }

——将请求参数封装到集合(了解)

原理:使用ognl表达式实现。

1、将数据封装到List集合
    页面:
        用户名1:<input type="text" name="users[0].username" /><br/>

        密    码1:<input type="password" name="users[0].password" /><br/>
        用户名2:<input type="text" name="users[1].username" /><br/>
        密    码2:<input type="password" name="users[1].password" /><br/>

Action类:
        private List<User> users;
        get / set方法

2、将数据封装到Map集合
    页面:
        用户名1:<input type="text" name="users['aaa'].username" /><br/>

        密    码1:<input type="password" name="users['aaa'].password" /><br/>
        用户名2:<input type="text" name="users['bbb'].username" /><br/>
        密    码2:<input type="password" name="users['bbb'].password" /><br/>

    Action类:
        private Map<String, User> users;
        get / set方法


——总结

1、Action接收请求参数

*   关于Struts2中的MVC
    *   属性驱动
        >   直接将Action作为JavaBean。
        >   Action中封装JavaBean,在页面上需要使用ognl表达式来给组件起名。
    *   模型驱动
        >   让Action实现ModelDriven接口,重写getModel()方法实例化一个JavaBean对象,该方法返回的就是实例化的JavaBean对象。
    *   关于请求参数封装到集合
        >   List
        >   Map