Struts2-01-HelloWolrd

这里写图片描述

1、 概述

(1) 学习Struts2需具备的知识

  • Java
  • Filters、JSP、Tag Libraries
  • JavaBeans
  • HTML and HTTP
  • Web Containers(比如Tomcat)
  • XML

(2) Struts的发展历程

Struts1一经推出就得到了世界上JavaWeb开发者的拥护。经过这么多年的发展,它已经成为了世界上使用最广泛的MVC框架,拥有丰富的开发人群。
随着Web技术的不断发展和Web应用的不断扩大,Struts1的出现了诸多缺陷和局限性,主要表现为以下几点:
1、所支持的表现层技术比较单一。
只支持JSP作为表现层,没有提供对目前流行的FreeMarker、Velocity等表现层的支持。

2、与ServletAPI耦合严重,难预测试。
它完全基于ServletAPI,业务逻辑控制器内充满了大量的ServletAPI。一旦脱离Web容器,Action的测试将非常困难。

3、属于侵入式设计
影响了代码重用,一旦系统需要重构,这种侵入式设计将会带来很多的问题。

(3) Struts2概述

Struts2的体系与Struts1体系的差别非常大,因为Struts2使用了WebWork的设计核心,而不是Struts1的设计核心。Struts2中大量使用拦截器来处理用户的请求,从而允许用户的业务逻辑控制器与Servlet API分离。
这里写图片描述
Struts2对Struts1进行了巨大的改进。主要表现在如下几个方面(简单看看即可,从其他讲师处复制来的):
1、在Action的实现方面:Struts1要求必须统一扩展自Action类,而Struts2中可以是一个普通的POJO。   
2、线程模型方面:Struts1的Action工作在单例模式,一个Action的实例处理所有的请求。Struts2的Action是一个请求对应一个实例。没有线程安全方面的问题。
3、Servlet依赖方面:Struts1的Action依赖于Servlet API,比如Action的execute方法的参数就包括request和response对象。这使程序难于测试。Struts2中的Action不再依赖于Servlet API,有利于测试。   
4、封装请求参数:Struts1中强制使用ActionForm对象封装请求的参数。Struts2可以选择使用POJO类来封装请求的参数,或者直接使用Action的属性。   
5、表达式语言方面:Struts1中整合了EL,但是EL对集合和索引的支持不强,Struts2整合了OGNL(Object Graph NavigationLanguage)。   
6、绑定值到视图技术:Struts1使用标准的JSP,Struts2使用“ValueStack”技术。
7、类型转换:Struts1中的ActionForm基本使用String类型的属性。Struts2中使用OGNL进行转换,可以更方便的使用。
8、数据校验:Struts1中支持覆盖validate方法或者使用Validator框架。Struts2支持重写validate方法或者使用XWork的验证框架。   
9、Action执行控制的对比:Struts1支持每一个模块对应一个请求处理,但是模块中的所有Action必须共享相同的生命周期。Struts2支持通过拦截器堆栈为每一个Action创建不同的生命周期。

2、 HelloWorld 及 xml的配置

1. 搭建步骤

1 . 新建一个Web工程并找到所需的jar包:发行包的lib目录中(不同版本需要的最小jar包是不同的,参见不同版本的文档),也可以参照Struts2的例子中的包(将目录app中的例子如blank中的lib包拷贝过来使用)。

2 . 在应用的WEB-INF/classes目录下建立一个名称为 struts.xml的配置文件,内容如下:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
    <constant name="struts.devMode" value="true" />
    <package name="mimosa" namespace="/" extends="struts-default">
    </package>
    <!-- Add packages here -->
</struts>

3 . 在web.xml文件中配置核心控制器,就是一个过滤器
这里注意在struts2.1之前使用的是FilterDispatcher,之后建议采用的是 StrutsPrepareAndExecuteFilter。这里以StrutsPrepareAndExecuteFilter为例。

<filter>
    <filter-name>struts2</filter-name>
    <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>struts2</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

4 . 部署项目,如果Tomcat启动成功,没有报错,证明环境搭建成功!

2. 第一个例子

1 . 新建一个处理类JavaBean,生成getter和setter方法

