美文网首页JAVAEE
JAVAEE框架学习——Struts2——Action API

JAVAEE框架学习——Struts2——Action API

作者: So_ProbuING | 来源:发表于2018-05-30 16:04 被阅读3次

    Action API

    通过ActionContext 获取不同域对象 存放值

    • Object get(Object key) 类似于调用HttpServletRequest 的 getAttribute(String name)方法
    • Map getApplication() 返回一个Map对象 该对象模拟了应用ServletContext实例
    • static ActionContext getContext() 静态方法 获取系统的ActionContext实例
    • Map getParameters() 获取所有的请求参数。类似调用HttpServletRequest对象的getParameterMap()方法
    • Map getSession() 返回一个Map对象 该Map对象模拟了HttpSession实例
    • void setApplication(Map application) 直接传入一个Map实例,将该Map实例里的key-value对象转换成application的属性名、属性值
    • void setSession(Map session) 直接传入一个Map实例,将该Map实例里的key-value对转换成session的属性名、属性值

    结果跳转方式

    Struts2中常用的结果跳转方式有4中:

    转发

     <package name="result" extends="struts-default">
            <action name="Demo1Action" class="cn.probuing.struts2lesson.action.Demo1Action">
                <result name="success" type="dispatcher">/hello.jsp</result>
            </action>
    </package>
    

    查看源码分析

    Struts2按照struts-default.xml配置文件可以找到 dispathcer对应的类 名为
    rg.apache.struts2.dispatcher.ServletDispatcherResult
    进入这个类中,我们可以看到如下的代码

     /**
         * Dispatches to the given location. Does its forward via a RequestDispatcher. If the
         * dispatch fails a 404 error will be sent back in the http response.
         *
         * @param finalLocation the location to dispatch to.
         * @param invocation    the execution state of the action
         * @throws Exception if an error occurs. If the dispatch fails the error will go back via the
         *                   HTTP request.
         */
        public void doExecute(String finalLocation, ActionInvocation invocation) throws Exception {
            if (LOG.isDebugEnabled()) {
                LOG.debug("Forwarding to location " + finalLocation);
            }
    
            PageContext pageContext = ServletActionContext.getPageContext();
    
            if (pageContext != null) {
                pageContext.include(finalLocation);
            } else {
                HttpServletRequest request = ServletActionContext.getRequest();
                HttpServletResponse response = ServletActionContext.getResponse();
                RequestDispatcher dispatcher = request.getRequestDispatcher(finalLocation);
    
                //add parameters passed on the location to #parameters
                // see WW-2120
                if (StringUtils.isNotEmpty(finalLocation) && finalLocation.indexOf("?") > 0) {
                    String queryString = finalLocation.substring(finalLocation.indexOf("?") + 1);
                    Map<String, Object> parameters = getParameters(invocation);
                    Map<String, Object> queryParams = urlHelper.parseQueryString(queryString, true);
                    if (queryParams != null && !queryParams.isEmpty())
                        parameters.putAll(queryParams);
                }
    
                // if the view doesn't exist, let's do a 404
                if (dispatcher == null) {
                    response.sendError(404, "result '" + finalLocation + "' not found");
                    return;
                }
    
                //if we are inside an action tag, we always need to do an include
                Boolean insideActionTag = (Boolean) ObjectUtils.defaultIfNull(request.getAttribute(StrutsStatics.STRUTS_ACTION_TAG_INVOCATION), Boolean.FALSE);
    
                // If we're included, then include the view
                // Otherwise do forward
                // This allow the page to, for example, set content type
                if (!insideActionTag && !response.isCommitted() && (request.getAttribute("javax.servlet.include.servlet_path") == null)) {
                    request.setAttribute("struts.view_uri", finalLocation);
                    request.setAttribute("struts.request_uri", request.getRequestURI());
    
                    dispatcher.forward(request, response);
                } else {
                    dispatcher.include(request, response);
                }
            }
        }
    

    由源码可以看到

    • 先通过ServletActionContext.getRequest() 获取到了HttpServletRequest 这就是请求对象
    • 通过ServletActionContext.getResponse()获取到了HttpServletResponse() 响应对象
    • 通过请求和响应对象来进行结果的操作,其中
      * 请求对象 request.getRequestDispatcher() 获得转发器,在最后dispathcer.forward(req,res)
      可以看出 Struts2的转发 就是封装的Servlet的转发,加入了一些逻辑

    重定向

    <package name="result" extends="struts-default">
         <action name="Demo2Action" class="cn.probuing.struts2lesson.action.Demo2Action">
                <result name="success" type="redirect">/hello.jsp</result>
            </action>
        </package>
    

    查看源码分析

    HttpServletResponse response = (HttpServletResponse) ctx.get(ServletActionContext.HTTP_RESPONSE);
    sendRedirect(response, finalLocation);
    

    同样 封装的Servlet重定向

    转发到Action

       <action name="Demo3Action" class="cn.probuing.struts2lesson.action.Demo3Action">
                <result name="success" type="chain">
                    <!--结果集完成后会转发到namespace上的actionName-->
                    <param name="actionName">Demo1Action</param>
                    <param name="namespace">/</param>
                </result>
            </action>
    

    重定向到Action

     <action name="Demo4Action" class="cn.probuing.struts2lesson.action.Demo4Action">
                <result name="success" type="redirectAction">
                    <param name="actionName">Demo1Action</param>
                    <param name="namespace">/</param>
                </result>
            </action>
    

    获得Servlet API

    Struts2的Action没有与任何Servlet API耦合,这是Struts2的一个改良之处

    原理

    原理

    通过ActionContext

    Struts2提供了ActionContext来访问Servlet API ActionContext是Action执行的上下文对象。在ActionContext中保存了Action执行所需要的所有对象。包括parameters,request,session,application等

     ActionContext context = ActionContext.getContext();
            //获得request域 struts不推荐使用request域
            Map<String, Object> requestScope = (Map<String, Object>) context.get("request");
            //推荐 ActionContext
            ActionContext.getContext().put("name", "requestTom");
    
            //获得session域
            Map<String, Object> session = context.getSession();
            session.put("name", "sessionTom");
            //获得application域
            Map<String, Object> application = context.getApplication();
            application.put("name", "applicationTom");
            return SUCCESS;
    

    获得session域

    • Map<String, Object> session = context.getSession();

    获得Application域

    • Map<String, Object> application = context.getApplication();

    通过ServletActionContext

    为了直接访问Servlet API Struts2框架还提供了ServletActionContext类

    public String execute(){
            //原生request
            HttpServletRequest request = ServletActionContext.getRequest();
            //原生session
            HttpSession session = request.getSession();
            //原生response
            HttpServletResponse response = ServletActionContext.getResponse();
            //原生servletContext
            ServletContext servletContext = ServletActionContext.getServletContext();
            return SUCCESS;
        }
    

    通过实现接口方式

    Struts2接口
    public class Demo7Action extends ActionSupport implements ServletRequestAware, ServletResponseAware, ServletContextAware {
        private ServletContext context;
        private HttpServletRequest request;
        private HttpServletResponse resp;
    
        @Override
        public void setServletRequest(HttpServletRequest request) {
            this.request = request;
        }
    
        @Override
        public void setServletResponse(HttpServletResponse response) {
            this.resp = response;
        }
    
        @Override
        public void setServletContext(ServletContext context) {
            this.context = context;
        }
    
        public String execute() throws Exception {
            System.out.println("原生request" + request);
            return SUCCESS;
        }
    

    由拦截器完成

    Action中获得参数

    第一种:通过与参数键名称相同的属性

     private String name;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        @Override
        public String execute() throws Exception {
            System.out.println(this.name);
            return SUCCESS;
        }
    

    属性驱动获得参数

     private String name;
        private Integer age;
        private Date birthday;
    
        public Date getBirthday() {
            return birthday;
        }
    
        public void setBirthday(Date birthday) {
            this.birthday = birthday;
        }
    
        public Integer getAge() {
            return age;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        @Override
        public String execute() throws Exception {
            System.out.println(this.name);
            System.out.println(this.age);
            System.out.println(this.birthday);
            return SUCCESS;
        }
    
    <form action="${pageContext.request.contextPath}/Demo8Action" method="post">
        用户名:<input type="text" name="name"/><br/>
        年龄:<input type="text" name="age"/><br/>
        生日:<input type="text" name="birthday"/><br/>
        <input type="submit" value="提交"/>
    </form>
    

    第二种 对象驱动

    • 创建对象
    public class User {
        private String name;
        private Integer age;
        private Date birthday;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Integer getAge() {
            return age;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    
        public Date getBirthday() {
            return birthday;
        }
    
        public void setBirthday(Date birthday) {
            this.birthday = birthday;
        }
    }
    
    • 页面指定提交到对象的对应属性
    <form action="${pageContext.request.contextPath}/Demo9Action" method="post">
        用户名:<input type="text" name="user.name"/><br/>
        年龄:<input type="text" name="user.age"/><br/>
        生日:<input type="text" name="user.birthday"/><br/>
        <input type="submit" value="提交"/>
    </form>
    
    • Action 中声名对象属性
      private User user;
    
        public User getUser() {
            return user;
        }
    
        public void setUser(User user) {
            this.user = user;
        }
    
        @Override
        public String execute() throws Exception {
            System.out.printf(this.user.toString());
            return SUCCESS;
        }
    

    其实某种意义上 对象驱动和属性驱动没有什么区别,只是将属性换成了对象

    第三种 模型驱动

    • Action实现ModelDriven<模型>接口
    public class Demo10Action extends ActionSupport implements ModelDriven<User> {
    
        private User user = new User();
    
    
        @Override
        public String execute() throws Exception {
            System.out.printf(this.user.toString());
            return SUCCESS;
        }
    
        /**
         * @return 返回需要封装的对象
         */
        @Override
        public User getModel() {
            return user;
        }
    }
    
    • 页面正常提交
    <form action="${pageContext.request.contextPath}/Demo10Action" method="post">
        用户名:<input type="text" name="name"/><br/>
        年龄:<input type="text" name="age"/><br/>
        生日:<input type="text" name="birthday"/><br/>
        <input type="submit" value="提交"/>
    </form>
    

    缺点:封装的模型单一

    原理(正在学习 日后补)

    集合类型参数封装

    封装list

    • Action类
     private List<String> list;
    
        public List<String> getList() {
            return list;
        }
    
        public void setList(List<String> list) {
            this.list = list;
        }
    
        @Override
        public String execute() throws Exception {
            System.out.println("list" + list);
            return SUCCESS;
        }
    
    • 页面page
        list:<input type="text" name="list"/>
        list:<input type="text" name="list[1]"/>
        <input type="submit" value="提交"/>
    

    前端表单指定name="list" Struts2直接将参数封装到list集合中

    指定添加索引

       list:<input type="text" name="list[1]"/>
    

    封装Map

    • Action类
     public void setMap(Map<String, String> map) {
            this.map = map;
        }
    
        public List<String> getList() {
            return list;
        }
    @Override
        public String execute() throws Exception {
            System.out.println("list" + list);
            System.out.println("map" + map);
            return SUCCESS;
        }
    
    • 页面page
        list:<input type="text" name="map['haha']"/>
    

    扩展知识

    StrutsMVC

    StrutsMVC

    Action 生命周期

    • 每次接收请求到来时,都会创建一个新的Action实例
    • Action是线程安全的,可以使用成员变量接收参数

    相关文章

      网友评论

        本文标题:JAVAEE框架学习——Struts2——Action API

        本文链接:https://www.haomeiwen.com/subject/rvgjjftx.html