zoukankan      html  css  js  c++  java
  • (五)Struts之Action类基础(二)

    • 上一章节末((三)Struts之Action类基础(一))介绍了如何获取用户输入数据的获取。接着就是在Struts中怎么把数据响应给用户端,这就必须要求我们把数据放到作用域中,然后才能显示到用户浏览器。

    一、将数据放到作用域并在用户浏览器中显示

      A、 使用Servlet原生作用域(request、session、servletContext)

    index.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <%
    String path=request.getContextPath();
    %>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
        <pre>
            <h3>把数据放到Servlet原生作用域(request、session、servletContext)然后显示</h3>
            
            <a href="<%=path%>/scope/scope_1">点我显示数据</a>
    
        </pre>
    </body>
    </html>

    界面:

    struts.xml

    <struts>
    
        <constant name="struts.enable.DynamicMethodInvocation" value="true" />
        <constant name="struts.devMode" value="true" />
    
        <package name="default" namespace="/scope" extends="struts-default">
            <action name="scope_1" class="scope.ActionScope_1">
            <result name="show">/show.jsp</result>
            </action>
        </package>
    
    </struts>

     ActionScope.java

    package scope;
    
    import action.BaseAction;
    
    public class ActionScope_1  extends BaseAction{
    
        @Override
        public String execute() {
        
            request.setAttribute("request_key", "request作用域的值");
            session.setAttribute("session_key", "session作用域的值");
            servletContext.setAttribute("servletContext_key", "servletContext作用域的值");
            return "show";
        }
    }

    show.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
        <pre>
                    <h3>显示放在作用域中的数据</h3>
            request作用域的值为:${requestScope.request_key }
            session作用域的值为:${sessionScope.session_key }
            servletContext作用域的值为:${applicationScope.servletContext_key }
        </pre>
    </body>
    </html>

    结果:

      B、使用struts封装的作用域

    •  使用struts封装的作用域,把reuqest、session、servletContext作用域封装成Map

    index.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <%
    String path=request.getContextPath();
    %>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
        <pre>
            <h3>把数据放到Struts封装的作用域中然后显示</h3>
            
            <a href="<%=path%>/scope/scope_2">点我显示数据</a>
    
        </pre>
    </body>
    </html>

    界面:

    • struts.xml
    <struts>
    
        <constant name="struts.enable.DynamicMethodInvocation" value="true" />
        <constant name="struts.devMode" value="true" />
    
        <package name="default" namespace="/scope" extends="struts-default">
            <action name="scope_2" class="scope.ActionScope_2">
            <result name="show">/show.jsp</result>
            </action>
        </package>
    
    </struts>
    • ActionScope_2.java
    package scope;
    
    import java.util.Map;
    
    import com.opensymphony.xwork2.ActionContext;
    
    import action.BaseAction;
    
    public class ActionScope_2  extends BaseAction{
    /**
     * 用Struts封装的作用域ActionContext(Action上下文)存放数据
     * ActionContext和ServletActionContext的区别,ServletActionContext用于
     * 获取servlet原生对象
     * ActionContext把servlet作用域封装成Map
     */
        
        @Override
        public String execute() {
            ActionContext actionContext=ActionContext.getContext();
            //request作用域的获取比较特殊
            //获取action封装后的作用域
            Map<String,Object> requestMap=(Map<String,Object>)actionContext.get("request"); 
            Map<String,Object> sessionMap=actionContext.getSession();
            Map<String,Object> applicationMap=actionContext.getApplication();
            
            //在作用域中存放数据
            requestMap.put("requestMap_key", "requset中的值1");
            sessionMap.put("sessionMap_key", "sessionMap中的值1");
            applicationMap.put("applicationMap_key", "applicationMap中的值1");
            return "show";
        }
    
    }
    • show.jsp
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
        <pre>
                    <h3>显示放在作用域中的数据</h3>
            request作用域的值为:${requestScope.requestMap_key }
            session作用域的值为:${sessionScope.sessionMap_key }
            servletContext作用域的值为:${applicationScope.applicationMap_key }
        </pre>
    </body>
    </html>

    结果:

    • 解析: Struts中通过ActionContext这个静态类可以得到request、session、servletContext作用域,并把这些作用于封装成Map对象,而在JSP页面中,通过EL表达式获取作用域中的值的方式没有改变,${requestScope.value1 }或${sessionScope.value2}或${applicationScope.value3}


    •  上述例子中显示数据的方式是EL表达式,在Struts中可以用Struts的方式来显示数据。

    二、数据在页面上的显示

      A、 使用EL表达式+JSTL标签

    以上述例子所示,index.jsp和struts.xml和ActionScope_2.java文件均与上例一样,show.jsp如下:

     1 <%@ page language="java" contentType="text/html; charset=UTF-8"
     2     pageEncoding="UTF-8"%>
     3  <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
     4 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
     5 <html>
     6 <head>
     7 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
     8 <title>Insert title here</title>
     9 </head>
    10 <body>
    11     <pre>
    12                 <h3>El表达式+JSTL标签显示放在作用域中的数据</h3>        
    13         <c:if test="${requestScope.requestMap_key==null}">        
    14             <c:out value="${requestScope.requestMap_key}"></c:out>    
    15         </c:if>
    16 
    17         session作用域的值为:${sessionScope.sessionMap_key }
    18         servletContext作用域的值为:${applicationScope.applicationMap_key }
    19     </pre>
    20 </body>
    21 </html>
    •  注意第13行中的语句${requestScope.requestMap_key==null} 如果requestScope中的requestMap_key值等于null的话就显示出来,否则不显示,结果如下,并不显示reqeuset作用域中的数据,说明JSTL+EL表达式成功运行:

      B、使用OGNL表达式+Struts标签

    •  Struts标签中不能用EL表达式,如<s:if test="${sessionScope.sessionMap_key}" 这是错的<s:if>是struts标签,而${sessionScope.sessionMap_key是el表达式。同理,JTSL标签中不能用OGNL表达式。
    •  以上述例子所示,index.jsp和struts.xml和ActionScope_2.java文件均与上例一样,show.jsp如下:
     1 <%@ page language="java" contentType="text/html; charset=UTF-8"
     2     pageEncoding="UTF-8"%>
     3  <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
     4  <%@ taglib prefix="s" uri="/struts-tags" %>
     5 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
     6 <html>
     7 <head>
     8 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
     9 <title>Insert title here</title>
    10 </head>
    11 <body>
    12     <pre>
    13                 <h3>El表达式+JSTL标签显示放在作用域中的数据</h3>        
    14         <c:if test="${requestScope.requestMap_key==null}">        
    15             <c:out value="${requestScope.requestMap_key}"></c:out>    
    16         </c:if>
    17 
    18         <h3>OGNL表达式+Struts标签显示放在作用域中的数据</h3>
    19     
    20     <s:if test="#request.requestMap_key!=null"> 
    21         <s:property value="#request.requestMap_key"/>
    22     </s:if>
    23     </pre>
    24 </body>
    25 </html>
    • 注意EL表达式和OGNL表达式取值的方法,EL表达式取出reqeuse、session、application作用域中值的方法为requestScope.属性名【sessionScope.属性名】【applicationScope.属性名】  而OGNL表达式取出作用域中的值的方法为#request.属性名【#session.属性名】【#application.属性名


    三、Struts和servlet同时使用

    •  当我们部署好Struts之后,web.xml中的

     <filter-mapping>
        <filter-name>EncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
      </filter-mapping>

    • 会拦截一切页面,其中如果定义了一个servlet,也会把当作action处理。比如当URL=“工程名/servlet/TestServlet”
    • web.xml
     <servlet>
        <description></description>
        <display-name>TestServlet</display-name>
        <servlet-name>TestServlet</servlet-name>
        <servlet-class>servlet.TestServlet</servlet-class>
      </servlet>
      <servlet-mapping>
        <servlet-name>TestServlet</servlet-name>
        <url-pattern>/servlet/test</url-pattern>
      </servlet-mapping>

    我们希望会执行servlet.TestServlet这个servlet类,但是实际上被struts拦截器当成action了,就去struts.xml中找命名空间为/servlet的action名为TestServlet,但是找不到于是就是报错。

    • 解决上述问题的方法

    要解决这个问题就不得不提起struts.xml中的一个常量<constant name="struts.action.extension" value="=action,,"/> 默认也是这个,意思是对于所有的请求后缀名为action或者为空的请求,都会被拦截,并到struts.xml中寻找相对应的Action.

          A、 解决方法1 :将servlet的后缀名更改为与Struts中常量(struts.action.extension)不一样的后缀名,适用于servlet文件比较少的项目

          B、 解决方法2:将struts的后缀名改掉,适用于struts文件比较少的项目,比如:

      <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>*.action</url-pattern>
      </filter-mapping>

         C、解决方法3: 当项目中struts和servlet文件都差不多的话,如果改后缀名会很麻烦,那么我们可以重写StrutsPrepareAndExecuteFilter里的方法,即如下配置:

    web.xml

    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
      </filter>
      <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
      </filter-mapping>
      <servlet>
    <servlet>
        <description></description>
        <display-name>TestServlet</display-name>
        <servlet-name>TestServlet</servlet-name>
        <servlet-class>servlet.TestServlet</servlet-class>
      </servlet>
      <servlet-mapping>
        <servlet-name>TestServlet</servlet-name>
        <url-pattern>/servlet/test</url-pattern>
      </servlet-mapping

    如上,无论访问哪个页面都会被Struts的StrutsPrepareAndExecuteFilter这个过滤器拦截然后转到Struts.xml中解析,如果Struts和sevlet中都不添加后缀名的话,servlet就无法被访问到。

    • 具体方法:    1.   定义一个类,继承StrutsPrepareAndExecuteFilter这个过滤器,重写doFilter()方法,

               2.   在web.xml中把 StrutsPrepareAndExecuteFilter过滤器换成我们定义的类。

    • 解决方法3示例:

    index.jsp:

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <%
    String path=request.getContextPath();
    %>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
        <pre>
        <a href="<%=path%>/servlet/test">点击跳转到servlet页面</a>
        </pre>
    </body>
    </html>
    • a标签中的请求为servlet请求
    • StrutsFilter.java 这个类重写了StrutsPrepareAndExecuteFilter过滤器中的doFilter()方法,
    package filter;
    
    import java.io.IOException;
    
    import javax.servlet.FilterChain;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServletRequest;
    
    import org.apache.struts2.dispatcher.ng.filter.StrutsPrepareFilter;
    
    public class StrutsFilter extends StrutsPrepareFilter{
    
        @Override
        public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
                throws IOException, ServletException {
        /**
         * 判断请求是sevlet还是struts请求
         *     
         */
            HttpServletRequest request=(HttpServletRequest)req;    
            String requestPath=request.getRequestURI();
            
            if(requestPath.indexOf("/servlet/") !=-1){
                //请求为servlet请求,如果是servlet请求则跳过这个过滤器让下一个过滤器来处理。
                System.out.println("aaa");
                chain.doFilter(req, res);
                    
            }else{
                //请求为struts请求,是struts请求直接让父类来处理
                System.out.println("bbb");
                super.doFilter(req, res, chain);
            }        
        }
    }
    • 最后修改web.xml配置。 web.xml
     <filter>
        <filter-name>struts2</filter-name>
        <filter-class>filter.StrutsFilter</filter-class>
      </filter>
      <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
      </filter-mapping>
      <servlet>
        <description></description>
        <display-name>TestServlet</display-name>
        <servlet-name>TestServlet</servlet-name>
        <servlet-class>servlet.TestServlet</servlet-class>
      </servlet>
      <servlet-mapping>
        <servlet-name>TestServlet</servlet-name>
        <url-pattern>/servlet/test</url-pattern>
      </servlet-mapping>

     如上述,StrutsPrepareAndExecuteFilter换成了我们自己定义的类。


    • 解决方法1示例:
    • index.jsp
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <%
    String path=request.getContextPath();
    %>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
        <pre>
          <a href="<%=path%>/servlet/test.do">点击跳转到servlet页面</a>
        </pre>
    </body>
    </html>
    • struts.xml
    <struts>
    
        <constant name="struts.enable.DynamicMethodInvocation" value="true" />
        <constant name="struts.devMode" value="true" />
        <constant name="struts.action.extension" value="=action,,"/>
        <package name="default" namespace="/scope" extends="struts-default">
            <action name="scope_2" class="scope.ActionScope_2">
            <result name="show">/show.jsp</result>
            </action>
        </package>
    
    </struts>
    • web.xml
      <servlet>
        <description></description>
        <display-name>TestServlet</display-name>
        <servlet-name>TestServlet</servlet-name>
        <servlet-class>servlet.TestServlet</servlet-class>
      </servlet>
      <servlet-mapping>
        <servlet-name>TestServlet</servlet-name>
        <url-pattern>/servlet/test.do</url-pattern>
      </servlet-mapping>
    •  TestServlet.java
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            PrintWriter out=response.getWriter();
            
            
            out.print("我是servlet");
        }

    结果:


  • 相关阅读:
    springboot 整合 mybatis plus
    Centos7下安装Docker
    idea 将项目打包成 docker 镜像 推送到 阿里云
    Windows10 使用 docker toolbo x安装 docker
    js 修改 url 但不刷新页面
    MySQL-建数据库的字符集与排序规则说明
    7.Redis 缓存过期处理与内存淘汰机制
    6.Redis 主从复制原理总结
    5.Redis 持久化
    4.Springboot整合Redis
  • 原文地址:https://www.cnblogs.com/shyroke/p/6553811.html
Copyright © 2011-2022 走看看