Struts2深入理解

访问Servlet API

关于Servlet,里边会有doGet和doPost两个方法,两个方法体里会有两个参数,一个是HttpServletRequest类型,一个是HttpServletResponse类型,这两个参数其实就是Servlet API,还有一个类型ServletContext。也就是说在Servlet可以直接调用Servlet API。

然后在看看Struts2中Action的execute方法

@Override
public String execute() throws Exception{
    System.out.println("执行Action");
    return SUCCESS;
}

里边没有任何参数,不存在HttpServletRequest和HttpServletResponse,所以是不存在Servlet API。不和Servlet API进行组合,execute方法可以轻松地进行测试,不需要存入参数。但是还是需要去访问Servlet API的。

Struts2提供了三种方式去访问Servlet API:
1.ActionContext(上下文的类,通过它可以获得相关对象,在这里所有对象都是以Map方式进行存储)
2.实现**Aware接口
3.ServletActionContext

Action搜索顺序

比如要访问

http://localhost:8080/struts2/path1/path2/path3/test.action

在struts.xml文件中package有属性namespace。
第一步,先是判断package是否存在,如path1/path2/path3/是否有包存在
如果存在:
第二步,判断action是否存在,如果包下有这个action就直接执行,如果不存在就去默认的namespace的package里面寻找action。
第三步,如果没有就报错。
如果不存在:
第二步,检查上一级路径的package是否存在(直到默认namespace),重复第一步。
第三步,如果没有,就报错。

补充:默认的命名空间namespace="", 根命名空间namespace="/"
<package name="test" extends="struts-default"> ,如果未指定命名空间,则命名空间默认为namespace=""

解释更详细一点:
1.获得请求路径的URI,例如url是:http://server/struts2/path1/path2/path3/test.action
2.首先寻找namespace为/path1/path2/path3的package,如果存在这个package,则在这个package中寻找名字为test的action,如果不存在这个package则转步骤3;
3.寻找namespace为/path1/path2的package,如果存在这个package,则在这个package中寻找名字为test的action,如果不存在这个package,则转步骤4;
4.寻找namespace为/path1的package,如果存在这个package,则在这个package中寻找名字为test的action,如果仍然不存在这个package,就去默认的namaspace的package下面去找名字为test的action,如果还是找不到,页面提示找不到action。

动态方法调用

动态方法调用就是为了解决一个Action对应多个请求的处理,一面Action太多。
如果一个action里边有一个可执行方法execute,当我们访问这个action的时候,不指定这个方法,但是如果这个方法是不包含任何参数的,这个方法默认调用。如果每个模块写一个action并且写一个默认方法,那么会给开发造成麻烦。所以需要动态方法调用来解决。

Struts2提供了三种方式来访问方法:
指定method属性
感叹号方式
通配符方式

比如我们的原本配置文件如下

<struts>
    <package name="default" namespace="/" extends="struts-default">
        <action name="helloword" class="com.imooc.action.HelloWorldAction">
            <result>/result.jsp</result>
        </action>
    </package>
</struts>

在HelloWordAction中有execute方法,又新增了add()和update()方法。

指定method方法

<struts>
    <package name="default" namespace="/" extends="struts-default">
        <action name="helloword" class="com.imooc.action.HelloWorldAction">
            <result>/result.jsp</result>
        </action>
        <action name="addAction" method="add" class="com.imooc.action.HelloWorldAction">
            <result>/add.jsp</result>
        </action>
        <action name="updateAction" method="update" class="com.imooc.action.HelloWorldAction">
            <result>/update.jsp</result>
        </action>
    </package>
</struts>

如果我们这个时候访问addAction这个action的话,就会找到HelloWorldAction这个action,同时会找到add这个方法,,然后就去执行add这个方法的逻辑。
在url中输入http://localhost:8080/HelloWord/addAction.action,就可以调到add.jsp页面。
也就是说现在我们通过配置解决了我们通过网页来动态调用执行方法。但是如果方法特别多,那么我们就要写很多个action,开发量不小。

感叹号方式

