Struts2学习

1)Struts2

  Struts2是一个基于MVC设计模式的Web应用框架,它本质上相当于一个servlet,在MVC设计模式中,Struts2作为控制器(Controller)来建立模型与视图的数据交互。Struts2在Struts1融合webwork。

2)Struts2处理用户请求的完整流程

 步骤:

1)首先客户端浏览器发送一个请求(HttpServletRequest)。

2)接着程序会调用 StrutsPrepareAndExecuteFilter,然后询问 ActionMapper 这个请求是否需要调用某个 Action。

3)如果 ActionMapper 决定需要调用某个 Action,StrutsPrepareAndExecuteFilter 会把请求的处理交给 ActionProxy。

4)ActionProxy 通过配置管理器(Configuration Manager)从配置文件(struts.xml)中读取框架的配置信息,从而找到需要调用的 Action 类。

5)ActionProxy 会创建一个 ActionInvocation 的实例。

6)ActionInvocation 使用命名模式调用 Action,在调用 Action 前,会依次调用所有配置的拦截器(Intercepter1、Intercepter2……)。

7)一旦 Action 执行完,则返回结果字符串,ActionInvocation 就会负责查找结果字符串对应的 Result,然后执行这个 Result。通常情况下 Result 会调用一些模板(JSP 等)呈现页面。

8)产生的 Result 信息返回给 ActionInvocation,在此过程中拦截器会被再次执行(顺序与 Action 执行之前相反)。

9)最后产生一个 HttpServletResponse 的响应行为,通过 StrutsPrepareAndExecuteFilter 反馈给客户端。

3)Struts2环境搭建与使用

  1. 导入Struts2 - jar包(导入核心包即可)
  2. 在web.xml中配置过滤器
  3. 编写Action类
  4. 配置struts.xml

4)web.xml配置过滤器

配置struts2的核心过滤器:

<filter>
  <filter-name>struts</filter-name>
  <filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class>
  <init-param><!-- 传递参数,设置字符编码 -->
    <param-name>encoding</param-name>
    <param-value>UTF-8</param-value>
  </init-param>
</filter>
<filter-mapping>
  <filter-name>struts</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>
View Code

注意:配置struts2过滤器要放到其他过滤器后面,保证其他过滤器可以执行。

5)Action类与配置

Action类相当于javaWeb阶段下的Servlet类,做着调用service层的关系,实现页面的跳转,完成业务逻辑操作。

● Action的创建(注意:action类的全路径(即包名)必须含有”action”的词汇)

 ① 创建一个POJO类;(hibernate自动会封装成PO类)

public class DefaultAction {

    public String execute() throws Exception {
        System.out.println("DefaultAction...run");
        return "";
    }
}
View Code

 ② 创建一个类实现一个实现Action接口;

import com.opensymphony.xwork2.Action;

public class ImplAction implements Action {

    public String execute() throws Exception {
        System.out.println("ImplAction...run");
        return "defaultAction";
    }
}
View Code

 ③ 创建一个类继承ActionSupport类;

import com.opensymphony.xwork2.ActionSupport;

public class ExtAction extends ActionSupport {

    @Override
    public String execute() throws Exception {
        System.out.println("ExtAction...run");
        return "";
    }

}
View Code

● 访问Action类

 ① 直接通过<action>标签来配置,通过method来指定访问的方法,如果method没有,默认访问的是execute方法;

 ② 简化的 action 访问方式,可以使用*通配符来访问,使用*来简化操作方案,它对名称规范必须进行一个统一。

struts.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC 
    "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
     "http://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
    
    <constant name="struts.devMode" value="true"></constant>
    <constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>
    
    <!-- name:配置包名 ;namespace:给action的访问路径定义一个命名空间;extends:固定形式继承struts-default -->
    <package name="MyPackage" namespace="/" extends="struts-default">
        <global-allowed-methods>regex:.*</global-allowed-methods>
        <action name="LoginAction_*" class="com.sikiedu.web.UserAction" method="{1}">
            <!-- 重定向 -->
            <result name="success" type="redirect">/index.html</result>
            <!-- 默认为转发 -->
            <result name="error">/login.jsp</result>
        </action>
        
        <action name="LoginActionDefault" class="com.sikiedu.web.DefaultAction" method="execute"></action>
        <action name="LoginActionImpl_*" class="com.sikiedu.web.ImplAction" method="{1}">
            <!-- 转发到LoginActionDefault -->
            <result name="defaultAction" type="chain">LoginActionDefault</result>
            <!-- 重定向到Action(LoginAction_*) -->
            <result name="toLogin" type="redirectAction">
                <param name="actionName">LoginAction_login</param>
                <param name="username">${username}</param>
                <param name="password">${password}</param>
            </result>
        </action>
    </package>
</struts>
View Code

● 核心配置:

