Struts2框架

Struts2是一个基于MVC设计模式的Web应用框架,它本质上相当于一个servlet,在MVC设计模式中,Struts2作为控制器(Controller)来建立模型与视图的数据交互。

Struts 2以WebWork为核心,采用拦截器的机制来处理用户的请求,这样的设计也使得业务逻辑控制器能够与ServletAPI完全脱离开。

Struts2框架提供的功能支持:

  • 1、请求数据自动封装
  • 2、文件上传和下载
  • 3、对国际化功能的简化
  • 4、数据效验功能
  • 5、ajax的支持
  • 6、防止表单的重复提交



一、MVC设计模式

MVC全名是Model View Controller,即是是模型-视图-控制器,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码。MVC被独特的发展起来用于映射传统的输入、处理和输出功能在一个逻辑的图形化用户界面的结构中。

  • Model(模型)
    • 是应用程序中用于处理应用程序数据逻辑的部分。通常模型对象负责在数据库中存取数据。
  • View(视图)
    • 是应用程序中处理数据显示的部分。通常视图是依据模型数据创建的。
  • Controller(控制器)
    • 是应用程序中处理用户交互的部分。通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据。

MVC 分层有助于管理复杂的应用程序,可以在一个时间内专门关注一个方面。可以在不依赖业务逻辑的情况下专注于视图设计。同时也让应用程序的测试更加容易。

Struts2框架_第1张图片





二、第一个struts2案例

(一)struts2工作原理

先了解一下,整个struts2执行的过程。

  • 1、用户发送请求到服务器

  • 2、FilterDispatcher 查看请求,会将请求转发给ActionMapper,ActionMapper负责识别当前的请求是否需要Struts2做出处理。

  • 3、如果ActionMapper需要处理该请求,FilterDispatcher把请求的处理交给ActionProxy

  • 4、ActionProxy通过ConfigurationManager询问框架的配置文件,找到需要调用的Action类

  • 5、ActionProxy创建一个ActionInvocation实例,Action完整的调用过程都是由ActionInvocation对象负责

  • 6、同样,配置的拦截器做任何后期处理,如果需要的话

  • 7、然后execute方法返回结果(Result),将结果返回给用户

Struts2框架_第2张图片



(二)引入相关jar包

相关jar包可以在maven公库中找到。
我这次使用的是以下 的版本:
Struts2框架_第3张图片

引入jar包后,我们可以看到以下几个核心jar包:
1、 struts2-core-2.1.8.1.jar Struts 2框架的核心类库
2、xwork-core-2.1.6.jar XWork类库,Struts 2在其上构建
3、ognl-2.7.3.jar (Object Graph Navigation Language), 通过其读写对象的属性
4、freemarker-2.3.15.jar : Struts 2的UI标签的模板使用FreeMarker编写
5、commons-logging-1.1.x.jar ASF出品的日志包,Struts 2框架使用这个日志
6、commons-fileupload-1.2.1.jar 文件上传组件,2.1.6版本后需要加入此文件
7、commons-io-1.3.2.jar 上传文件依赖的jar包



(三)在web.xml配置struts2引擎过滤器

web.xml配置文件是一个J2EE的配置文件,决定如何处理元素的HTTP请求由servlet容器。这个文件为任何Web应用程序提供了一个切入点。 Struts2 应用程序的入口点,将是一个部署描述符(web.xml)中定义的过滤器。因此,我们将定义在web.xml中的FilterDispatcher是类的项。需要创建的文件夹的WebContent/ WEB-INF下web.xml文件。

在struts2中,struts框架是通过拦截器来启动的。


<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">


<filter>
    <filter-name>struts2Filterfilter-name>
    <filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilterfilter-class>
    
filter>