<struts>
    <package name="default" namespace="/" extends="struts-default">
        <action name="helloword" class="com.imooc.action.HelloWorldAction">
            <result>/result.jsp</result>
            <result name="add">/add.jsp</result>
            <result name="update">/update.jsp</result>
        </action>
    </package>
    <constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>
</struts>

这种方式官方并不推荐。
要使用这种方式,要在struts.xml文件里开启一个功能。
在url中访问的时候采用如下写法http://localhost:8080/HelloWord/helloword!add.action,就可以访问到add.jsp页面。

通配符方式

<struts>
    <package name="default" namespace="/" extends="struts-default">
        <action name="helloword_*" method="{1}" class="com.imooc.action.HelloWorldAction">
            <result>/result.jsp</result>
            <result name="add">/{1}.jsp</result>
            <result name="update">/{1}.jsp</result>
        </action>
    </package>
</struts>

这种方式官方是推荐使用的。
把method当成一个参数,动态传递。如何传递,就是在action的name后面加_*。星号对应的就是{1},如果想再加上一个下划线和星号,method里边可以写为{1}{2}。
在使用的时候,在url输入http://localhost:8080/HelloWord/helloword_add.action,输入了helloword_add.action,就可以执行add方法,同时返回add.jsp页面

指定多个配置文件

<include file="login.xml"></include>

如果一个项目中有特别多action,要想把它们全部配置进一个xml文件中,文件会非常大,可以用上边的方法,将每个模块的xml文件包含进来。
但是要注意添加dtd这样一个文档描述的开头。

<!DOCTYPE struts PUBLIC
    "-//Apatch Software Foundation//DTD Struts Configuration 2.3//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd">

要注意每个配置文件的字符类型,我们也可以在总的配置文件里加上编码来统一

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

默认Action

当用户访问action的时候,如果找不到这个action,默认的action就会顶替用户需要找的action,提升了用户体验。
默认action是在一个package下边的,要写在package标签里。

<default-action-ref name="index"></default-action-ref>

<action name="index">
    <result>/error.jsp</result>
</action>

default-action-ref中的name要和下边的action的name相对应。

Struts2后缀

前边访问的时候,后缀都是.action,有的时候我们想让后缀名不是.action,比如.html,.do。这个时候可以写一个常量。

<constant name="struts.action" value="html"></constant>

这样后缀就变为了html。
如果没有上一行代码那样的配置,或者value为空,那么访问的时候,可以不加后缀。

接收参数

如何在action里边接收参数?常用三种方式:
1.使用Action的属性接收参数
2.使用DomainModel接收参数
3.使用ModelDriven接收参数

使用Action的属性接收参数
首先我们在登录页面先建一个form表单,然后要有action和提交方式method。里边有两个字段用户名和密码。

<form action="LoginAction.action" method="post">
    用户名:<input type="text" name="username">
    密码:<input type="password" name="password">
    <input type="submit" value="提交"/>
</form>

然后我们要创建我们的action,新建一个类LoginAction,选择它的父类ActionSupport,为什么要继承ActionSupport,因为像返回的SUCCESS这样的常量就在ActionSupport的父类Action中,当然也有一些其他的属性。

public class LoginAction extends ActionSupport{

    public String login(){
        return SUCCESS;
    }
}

我们在LoginAction里边创建一个方法,返回SUCCESS。

然后需要在配置文件去配置这个action。

<action name="LoginAction" method="login" class="com.imooc.action.LoginAction">
    <result>/success.jsp</result>
</action>

还需要新建一个页面success.jsp。
建好了之后,下一步就是要考虑怎么通过action的属性来获取用户名和密码。
要在LoginAction里边建两个属性username和password,然后就是它们的set和get方法。
然后在login方法里打印输出一下就可以了。

public class LoginAction extends ActionSupport{

    private String username;
    private String password;

    public String login(){
        System.out.println(username);
        return SUCCESS;
    }

    public String getUsername(){
        return username;
    }
    public void setUsername(String username){
        this.username=username;
    }
    public String getPassword(){
        return password;
    }
    public void setPassword(String password){
        this.password=password;
    }
}

在登录页面输入用户名和密码,会跳转到success.jsp,后台会输出刚刚输入的用户名。

