Structs2学习配置文件,package,action,结果视图result,servletapi

Struts2的配置文件

当应用被tomcat加载的时候,struts2的配置文件就已经被加载过了。
加载顺序为:

  • 1、default.properties(struts2-core-2.3.15.3.jar\org\apache\struts2)
  • 2、struts-default.xml(struts2-core-2.3.15.3.jar)
  • 3、strtuts-plugin.xml(在struts2提供的插件jar包中)
  • 4、struts.xml(在我们的应用当中,推荐使用的方式)
  • 5、struts.properties(我们的应用当中)
  • 6、web.xml(应用当中)

Struts2提供了两种配置的方式,一种是属性文件struts.properties的方式,一种是struts.xml的方式,这两种方式,推荐使用xml的方式,因为这种方式可以表示层级关系,而struts.properties不能表示层级
当多个配置文件中,有相同的参数,顺序后面的会把前面的替换掉

Struts2提供的常量
struts2当中的常量定义在了default.properties配置文件当中,体现形式都是key=value的方式
常用的有
这里写图片描述

一般使用的覆盖方式是

<constant name="" value=""></constant>
<!-- 修改struts中default.properties定义的常量值 -->
<!-- 打开开发模式,修改了struts.xml时可以不用重写部署-->
<constant name="struts.devMode" value="true" />

<!-- 修改struts中默认的后缀名,默认为action,修改为do -->
<constant name="struts.action.extension" value="do" />

在web.xml中配置过滤器参数
开始的时候我们在web.xml当中编写了一struts2的配置参数,其实就是过滤器

  <!-- 配置Struts的核心控制器,就是一个过滤器 -->
   <filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
        <init-param>
            <!--把后缀名字改为abcd-->
            <param-name>struts.action.extension</param-name>
            <param-value>abcd</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

package的作用

package元素:是定义一个struts的包,它是把配置文件按照面向对象的思想来管理。分模块开发。

<package name="p2" extends="struts-default" namespace="/user">
    <action name="action2" class="com.itheima.web.action.Demo1Action" method="saveUser2" >
        <result name="success">/success.jsp</result>
    </action>
</package>
  • name属性:指定包的名称。注意:包的名称在配置文件中唯一。
  • extends属性:指定当前包的父包。它是按照面向对象的思想管理的体现。
  • abstract属性:把包声明为一个抽象包。抽象包就是用来被继承的。只有没有action元素的包,才能被定义为抽象包。所以上述包不能设置为抽象的。
  • namespace属性:名称空间。
    • 当指定了名称空间之后,访问路径就变成了:访问路径 = 名称空间+动作名称
    • 当不指定该属性时,该属性有默认值,默认值是”“。

寻找规则如下:
1.假设请求路径的URI,例如url是:http://www.netingcn.com/path1/path2/test.do

2.首先寻找namespace为/path1/path2的package,如果存在这个package,则在这个package中寻找名字为test的action,若找到则执行,否则转步骤5;如果不存在这个package则转步骤3。

3.寻找namespace为/path1的package,如果存在这个package,则在这个package中寻找名字为test的action,若找到则执行,否则转步骤5;如果不存在这个package则转步骤4。

4 . 寻找namespace为/的package,如果存在这个package,则在这个package中寻找名字为test的action,若找到则执行,转步骤5;如果不存在转步骤5。

5 . 如果存在缺省的命名空间,就在该package下查找名字为test的action,若找到则执行,否则页面提示找不到action;否则提示面提示找不到action。
上述一个很重要的地方就是一旦找到对应的namespace的package就停止向上级路径查找了,另外缺省命名空间(package中没有指明namespace属性或namespace属性值为空)的package的可以不存在。
深入理解namespace的工作原理

这里写图片描述


action元素:配置动作用。

  • name:动作名称
  • class:动作类全名。默认的动作类是:com.opensymphony.xwork2.ActionSupport
    在struts-default.xml中定义的
    这里写图片描述
    要想替换默认动作类:在应用的struts.xml中,package中加入:
<package name="p1" extends="struts-default" namespace="/user">
    <default-class-ref class="自己的类的名字"></default-class-ref>
</package>
  • method:动作类中的方法名称。默认是public String execute(){},要求如下
    • 1.public的
    • 2.返回值必须是String
    • 3.没有参数
public class HelloAction {//动作类