public class _01_helloworld {
    public String message;
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
    // 执行方法
    public String execute(){
        this.message = "Hello Struts2 !!!";
        return "success";
    }
}

2 . 在struts2.xml文件进行配置

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd">

<struts>
    <constant name="struts.devMode" value="true" />
    <!-- 
    pageckage:方便管理动作元素 
    name:必须有。包的名称,配置文件中必须保证唯一
    namespace:该包的名称空间, 一般是以"/"开头 
    extends:集成的父包的名称. struts-default名称的包是struts2框架已经命名好的一个包.(在struts2-core.jar中有一个struts-default.xml中) 
    abstract:是否是抽象包, 没有任何action元素的包就是抽象包(java类) 
    -->
    <package name="mimosa" namespace="/" extends="struts-default">
        <!--
            action:代表一个请求动作
            name:同包中必须唯一, 动作的名称
            class:负责处理的JavaBean的类全名
            method:JavaBean中的对应处理方法(动作方法:特点是,public String 方法名(){})
        -->
        <action name="helloworld" class="mimosa.struts2.a_helloworld._01_helloworld" method="execute">
            <!--
                result:结果类型
                name:动作方法(上面的method)返回的字符串
                主体内容:View的具体地址,相对于WebRoot(或者在tomcat中相对于项目根目录)
            -->
            <result name="success">/index.jsp</result>
        </action>
    </package>
    <!-- Add packages here -->
</struts>

3 . 在 index.jsp 中通过EL表达式 ${message} 可以访问message
这里写图片描述

3. 注意的问题

  • Action名称的搜索顺序: 以namespace为基名称
    http://localhost:8080/Ice_Struts2_01/path1/path2/path3/helloworld
  • Action配置中的各项默认值
    1 . 如果没有指定class, 默认是ActionSupport
    2 . 如果没有指定method, 默认是Action中的execute()方法
    3 . 如果没有指定result的name, 默认是success
    实际开发中:自己编写的动作类一般情况下继承
    com.opensymphony.xwork2.ActionSupport
  • result中的 type 类型, 默认是转发 (在struts-default.xml有定义 dispatcher默认为true)
    dispatcher:普通的转发到某个页面
    chain:普通的抓发到某个动作名称
    redirect:重定向到一个页面
    redirectAction:重定向到一个动作名称
    plainText:以纯文本的形式输出JSP内容
<result-types>
   <result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/>
   <result-type name="dispatcher" class="org.apache.struts2.dispatcher.ServletDispatcherResult" default="true"/>
   <result-type name="freemarker" class="org.apache.struts2.views.freemarker.FreemarkerResult"/>
   <result-type name="httpheader" class="org.apache.struts2.dispatcher.HttpHeaderResult"/>
   <result-type name="redirect" class="org.apache.struts2.dispatcher.ServletRedirectResult"/>
   <result-type name="redirectAction" class="org.apache.struts2.dispatcher.ServletActionRedirectResult"/>
   <result-type name="stream" class="org.apache.struts2.dispatcher.StreamResult"/>
   <result-type name="velocity" class="org.apache.struts2.dispatcher.VelocityResult"/>
   <result-type name="xslt" class="org.apache.struts2.views.xslt.XSLTResult"/>
   <result-type name="plainText" class="org.apache.struts2.dispatcher.PlainTextResult" />
   <result-type name="postback" class="org.apache.struts2.dispatcher.PostbackResult" />
</result-types>
result标签中元素的写法:
方式一:
    <result type="chain" name="success">a2</result>
方式二:
    <result type="chain" name="success">
        <!--name对应的chain的处理器中的setActionName()方法-->
        <param name="actionName">a2</param>
    </result>

注意:如果要转向的是在另外一个名称空间的动作,那么只能使用方式二

<package name="p1" namespace="/namespace1" extends="struts-default">
    <action name="a2">
        <result type="dispatcher" name="success">/index.jsp</result>
    </action>
</package>
<package name="p2" namespace="/namespace2" extends="struts-default">
    <action name="a1">
        <result type="chain" name="success">
            <param name="namespace">/namespace1</param>
            <param name="actionName">a2</param>
        </result>
    </action>
</package