<filter-mapping>
    <filter-name>struts2Filterfilter-name>
    
    <url-pattern>/*url-pattern>
filter-mapping>

web-app>

拦截器和过滤器的区别
1、拦截器是基于Java的反射机制的,而过滤器是基于函数回调
2、拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用
3、拦截器可以访问action上下文、值栈里的对象,而过滤器不能
4、在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次



(四)struts.xml配置文件




<struts>

    
    <package name="action" extends="struts-default">

        
        <action name="userAction" class="org.struts2.action.UserAction">

            

             
            <result name="success" type="dispatcher">/success.jspresult>
        action>

    package>

struts>



(五)编写Action类

Action动作是Struts2框架的核心。浏览器提交的请求将被映射到一个特定的动作,它提供了对请求处理逻辑。

1、自定义普通类

Action类可以自己编写,一般需要编写execute方法,因为struts默认调用该方法。

package org.struts2.action;

public class UserAction{

    //execute会被struts2调用处理请求
    //返回succes就是对应我们之前在 struts.xml文件配置的  元素,将会转发到success.jsp页面
    public String execute(){
        System.out.println("成功处理请求..");

        return "success";
    }
}


2、实现Action接口

Action接口中,定义了execute方法,预定义的一系列的字符串常量,用于返回一些预定的result。

//字符串常量:
SUCCESS="success"
NONE="none"
ERROR="error"
INPUT="input"
LOGIN="login"
package org.struts2.action;

import com.opensymphony.xwork2.Action;

public class UserAction inplements Action{

    @Override
    public String execute() throws Exception{
        System.out.println("成功处理请求..");

        return SUCCESS;
    }

}


3、继承ActionSupport类(推荐使用)

ActionSupport类本身实现了Action接口。还实现了其他几个接口,提供更多的功能。

  • 1、Validateabble 接口:提供validate()方法为Action增加验证功能
  • 2、Validateaware 接口:提供方法保存和恢复Action或field级的错误信息
  • 3、TextProvider 接口:提供获取本地信息文本的功能
  • 4、LcaleProvider 接口:提供getLocale()方法来获取本地信息
package org.struts2.action;

import com.opensymphony.xwork2.ActionSupport;

public class UserAction extends ActionSupport{

    @Override
    public String execute() throws Exception {
        System.out.println("成功处理请求..");

        return SUCCESS;
    }

}

我们可以运行一下,直接请求 userAction ,则就会直接转发到 succes.jsp页面。
Struts2框架_第4张图片
可以看到后天输出:
Struts2框架_第5张图片





二、Action类功能

(一)获取提交参数(通过反射机制)

struts2提供了更加方便的方式来获取,浏览器提交的参数。会通过反射机制,自动向 Action 类 与提交参数同名的 成员变量 注入值。


1、获取基本数据类型

页面表单提交参数:

    <form action="userAction1">
        
        <input type="text" name="userName"/>
        <input type="password" name="password"/>
        <input type="submit" value="登陆"/>

    form>

Action类:

public class UserAction extends ActionSupport{

    //struts2会自动帮我们将提交参数注入到同名的 Action类的成员变量中

    //①在Action定义公共属性,属性名与参数名一致
    public String userName;

    //②在Action中定义私有属性,属性名与参数名一致。并提供setter方法。(推荐使用)
    private String password;
    public void setPassword(String password){
        this.password = password;
    }

    @Override
    public String execute() throws Exception {
        System.out.println("用户名:"+userName+",密码:"+password);

        return null;
    }
}


2、获取自定义封装类

页面表单提交参数:

    <form action="userAction1">
        
        <input type="text" name="user.userName"/>
        <input type="password" name="user.password"/>
        <input type="submit" value="登陆"/>
    form>

Action类:

public class UserAction extends ActionSupport{

    //struts2会自动帮我们将提交参数注入到同名的 Action类的成员变量中
    private User user;
    public void setPassword(User user){
        this.user = user;
    }

    @Override
    public String execute() throws Exception {
        System.out.println("用户名:"+user.userName+",密码:"+user.password);

        return null;
    }
}

自定义类:

public class User {
    private int userName;
    private String password;
    public User() {};
    public int getUserName() {return userName;}
    public void setUserName(int userName) {this.userName = userName;}
    public String getPassword() {return password;}
    public void setPassword(String password) {this.password = password;}
}


3、获取集合

(1)List集合
页面表单提交参数:

    <form action="userAction" method="post">
        
        <input type="text" name="users[0].userName"/>
        <input type="text" name="users[1].userName"/>
        <input type="submit" value="确定"/>
    form>

Action类:

public class UserAction extends ActionSupport{

    //struts2会自动帮我们将提交参数注入到同名的 Action类的成员变量中
    private List users;
    public void setPassword(User users){
        this.users = users;
    }

    @Override
    public String execute() throws Exception {
        System.out.println(users.size());
        if(users.get(0)!=null) {
            System.out.println("用户1:"+users.get(0).getUserName()+",用户2:"+users.get(1).getUserName());
        }
        return null;
    }
}


(2)Map集合
页面表单提交参数:

<form action="userAction" method="post">
        
        <input type="text" name="users.user1.userName"/>
        <input type="text" name="users.user2.userName"/>
        <input type="submit" value="确定"/>

    form>

Action类:

public class UserAction extends ActionSupport{

    private Map users;
    public Map getUsers() {
        return users;
    }
    public void setUsers(Map users) {
        this.users = users;
    }

    @Override
    public String execute() throws Exception {
        System.out.println("用户1:"+users.get("user1").getUserName());

        return null;
    }

}


PS : 出现异常:
No result defined for action org.struts2.action.UserAction and result input
原因:
这个input结果是Struts2定义的当验证参数出错时产生的默认结果。这说明你传递给Action的参数值与Action中的属性可能存在不匹配。
解决方法:
1、仔细检查参数名称与Action中的属性名称是否相等
2、仔细检查参数值的类型与Action中的属性类型是否匹配


4、通过struts.xml文件注入(不推荐,一般作为一些初始化参数的获取)

Struts2为Action中的属性提供了依赖注入功能,在struts2的配置文件中,我们可以很方便地为Action中的属性注入
值。
注意:属性必须提供setter方法。
配置文件中,在action元素中添加 param元素:

<action name="userAction" class="org.stuts2.action.UserAction" method="execute">
                             
            <param name="userName">leeparam>      

action>

Action类:

public class UserAction extends ActionSupport{

    private String userName;
    public void setUserName(String userName) {
        this.userName = userName;
    }

    @Override
    public String execute() throws Exception {
        System.out.println(userName);
        return null;
    }

}


PS:以上在Action获取的提交参数,只要在Action中提供getter方法。在同一请求链上的JSP页面,可以同过EL表达式获取这些提交参数。
即是,通过setter方法自动封装用户提交的参数,通过getter方法可以直接在jsp页面用EL表达式获取参数(放到请求域中)



(二)Action获得 request/response/session 等对象


1、使用ServletActionContext获取域对象(不推荐)

这种方法与servletAPI有耦合,不推荐使用。

public class UserAction1 extends ActionSupport {

    @Override
    public String execute() throws Exception {

        HttpServletRequest res = ServletActionContext.getRequest();
        HttpServletResponse resp = ServletActionContext.getResponse();
        ServletContext context = ServletActionContext.getServletContext();

        return null;
    }

}


2、使用ActionContext获取域对象

此种方式实现了Action 跟servletAPI的解耦,推荐使用此种方式。

public class UserAction1 extends ActionSupport {

    @Override
    public String execute() throws Exception {
        //ActionContext是Struts封装的一个类,方便对数据的操作
        ActionContext ctx = ActionContext.getContext();

        //拿到Map,是struts对HttpServletRequest封装的对象(是一个 Map)
        Map request1 = (Map) ctx.get("request");
       //得到代表request的map对象
        Map request = ctx.getContextMap();

        //得到代表session的Map对象
        Map session = ctx.getSession();
       //得到代表servletContext的对象
        Map application = ctx.getApplication();

        //获取请求参数
        HttpParameters params = ctx.getParameters();

        return null;
    }
}

Struts2框架_第6张图片


3、通过aware接口获取域对象

实现了aware相关接口的action,struts在运行的时候,会分别把代表request、response、servletcontext的map对象注入进来。
如果业务方法很多,为了避免在每个业务方法获取范围对象,推荐使用此种方式。实际开发中,可以定义BaseAction实现此接口,其他Action全部继承BaseAction即可。

public class UserAction1 extends ActionSupport 
    implements ServletContextAware,ServletRequestAware,ServletResponseAware
{



    @Override
    public String execute() throws Exception {
        return null;
    }


    private Map res;
    private Map resp;
    private Map context;
    @Override
    public void setServletResponse(HttpServletResponse resp) {
        this.resp = (Map) resp;
    }

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

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


}



(三)如何访问Action的自定义方法

Struts2默认访问 Action的execute方法。我们可以通过配置来实现访问Action的其他方法。


<action name="userActionLogin" class="org.struts2.action.UserAction" method="login">action>
<action name="userActionRegister" class="org.struts2.action.UserAction" method="register">action>


<action name="userAciton_*" class="org.struts2.action.UserAction2" method="{1}"> 

            
            <allowed-methods>login,registerallowed-methods>
action>



(四)反馈结果

每个动作方法都返回一个String类型的值,Struts会根据这个值,来决定应该执行什么结果。
例如,如果某个动作可能会返回了SUCCESS和ERROR,则它的动作声明必须包含两个result元素。

public class UserAction extends ActionSupport{

    private String flag;
    public String getFlag() {
        return flag;
    }
    public void setFlag(String flag) {
        this.flag = flag;
    }

    @Override
    public String execute() throws Exception {

        //这个Action类就设置两种返回值的可能
        //因此在 action元素中也必须有 两个 result 元素 来对应不同的返回值。
        if(flag=="true") {
            return SUCCESS;
        }else {
            return ERROR;
        }

    }
}
<action name=“userAction" class=“org.struts2.action.UserAction“>     

    <result name=“success”>/success.jspresult>
    <result name=“error”>/error.jspresult>
action>

1、结果名name
结果的名字,必须与动作返回的结果值匹配
可选,不写默认是success。

2、结果类型(result Type)
结果类型,不写默认是dispatcher。Struts支持的结果类型:

Struts2框架_第7张图片

也可以配置全局的results

<package name="action" extends="struts-default" >
        
        <global-results>
            <result name="error">/error.jspresult>
            <result name="notLogin">/login.jspresult>
        global-results>
        <action name="userAction" class="org.struts2.action.UserAction" >action>

    package>





三、struts.xml相关配置介绍


(一)Struts2相关知识

1、Struts2默认后缀处理原则

org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter是Struts2中的核心控制器,该Filter主要的任务是拦截用户/*的所有请求。如果请求的路径中带后缀为.action或没有带后缀,此时将请求交给Struts2框架处理。否则不做任何处理。例如:请求路径为/index.jsp直接访问页面

2、Struts2配置文件加载的顺序

1、struts-default.xml
2、strtus-plugin.xml
3、struts.xml
4、struts.properties (用户自定义配置文件)



(二)Struts-default.xml介绍

struts-default.xml文件是struts2框架默认加载的配置文件。它定义struts2一些核心的bean和拦截器。

     
    <constant name="struts.i18n.encoding" value="UTF-8"/>
     
    <constant name="struts.action.extension" value="do"/>
    
    <constant name="struts.serve.static.browserCache" value="false"/>
     
    <constant name="struts.configuration.xml.reload" value="true"/>
     
    <constant name="struts.devMode" value="true" />
     
    <constant name="struts.ui.theme" value="simple" />
     
    <constant name="struts.objectFactory" value="spring" />
     
    <constant name="struts.enable.DynamicMethodInvocation" value="false"/>
     
    <constant name="struts.multipart.maxSize" value=“10701096"/>



(三)struts.xml配置

struts.xml配置文件的元素介绍

  • Constant元素, 常量。用于配置struts框架的一些设置,比如指定字符集编码、是否是开发模式、上传文件大小限制等。该配置会覆盖default.properties设置的默认常量值。
  • Package元素, Struts2 把各种 Action 分门别类地组织成不同的包。可以给每个模块定义一个包. 一个struts.xml 文件可以有一个或多个包。
    • Name属性,每个package必须有一个name属性。
    • Namespace,命名空间,可选属性,默认是”/”,如果想调用包里的action,必须把定义的namespace属性添加到访问的uri里面。
    • Extends属性,扩展另外一个package struts-default,则可以使用struts-default.xml 文件里的结果类型和拦截器。通常每个包都应该继承struts-default包, struts-default包是由struts内置的,它定义了struts2内
    • 部的众多拦截器和Result类型。
    • Abstract,是否是抽象包。可以通过abstract=“true”定义为抽象包,抽象包中不能包含action。
  • Action元素,动作,嵌套在package里面,表示一个struts请求。
    • name属性,必填项,name属性跟请求的URI有着一 一对应的关系,URI里面需要包含name属性。
    • classs属性,处理请求的动作类,可选,默认值为com.opensymphony.xwork2.ActionSupport。
    • method属性,指定处理请求的方法,可选,默认是execute方法。
    • Result子元素,动作的结果。result 元素: 的一个子元素, 它告诉 struts 在完成动作后把控制权转交到哪里. result 元素(的name 属性)对应着 Action 方法的返回值. 因为动作方法在不同情况下可能返回不同的值, 所以同一个 action 元素可能会有多个 result 元素。
      • Name属性,可选,默认值是”success”。其建立result和action返回值之间的关系。
      • Type,结果类型。type 属性的默认值为 dispatcher。type 属性的值必须是在包含当前包或者是当前包的父包里注册过的结果类型。类型包括:
        • dispatcher ,请求转发 ,默认的类型
        • chain ,
        • redirect
        • redirectionAction
        • stream
        • plaintext
    • interceptor-ref子元素。指定action的拦截器。
    • param 元素,通过param传递参数给action。
  • interceptor-stack 。拦截器栈
  • default-interceptor-ref。 默认的拦截器栈
  • default-action-ref 。默认action类。如果找不到处理的action,则调用此action处理。





四、拦截器和统一异常处理

拦截器是动态拦截Action调用的对象。它提供了一种机制可以使开发者可以定义在一个action执行的前后执行的代码,也可以在一个action执行前阻止其执行。拦截器的概念是Servlet过滤器或JDK代理类一样的。拦截器允许横切功能分开实现的动作,以及框架。使用拦截器,可以实现如下

  • 提供预处理行动之前被称为逻辑。
  • 提供后处理逻辑动作后被调用
  • 捕获异常,这样可以进行替代处理。

Struts2框架提供的许多功能都使用拦截实现的例子包括异常处理,文件上传,生命周期回调和验证等事实上作为Struts2的基础,其功能拦截,这可能有7或8拦截器分配给每个动作。
Struts 2已经为您提供丰富多样的,功能齐全的拦截器实现。大家可以至struts2的jar包内的struts-default.xml查看关于默认的拦截器与拦截器链的配置。



(一)struts2默认拦截器介绍

拦截器 名字 说明
Alias Interceptor alias 在不同请求之间将请求参数在不同名字件转换,请求内容不变。
Chaining Interceptor chain 让前一个Action的属性可以被后一个Action访问,现在和chain类型的result()结合使用。
Checkbox Interceptor checkbox 添加了checkbox自动处理代码,将没有选中的checkbox的内容设定为false,而html默认情况下不提交没有选中的checkbox。
Cookies Interceptor cookies 使用配置的name,value来是指cookies
Conversion Error Interceptor conversionError 将错误从ActionContext中添加到Action的属性字段中。
Create Session Interceptor createSession 自动的创建HttpSession,用来为需要使用到HttpSession的拦截器服务。
Debugging Interceptor debugging 提供不同的调试用的页面来展现内部的数据状况。
Execute and Wait Interceptor execAndWait 在后台执行Action,同时将用户带到一个中间的等待页面。
Exception Interceptor exception 将异常定位到一个画面
File Upload Interceptor fileUpload 提供文件上传功能
I18n Interceptor i18n 记录用户选择的locale
Logger Interceptor logger 输出Action的名字
Message Store Interceptor store 存储或者访问实现ValidationAware接口的Action类出现的消息,错误,字段错误等。
Model Driven Interceptor model-driven 如果一个类实现了ModelDriven,将getModel得到的结果放在Value Stack中。
Scoped Model Driven scoped-model-driven 如果一个Action实现了ScopedModelDriven,则这个拦截器会从相应的Scope中取出model调用Action的setModel方法将其放入Action内部。
Parameters Interceptor params 将请求中的参数设置到Action中去。
Prepare Interceptor prepare 如果Acton实现了Preparable,则该拦截器调用Action类的prepare方法。
Scope Interceptor scope 将Action状态存入session和application的简单方法。
Servlet Config Interceptor servletConfig 提供访问HttpServletRequest和HttpServletResponse的方法,以Map的方式访问。
Static Parameters Interceptor staticParams 从struts.xml文件中将中的中的内容设置到对应的Action中。
Roles Interceptor roles 确定用户是否具有JAAS指定的Role,否则不予执行。
Timer Interceptor timer 输出Action执行的时间
Token Interceptor token 通过Token来避免双击
Token Session Interceptor tokenSession 和Token Interceptor一样,不过双击的时候把请求的数据存储在Session中
Validation Interceptor validation 使用action-validation.xml文件中定义的内容校验提交的数据。
Workflow Interceptor workflow 调用Action的validate方法,一旦有错误返回,重新定位到INPUT画面
Parameter Filter Interceptor N/A 从参数列表中删除不必要的参数
Profiling Interceptor profiling 通过参数激活profile



(二)自定义拦截器

现在,我们尝试自定义一个 验证登陆的拦截器。


1、编写拦截器类

自定义拦截器需要实现com.opensymphony.xwork2.interceptor.Interceptor接口,实现该接口需要实现,init()初始化拦截器,destroy() 销毁拦截器,intercept()处理拦截 方法。

package org.struts2.intercepter;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;
public class LoginIntercepter implements Interceptor{

    @Override
    public void destroy() {
        System.out.println("销毁拦截器");
    }
    @Override
    public void init() {
        System.out.println("初始化拦截器");
    }
    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
        System.out.println("进入拦截器..");

        //可以通过下面的三个方法,可以获得相应的session域对象。用来进行登陆验证
        //(其他的域对象也可以获得)
        //ActionContext.getContext().getSession().get("user");
        //invocation.getInvocationContext().getContext().get("session");
        //ServletActionContext.getRequest().getSession()

        //当完成验证时,需要调用 ActionInvocation 对象的 invoke()方法来 放行。
        //其原理和过滤器一样
        invocation.invoke();

        //同样的,当执行完 被拦截Action后,会继续执行 intercept方法下 invocation.invoke();之后的代码
        System.out.println("完成拦截器的调用");

        return null;
    }

}

实际行动将使用拦截器执行invocation.invoke()调用。所以,可以做一些前处理和一些处理后,根据需要。
Struts2框架_第8张图片


2、编写struts.xml配置

<package name="package1" extends="struts-default">

        <interceptors>
            
            <interceptor name="loginInterceptor" class="org.struts2.intercepter.LoginIntercepter" />

            
            <interceptor-stack name="myStack">
                
                <interceptor-ref name="loginInterceptor" />
                
                <interceptor-ref name="defaultStack" />
            interceptor-stack>
        interceptors>

        

        <action name="loginAction" class="org.struts2.action.LoginAction" >

             
            <interceptor-ref name="myStack"/>
        action>
    package>

现在,我们直接访问 Action类,可以看到后台输出:
Struts2框架_第9张图片



(三)统一异常处理

Struts提供了一个更简单的方式来处理未捕获的异常,并将用户重定向到一个专门的错误页面。可以轻松地配置到不同的异常转向不同的错误页面。“exception”拦截器作为默认的栈的一部分,所以不必做任何额外的配置。

但这种支持不太灵活,建议还是自定义的统一异常处理拦截器,可以有更多功能的实现。

实现struts2提供的统一异常处理,只需要在配置文件配置即可。




<struts>

    <package name="package1" extends="struts-default">

        
        <global-exception-mapping>
            <exception-mapping result="notFind" exception="ClassNotFoundException">exception-mapping>
        global-exception-mapping>

        
        <global-results>
            <result name="notFind">/error.jspresult>
        global-results>



        <action name="loginAction" class="org.struts2.action.LoginAction" >

            
             <exception-mapping result="mathException" exception="java.lang.ArithmeticExcption"/>
             <result name="mathException">/mathError.jspresult>

        action>

    package>
struts>





五、struts2提供的功能支持

struts2提供的功能支持主要有:

  • 1、请求数据自动封装
  • 2、文件上传和下载
  • 3、对国际化功能的简化
  • 4、数据效验功能
  • 5、ajax的支持
  • 6、防止表单的重复
  • 7、对json数据格式的支持

请求数据自动封装,我们已经在上面学习过了。现在主要讲解

(一)对json数据格式的支持

JSON(JavaScript Object Notation, JS 对象标记) 是一种轻量级的数据交换格式。它基于 ECMAScript (w3c制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。


1、使用Gson工具

(1)引入Gson的jar包
在maven公库中可以找到。Gson
Struts2框架_第10张图片


(2)使用GSON

public class UserAction3 extends ActionSupport {

    //自定义的json
    public String execute() throws IOException {
        List list = new ArrayList<>();
        list.add("LEE");
        list.add("WANG");
        list.add("YANG");

        //使用Json
        Gson gson  = new Gson();
        String gsonStr = gson.toJson(list);

        ServletActionContext.getResponse().getWriter().write(gsonStr);

        return null;
    }
}

struts.xml配置:

<package name="action1" extends="struts-default">
        <action name="userAction3" class="org.struts2.action.UserAction3" >
        action>
package>

(3)结果
Struts2框架_第11张图片


2、使用struts2支持的json工具

实现步骤:
①导入jar包 struts2-json-plugin和 json-lib

Struts2框架_第12张图片
Struts2框架_第13张图片

②package的extends属性需要设置为”json-default”,
Result的type需要指定是json类型 ,
result的root属性文本 指定 Action中需要转换成json数据格式的 成员变量

<package name="action1" extends="json-default">

        <action name="userAction3" class="org.struts2.action.UserAction3" >

            
            <result name="success" type="json" >

                
                <param name="root">userparam>
            result>
        action>
package>

Struts2框架_第14张图片

④结果
Struts2框架_第15张图片



(二)文件上传、下载

1、提交表单

表单的属性enctype要为 “multipart/form-data”,提交方式method 为 post。

<form method="post" action="upload" enctype="multipart/form-data" >
        
        <input type="file" name="up" />
        <input type="submit"/>
form>


2、Action类

package org.struts2.action;

import java.io.File;
import com.opensymphony.xwork2.ActionSupport;
public class FileUploadAction extends ActionSupport{

    //都要提供setter方法

    private File up;
    //只要 属性名+FileName就能获得 上传文件的名字
    private String upFileName;
    //只要 属性名+ContentType就能获得 上传文件的类型
    private String upContentType;

    public void upload() {
            System.out.println(up.length());
            System.out.println(upFileName);
            System.out.println(upContentType);
    }

    public File getUp() {return up;}
    public void setUp(File up) {this.up = up;}
    public String getUpFileName() {return upFileName;}
    public void setUpFileName(String upFileName) {this.upFileName = upFileName;}
    public String getUpContentType() {return upContentType;}
    public void setUpContentType(String upContentType) {this.upContentType = upContentType;}

}


3、配置文件

<action name="upload" class="org.struts2.action.FileUploadAction" method="upload">
action>

尝试,访问upload.jsp,上传文件,成功
这里写图片描述


PS:遇到异常 java.lang.ClassNotFoundException: org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter
很明显地是没有找到相应的类,但是实际上该类存在的话。就可能是部署的问题,找到 web deployment assembly ,将相应的 存放jar包的lib部署上去。后面发现,在maven update时,有可能导致整个工程的 java buil path \ projact facts \deployment assembly 下的配置出现改变,要注意。


(下载)4、Action类

package org.struts2.action;

import java.io.FileInputStream;
import java.io.FileNotFoundException;

public class DownloadAction {
    //都必须提供 getter方法

    //提供一个输出流,向浏览器输出文件
    private FileInputStream input;
    //定义文件名称,需要在响应头设置contentDisposition
    private String fileName;
    public FileInputStream getInput() {
        return input;
    }
    public void setInput(FileInputStream input) {
        this.input = input;
    }
    public String getFileName() {
        return fileName;
    }
    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

    public String download() throws FileNotFoundException { 
        //添加一个 文件输出流
        input = new FileInputStream("C:\\Users\\lenovopc\\Desktop\\1.PNG");
        //文件名称
        fileName = "1.PNG";

        //成功处理请求
        return "success";
    }

}


(下载)5、配置文件




<struts>
    <package name="action1" extends="struts-default">
        <action name="donwload" class="org.struts2.action.DownloadAction" method="download">

            
            <result name="success" type="stream">

                
                <param name="contentType">image/pngparam>
                <param name="inputName">inputparam>
                <param name="contentDisposition">attachment;filename="${fileName}"param>
            result>
        action>
    package>
struts>





五、struts2注解

使用Struts 注解,我们可以实现零配置。

(一)引入jar包

Struts2注解是由Struts 2的约定插件的支持,所以需要引入jar包。

Struts2框架_第16张图片



(二)使用注解


1、@Namespace

在Action类类名上配置,用于Action类的命名空间,只有value属性,用来指明包的命名空间。

@Namespace("/package1")
public class UserAction extends ActionSupport{
    //...   
}


2、@ParentPackage

用来为Action类指定父包,只有value属性,用来指定父包的名字。零配置的时候,所有的Action都是单独放置的,暂时没有包的概念。所以需要在每个Action类上指定自己的父包,如果不指定的话默认为struts-default。

@ParentPackage ("struts-default")
public class UserAction extends ActionSupport{
    //...   
}


3、@Action

@Action 可以为Action类指定引用名,即是指定URL中的映射名称,同时可以包含其他注解。
@Action 注解有以下属性:

  • value: 指定URL中的映射名称
  • params:指定需要注入到Action类的参数
  • result:指定结果
  • interceptorRefs:指定拦截器引用
  • execeptionMappings:声明错误处理
@ParentPackage("struts-default")
@Namespace("/package")
@Action(value="action1",results= {  //指定结果
        @Result(name="success",location="/success.jsp"), 
        @Result(name="error",location="/error.jsp")
        },interceptorRefs= {    //指定拦截器
            @InterceptorRef("defaultStack")
    },exceptionMappings= {   //声明错误处理
            @ExceptionMapping(exception="java.lang.Exception",result="error")
    })
public class UserAction extends ActionSupport{
    //...
}


4、@Result

@Result 注解用于声明一个结果。有以下属性:

  • name:指定结果的名字,默认为success
  • type:指定结果的类型。默认为dispatcher
  • location:指定结果的页面位置
  • params:指定结果的可选参数,形式为{键,值,键,值…………},键值总是会成对出现
@ParentPackage("struts-default")
@Namespace("/package")
@Action(value="action1",results= {
        @Result(name="success",type="stream",
            params= {
                    "contentType","image/png","inputName","input","contentDisposition","attachment;filename=${fileName}"   
            }
        )
    }
)
public class UserAction extends ActionSupport{

    private FileInputStream input;
    private String fileName;
    public FileInputStream getInput() {
        return input;
    }
    public void setInput(FileInputStream input) {
        this.input = input;
    }
    public String getFileName() {
        return fileName;
    }
    public void setFileName(String fileName) {
        this.fileName = fileName;
    }
    public String execute() throws FileNotFoundException {
        input = new FileInputStream("C:\\Users\\lenovopc\\Desktop\\1.PNG");
        fileName="1.PNG";

        return SUCCESS;
    }

}


5、@Results

@Results 注解用来声明多个结果,它只有一个value属性,这个value属性又需要一个@Result 数组。
java注解规定在同一个语法单元上,同一种注解只能使用一个,因此,如果一个Action、可能有多个后继页面的时候,决不能再用一个Action类上使用U盾讴歌@Result 而是应该是使用@Results 包含多个@Result 。

@ParentPackage("struts-default")
@Namespace("/package")
@Action("action2")
@Results({
    @Result(name="success",location="/success.jsp"), @Result(name="error",location="/error.jsp")
    }
)
public class UserAction1 extends ActionSupport{
    //..
}


6、@InterceptorRef和@InterceptorRefs

@InterceptorRefs 注解用来声明多个拦截器引用,它只有一个value属性,而这个value属性有需要一个@ InterceptorRef 数组。

@ParentPackage("struts-default")
@Namespace("/package")
@Action("action2")
@InterceptorRefs({
    @InterceptorRef("defaultStack")
})
public class UserAction1 extends ActionSupport{
    //...   
}


7、@ExceptionMapping和@ExceptionMappings

@ExceptionMapping 注解用来为这个Action声明错误处理,有以下属性:

  • exception:指定处理的异常
  • result:指定捕获了指定异常之外跳转那个结果
  • params:指定额外的参数
@ParentPackage("struts-default")
@Namespace("/package")
@Action("action2")
@Results({
    @Result(name="success",location="/success.jsp"),
    @Result(name="error",location="error.jsp")
})
@InterceptorRefs({
    @InterceptorRef("defaultStack")
})
@ExceptionMappings({
    @ExceptionMapping(exception="java.lang.Exception",result="error")
})
public class UserAction1 extends ActionSupport{
    //...   
}


8、总结

除了action元素,struts.xml配置文件中还有很多东西,比如全局结果 声明一个全局拦截器 等。到现在为止,注解还做不到。

因此,注解并不能完全地代替struts.xml,而是代替了其中Action部分的配置信息。一般是,注解和配置文件共存。

你可能感兴趣的:(Struts2框架)