Struts2核心

MVC框架及Struts2介绍
Struts2核心
Struts2拦截器
Struts2值栈和OGNL表达式
Struts2标签库

1 xml文件模块化管理

  大部分应用中,随着应用规模的增加,系统中Action的数量也会大量增加,导致struts.xml配置文件变得很大。为了避免struts.xml文件过大,提高struts.xml文件的可读性,可以将一个struts.xml配置文件分解成多个配置文件,然后在struts.xml主文件中引入其他配置文件。配置文件的基本格式与struts.xml文件一样,写在resources文件(Source Folder文件)中。
  struts.xml中<include>引入其他配置文件:

<struts>
    <package name="default" namespace="/" extends="struts-default">
    ...
    </package>
    <!-- 引入struts-system.xml文件 -->
    <include file="struts-system.xml"></include>
</struts>

2 <package>标签

  在配置文件中,需要将<action>标签写在<package>中,<package>类似Java中的包,可以唯一确定一个包中的<action>,不同包中<action>可以同名,同包中不能同名。<package>的目的是为了进行模块化管理。

<package name="default" namespace="/" extends="struts-default" abstract="false">
    ...
</package>

  name:包名,在整个应用中不能重复;
  namespace:包命名空间,访问该包中action时额外加的路径;
  extends:继承,继承其他包的配置文件,通常继承struts-default.xml中的;
  abstract:当前包是抽象的包(用来被继承的,struts-default.xml中为”true”)。

  访问action
  http ://ip:port/<appContextPath>/<packageNamespace>/<actionName>[.action]
  http ://ip:端口/<上下文路径>/<包的命名空间>/<action名称>[.后缀名]
  如果上下文路径path=”“,namespace=”/”,则不需要加/<上下文路径>/<包的命名空间>。

3 Action的查找流程

  简单查找流程

<package name="default" namespace="/system" extends="struts-default">
    <action name="hello"></action>
</package >

  访问的uri:http ://localhost/system/hello
  uri分为两部分:
  packageNamespace : /system
  actionName:hello
  查找Action时,首先通过packageNamespace在配置文件中查找对应的<package>标签,然后通过actionName在<package>标签中查找对应<action>。

  复杂查找流程

<package name="default" namespace="/" extends="struts-default" >
        ...
</package >
<package name="path1" namespace="/path1" extends="struts-default" >
    ...
</package>
<package name="path2" namespace="/path1/path2" extends="struts-default" >
    ...
</package>

  访问uri:http ://localhost/path1/path2/hello
  先找<package>:
  先会通过/path1/path2找对应的<package namespace=”/path1/path2”…>包,如果没有这个包,就退一级找/path1对应的<package namespace=”/path1”…>包,如果没有这个包,就找到<package namespace=”/”…>根包。

  再找<action>:
  如果找到包,就在当前包下面找Action,如果没有找到Action,不会退级找,而是到默认包中查找Action,如果还没有就报错。namespace=”/”代表根包,namespace=”“代表默认包。

4 Struts配置文件

4.1 配置文件

Struts2框架加载配置顺序
  1.default.properties:该文件在struts2-core-2.3.20.jar/ org.apache.struts2中,配置中很多常量在其中;
  这里写图片描述
  2.struts-default.xml:该文件在struts2-core-2.3.20.jar中,可以查看配置方式;
  这里写图片描述
  3.struts-plugin.xml:该文件在struts2项目的lib包中,比如struts2-spring-plugin-2.3.20.jar,保存着一些插件;
  4.struts.xml:web应用默认的struts配置文件;
  5.struts.properties:struts的默认配置文件(一般配置不写在其中);
  6.web.xml:web应用的配置文件(一般配置不写在其中)。

  前三个文件是Struts2默认的配置文件,不能进行修改,如果多个文件配置了同一个常量,后一个配置文件会覆盖前一个配置文件的常量。

4.2 常量配置

  常量配置在default.properties文件中,可以通过struts.xml配置常用常量(也可以在web.xml和struts.properties配置,但是不推荐)。
  开发者模式
  修改配置不需要重启服务器

<constant name="struts.devMode" value="true"/>

  开发时使用,项目上线前需要关闭。

  设置系统编码

<constant name="struts.i18n.encoding" value="utf-8"></constant>

  设置后缀名

<constant name="struts.action.extension" value="action,do,,"></constant>

  后缀名之间用逗号分隔,一般留下一个空串,访问时使用actionName.action、actionName.do或actionName。

4.3 默认配置

  package继承了struts-default包,在struts-default.xml中配置了<action>和<result>标签的默认值。

<package name="default" namespace="/" extends="struts-default">
    <action name="index">
        <result>/index.jsp</result>
    </action>
</package>

  <action>
  class属性可以不写,但一般写上,默认的属性值为:
  <default-class-ref class=”com.opensymphony.xwork2.ActionSupport” />
  method属性可以不写,默认值为:execute

  <result>
  name属性可以不写,默认为:success
  type属性可以不写,默认为:dispatcher