使用DomainModel接收参数
前边的简单登录有两个文本框,但是如果页面很大,有非常多的文本框,那么建很多个属性就显得很麻烦。
Java是一种面向对象的语言,那么是否可以将这些属性放到一个对象里来进行开发?答案是肯定的,这就需要第二种方式,使用DomainModel接收参数。

新建一个类User,将属性都放在里边,在里边实现各个属性的get和set方法。

public class User{

    private String username;
    private String password;

    public String getUsername(){
        return username;
    }
    public void setUsername(String username){
        this.username=username;
    }
    public String getPassword(){
        return password;
    }
    public void setPassword(String password){
        this.password=password;
    }
}

然后要在LoginAction类中声明一个属性user,并将它的get和set方法加进来。然后打印一下,里边的参数为user.getUsername()。

public class LoginAction extends ActionSupport{

    private User user;

    public String login(){
        System.out.println(user.getUsername());
        return SUCCESS;
    }

    public User getUser(){
        return user;
    }
    public void setUser(User user){
        this.user=user;
    }
}

只是这样还不够,假如有多个对象,每个里边都有一下属性,当参数传过来的时候,很容易乱,所以在登录页面的表单里也需要修改。

<form action="LoginAction.action" method="post">
    用户名:<input type="text" name="user.username">
    密码:<input type="password" name="user.password">
    <input type="submit" value="提交"/>
</form>

指定属性名称传入哪一个对象里边,这样就可以避免混乱。

使用ModelDriven接收参数
这种方法要求实现ModelDriven接口,里边的泛型输入我们需要转换的类。
这里我们的类型就为User。
既然是实现接口,那么就要实现里边的方法,getModel,返回我们当前需要转换的对象。

public class LoginAction extends ActionSupport implements ModelDriven<User>{

    private User user = new User();

    public String login(){
        System.out.println(user.getUsername());
        return SUCCESS;
    }

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

要注意,我们的user对象一定要进行实例化,并且使用了ModelDriven方法的话,get和set方法是不需要的。
实例化之后,登录页面的form表单里,那些name就不需要指定属于哪个对象了

之前讲到的都是传入的String类型的参数,那么如果是传入一个数据集要怎么办?
在User类中有一个List

private List<String> bookList;

同时也给了它set和get方法,这里没写出。
那么在form表单里要怎么写?

<form action="LoginAction.action" method="post">
    用户名:<input type="text" name="username">
    密码:<input type="password" name="password">
    书籍1:<input type="text" name="bookList[0]">
    书籍2:<input type="text" name="bookList[1]">
    <input type="submit" value="提交"/>
</form>

用这种方法就可以。

处理结果类型

首先看一下Struts2的处理流程
这里写图片描述
用户请求通过路径到达Struts框架来解析,然后找到控制器(Action),Action将处理结果(处理结果是字符串)返回给Struts框架,然后会把一些数据传给视图资源。

<result name="success">/success.jsp</result>

result元素中的name就是result元素的逻辑视图名称。如果省略了name属性,系统将采用默认的name属性值,默认的name值是success。
SUCCESS是系统内置的,我们还有没有其他的一些系统内置的属性?
com.opensymphony.xwork2.Action中有五个内置属性:
SUCCESS:Action正确地执行完成,返回相应的视图,success是name属性的默认值
NONE:表示Action正确地执行完成,但是并不返回任何视图
ERROR:表示Action执行失败,返回到错误处理视图
LOGIN:Action因为用户没有登录的原因没有正确执行,将返回该登录视图,要求用户进行登录验证
INPUT:Action的执行,需要从前端界面获取参数,INPUT就是代表这个参数输入的界面,一般在应用中,会对这些参数进行验证,如果验证没有通过,将自动返回到该视图

处理结果是通过struts.xml使用<result/>标签配置结果。
根据位置不同,分为两种结果:
1.局部结果,将<result/>作为<action/>元素的子元素配置
2.全局结果,将<result/>作为<global-result/>元素的子元素配置

result标签还有子标签param,param标签有两个属性
1.location:该属性定义了该视图对应的实际视图资源
2.parse:该参数指定是否可以在实际视图名字中使用OGNL表达式

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值