1、namespace = "" 处理的是找不到对应的namespace的所有情况

比如有一个package, namespace = "/top" result为/index.jsp
        有一个package, namespace = ""     result为/index.jsp
    如果我敲/bottom/index.jsp,没有对应的namespace, 那么为namespace =""的package就来处理这个action, 
    在它的result里找有没有index.jsp,如果还没有就报错
    
2、tomcat处理地址的过程:
    eg, http://localhost:8080/MyStrcuts/HelloWorld/HelloWorld.jsp;

看有没有filter过滤,于是发现struts2,于是交给它处理,找不到再返回来
   
3、action里有指定class的情况:
    eg, <action name="test" class="com.zaq.mystructs.IndexAction">
            <result>
                /hello.jsp
            </result>
        </action>
        
    省略了class, 它默认的class是ActionSupport.class, 这个class的execute就返回了"success"
    
4、java三种写action的方法:
    直接在class中写String xxx()方法
    实现Action接口
    继承自ActionSupport类 (推荐)

5、匹配URL的三种方法:
    1、常规通过action result 指定具体的class,(method),和result地址
    2、使用!感叹号的形式:
    eg. <action name="user" class="com.zaq.mystructs.User">
            <result>
                /User.jsp
            </result>
        </action>
        
        而User.class里有一个add的方法,返回success
        那么可以这么写:http://localhost:8080/WebApp/package_namespace/user!add来访问这个方法
        好处是不用写多个Action来分别指定执行的method, 动态选择method来执行
        注意要加上:<constant name="struts.enable.DynamicMethodInvocation" value="true"/>
        还要加上<global-allowed-methods>regex:.*</global-allowed-methods>
        
    3、通配符的方法,要求约定好形式:
    <action name="*_*" class="com.zaq.mystructs.{1}" method="{2}">
            <result name="{2}">
                /{1}_{2}.jsp
            </result>
    </action>

可以这么写:
    http://localhost:8080/WebApp/package_namespace/User_Login来访问, 那么{1}就代表User,{2}代表Login,
    访问的是mystructs.User下Login方法(返回String login),接收返回值"login"后跳转到User_Login.jsp
    很无敌
    这样就可以类似http://localhost:8080/WebApp/package_namespace/User_Register来同样操作,
    只要在User里加一个Register()即可;很灵活
    
    
6、利用Action的属性接受参数:
    在User里指定字段name, age, 写setter,getter,然后:
    http://localhost:8080/WebApp/package_namespace/User_Login?name=zaq&age=20
    这样默认调用了setter, 可以直接使用name,age字段,连new User()都不用

7、利用DomainModel接收参数:
    如果字段有很多,6比较麻烦,此时可以这么写:
    在UserMgr中直接定义User user这个对象字段, 只写getUser(),setUser()然后:
    http://localhost:8080/WebApp/package_namespace/User_Login?user.name=zaq&user.age=20
    这样默认先set好一个User, 再给UserMgr;

8、利用ModelDriven接收参数
    实现ModelDriven<User>的接口,重写getModel()方法,然后return user;
    这里可以省略user的getter和setter,取而代之的是写User user = new User();
    没错一定要new一个

9、中文编码:
    默认就是UTF-8 配置的方法就是struts.i18n.encoding=UTF-8
    
10、数据验证:
    通过valueStack 和 fieldError:
    后台在拿到参数后,进行业务逻辑判断,调用addFieldError来设置错误的键值对;
    eg if(name != 'admin'){
        this.addFieldError("login", "not admin");
    }
    result配置到前台,通过定义structs的标签:
    <%@taglib uri = "/struts-tags" prefix="s"%> 
    
    就可以拿数据:
    <s:property value="name"/>  //"AL"
    <s: property value="fieldErrors.login[0]" />   //"not admin"
    
    注意:
    1、后台设置错误键值对可以多设几个:
    eg:this.addFieldError("login", "not admin");
    this.addFieldError("login", "length too long");
    这样在前台拿的时候可以依次:
    <s: property value="fieldErrors.login[0]" />   //"not admin"
    <s: property value="fieldErrors.login[1]" />   //"length too long"
    
    2、加入<s:debug/>标签可以在前台调出valueStack 和 ContextStack 的信息
    里面包含了property的键值对,可以参考stack来写vaule;
    
    比如,fieldErrors.login[0]代表:
    在VauleStack中, fieldErrors是一个Key, 对应的Value是一个Map, 
    取出其中Key为login的Value, 再取出Value的第一个元素[0]
    
    