5 Struts2获取ServletAPI

  Struts2可以在不使用ServletAPI的情况下获取参数,也可以通过结果视图进行页面跳转。但是在一些特殊情况中依然需要获取request、response对象,比如获取浏览器的信息,获取当前项目所在的实际路径等。

5.1 ActionContext/ServletActionContext
public class ApiAction {
    public String execute(){
        // 通过ActionContext获取作用域对象
        Map<String, Object> session = ActionContext.getContext().getSession();
        Map<String, Object> application = ActionContext.getContext().getApplication();
        // 通过ServletActionContext获取请求和响应对象
        HttpServletRequest request = ServletActionContext.getRequest();
        HttpServletResponse response = ServletActionContext.getResponse();
        return "success";
    }
}

  通过ActionContext获取作用域对象Session时,获取的实际上是SessionMap,底层中封装了HttpSession对象,通过Map设置或获取值时实际上是往当前请求的Session中设置或获取值。这种方式更简单,类本身脱离了ServletAPI,通常使用这种方式。

5.2 ServletRequestAware/ServletResponseAware
public class ApiAction implements ServletRequestAware,ServletResponseAware {
    private HttpServletRequest request;
    private HttpServletResponse response;
    public String execute(){
        return "success";
    }
    // request
    @Override
    public void setServletRequest(HttpServletRequest request) {
        this.request = request;
    }
    // response
    @Override
    public void setServletResponse(HttpServletResponse response) {
        this.response = response;
    }
}

  通过Action类实现ServletRequestAware、ServletResponseAware接口获取请求与响应对象,只要Action实现了Aware(可感知)接口,Struts2就能感知到,框架就可以调用接口对应的方法。

6 Struts2返回类型

6.1 视图返回类型

  在struts-default.xml配置文件中,Struts2定义了很多返回结果类型,并且为每个结果类型封装了一个类:
  这里写图片描述
  dispatcher:请求转发,默认类型
  redirect:重定向
  redirectAction:重定向到Action
  velocity、freemarker:在模版中使用

  结果视图的完整写法

<result name="success" type="dispatcher">
    <param name="location"> index.jsp</param>
</result>

  <result>标签中的属性:
  name:指定配置逻辑视图名(和Action方法返回值对应),默认值为success;
  type:指定结果类型,默认值为dispatcher。
  标签中的内容为视图路径地址。

  struts.xml中新增结果类型名称

<package name="default" namespace="/" extends="struts-default">
    <result-types>
        <result-type name="forward" class="org.apache.struts2.dispatcher.ServletDispatcherResult"/>
    </result-types>
</package>

  定义在<package>标签中,class为struts2为结果类型封装的类,替代dispatcher。

  redirectAction
  1.同包中跳转到Action

<package name="result" namespace="/result" extends="struts-default">
    <action name="result01" class="cn.wenwen.action._01RedirectAction">
        <result name="success" type="redirectAction">
            result02
        </result>
    </action>
    <action name="result02" class="cn.wenwen.action._02RedirectAction">
        <result name="success">
            /index.jsp
        </result>
    </action>
</package>

  ”result01”跳转到”result02”,跳转结果为Actionname,无需加”/”

  2.异包中跳转到Action

<package name="result" namespace="/result" extends="struts-default">
    <action name="result02" class="cn.wenwen.action._02RedirectAction">
        <result name="success">
            /index.jsp
        </result>
    </action>
</package>

<package name="res" namespace="/res" extends="struts-default">
    <action name="result01" class="cn.wenwen.action._01RedirectAction">
        <result name="success" type="redirectAction">
            <param name="namespace">/result</param>
            <param name="actionName">result02</param>
        </result>
    </action>
</package>

  ”result01”跳转到另一个包中的”result02”时,需要在<result>中设置参数,通过namespace找到另一个包,然后通过actionName找到包中的Action。

  3.使用redirect也可以跳转到其它Action

<package name="default" namespace="/" extends="struts-default">
    <action name="result01" class="cn.itsource._04_result.ResultAction01">
        <result name="success" type="redirect">
            /result/result02
        </result>
    </action>
</package>

<package name="result" namespace="/result" extends="struts-default">
    <action name="result02" class="cn.itsource._04_result.ResultAction02">
        <result name="success">
            /success.jsp
        </result>
    </action>
</package>

  结果视图内容为:/其它包namespace/其它action的name。

6.2 全局视图

  局部视图只能在当前的<action>中使用,如果一个包中多个需要使用同一个结果视图,就需要定义全局视图。

<package name="default" namespace="/" extends="struts-default">
    <global-results>
        <result name="login">
            /login.jsp
        </result>
    </global-results>
    ...
</package>

  将全局视图<global-results>配置在<package>中,包中的所有<action>都可以使用。如果局部视图中有一个结果视图与全局中的结果视图名称相同,会使用局部视图。
  如果写一个返回视图给几个包都使用,可以使用包之间的继承来实现。

7 Struts2实现Action的方式

7.1 普通Action类

  使用POJO(JavaBean)类,并提供public修饰的无参方法。