    /**
     * 在动作类中的指定的动作方法
     * 动作方法的书写要求:
     *      1、都是public的
     *      2、返回值必须是一个String
     *      3、必须没有参数
     * @return
     */
    public String sayHello(){
        System.out.println("HelloAction的sayHello方法执行了");
        return "success";//与配置文件中result的name取值相对应
    }

}

动作类的定义方式
  • 方式一:动作类就是一个POJO(Plain Old Java Object 原始的java对象),非常简单的javabean。
  • 方式二:动作类实现com.opensymphony.xwork2.Action接口。
  • 方式三:动作类继承com.opensymphony.xwork2.ActionSupport 推荐使用
public class Demo3Action extends ActionSupport{
    //当我们在类中什么都不写,一个动作方法都不提供时,有一个默认的动作方法:execute()
}

常量:给动作方法返回值用的。用常量可以使你的应用规范和统一。
这里写图片描述

动作的访问
绝对匹配优先:

<action name="deleteUser" class="com.itheima.web.action.UserAction" method="deleteUser">
        <result name="success">/deleteUser.jsp</result>
</action>

使用通配符:使用通配符*来表示name,在method当中{1}来表示和*表示的一样的方法名。下面的做法和上面的有一样的功能。

<action name="*" class="com.itheima.web.action.UserAction" method="{1}">
    <result name="success">/{1}.jsp</result>
</action>

动态方法的调用:
将/换成!

<a href="${pageContext.request.contextPath}/user!addUser.action" >添加用户</a>
<a href="${pageContext.request.contextPath}/user!updateUser.action" >更新用户</a>
<a href="${pageContext.request.contextPath}/user!deleteUser.action" >删除用户</a>
<a href="${pageContext.request.contextPath}/user!findUser.action" >查询用户</a>

然后在配置文件当中设置可以动态调用(一般不推荐使用,不安全)

<!-- 开启动态方法调用 -->
<constant name="struts.enable.DynamicMethodInvocation" value="true"/>

结果类型视图(逻辑结果视图)

前奏:该部分内容指的就是struts配置文件中的result元素的使用

result元素:为动作指定结果视图

属性:
name:逻辑视图的名称,对应着动作方法的返回值。默认值是success。
type:结果类型,指的就是用什么方式转到定义的页面。默认是dispatcher。type属性的取值在struts-default.xml中定义着。
这里写图片描述
常用取值:

dispatcher:请求转发  默认值
redirect:重定向
chain:转发到另一个动作
    转发到同包(同名称空间)下的另一个动作
    <result name="success" type="chain">action2</result>
    转发到不同包(不同名称空间)下的另一个动作
    <result name="success" type="chain">
    使用的是注入的思想,在执行之重定向之前,会先获取这两个参数的值
    调用的就是setNamespace("/n2")和setActionName("action3")
    <param name="namespace">/n2</param>
    <param name="actionName">action3</param>
    </result>
redirectAction:重定向到另一个动作
    重定向到同包(同名称空间)下的另一个动作
    <result name="success" type="redirectAction">action2</result>
    重定向不同包(不同名称空间)下的另一个动作
    <result name="success" type="redirectAction">
    使用的是注入的思想,在执行之重定向之前,会先获取这两个参数的值
    调用的就是setNamespace("/n2")和setActionName("action3")
    <param name="namespace">/n2</param>
    <param name="actionName">action3</param>
    </result>
自定义结果类型

通过前面的内容,我们看出,其实结果类型就是一个类,这些类都实现了com.opensymphony.xwork2.Result接口。
或者继承自该接口的实现类org.apache.struts2.dispatcher.StrutsResultSupport。
这些类都有一个doExecute方法,用于执行结果视图。

写一个类,实现接口或者继承接口的实现类

package com.itheima.web.result;

import javax.servlet.http.HttpServletResponse;

import org.apache.struts2.ServletActionContext;
import org.apache.struts2.dispatcher.StrutsResultSupport;

import cn.dsna.util.images.ValidateCode;

import com.opensymphony.xwork2.ActionInvocation;
/**
 * 自定义结果类型
 *  第一步:
 *      编写一个普通类,继承自StrutsResultSupport的类,并且重写doExcecute方法
 * @author zhy
 *
 */
public class CAPTCHAResult extends StrutsResultSupport {

    //通过配置文件,调整生成图片的大小
    private int width;
    private int height;