11、获得Web元素:Request, Session, Application (依赖容器/IoC)
    方法一:利用Map容器:
    
    Map request;
    Map session;
    Map application;

构造方法里:
    request = (Map)ActionContext.getContext().get("request");
    session = ActionContext.getContext().getSession();
    application = ActionContext.getContext().getApplication();
    
    execute()的时候:
    //进行业务逻辑操作
    request.put("name", name);
    session.put("name",name);
    application.put("name", name);
    
    前台:因为找的是context, 所以要加#, 在debug里也能看的
    <s:property value = "#request.name"/>
    <s:property value = "#session.name"/>
    <s:property value = "#application.name"/>
    
    方法二: IoC 控制反转  常用!
    使用接口,RequestAware,SessionAware, ApplicationAware
    实现方法 setRequest(Map<String, Object> request), setSession(Map<String, Object> session), setApplication(Map<String, Object> application);
    this.request = request;
    this.session = session;
    this.application = application;
    
    与方法一不一样的是不用自己去getContext().getXXX;
    
    
12、模块包含
    在pacakge里可以直接<include file=""/> 来原封不动引入配置

13、default模式
    加入<default-action-ref name="index"/>
    表示如果namespace下找不到对应的action,就转到index这个action
    注意这个标签一定要加在<global-allowed-methods>前面 否则报错
    而且这个package里不要有通配符的使用, 否则好像也会报错

14、结果集的跳转(4个):
    1、dispatcher (默认的)
    服务器端跳转到jsp
    2、redirect
    重定向到jsp, 客户端跳转,url地址跟着变的
    3、chain:
    跳转到action 不同包下的action要通过<param>标签指定namespace 和 actionName 来跳转
    4、redirectAction:
    客户端跳转Action, url地址跟着变
    
    客户端跳转就是重新发起一个request, valueStack也是新的, 而服务器端跳转一直是同一个request, 共享同一个valueStack
    
15、globalResult:
    全局结果集, 定义在package里:
    例如:
      <global-results>
            <result name="mainpage">/mainpage.jsp</result>
        </global-results>
    代表这个package里任何一个action返回mainpage都会往这个result里走

如果别的包也要这个全局的result, 在自己的package里extend = "那个包名" 就好
    
16、动态结果集:
    在class里指定结果集:
    eg:
    test.java的execute()里,写 r = "mainpage.jsp";
    那么result里写${r}即可
    
17、调用参数:
    通常发生在要Redirect的时候,此时不共享同一个valueStack
    例如:test.java: 
                name = AL;
    action:
        class = test.java
    result:
        type="redirect" -> /test.jsp?newName=${name}
    test.jsp:
        <s:property value ="newName"/> ❌ 不能从valueStack里拿了,因为不是同一个valueStack,而且你url里的参数又没传到新的值栈里
        <s:property value = "#parameters.newName"/> ✔  可以从actionContext里的patameters里取值。