public class MethodAction {
    public String execute(){
        return null;
    }
}

  struts.xml配置

<package name="method" namespace="/method" extends="struts-default">
    <action name="methodAction" class="cn.wenwen.MethodAction " method="execute">
    </action>
</package>

  访问
  http ://localhost/method/methodAction

7.2 实现Action接口

  实现com.opensymphony.xwork2.Action接口,并覆写方法:

public class MethodAction implements Action {
    @Override
    public String execute() throws Exception {
        return NONE;
    }
}

  在Action中,封装了SUCCESS、ERROR、INPUT、LOGIN、NONE字段以及execute()方法。

7.3 继承ActionSupport类

  继承ActionSupport类,并覆写execute()方法。

public class MethodAction extends ActionSupport {
    @Override
    public String execute() throws Exception {
        return NONE;
    }
}

  ActionSupport实现了Action类,同时定义了表单域校验、错误信息设置和获得国际化信息等方法。

  最佳实践
  写一个BaseAction继承ActionSupport,可以继承ActionSupport的功能,也可以扩展一些公共的常量和方法。让其它的Action来继承BaseAction,这样就可以使用自定义的常量和方法。

8 Action多方法配置

  在一个Action中会有CRUD等多个方法,这时需要通过在struts.xml中配置,调用Action中不同的方法。

8.1 动态调用

  采用”/Actionname!方法名”调用,需要开启动态调用的配置。

<package name="dynamic" namespace="/dynamic" extends="struts-default">
    <!-- 开启动态调用 -->
    <constant name="struts.enable.DynamicMethodInvocation" value="true" />
    <action name="method" class="cn.wenwen.MethodAction " method="execute">
        ...
    </action>
</package>

  访问add()方法:http ://localhost/dynamic/method!add
  动态调用的安全性不高,通常不使用。

8.2 使用通配符*

  单通配符

<package name="default" namespace="/" extends="struts-default">
    <action name="method_*" class="cn.wenwen.MethodAction" method="{1}">
        ...
    </action>
</package>

  ”method_*”中星号表示一个通配符,根据传入的方法名在Action中匹配,{1}表示第一个通配符。访问add()方法:http ://localhost/method_add,如果访问的是execute()方法,可以不加_*直接用/method。

  多通配符

<package name="default" namespace="/" extends="struts-default">
    <action name="*_*" class="cn.wenwen.{1}Action" method="{2}">
        ...
    </action>
</package>

  {1}表示第一个通配符,替代部分类名,{2}表示第二个通配符,代表方法名。
  访问add()方法:http: //localhost/Method_add

9 接收参数方式

9.1 普通参数

  接收普通参数如name、password:

public class ParamAction extends ActionSupport {
    private String name;
    private String password;

    public String execute() {
        return NONE;
    }

    public void setName(String name) {
        this.name = name;
    }
    public void setPassword(String password) {
        this.password = password;
    }
}

  写一个Action类继承ActionSupport覆写方法,定义需要接收的参数,只需提供set()方法,框架会匹配属性设置值。这种方式如果参数过多就会变得复杂。

  struts.xml配置

<package name="default" namespace="/" extends="struts-default">
    <action name="params" class="cn.wenwen.ParamAction"></action>
</package>

  前台页面

<form action="/params" method="post">
    用户名:<input type="text" name="name" /> <br />
    密码:<input type="password" name="password" /> <br />
    <input type="submit" value="...提交..." />
</form>
9.2 接收对象

  如果参数过多,需要将数据封装为对象,比如User对象。

public class User {
    private Long id;
    private String name;
    private String password;
    // set、get方法
    ...
}

  方式一:Action中将User实例化

public class ParamAction extends ActionSupport {
    private User user = new User();

    public String execute() {
        return NONE;
    }

    // 框架获取User对象,然后调用User里面setter方法设置值
    public User getUser() {
        return user;
    }
}

  框架会通过getUser()获取User对象,然后调用User中的setter方法把值设置到对象属性中。

  方式二:提供set方法。

public class ParamAction extends ActionSupport {
    private User user;

    public String execute() {
        return NONE;
    }

    // 框架获取User对象,然后调用User里面setter方法设置值
    public User getUser() {
        return user;
    }
    public void setUser(User user) {
        this.user = user;
    }
}

  如果没有实例化User,无法直接获取User对象,框架会通过反射创建一个User对象,调用setUser()方法将对象设置进去,然后获取User对象并设置属性值。

9.3 实现ModelDriven接口

  实现ModelDriven(模型驱动)接口

public class ParamAction extends ActionSupport implements ModelDriven<User> {
    private Long id;
    private User user = new User();

    public String execute() {
        return NONE;
    }

    @Override
    public User getModel() {
        return user;
    }

    public void setId(Long id) {
        this.id = id;
    }
}

  实现ModelDriven接口后,框架在设置参数时就会先调用getModel()方法来获取对象,然后调用对象中的setter方法设置属性值。这种方法可以和普通参数方法结合使用,利用普通参数方法设置id。如果一个Action中只封装了一个对象,就可以用这种方式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值