① package标签(strust.xml只存在一个package相当于一个struts的项目)
  ● name:定义一个包的名称,用来指定包名,它必须唯一;建议跟namespace保持一致
  ● namespace:用来action的访问路径定义一个命名空间;与URL中的路径保持一致;
  ● extends:指定继承自哪个包。一般值是struts-default,struts-default包是 在struts-default.xml文件中声明的。
  ● abstruct:它代表当前包是一个抽象的,主要是用于被继承。
② action标签(对应相应的以action结尾的类,一个package可以有多个action)   ● name:action访问的资源路径,与package的namespace联合使用。对应Servlet中的:url-pattern;   ● class:表示当前action的完整类名。   ● method:表示调用action类中的哪个方法处理请求。
③ result标签(用于显示视图的结果)   ● name:与action中的的method方法的返回值进行匹配,来确定跳转路径。默认是"success"   ● type:是用于指定打开结果对应页面或资源的方式。默认是"dispatch"

● 动态方法调用:

<constant name="struts.devMode" value="true"></constant>
<constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>
<package name="MyPackageName" namespace="/" extends="struts-default">
  <global-allowed-methods>regex:.*</global-allowed-methods>
  <action name="LoginActionImpl_*" class="com.sikiedu.web.ImplAction" method="{1}">
    ...
  </action>
</package>

● 结果集的处理:

<!-- 重定向 -->
<result name="success" type="redirect">/index.html</result>
<!-- 默认为转发 -->
<result name="error">/login.jsp</result>
<!-- 转发到Action - LoginActionDefault -->
<result name="defaultAction" type="chain">LoginActionDefault</result>
<!-- 重定向到Action - Action(LoginAction_*) -->
<result name="toLogin" type="redirectAction">
  <param name="actionName">LoginAction_login</param><!--  actionName固定形式  -->
  <param name="username">${username}</param><!-- ${}ognl表达式 -->
  <param name="password">${password}</param>
</result>

Struts2错误状态记录器未找到log4j2配置文件传送门

解决中文乱码问题:web.xml中配置encoding

<filter>
  <filter-name>struts</filter-name>
  <filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class>
  <init-param>
    <param-name>encoding</param-name>
    <param-value>UTF-8</param-value>
  </init-param>
</filter>
<filter-mapping>
  <filter-name>struts</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>
View Code

6)参数传递

● 接收参数:属性驱动、模型驱动

属性驱动:
  1.在 Action 类中创建与请求参数匹配的属性,
  2.为属性提供get/set方法
模型驱动:
  1.让 Action 类要实现一个指定接口 ModelDriven;
  2.实例化模型对象(就是要new出来javaBean);
  3.重写getModel方法将实例化的模型返回。

● 传递参数:ActionContext、ServletActionContext

//获得Request域
ActionContext.getContext().put("key", "value");
ServletActionContext.getRequest().getAttribute("key");
//获得Session域
ActionContext.getContext().getSession().put("key", "value");
ActionContext.getContext().getSession().get("key");
//获得Application域
ActionContext.getContext().getApplication().put("key", "value");
ActionContext.getContext().getApplication().get("key");、

//得到原生的Request、Response等域。
ServletActionContext.getRequest();
ServletActionContext.getResponse();

 ① ActionContext生命周期是一次请求,每次请求都会创建一个对应的ActionContext对象,请求结束时销毁ActionContext对象。

   就和request一样,它本身也具备了request域的功能,可以从后台携带数据到前台。

 ② 通过ActionContext的子类ServletActionContext可以直接获得session和application等多个域对象,操作方便。

 ③ ActionContext本身也是一个map,它存储了很多对象例如request、response等多个对象。

7)ONGL与Struts标签

OGNL是Object-Graph Navigation Language(对象图导航语言)的缩写,它是一种功能强大的表达式语言,通过它简单一致的表达式语法,可以存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能。它使用相同的表达式去存取对象的属性。

struts2框架内置了OGNL,OGNL本身也是一个项目,它是可以单独使用

OGNL作用

● 支持对象的操作,调用对象的方法;
● 支持静态成员访问;
● 支持赋值操作与表达串联;
● 访问OGNL上下文,访问ActionContext;
● 操作集合对象。

Strtus2框架中如何使用ognl表达式

在struts2框架中我们使用ognl表达式的作用是从valueStack中获取数据,在struts2框架中可以使用ognl+valueStack达到在页面(jsp)上来获取相关的数据,要想在jsp页面上使用ognl表达式,就需要结合struts2框架的标签<s:property value=”表达式”>来使用。

<s:iterator value="" var=""></s:iterator><!-- 遍历集合 -->
<s:property value="key"/><!-- 获取数据 -->
<!-- 如果访问的数据是包装类型,需要加# -->
<s:property value="#Object.key"/>
<s:if test="布尔表达式"></s:if>
<s:else></s:else>

8)valueStack