18、OGNL:
    1、只有传值,才会构造,用.来一层一层深入,必须保留无参构造函数
    2、访问普通方法:<s:property value="login()"/>
                    <s:property value="userInfo.update()"/>
                    <s:property value="name.length()"/> //相当于string.length();
        访问成员变量:
                <s:property value="name"/>
                <s:property value="userInfo.phonne"/>
        访问静态成员变量:
                <s:property value="@com.zaq.test@STATIC_STRING"/>   //test.class里的一个静态成员STATIC_STRING
                <s:property value="@com.zaq.test@static_method()"/> //test.class里的一个静态方法static_method()
                
        注意必须要加上<constant name="struts.ognl.allowStaticMethodAccess" value="true"/>
                    
    3、访问容器:
    <s:property value="list[0]"/>
    <s:property value="list[1]"/>
    <s:property value="array[1]"/>
    <s:property value="map.somekey"/>
    <s:property value="set"/> 
    //由于set内部元素排列是无序的,
    所以带下标访问是没有意义的,只能整体拿出来
    
    对于Map,还有:
    <s:property value="map.size()"/>
    <s:property value="map.size"/>  //同上
    <s:property value="map.keys"/>
    <s:property value="map.values"/>
    
    对于list:
    <s:property value="list.{name}"/> 把元素中属性为name的值都拿出来
    
    
    4、投影/过滤 ?#,^#,$#
    eg:
    <s:property value="list.{?#this.age>20}"/> 
    取出list中元素属性age>20的
    this表示当前list代表的对象
    
    <s:property value="list.{^#this.age>20}"/>
    与正则表达式相似,取出第一个满足条件的(得到的是集合,取其中元素可以加上[0])
    
    <s:property value="list.{$#this.age>20}"/>
    与正则表达式相似,取出最后一个满足条件的(得到的是集合,取其中元素可以加上[0])
    
    5、[]访问值栈
    可以直接这么写:
    <s:property value="[i]"/>
    代表访问值栈从栈第i个元素(也就是栈顶)往下取所有的栈元素,是一个集合
    而不是第i个栈元素的意思
    
    valueStack可以有多个栈元素呀,
    也就是有多个action呀,
    也就是chain的时候呀
    
19、tag:
    1、property: (value的类型是Object!)
    <s:property value="name"/> 拿值栈里叫name的,是OGNL表达式
    <s:property value="'name'"/> 
    这里拿出来的是字符串name,而非OGNL表达式,不是去取key=name的值
    
    <s:property value="admin" default="zaq"/> 
    valueStack里没有admin, 这就用default的值
    
    <s:property value="'<br>'" escapeHtml="true"/>   //代表直接展现字符串<br>
    <s:property value="'<br>'" escapeHtml="false"/>
    //代表展现html的元素<br>,也就是打印了一个换行
    
    2、set: (value的类型也是Object!)
    
    <s:set var="name" value="'zaq'"/> //注意啊注意啊一定要加''不然这是OGNL表达式 不是字符串啊啊啊
    定义变量name = zaq, 默认的scope是action-->放在actionContext,和request
        取值:
        <s:property value="#name"/>
        <s:property value="#request.name"/>
        都可以
        
    <s:set var="name" value="'zaq'" scope = "session"/>
    定义变量name = zaq, 放在actionContext的session里
    取值:
        <s:property value="#session.name"/>
        
        
    <s:set var="name" value="'zaq'" scope = "request"/>
    定义变量name = zaq, 放在actionContext的request里
    取值:
        <s:property value="#request.name"/>

3、include
    尽量别用,因为如果包含的文件有中文字符会不显示,很麻烦
    <s:include value="/index.jsp"/>
    
    4、%{}
    代表将内容转换为OGNL表达式
    比如:
    <s:set var="incPage" value="'/index.jsp'"/>
    <s:include value="#incPage"/>
    没用,因为他把value翻译为字符串了
    
    得这么写:表示这是OGNL表达式,你给我取incPage它的value
    <s:include value="%{#incPage}"/>
    
    
    5、ifelse
    eg:
    url: xxxxx.jsp?age=30
    
    <s:if test="#parameters.age[0]>20">too old</s:if>
    <s:elseif test="#parameters.age[0]>20">too young</s:elseif>
    <s:else>too young</s:else>
    记得这里age要加[],因为可能传多个age
    
    6、iterator
    <s:iterator value="{1,2,3}">
        <s:property/>
    </s:iterator>
    输出每个元素
    
    <s:iterator value="{1,2,3}" var="ele">
        <s:property value="#ele"/>
    </s:iterator>
    输出每个元素
    
    
    <s:iterator value="#{'a','b','c'}" status="status">
        <s:property value="#status.count"/>  //当前遍历的次数1,2,3
        <s:property value="#status.index"/> //索引:0,1,2
        <s:property value="#status.odd"/> //是否为奇数
        <s:property value="#status.even"/> //是否为偶数
        <s:property value="#status.last"/> //是否是最后一个
        <s:property value="#status.first"/> //是否是第一个
    </s:iterator>
    
    //定义map:
    <s:iterator value="#{1:'a',2:'bb',3:'ccc'}">
        <s:iterator value="key"/>
        <s:iterator value="value"/>
    </s:iterator>
    
    7、theme
        比较复杂,繁琐,用的少,simple什么的,知道了解即可
        
