• Struts2.X深入浅出 学习笔记


    第一节、MVC以及Struts2简介

    第二节、Action生命周期以及接收表单数据

    第三节、Struts2配置以及Struts.xml详解

    • Struts2 主要配置文件

    Web.xml 设置过滤器以及annotation初始化参数 
    Struts.xml 主配置文件 
    Struts.properties 默认属性文件 
    Struts-default.xml 默认配置文件 
    Struts-plugin.xml 插件配置文件 
    • Struts2 主要配置加载次序

    由上至下,以此为:
    Struts-default.xml
    Struts-plugin.xml
    Struts.xml
    Struts.properties
    Web.xml
    如果在多个文件中配置了同一个Struts2常量,则后一个文件中的配置的常量值将覆盖前面文件中配置的常量值。在不同文件中配置常量的方式是不一样的,但不管哪个文件中,配置Struts2常量都要指定两个属性:常量name和常量value
    推荐在struts.xml文件中配置Struts2常量 
    • Struts-default.xml 配置信息

    Bean元素属性 
    class:必选,指定了Bean实例的实现类 
    type:可选,通常是通过某个接口或者在此前定一个过的Bean 
    name:可选,它指定的Bean实例的名字,对于有相同type的多个Bean,name必须唯一 
    scope:可选,指定Bean的作用域,只能是default、singleton、request、session和thread之一 
    static:可选,它指定Bean是否使用静态方法注入。通常而言,当指定了type属性时,该属性就不应该设置为true 
    optional:可选,指定Bean是否是一个可选Bean 
    • default.properties 默认属性信息

    ##字符集 
    struts.i18n.encoding=UTF-8 
    struts.objectFactory.spring.autoWire = name 
    struts.objectFactory.spring.useClassCache = true 
    struts.objectFactory.spring.autoWire.alwaysRespect = false 
    struts.multipart.parser=jakartastruts.multipart.saveDir=struts.multipart.maxSize=2097152 
    ##请求后缀 
    struts.action.extension=action,, 
    struts.serve.static=true 
    struts.serve.static.browserCache=true 
    struts.enable.DynamicMethodInvocation = false 
    struts.enable.SlashesInActionNames = false 
    struts.mapper.action.prefix.enabled = false 
    struts.mapper.action.prefix.crossNamespaces = false 
    struts.tag.altSyntax=true 
    ##开发模式 
    struts.devMode = false 
    struts.i18n.reload=false 
    struts.ui.theme=xhtmlstruts.ui.templateDir=template 
    struts.ui.theme.expansion.token=~~~struts.ui.templateSuffix=ftl 
    struts.configuration.xml.reload=false 
    struts.velocity.configfile = velocity.properties 
    struts.velocity.contexts = 
    struts.velocity.toolboxlocation= 
    struts.url.http.port = 80struts.url.https.port = 443 
    struts.url.includeParams = none 
    struts.dispatcher.parametersWorkaround = false 
    struts.freemarker.templatesCache=false 
    struts.freemarker.beanwrapperCache=false 
    struts.freemarker.wrapper.altMap=true 
    struts.freemarker.mru.max.strong.size=0 
    struts.xslt.nocache=false 
    struts.mapper.alwaysSelectFullNamespace=false 
    struts.ognl.allowStaticMethodAccess=false 
    struts.el.throwExceptionOnFailure=false 
    struts.ognl.logMissingProperties=false 
    struts.ognl.enableExpressionCache=true 
    struts.handle.exception=true 
    • Struts.xml 配置信息

    <struts> 
        <!--重置属性—> 
        <constant name="struts.devMode" value="true"> </constant> 
        <constant name="struts.i18n.encoding" value="urf-8"></constant> 
        <!--定义包—> 
        <package name="default" namespace="/" extend="struts-default"> 
            <!--动作—> 
            <action name="" class=""> 
                <result name="" class="" ></result> 
            </action> 
        </package> 
    </struts> 
    Constant 常量 
    Package 包 解决Action重名,方便继承 
      -name 包名 
      -extends 父包名 
      -namespace 命名空间 
    Action 
      -name 动作名 
      -class 实现类 
    global-results 全局结果 
    Result 局部结果

    第四节、Action 高级

    • method 属性

    <action name="admin" class="net.nw.action.AdminAction" method="add"> 
        <result>result.jsp</result>
    </action> 
    • DMI动态方法调用

    <action name="admin" class="net.nw.action.AdminAction"> 
        <result>result.jsp</result>
    </action>
    <a href="<%=path%>/admin/admin!add.action">添加</a> 
    • Forword Action(页面跳转)

    • 默认Action

    <default-action-ref name="error"></default-action-ref>
    <action name="error">
        <result>error.jsp</result>
    </action>
    • 通配符映射

    <action name="Student*" class="net.nw.struts2.action.StudentAction" method="{1}">
        <result>/Student{1}_success.jsp</result>
    </action>
    
    {0} 表示匹配所有内容
    {1} 表示前面的第一个*的内容
    *  0-N不包括 "/"
    ** 0-N包括 "/"
      转义符
    • Zero Configuration (Annotation配置)

    引入struts2-convention-plugin-2.2.1.jar包
    //web.xml
    <filter>
        ……
        <init-param>
        <param-name>actionPackages</param-name>
        <param-value>net.nw.action</param-value>
        </init-param>
        <init-param>
        <param-name>encoding</param-name>
        <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    //注解
    @parentPackage(value="struts-default")
    @Namespace(value="/")
    @Result(name="login_success",location="/login_success.jsp")
    @Results({
    @Result(name="login_success",location="/login_success.jsp","type="redirect"),
    @Result(name="login_failure",location="/login_failure.jsp","type="redirect")
    })
    • 包含模块

    <include file="admin.xml">
    • 出错页面

    <action name="**">
        <result>error.jsp</result>
    </action>

    第五节、访问Web元素以及Result类型

    • Action访问web对象四种方式:

    1.创建request,session,application Map对象
    Map request = (Map)ActionContext.getContext().get("request");
    Map session = ActionContext.getContext().getsession();
    Map application = ActionContext.getContext().getApplication(); 
    2.实现RequestAware,SessionAware,ApplicationAware接口 Map对象(常用)
    3.创建传统的HttpServletRequest、HttpSession、ServletContext对象
    HttpServletReques request = ServletActionContext.getRequest();
    HttpSession session = request.getSession();
    ServletContext application = session.getServletContext(); 
    4.实现ServletRequestAware、ServletContextAware接口
    • Result类型

    Dispatcher:转发到URL,通常是JSP(服务器)
    Redirect:重定向到URL,通常是JSP(客户端)
    Chain:转发到一个Action(服务器)
    redirectAction:重定向到一个Action(客户端)
    freemarker:处理FreeMarker模型
    Httpheader:控制特殊HTTP行为的结果类型
    Stream:向浏览器发送InputSream对象,通常用来处理文件下载,还可用于返回AJAX数据
    Velocity:处理Velocity模版
    Xslt:处理XML/XLST模版
    plainText:显示原始文件内容,例如文件源代码

    第六节、Validation框架和i18n

    • Exception异常处理

    <global-results>
        <result name = "error" > /error.jsp</result>
    </global-results>
    <global-exception-mappings>
        <exception-mapping result="error" exception="java.lang.Exception"></exception>
    </global-exception-mappings> 
    • Validation框架

      分为validate() / XML / Annotation 三种方式

    重写validate() 方法,验证action中所有的方法。
    @Override
    public void validate(){
        if(! false){
            this.addFieldError("validate_error","验证错误!");
        }
        super.validate();
    }
    编写ActionName-validation.xml,验证action中所有的方法。
    //Login-validation.xml
    <!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.3//EN"
            "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
    <validators>
      <field name="username">
          <field-validator type="requiredstring">
              <message>用户名不能为空</message>
          </field-validator>
          <field-validator type="email">
              <message>用户名必须为邮箱格式</message>
          </field-validator>
      </field>
      <field name="password">
          <field-validator type="requiredstring">
              <message>密码不能为空</message>
          </field-validator>
          <field-validator type="stringlength">
              <param name="minLength">6</param>
              <param name="maxLength">20</param>
              <message>密码长度必须在 ${min} ~ ${max}之间</message>
          </field-validator>
      </field>
    </validators> 
    validateMethodName(), 验证指定方法
    //User.java
    public void validateLogin(){
        if(! false){
            this.addFieldError("validate_error","验证错误!");
        }
    } 
    Struts.xml配置, 验证指定方法
    //User.java
    @Override
    public void validate(){
        if(! false){
            this.addFieldError("validate_error","验证错误!");
        }
        super.validate();
    }
    //Struts.xml
    <action>
        <interceptor name="defaultStack">
            <param name="validation.includeMethods">add</param>
        </interceptor>
    </action> 
    Annotation注解
    @Action(interceptorRefs=@InterceptorRef(value="defaultStack",params={"validation.includeMethod},"add")) 
    
    @SkipValidation (推荐) 
    出错信息
    <s:filederror cssStyle="color:red" /> 
    • i18n

    i18n:Internationalization  国际化

    L10n:localization 本地化

    创建资源文件(包名_语言_国家.properties)
    App_en_US.properties
    App_zn_CN.properties 
    Struts.xml加载属性文件
    <constant name="struts.custom.i18n.resources" value="APP"></constant> 
    
    //.html
    <a href="<%=path%>"/language.action?request_local=en_US">英文</a>
    <s.property value="getText('label.username)" /> 
    
    //Validation.xml
    <message>
    ${getText("login.field.isnull",{getText("label.username")})}
    </message>

    第七节、OGNL(一)

    • OGNL简介

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

    • 对象导航图

    • 方法调用

    普通方法

    //java
    public String method(){
      return "aaaaa";
    }
    //jsp
    <s:property value="obj.method()" />

    Action普通方法

    //jsp
    <s:property value="method()" />

    静态方法

    //struts.xml
    <constant name="struts.ognl.allowStaticMethodAcces" value="true"></constant>
    //jsp
    <s:property value="@package.ActionName@method()" />

    静态属性(注意,必须是public)

    //java
    public static Int num = 123;
    //jsp
    <s:property value="@package.ActionName@num" />

    构造方法

    <s:property value="new package.construct() " />

    系统Math方法

    <s:property value="@@random() " />

    系统其他类方法

    <s:property value="@java.util.Calendar@getInstance() " />
    • 集合对象

    List(有序,可重复)

    Set(无序,不可重复)

    Map(键值对)

    获取集合长度  list.size();

    //java
    private List<String> aaa = new ArrayList<String>();
    private Set<String> bbb = new HashSet<String>();
    private Map<Interget,String> ccc= new HashMap<interger String>();
    public construct()
    {
        aaa.add("aaaaaa");
        bbb.add("bbbbbb");
        ccc.put("1","ccc");
    }
    //jsp
    <s:property value="aaa" />                <!---List 集合 ->
    <s:property value="aaa[0]" />            <!---List 集合对象 ->
    <s:property value="aaa.{attr}" />       <!---List 集合属性 ->
    <s:property value="aaa.{attr}.[0]" />  <!---List 集合属性 ->
    <s:property value="bbb" />                <!---Set 集合 ->
    <s:property value="bbb[0]" />            <!---Set 集合对象 ->
    <s:property value="ccc" />                <!---Map 集合 ->
    <s:property value="ccc[1]" />            <!---Map 集合对象 ->
    <s:property value="ccc.keys" />         <!---Map 集合中key对象 ->
    <s:property value="ccc.values" />       <!---Map 集合中values对象 ->
    <s:property value="ccc.size()" />        <!---Map 集合中的长度 ->

    第八节、OGNL(二)

    • 投影和选择

    #this       当前
    ?            所有
    ^           第一个
    $           最后一个

    //java
    private List<Students> stus = new ArrayList<Students>();
    public construct()
    {
        stus.add(new Students("张三",18));
        stus.add(new Students("李四",28));
        stus.add(new Students("王五",38));
    }
    //jsp
    <s:property value="stus.{?#this.age>=30}.{name}" />
    <s:property value="stus.{^#this.age>=30}.{name}" />
    <s:property value="stus.{$#this.age>=30}.{name}" />
    • #符号的使用

    访问根对象
        Struts2 中值栈为根对象,如ODNL上下文和Action上下文,#相当于ActionContext.getContext();
        下面是几个ActionContext中有用的属性:

        #parameters       URL地址参数
        #request            请求参数
        #session            SESSION参数
        #application
        #attr                用于按request > session > application 顺序访问其属性(attribute)

    用于选择和投影

    构造Map

    #{'foo1':'bar1','foo2':'bar2'}

    • $符号的使用

    用于在国际化资源文件中,引用OGNL表达式

    在Struts 2 配置文件中,引用OGNL表达式(不推荐)

    • 值栈

    Struts2 为每一次请求生成一个值栈,不同的请求对应不同的值栈

    Struts2 接收到一个action请求,首先创建Action类的实例对象,把该对象压进值栈。此时action中的所有属性都是默认值。然后执行定义该action上的所有拦截器,最后执行action动作。
    Action构造方法->拦截器->动作方法
    注意:拦截器可以改变属性的值,当改变某个属性值后,Action类的相应属性值就会变成在拦截器中最后改变该属性的这个值。

    两个action之间采用的是服务器跳转,如果两个action有名字相同的属性,则对后一个属性的修改是否会覆盖前一个action的属性。分以下两种情况:

    如果具体相同名字的属性是引用类型,则会覆盖。

    如果具体相同名字的属性是基本类型,则不会覆盖。

    将对象压入值栈

    ActionContext.getContext().getValueStack().push(obj); 

    访问值栈中的对象

    [0].attr          //从值栈第一个对象开始寻找
    [1].method()   //从值栈第二个对象开始寻找 
    
    <s:property value="[0]" />
    <s:property value="[1]" />
    <s:property value="[2]" />

    第九节、Interceptor拦截器

    • 拦截器原理

    拦截器(Interceptor) 是Struts2框架的核心,Struts2中包括解析请求参数、将请求参数赋值给Action属性、执行数据校验、文件上传等工作都是通过拦截器实现的,Struts2设计的灵巧性,更大程度地得益于拦截器设计,当需要扩展Struts2功能时,只需要提供对应拦截器,并将它配置在Struts2容器中即可;如果不需要该功能时,也只需要取消该拦截器的配置即可。

    Struts2 内建了大量的拦截器,这些拦截器以name-class对的形式配置在struts-default.xml文件中,其中name是拦截器的名字,就是以后使用该拦截器的唯一标识;class则指定了该拦截器的实现类,如果我们定义的package继承了Struts2的默认struts-default包,则可以自由使用下面定义的拦截器,否则必须自己定义这些拦截器。

    • 常见的内置拦截器

    chain:服务器内部跳转

    execAndWait:等待执行拦截器

    fileUpload:文件上传拦截器

    timer:统计动作执行时间

    token:表单令牌

    token-session:表单令牌会话

    • 拦截器与过滤器的区别

    拦截器拦截的是动作(action),过滤器过滤的是请求(request),过滤器一般映射为 /* ,过滤所有请求。

    拦截器是基于java反射机制的,而过滤器是基于函数回调的。

    过滤器依赖于servlet容器,而拦截器不依赖于servlet容器。

    拦截器可以访问Action上下文、值栈里的对象,而过滤器不能。

    在Action的生命周期中,拦截器可以多次调用,而过滤器只能在容器初始化时被调用一次。

    自定义拦截器

    实现Interceptor接口(不推荐)

    继承AbstractInterceptor抽象类,对所有方法进行拦截

    //java
    class demoInterceptor extents AbstractInterceptor{
        @Override
        public String intercept(ActionInvocation invocation) throws Exception{
            //拦截之前
            String result = invocation.invokde();
            //拦截之后
            return result;
        }
    }
    //struts.xml
    <package name="default"  namespace="/"  extends="struts-default">
        <interoeptors>
            <interceptor name="demoInterceptor" class="package.demoInterceptor" />
            <intorceptor-stack name="mydefaultStack">
                <interceptor-rel name="demoInterceptor" ></interceptor-rel>
                <interceptor-rel name="defaultStack" ></interceptor-rel>
            </intorceptor-stack>
        </interoeptors>
    </package>
    <package name="user"  namespace="/user" extends="default">
        <action name="login" class="package.UserAction">
            <interceptor-rel name="mydefaultStack" ></interceptor-rel>
        </action>
    </package> 

    MethodFilterInterceptor,对指定方法进行拦截

    //java
    class demoInterceptor extents MethodFilterInterceptor{
        @Override
        public String doIntercept(ActionInvocation invocation) throws Exception{
            //拦截之前
            String result = invocation.invokde();
            //拦截之后
            return result;
        }
    }
    //struts.xml
    <package name="default"  namespace="/"  extends="struts-default">
        <interoeptors>
            <interceptor name="demoInterceptor" class="package.demoInterceptor" />
            <intorceptor-stack name="mydefaultStack">
                <interceptor-rel name="demoInterceptor" >
                    <param name="excludeMethods">excludeFun</param>
                </interceptor-rel>
                <interceptor-rel name="defaultStack" ></interceptor-rel>
            </intorceptor-stack>
        </interoeptors>
    </package>
    <!--另一种方式-->
    <package name="user"  namespace="/user" extends="default">
        <action name="login" class="package.UserAction">
            <interceptor-rel name="mydefaultStack" >
                <param name="demoInterceptor.excludeMethods">excludeFun</param>
                <param name="demoInterceptor.includeMethods">includeFun</param>
            </interceptor-rel>
        </action>
    </package> 

    PreResultListener 监听器 在返回结果集之前执行的方法

    //java
    class BeforeResultInterceptor extents PreResultListener{
        public void beforeResult(ActionInvocation invocation,String str){
            //返回结果集之前执行
        }
    }
    class demoInterceptor extents MethodFilterInterceptor{
        @Override
        public String doIntercept(ActionInvocation invocation) throws Exception{
            invocation.addPreResultListener(new BeforeResultInterceptor());
            //拦截之前
            String result = invocation.invokde();
            //拦截之后
            return result;
        }
    }

    使用拦截器解决表单重复提交

    //struts.xml
    <interceptor-ref name="token">
        <!-- 显示重复提交出错页面-->
    </interceptor-ref>
    <interceptor-ref name="tokenSession">
        <!-- 显示重复提交成功页面,但不执行重复提交动作-->
    </interceptor-ref>
    <result name="invalid.token">/tokenerror.jsp</result>
    //jsp
    <s:token></s:token>  

    第十节、UI表单标签

    第十一节、OtherTag和类型转换

    第十二节、FileUpload组件

    第十三节、页面圆形和Tiles布局

    第十四节、数据建模和用例分析

    第十五节、验证码以及权限管理

    第十六节、分页

  • 相关阅读:
    字符编码解码
    综合练习[购物车]
    for 循环实例
    数据类型
    字符串格式化输出
    集成开发环境
    while循环实例
    赋值运算符、逻辑运算符、表达式
    if,else语句猜最大值
    计算今天和今天的上一月的日期
  • 原文地址:https://www.cnblogs.com/linzhenjie/p/3704674.html
Copyright © 2020-2023  润新知