valueStack的主要目的是为action中产生的数据携带到页面上,也就是说valueStack它就是一个容器,在Struts2框架中将valueStack设计成一个接口,当客户端向我们发送一个请求,服务器就会创始一个Action来处理请求,struts2中的action是一个多例,每一次请求都会有一个新的action对应。所以它不存在线程安全问题,一个valueStack对应一个action,valueStack贯穿整个action的生命周期,struts2框架将valueStack保存在request中。

9)action原理

10)result结果处理

result是用于做输出的组件,用于向页面输出一些内容,转发重定向可以理解为特殊方式的输出。每一个result就是一个类,这些类都实现了共同的接口Result,struts2预置了10种类型的result,他们定义在struts-default.xml中。

<result-types>
    <result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/>
    <result-type name="dispatcher" class="org.apache.struts2.result.ServletDispatcherResult" default="true"/>
    <result-type name="freemarker" class="org.apache.struts2.views.freemarker.FreemarkerResult"/>
    <result-type name="httpheader" class="org.apache.struts2.result.HttpHeaderResult"/>
    <result-type name="redirect" class="org.apache.struts2.result.ServletRedirectResult"/>
    <result-type name="redirectAction" class="org.apache.struts2.result.ServletActionRedirectResult"/>
    <result-type name="stream" class="org.apache.struts2.result.StreamResult"/>
    <result-type name="velocity" class="org.apache.struts2.result.VelocityResult"/>
    <result-type name="xslt" class="org.apache.struts2.views.xslt.XSLTResult"/>
    <result-type name="plainText" class="org.apache.struts2.result.PlainTextResult" />
    <result-type name="postback" class="org.apache.struts2.result.PostbackResult" />
</result-types>

1、所有的 <result> 默认的名称 ( name ) 都是 success ,默认的 类型 ( type ) 都是 dispatcher
2、dispatcher 等同于 RequestDispatcher 中的 forward 操作 ,redirect 等同于 HttpServletResponse 中的 sendRedirect 操作

3、当 type = "redirect" 时,可以指定任意的位置

<result type="redirect">http://www.google.com</result>

redirectAction 类似于 redirect , 与 redirect 不同的是它专门重定向到 <action>

<result name="success" type="redirectAction">
  <param name="namespace">/customer</param>
  <param name="actionName">page/success/register</param>
</result>
全局的 result
1、<global-results>在这里所写的 result 属于当前包 的全局 result,当前包 的所有<action>可以访问
2、action标签呢的result属于局部的result,仅仅当前的 <action> 可以访问

11)拦截器

如图所示,Struts2拦截器的实现原理相对简单,当请求struts2的action时,Struts 2会查找配置文件,并根据其配置实例化相对的拦截器对象,然后串成一个列表,最后一个一个地调用列表中的拦截器。

intercept方法所依赖的参数ActionInvocation则是Action调度者。ActionInvocation中的invoke()方法具备以下2层含义(详细看DefaultActionInvocation源代码):

  • 如果拦截器堆栈中还有其他的Interceptor,那么invocation.invoke()将调用堆栈中下一个Interceptor的执行。
  • 如果拦截器堆栈中只有Action了,那么invocation.invoke()将调用Action执行。

创建拦截器的两种方式

① 实现com.opensymphony.xwork2.interceptor.Interceptor 接口;实现其中的destroy() 、init() 、intercept() 方法

② 继承com.opensymphony.xwork2.interceptor.AbstractInterceptor 类;实现其中的intercept() 方法

拦截器和过滤器的比较

1、拦截器和过滤器的概念非常类似,拦截器中的intercept()和过滤器中的doFilter()方法。
2、拦截器是基于动态代理来实现,而过滤器是基于函数回调。
3、过滤器隶属于web容器,可以过滤一切请求(包括action、servlet、jsp、html等等)。
4、而拦截器隶属于struts2框架,只能拦截action(无法拦截对jsp的请求)。
5、在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次
6、执行顺序 :过滤前 - 拦截前 - Action处理 - 拦截后 - 过滤后。

拦截器执行顺序:按照引用顺序依次执行,拦截器栈中拦截器,按照拦截器栈的顺序去依次执行。

配置拦截器:

<interceptors>
    <!-- 注册拦截器 -->
    <interceptor name="MyIntercept" class="com.sikiedu.web.intercept.MyIntercept"></interceptor>
    <!-- 注册拦截器栈 -->
    <interceptor-stack name="myStack">
        <!-- 引入自己创建的拦截器 -->
        <interceptor-ref name="MyIntercept">
            <!-- 拦截器排除方法 -->
            <param name="excludeMethods">login</param>
        </interceptor-ref>
        <!-- 引入struts默认写好的拦截器(20) -->
        <interceptor-ref name="defaultStack"></interceptor-ref>
    </interceptor-stack>
</interceptors>
<!-- 在指定包中的默认拦截器栈 -->
<default-interceptor-ref name="myStack"></default-interceptor-ref>
原文地址:https://www.cnblogs.com/Dm920/p/11742916.html