20、声明异常处理:
    当action处理方法时抛出了异常:通过throws XXXException来通知struts我这会抛异常
    1、局部异常处理:
    <action name="exceptionAction" class="com.zaq.mystructs.user.ExceptionAction">
    //有异常时设置返回值,在这里部署一下就好
        <exception-mapping exception="java.io.FileNotFoundException" result="error"/>
        <result name="error">
            /error.jsp
        </result>
        
        <result name="success">
            /index.jsp
        </result>
    </action>

2、全局的异常处理:
    定义一个包,继承struts-default,在让别的包继承这个包就行,这里result写在map前
     <package name="gloablExc" extends="struts-default">
        <global-results>
            <result name="error">/error.jsp</result>
        </global-results>

<global-exception-mappings>
            <exception-mapping exception="java.io.FileNotFoundException" result="error"/>
        </global-exception-mappings>
      </package>
      
      
21、拦截器:
    struts的拦截器实现原理:类似设计模式里的责任链:
    从过滤doFilter开始一步步跟:
    StrutsPrepareAndExecuteFilter.doFilter()->Dispatcher.serviceAction()
    ->StrutsActionProxy.execute()->DefaultActionInvocation.invoke()
    
    可以发现在invoke里通过迭代拦截器,执行interceptor.intercept()方法,
    而intercept()方法中又调用invoke(),再接着迭代下一个interceptor,
    于是一直到最后一个intercept()后,没用下一个interceptor了,
    开始原路返回:return到上一个intercept()的invoke()后的内容,
    执行完这个intecept()再一层一层返回,这样就形成一个责任链。
    
    最后执行invokeActionOnly() ,然后executeResult()
    
22、类型转换:
    再url里传参数时,int,String会自动转换,而容器:
    list<String>/set<String>/String[]/ :这样传递:list=a&list=b; 
    //必须指定泛型
    
    map<String,String>:
    map['a'] = 'good'&map['b']='justsoso' & map['c']=bad
    
    打印直接写<s:property vaule="xxx"/>
    
    日期类型Date:
    打印这么写:
    <s:date name="d" format="YYYY/mm/dd"/>与SimpleDateFormat那个类一样
    
    Object类型:
    可以自定义类型转换:
    写一个自定义的类,继承自DefaultTypeConverter,重写convertValue()方法:
        public class MyConverter extends DefaultTypeConverter {
        @Override
        public Object convertValue(Map context, Object value, Class toType) {
            if (toType == com.zaq.bean.User.class) {
                //这个setter,getter要写好,除非是public的字段
                User u = new User();
                String[] values = (String[]) value;  //传递的参数可能不止一个
                int id = Integer.parseInt(values[0].split(",")[0]);  //这里只对第一个进行类型转换
                int age= Integer.parseInt(values[0].split(",")[1]);
                u.id = id;
                u.age = age;
                return u;
            }
            return super.convertValue(context, value, toType); //要加上
        }
    }
    局部的:
    ActionName-conversion.properties
    写:p = com.zaq.mystruts.myConverter
    全局的:
    xwork-conversion.properties
    写 com.zaq.bean.User.u = com.zaq.mystruts.myConverter
    就行
    
    如此一来:url可以这么敲:.../?u=10001,18
    
    方便很多hhh
    
struts还有validation框架等等,需要时再学也是可以的