方式二是一种参考, 其他的转发类型对应的类属性也可以通过这种方式将属性注入给对应的类对象
  • 开发中配置文件的更改,在访问时让框架自动重新加载:
    struts.devMode = false(default.properties)
    利用strutx.xml中的constant元素来覆盖掉 default.properties 默认行为
<constant name="struts.devMode" value="true" />
  • 更改Action访问的扩展名
<constant name="struts.action.extension" value="action,,do" />
  • 为Action注入属性: 通过result中的
  • 在result中也可以使用${property}表达式来访问action中的属性, 表达式中的属性名对应Action中的属性

4. 常用的配置常量

这些常量配置都在 default.properties 有所定义,在strutx.xml进行覆盖
这里写图片描述

<!-- 指定默认编码, 作用于HttpServletRequest的setCharacterEncoding方法和freemaker、velocity的输出 -->
<constant name="struts.i18n.encoding" value="UTF-8" />
<!-- Struts2的实际过滤处理后缀 -->
<constant name="struts.action.extension" value="action,,do" />
<!-- 设置浏览器是否缓存静态内容, 默认为true (生产环境使用), 开发阶段最好关闭 -->
<constant name="struts.serve.static.browserCache" value="false" />
<!-- 开发模式使用, 打印更详细的错误信息 includes:
    ### - struts.i18n.reload = true
    ### - struts.configuration.xml.reload = true
-->
<constant name="struts.devMode" value="true" />
<!-- 默认视图的主题, 默认 xhtml-->
<constant name="struts.ui.theme" value="simple" />
<!-- 与Spring集成时, 由Spring负责Action的创建, 默认关闭未打开 -->
<constant name="struts.objectFactory" value="spring" />
<!-- 设置Struts2是否支持动态方法调用, 默认为false -->
<constant name="struts.enable.DynamicMethodInvocation" value="false" />
<!-- 上传文件的大小限制 -->
<constant name="struts.multipart.maxSize" value="2097152" />

5. 全局视图的配置

<package name="mypackage" extends="struts-default" >
        <!-- 配置全局错误, 范围只对本包有效 -->
        <global-results>
            <result name="error">/error.jsp</result>
        </global-results>
</package>

<package name="mimosa" namespace="/" extends="mypackage">
    <action name="helloworld" class="mimosa.struts2.a_helloworld._01_helloworld" method="execute">
            <result name="success">/index.jsp</result>
    </action>
</package>    

6. 配置文件Struts.xml的拆分

<struts>
    <include file="struts-order.xml" />
    <include file="struts-customer.xml" />
</struts>

7. 动态方法的调用

(1) 在Action存在多个方法, 可以使用 !+方法名 调用指定的方法, 该方法是否可以使用是在配置文件中有个常量开关 struts.enable.DynamicMethodInvocation
这里写图片描述

(2) 使用通配符定义 Action

<action name="crud_*" class="mimosa.struts2.a_helloworld._02_crud" method="{1}">
    <result name="success">/index.jsp</result>
</action>

8. 接收请求参数

public class ProductAction{
    private Integer id;

    //struts2通过反射技术调用与请求参数同名的属性的settter方法来获取请求参数值
    public void setId(Integer id){  
        this.id = id;
    }
    public Integer getId(){return id;}
}
public class ProductAction{
    private Product product;
    public void setProduct(Product product){
        this.product = product;
    }
    public Product getProduct(){return product;}
}

注意: 以上通过Post方式提交表单数据的时候不会存在乱码情况, 因为可以配置常量 struts.i18n.encoding 的值, 默认为UTF-8. 但通过Get方式请求则会出现乱码问题, 需要自定义一个过滤器手工转码, 过滤器的配置必须配置在Struts2核心过滤器之前.

3、 自定义类型转换器

1 . 编写一个类, 继承

com.opensymphony.xwork2.conversion.impl.DefaultTypeConverter

2 . 覆盖其中的 convertValue 方法

/*
     * context:ognl表达式的上下文
     * value:用户输入的值(保存数据时)或者模型中的属性. 用户输入的值是String数组,防止多个name属性(如表单的CheckBox) 
     * toType:目标类型
*/
public Object convertValue(Map<String, Object> context, Object value, Class toType) {
    try {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
        if(toType == Date.class){
            //1994/06/09----->java.util.Date 保存数据时
            String dateValue = ((String[])value)[0];        
            return sdf.parse(dateValue);
        }else{
            //java.util.Date----->1994/06/09 获取数据时
            return sdf.format((Date)value);
        }
    } catch (ParseException e) {
        throw new RuntimeException(e);
    }
}