    //Servlet的中原来怎么写,现在还怎么写
    protected void doExecute(String finalLocation, ActionInvocation invocation)
            throws Exception {
        /*
         * 使用第三方生成验证码的jar包
         *   1.拷贝ValidateCode.jar到工程lib目录
         *   2.创建ValidateCode的对象
         *   3.获取响应对象输出流
         *   4.输出到浏览器
         */
        //创建ValidateCode的对象
        //参数详解:1:图像宽度 2.图像高度 3.数字的格式 4.干扰线条数
        ValidateCode code = new ValidateCode(width,height,4,10);
        //获取响应对象
        HttpServletResponse response = ServletActionContext.getResponse();
        //输出到浏览器
        code.write(response.getOutputStream());
    }

    public int getWidth() {
        return width;
    }

    public void setWidth(int width) {
        this.width = width;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }
}

第二步:在struts.xml文件中配置结果类型,并且在action配置时引用

    <!-- 自定义结果类型的配置 -->
    <package name="p3" extends="myDefault">
        <action name="captchaAction" class="com.itheima.web.action.CaptchaAction" >
            <!-- 写在action内部的结果视图,是只能当前动作类使用的  -->
            <result name="success" type="captcha">
                <!--  配置图像的大小  -->
                <param name="width">240</param>
                <param name="height">40</param>
            </result>
        </action>
    </package>

全局视图和局部视图

局部视图
这里写图片描述
全局视图

    <!-- 全局结果视图 -->
    <package name="myDefault" extends="struts-default" abstract="true">
        <!-- 自定义结果类型 
              在包中配置的结果视图,是只能当前包和其子包中使用
        -->
        <result-types>
            <result-type name="captcha" class="com.itheima.web.result.CAPTCHAResult"></result-type>
        </result-types>
        <global-results>
            <!-- 结果视图的查找顺序,先找当前动作类自己的,如果没有的,再去全局的结果视图中查找 -->
            <result name="success" type="captcha"> 
                <param name="width">240</param>
                <param name="height">40</param>
            </result>
        </global-results>
    </package>

在动作类中访问Servlet的API

第一种方式:使用ServletActionContext类,其中有ServletActionContext对象可以得到request对象和response对象,从而可以得到session对象,推荐使用

public class Demo1Action extends ActionSupport {

    private HttpServletRequest request;
    private HttpServletResponse response;
    private ServletContext application;

    public String execute(){
        HttpServletRequest request = ServletActionContext.getRequest();
        HttpServletResponse response = ServletActionContext.getResponse();
        ServletContext application = ServletActionContext.getServletContext();
        HttpSession session = request.getSession();
        System.out.println(request);
        System.out.println(response);
        System.out.println(application);
        System.out.println(session);

        return null;
    }
}

第二种方式:使用实现接口的方式,使用注入的方式,

package com.itheima.web.action;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.struts2.interceptor.ServletRequestAware;
import org.apache.struts2.interceptor.ServletResponseAware;
import org.apache.struts2.util.ServletContextAware;

import com.opensymphony.xwork2.ActionSupport;

/**
 * 获取ServletAPI
 *  第一种方式:
 *      使用的是ServletActionContext的对象     推荐此种方式
 *  第二种方式:
 *      使用的是依赖注入的形式,把我们想要的对象注入进来
 *      是由一个拦截器为我们做的
 */
public class Demo1Action extends ActionSupport implements ServletRequestAware,ServletResponseAware,ServletContextAware{

    private HttpServletRequest request;
    private HttpServletResponse response;
    private ServletContext application;

    public String execute(){
        //HttpServletRequest request = ServletActionContext.getRequest();
        //HttpServletResponse response = ServletActionContext.getResponse();
        //ServletContext application = ServletActionContext.getServletContext();
        HttpSession session = request.getSession();
        System.out.println(request);
        System.out.println(response);
        System.out.println(application);
        System.out.println(session);

        return null;
    }

    @Override
    public void setServletContext(ServletContext application) {
        this.application = application;
    }

    @Override
    public void setServletResponse(HttpServletResponse response) {
        this.response = response;
    }

    @Override
    public void setServletRequest(HttpServletRequest request) {
        this.request = request;
    }
}

原理在struts2当中有一个过滤器,在过滤器中使用动态代理的方式来注入了request和response对象
这里写图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值