zoukankan      html  css  js  c++  java
  • Struts2零散笔记

    Struts2-Action:
        搭建MyEclipse框架,在Window/Prefrence中设置Server/Tomcat的目录,然后设置java选项卡中JDK的路径。
    
    Struts的运行机制:
        URL请求通过HTTP协议发送给TOMCAT(假设我们的url为http://localhost:8080/$webapplication的名字$/hello),
    根据URL中请求的webapplication再交给对应的webapplication处理,然后参考其web.xml的配置,其中有:
    ...
    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
    </filter>
    ...
    被org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter接受,它又会参考struts.xml的namespace,再根据其下对应的action和result,
    将请求转到对应的JSP文件。
    
    struts的作用就是将请求和视图分开。
    
    struts.xml解释:
    <struts>
    
        <constant name="struts.devMode" value="true" />
        <package name="front" extends="struts-default" namespace="/front">    //package区分重名的情况;namespace不为空时必须用'/'开头,当想访问这个namespace中的action就需要在前面带上这个路径
            <action name="index">
                <result>/Namespace.jsp</result>
            </action>
        </package>
     
        <package name="main" extends="struts-default" namespace="">
            <action name="index">
                <result>/Namespace.jsp</result>
            </action>
        </package>
    
    </struts>
    
    例如要访问name="index"的action,则url为http://localhost:8080/$webapplication的名字$/front/index
    namespace决定了action的访问路径,不写时默认为"",可以接收所有路径的action
    namespace可以写为/,或者/xxx,或者/xxx/yyy,对应的action访问路径为/index.action,/xxx/index.action,或者/xxx/yyy/index.action.
    namespace最好也用模块来进行命名。
    
        <constant name="struts.devMode" value="true" />
        <package name="front" extends="struts-default" namespace="/">
            <action name="index" class="com.bjsxt.struts2.front.action.IndexAction1">    //当请求这个action的时候,找到对应的class,执行它里面的execute()方法,返回值时String,就把他当成一个Action。
                <result name="success">/ActionIntroduction.jsp</result>
            </action>
        </package>
    
    具体视图的返回可以由用户自己定义的Action来决定。
    具体的手段是根据返回的字符串找到对应的配置项,来决定视图的内容。
    具体Action的实现可以是一个普通的java类,里面有public String execute方法即可。
    或者实现Action接口。
    不过最常用的是从ActionSupport继承,好处在于可以直接使用Struts2封装好的方法。
    
    Struts1和Struts2的一个区别:Struts2的每一个Action都是新NEW的,而Struts1不是,故2解决了线程同步问题。
    
    struts2中的路径问题是根据action的路径而不是jsp路径来确定,所以尽量不要使用相对路径。
    虽然可以用redirect方式解决,但redirect方式并非必要。
    解决办法非常简单,统一使用绝对路径。(在jsp中用request.getContextRoot方式来拿到webapp的路径)
    或者使用myeclipse经常用的,指定basePath:
    <%    //获取根目录路径
    String path = request.getContextPath();
    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
    %>
    <base href="<%=basePath%>" />    //设置当前页面下的链接的根路径
    
    Action执行的时候并不一定要执行execute方法。
    可以在配置文件中配置Action的时候用method=来指定执行哪个方法
    也可以在url地址中动态指定(动态方法调用DMI)(推荐):!+方法名
    前者会产生太多的action,所以不推荐使用。
    
    使用通配符可以将配置降到最低,不过一定要遵守“约定优于配置”。视频14。
    
    在action中传参数有三种方法。
    
    值堆栈中每一个元素都有一个名字和一个值。
    
    //用javascript指定这个form提交的action。
    <input type="button" value="submit1" onclick="javascript:document.f.action='login/login1';document.f.submit();" />
    
    ----LoginAction1.java----
    public class LoginAction1 extends ActionSupport {
        
        private Map request;
        private Map session;
        private Map application;
        
        public LoginAction1() {
            //利用这种方法发到request(类型为Map),session,application
            request = (Map)ActionContext.getContext().get("request");
            session = ActionContext.getContext().getSession();
            application = ActionContext.getContext().getApplication();
        }
        
        public String execute() {
            //在处理请求的时候往其中放值,在前台可以访问
            request.put("r1", "r1");
            session.put("s1", "s1");
            application.put("a1", "a1");
            return SUCCESS; 
        }
    前台页面:
    ...
        //利用<s:property value="#request.r1"/>访问,也可以用传统的方式<%=request.getAttribute("r1") %>来取值
        <s:property value="#request.r1"/> | <%=request.getAttribute("r1") %> <br />
        <s:property value="#session.s1"/> | <%=session.getAttribute("s1") %> <br />
        <s:property value="#application.a1"/> | <%=application.getAttribute("a1") %> <br />
    ...
    ----LoginAction2.java----
    ****最常用的方法****
    
    package com.bjsxt.struts2.user.action;
    
    import java.util.Map;
    
    import org.apache.struts2.interceptor.ApplicationAware;
    import org.apache.struts2.interceptor.RequestAware;
    import org.apache.struts2.interceptor.SessionAware;
    
    import com.opensymphony.xwork2.ActionContext;
    import com.opensymphony.xwork2.ActionSupport;
    
    public class LoginAction2 extends ActionSupport implements RequestAware,SessionAware, ApplicationAware {
        
        private Map<String, Object> request;
        private Map<String, Object> session;
        private Map<String, Object> application;
        
        public String execute() {
            //直接可以用(设计思想IoC或者DI),需要实现RequestAware,SessionAware, ApplicationAware借口
            request.put("r1", "r1");
            session.put("s1", "s1");
            application.put("a1", "a1");
            return SUCCESS; 
        }
    
        //利用setRequest(Map<String, Object> request)设置request
        public void setRequest(Map<String, Object> request) {
            this.request = request;
        }
    
        public void setSession(Map<String, Object> session) {
            this.session = session;
        }
    
        public void setApplication(Map<String, Object> application) {
            this.application = application;
        }
        
        
    }
    
    
    在struts.xml中增加以下语句可以解决中文编码问题:
    <constant name="struts.i18n.encoding" value="GBK" /> <!-- internationalization -->
    
    <include file="login.xml" />    //用于包含另外一个.xml文件到struts.xml文件中
    
    <default-action-ref name="index"><*default-action-ref>定义默认Action,当找不到指定Action(或者不指定Action)时,转到那个package下的Action
    
    Action总结:
    1.实现一个Action的最重用的方式:从ActionSupport继承
    2.DMI动态方法调用+!
    3.通配符:*asd*--{1}{2}
        *_*--{1}{2}
    4.接受参数的方法(一般用属性或者DomainModel来接受)
    5.简单参数验证addFieldError
        一般不适用Struts2的UI标签
    6.访问Web元素
        Map类型
            loc(最常用)
            依赖Struts2
        原始类型
            loc
            依赖Struts2
    7.包含文件配置
    8.默认Action处理
    
    result可以指定类型,默认为dispatcher(用服务器跳转到结果页面,不可以是Action),还有:
    redirect(不可以跳转到Action),chain(跳转到一个Action),redirectAction(跳转到另外一个Action)。
    以上四种最常用,前两中最最常用。还有freemarker,httpheader,stream,velocity,xsit,plaintext,tiles等类型。
    客户端跳转和服务器端跳转--视频27
    dispatcher和chain为服务器端跳转,而redirect和redirectAction为客户端跳转。
    
    chain类型跳转到另一个Action要带参数:
    <result type="chain">
        <param name="actionName">aasdafa</param>    //指定Action的名字
        <param name="namespace">/asdasd</param>        //指定Action的NameSpace
    </result>
    
    global-results用于处理包里的共有结果集,extend用于继承其他package中的global-results。
    
    动态指定result:在Action实现类中可以指定字符串参数来指向JSP页面地址,如:
    ...
        private String r;
    
        public String execute() throws Exception {
            if(type == 1) r="/user_success.jsp";
            else if (type == 2) r="/user_error.jsp";
            return "success";
        }
    ...
    在struts.xml中,
    ...
            <action name="user" class="com.bjsxt.struts2.user.action.UserAction">
                <result>${r}</result>
            </action>
    ...
    来确定result的展示页面,因为Action中的参数都会存放在值堆栈中。
    在index.jsp中直接用:
        <li><a href="user/user?type=1">返回success</a></li>
        <li><a href="user/user?type=2">返回error</a></li>
    来给action实现类中的参数传递参数。
    
    
    一次request中若有服务端跳转,则跳转前后的所有Action公用值堆栈,故各个Action之间不需要传递参数。
    但若跳转到jsp页面所传递的参数不存放在值堆栈中,只能利用actioncantext中取值。
    ...
            <action name="user" class="com.bjsxt.struts2.user.action.UserAction">
                <result type="redirect">/user_success.jsp?t=${type}</result>
            </action>    
    ...
    
    ...
        from valuestack: <s:property value="t"/><br/>    //从值堆栈中取值
        from actioncontext: <s:property value="#parameters.t"/>    //从actioncantext中取值
    ...
    
    OGNL(object grapg navigation language)表达式:
        必须为Action类传递参数,它才会构造(new)这个对象,此时必须有空的构造方法。
        也可以不传递参数而自己直接在类中构造。
    
    访问静态方法需要在struts.xml中设置如下语句:
        <constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant>
    访问静态属性和静态方法:
        <s:property value="@com.bjsxt.struts2.ognl.S@s()"/>
        <s:property value="@com.bjsxt.struts2.ognl.S@STR"/>
    "@类名@属性(方法)"
    "@@方法(属性)"--只能访问Math的方法和属性
    
    ----ognl.jsp----
    
    <?xml version="1.0" encoding="GB18030" ?>
    <%@ page language="java" contentType="text/html; charset=GB18030"
        pageEncoding="GB18030"%>
    <%@ taglib uri="/struts-tags" prefix="s" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=GB18030" />
    <title>OGNL表达式语言学习</title>
    </head>
    <body>
        <ol>
            <li>访问值栈中的action的普通属性: username = <s:property value="username"/> </li>
            <li>访问值栈中对象的普通属性(get set方法):<s:property value="user.age"/> | <s:property value="user['age']"/> | <s:property value="user["age"]"/> | wrong: <%--<s:property value="user[age]"/>--%></li>
            <li>访问值栈中对象的普通属性(get set方法): <s:property value="cat.friend.name"/></li>
            <li>访问值栈中对象的普通方法:<s:property value="password.length()"/></li>
            <li>访问值栈中对象的普通方法:<s:property value="cat.miaomiao()" /></li>
            <li>访问值栈中action的普通方法:<s:property value="m()" /></li>
            <hr />
            <li>访问静态方法:<s:property value="@com.bjsxt.struts2.ognl.S@s()"/></li>
            <li>访问静态属性:<s:property value="@com.bjsxt.struts2.ognl.S@STR"/></li>
            <li>访问Math类的静态方法:<s:property value="@@max(2,3)" /></li>
            <hr />
            <li>访问普通类的构造方法:<s:property value="new com.bjsxt.struts2.ognl.User(8)"/></li>
            <hr />
            <li>访问List:<s:property value="users"/></li>
            <li>访问List中某个元素:<s:property value="users[1]"/></li>
            <li>访问List中元素某个属性的集合:<s:property value="users.{age}"/></li>
            <li>访问List中元素某个属性的集合中的特定值:<s:property value="users.{age}[0]"/> | <s:property value="users[0].age"/></li>
            <li>访问Set:<s:property value="dogs"/></li>
            <li>访问Set中某个元素:<s:property value="dogs[1]"/></li>
            <li>访问Map:<s:property value="dogMap"/></li>
            <li>访问Map中某个元素:<s:property value="dogMap.dog101"/> | <s:property value="dogMap['dog101']"/> | <s:property value="dogMap["dog101"]"/></li>
            <li>访问Map中所有的key:<s:property value="dogMap.keys"/></li>
            <li>访问Map中所有的value:<s:property value="dogMap.values"/></li>
            <li>访问容器的大小:<s:property value="dogMap.size()"/> | <s:property value="users.size"/> </li>
            <hr />
            <li>投影(过滤):<s:property value="users.{?#this.age==1}[0]"/></li>
            <li>投影:<s:property value="users.{^#this.age>1}.{age}"/></li>
            <li>投影:<s:property value="users.{$#this.age>1}.{age}"/></li>
            <li>投影:<s:property value="users.{$#this.age>1}.{age} == null"/></li>
            <hr />
            <li>[]:<s:property value="[0].username"/></li>
            
        </ol>
        
        <s:debug></s:debug>
    </body>
    </html>
    
    投影(过滤):{?#this.age==1}、{^#this.age>1}、{$#this.age>1}为过滤条件。
    ^代表第一个,$代表末尾那个。
    <s:property value="[0].username"/>代表从第0个一直到末尾的集合。在服务器端跳转时就会有多个Action。
    
    
    Struts2的标签可以分为通用标签,控制标签,UI标签,AJAX标签,$#%的区别。
    
    1.通用标签:
        a)property
        b)set
            i.默认为action scope,会将值放入request和ActionContext中
                ii.page、request、session、application
        c)bean
        d)include(对中文文件支持有问题,不建议使用,如需包含,改用jsp包含)
        e)param
        f)debug
    
    2.控制标签
        a)if elseif else
        b)iterator
            i.collections map enumeration iterator array
        c)subset
    
    3.UI标签
        a)theme
            i.simple xhtml(默认) css_xhtml ajax
    
    4.AJAX标签
        a)补充
    
    5.$ # %的区别
        a)$用于i18n和struts配置文件
        b)#取得ActionContext的值
        c)%将原本的文本属性解析为ognl,对于本来就是ognl的属性不起作用
            i. 参考<s:property 和 <s:include
    
    命名规范: 1.数据库命名: 表命名(简单就是美): _表名,如: _Topic (使用驼峰标示,尽管数据库不区分大小写) 字段命名: 保持与属性名一致(尽量不要和数据库的命名冲突) 如:ID属性 id 外键 topicId 库名: 使用项目的名称 2.类和文件的命名: 有两种方式:1.先分模块再分层次2.先分层次再分模块 采用层次划分(包的命名都用小写): com.bjsxt.bbs.action.model.service Action类采用Action结尾,如:xxxAction.java JSP命名:*_* namespace:前台直接使用"/" 后台使用"/admin" package: 前台:aciton 后台:adminAction 项目开发顺序: 1.建立界面原型 2.建立Struts.xml a.确定namespace b.确定package c.确定Action的名称,空的方法 d.确定Rssult e.将界面原形页面进行修改,匹配现有设置 f.测试 g.做好规划 3.建立数据库(或者实体类) 4.建立Model层 5.建立Service层(hibernate) 使用Junit进行单元测试 6.着手开发 请求到来后被Filter过滤,调用特定的Action的特定方法,拦截器就是在调用的时候加东西。 (其实先调用拦截器,拦截器再调用Action,再返回给拦截器,又返回给Filter) I18N 在普通Editer直接写中文会乱码。 国际化文件可以用propertiesEditer插件,在这里面写的中文会转为UTF-8保存。 Struts2的国际化有三种方式: Action-Package-App级 主要用App,对整个项目有效。 struts2的实际执行过程: 1.Struts2Flter接受页面请求 2.调用Dispatcher的serviceAction()方法 3.Dispatcher创建一个ActionProxy对象,并调用它的execute()方法 4.execute()方法又会调用ActionInvocation的invoke()方法 5.invoke()方法又会调用第一个inerceptor对象的interceptor()方法 6.interceptor()方法又会调用ActionInvocation对象的invoke()方法 7.nvoke()方法又会调用下一个inerceptor对象的interceptor()方法 8.反复直到所有inerceptor调用完毕,ActionInvocation对象调用最中的Action类的execute()方法 传递多个相同参数的时候,可以使用集合容器,但是要使用泛型。 比如在action类中有属性: ...... List<interst>; //不用new ...... 使用token拦截器控制重复提交(很少用) 写自己的转换器: public class MyPointConverter extends DefaultTypeConverter{ @Override public Object convertValue(Object value, Class toType) { if(toType == Point.class) { Point p = new Point(); String[] strs = (String[])value; String[] xy = strs[0].split(","); p.x = Integer.parseInt(xy[0]); p.y = Integer.parseInt(xy[1]); return p; } if(toType == String.class) { return value.toString(); } return super.convertValue(value, toType); } } public class MyPointConverter extends StrutsTypeConverter{ @Override public Object convertFromString(Map context, String[] values, Class toClass) { Point p = new Point(); String[] strs = (String[])values; String[] xy = strs[0].split(","); p.x = Integer.parseInt(xy[0]); p.y = Integer.parseInt(xy[1]); return p; } @Override public String convertToString(Map context, Object o) { // TODO Auto-generated method stub return o.toString(); } } 三种注册方式: i.局部:XXXAction-conversion.properties   1.p(属性名称)= converter ii.全局:xwork-conversion.properties   1.com.xxx.XXX(类名)= converter iii.Annotation 如果遇到非常麻烦的映射转换   i.request.setAttribute();   ii.session
  • 相关阅读:
    CentOS 中安装和更新 git 客户端工具
    Python 快速入门笔记(2):数据类型
    Python 快速入门笔记(1):简介
    JavaScript快速入门笔记(15):Web storage 之 localStorage 和 sessionStorage
    JavaScript快速入门笔记(14):session
    JavaScript快速入门笔记(13):cookie
    JavaScript快速入门笔记(12):Ajax之XMLHttpRequest、jQuery、fetch()
    JavaScript快速入门笔记(11):事件处理
    python的线程和进程
    python中字符串编码转换
  • 原文地址:https://www.cnblogs.com/mosquito-woo/p/3819319.html
Copyright © 2011-2022 走看看