• 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
  • 相关阅读:
    CSS3—— 2D转换 3D转换 过渡 动画
    CSS3——边框 圆角 背景 渐变 文本效果
    CSS3——表单 计数器 网页布局 应用实例
    CSS3——提示工具 图片廓 图像透明 图像拼接技术 媒体类型 属性选择器
    CSS3——对齐 组合选择符 伪类 伪元素 导航栏 下拉菜单
    CSS3——分组和嵌套 尺寸 display显示 position定位 overflow float浮动
    CSS3——盒子模型 border(边框) 轮廓(outline)属性 margin外边距 padding填充
    Eclipse连接数据库报错Local variable passwd defined in an enclosing scope must be final or effectively final
    数据库——单表查询
    数据库——添加,修改,删除
  • 原文地址:https://www.cnblogs.com/mosquito-woo/p/3819319.html
Copyright © 2020-2023  润新知