马士兵老师Struts2学习笔记相关推荐

  1. Java高并发编程 (马士兵老师视频)笔记(一)同步器

    本篇主要总结同步器的相关例子:包括synchronized.volatile.原子变量类(AtomicXxx).CountDownLatch.ReentrantLock和ThreadLocal.还涉及 ...

  2. 马士兵坦克大战学习笔记(一)

    java初学者对于马士兵坦克大战的个人学习笔记及代码问题总结(第一阶段), 1.系统自动初始化了Graphics g参数 2.设计原则:高内聚,低耦合: 一个模块中的各元素之间的紧密程度越高,内聚性越 ...

  3. Java高并发编程 (马士兵老师视频)笔记(二)并发容器

    本篇主要总结了:线程安全的单例模式和并发容器.其中并发容器包含:ConcurrentHashMap.ConcurrentSkipListMap.CopyOnWriteArrayList和队列相关的内部 ...

  4. 马士兵hibernate(原始笔记)

    马士兵hibernate(原始笔记) 课程内容 1 HelloWorld a) Xml b) annotation 2 Hibernate原理模拟 - 什么是O/R Mapping以及为什么要有O/R ...

  5. [原创 - 尚学堂科技 - 马士兵老师]

    JAVA自学之路 一:学会选择 [转载请注明出处:http://www.bjsxt.com/zixue/zixuezhilu_1.html] 为了就业,不少同学参加各种各样的培训. 决心做软件的,大多 ...

  6. 马士兵python_马士兵:python学习(一)

    python学习 一. 输出函数print(P6) 1. 输出数字和字符串 print(520) print(52.01) print("hello world") print(h ...

  7. [转]尚学堂科技 - 马士兵老师-JAVA自学之路

    [原创 - 尚学堂科技 - 马士兵老师] JAVA自学之路 一:学会选择 [转载请注明出处:http://www.bjsxt.com/zixue/zixuezhilu_1.html] 为了就业,不少同 ...

  8. 2022年了Java架构师怎样进阶,马士兵老师给你答案

    苦于网络上充斥的各种java知识,多半是互相抄袭,导致很多后来者在学习java知识中味同嚼蜡,今天给大家推荐马士兵老师分享的进阶成为java架构师所必须掌握的核心知识点. 废话少说,直接上正题 1.多 ...

  9. 马士兵老师的Java自学之路(转长篇!!)

    作者:马士兵老师 JAVA自学之路 一:学会选择为了就业,不少同学参加各种各样的培训. 决心做软件的,大多数人选的是java,或是.net,也有一些选择了手机.嵌入式.游戏.3G.测试等.那么究竟应该 ...

  10. 马士兵老师经典J2SE中的经典语录

    最近的软考内容主要为马士兵老师讲的J2SE,老师讲的不只是知识,还有学习的经验,对生活的感悟,对我们的一些忠告,所以还是很喜欢看的.下边记录了一些让我感触很深的话,随着视频的进度,我会不断更新上的. ...

最新文章

  1. 再见了,公司的“烂系统”
  2. C++ 私有构造函数的作用
  3. cmf php,cmf公共函数解析-common.php
  4. how to extend odata service
  5. GMIC来了 HTC VIVE细化VR梦
  6. 2017.9.22 middle 失败总结
  7. java跟setattribute,java 中的request.setAttribute和session.setAttribute的区别
  8. java获取当前年月日历_转:JavaCalendar获取年、月、日、时间
  9. 世界各国英文简写一览表
  10. 计算机基础——4.1 数字通信入门
  11. HCIP 数通资料下载 肖哥视频
  12. CSMA/CD与CSMA/CA的区别
  13. 全国计算机一级证书重点知识,全国计算机一级
  14. Linux基础第一课——基础知识了解
  15. 宇宙最全面试题目实录(二)
  16. 【信息技术】【2004.05】双耳语音识别研究:声与电的听觉
  17. 设备功耗计算专题《测试仪器使用篇,EFM32GG-STK3700使用教程》
  18. ESP32(arduino)和声音传感器数据采集并实现连接WiFi进行MQTT通信
  19. 笔记:机器学习——吴恩达 第九周
  20. 数据分析案例——客户流失分析与预测

热门文章

  1. php time()的用法,PHP timezone_name_from_abbr() 函数用法及示例
  2. 用C语言程序进行比赛日程排列
  3. Paper reading (三十一):Personalized Nutrition by Prediction of Glycemic Responses(overview)
  4. Oracle细节,plsql语法大全
  5. rtl8201以太网卡调试
  6. 教你如何写原创歌词和卖你的原创歌曲
  7. 实现一个多线程安全的单向有序链表,add单个结点、与其他链表合并
  8. 设计心理学2-与复杂共处【读书笔记】
  9. UNI-APP_uni-app uni.getUserProfile微信授权,微信授权信息显示微信用户解决
  10. VirtualBox升级VirtualBox Guest Additions增强功能