3 . 注册类型转换器
局部类型转换器 : 只对当前的Action有效
在需要转换的动作类的包中, 建立一个名称是 “动作类名-conversion.properties”的配置文件.
增加内容:要验证的字段 = 验证器的类全名
如:birthday = mimosa.struts2.a_helloworld.DateConverter

全局类型转换器 : 对所有的Action都有效
在WEB-INF/classes目录下, 建立一个名称为 “xwork-conversion.properties”的配置文件.
增加内容:目标类型全名 = 验证器的类全名
如: java.util.Date = mimosa.struts2.a_helloworld.DateConverter

4 . 注意: 如果转换失败,Struts2框架会寻找result结果集中name=input的结果页面

 <result name="input">/form.jsp</result>

此时可以将结果页面写成未通过验证之前的表单, 方便数据的回显操作.

4、 获取Servlet的常用对象

(1)访问 request/session/application 域属性

ActionContext ac = ActionContext.getContext();

Map<String, Object> applicationMap = ac.getApplication();// 这个就是ServletContext对象中维护的那个Map
applicationMap.put("p", "application_p");// ServletContext.setAttribute(key,object);

Map<String, Object> sessionMap = ac.getSession();// 这个就是HttpSession对象中维护的那个Map
sessionMap.put("p", "session_p");// HttpSession.setAttribute(key,object);

ac.put("p", "request_p");// 相当于ServletRequest.setAttribute(key,obj);
然后在Jsp中获取域中的对象  

应用范围:${applicationScope.p }<br>
会话范围:${sessionScope.p }<br>
请求范围:${requestScope.p }<br>

(2)访问Servlet的相关对象
方式一:通过上面的ActionContext的子类

ServletActionContext类获取
ServletActionContext.getRequest();
ServletActionContext.getRequest().getSession();
ServletActionContext.getResponse();
ServletActionContext.getServletContext();

方式二:通过实现ServletRequestAware, ServletResponseAware,ServletContextAware接口并实现其中对应各个对象的set方法. 来获取struts2动用其中的方法以传给该类的HttpServletRequest, HttpServletResponse,HttpServletContext对象.

5、 文件的上传

(1) 单个文件的上传

1 . Jar包和from表单的注意事项
这里写图片描述

html的form标签

enctype="multipart/form-data" 
method="post"

2 . 在对应Action加入三个属性来表示上传文件的信息, 然和生成getter和setter

private File file; // 上传的文件 html标签name属性
private String fileFileName; // 上传的文件域 + FileName 得到上传文件名 
private String fileContentType;// 上传的文件域 + ContentType 得到上传文件类型

3 . execute 方法的编写

public String execute() throws Exception {
    // 得到文件上传目录的绝对路径
    ServletContext sc = ServletActionContext.getServletContext();
    String realPath = sc.getRealPath("/files");
    Streams.copy(new FileInputStream(file), new FileOutputStream(realPath + "\\" + fileFileName), true);
    System.out.println("上传文件类型为: " + fileContentType);
    ActionContext.getContext().put("message", "上传成功");
    return SUCCESS;
}

4 . 注意文件的上传限制大小由配置的常量限制, 若出现错误, struts2会转向name属性为input 的视图页面

(2) 多文件上传

1. 每个属性域改为数组的类型[], form表单文件的name都相同

private File[] files; 
private String[] filesFileName; 
private String[] filesContentType;

2 . execute方法

ServletContext sc = ServletActionContext.getServletContext();
String realPath = sc.getRealPath("/files");
if (files != null && files.length > 0) {
    for (int i = 0; i < files.length; i++) {
        Streams.copy(new FileInputStream(files[i]), new FileOutputStream(realPath + "\\" + filesFileName[i]), true);
        System.out.println("上传文件类型为: " + filesContentType[i]);
    }
}
ActionContext.getContext().put("message", "上传成功");
return SUCCESS;
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值