顶级架构师学习——第十九阶段:Struts2成功之路

25 篇文章 2 订阅
8 篇文章 0 订阅

我承认我的锅,昨天偷懒了emmm

今天学习Struts2~~

目录

一、Struts2简介

二、搭建Struts框架

三、配置详解

四、Action类详解

五、Struts进阶

1、结果跳转方式

 2、访问ServletAPI方式

3、如何获得参数

4、集合类型参数封装

5、OGNL表达式

6、拦截器


一、Struts2简介

在介绍 Struts2之前,先来认识一下 Struts。 Struts1是最早的基于MVC模式的轻量级Web框架它能够合理的划分代码结构,并包含验证框架、国际化框架等多种实用工具框架。但是随着技术的进步, Struts的局限性也越来越多的暴露出来。为了符合更加灵活、高效的开发需求, Struts2框架应运而生。

Struts2框架Struts1的下一代产品,是在 Struts和 Webwork技术的基础上进行合并后的全新框架( Webwork是由 Opensymphony组织开发的,致力于组件化和代码重用的J2 EE Web框架,它也是个MVC框架)。虽然 Struts.2的名字与 Struts1相似,但其设计思想却有很大不同。实质上, Struts2是以 Webwork为核心的,它采用拦截器的机制来处理用户的请求。这样的设计也使得业务逻辑控制器能够与 Servletapi完全脱离开,所以 Struts2可以理解为 Webwork的更新产品。

那么Struts2框架相比原先的一些Web框架有哪些优势呢?

  1. 项目目开源,使用及拓展方便,天生优势
  2. 提供 Exception处理机制
  3. Result方式的页面导航,通过 Result标签很方便的实现重定向和页面跳转
  4. 通过简单、集中的配置来调度业务类,使得配置和修改都非常容易
  5. 提供简单、统一的表达式语言来访问所有可供访问的数据
  6. 提供标准、强大的验证框架和国际化框架
  7. 提供强大的、可以有效减少页面代码的标签
  8. 提供良好的Ajax支持
  9. 拥有简单的插件,只需放入相应的JAR包,任何人都可以扩展 Struts2框架,比如自定义拦截器自定义结果类型、自定义标签等,为 Struts2定制需要的功能,不需要什么特殊配置,并且可以发布给其他人使用
  10. 拥有智能的默认设置,不需要另外进行繁琐的设置。使用默认设置就可以完成大多数项日程序开发所需要的功能。

为了让大家对Struts2有个直接的认识,奉上宝图一份!

二、搭建Struts框架

我们先从官网上下载下来Struts2框架,解压后将相应的jar包导入我们的工程当中去,工程中主要使用的jar包有下面这些:

接下来我们来配置struts.xml文件:

<struts>
    <package name="hello" namespace="/hello" extends="struts-default" >
        <action name="HelloAction" class="aciton.HelloAction" method="hello" >
            <result name="success">/hello.jsp</result>
        </action>
    </package>
</struts>

将struts2核心过滤器配置到web.xml文件当中:

<filter>
    <filter-name>struts2</filter-name>
    <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>

给出一个示例的Demo吧:

public class HelloAction {

	public String hello(){		
		System.out.println("hello world!");
		return "success";
	}	

}

现在我们测试一番,运行!

测试成功,那接下来我们简单说说上面struts.xml文件当中的配置与我们的HelloAction的关系吧。

package:将Action配置封装.就是可以在Package中配置很多action.
        name属性: 给包起个名字,起到标识作用.随便起.不能其他包名重复.
        namespace属性:给action的访问路径中定义一个命名空间
        extends属性: 继承一个 指定包
        abstract属性:包是否为抽象的; 标识性属性.标识该包不能独立运行.专门被继承
action元素:配置action类
        name属性: 决定了Action访问资源名.
        class属性: action的完整类名
        method属性: 指定调用Action中的哪个方法来处理请求
result元素:结果配置 
        name属性: 标识结果处理的名称.与action方法的返回值对应.
        type属性: 指定调用哪一个result类来处理结果,默认使用转发.
        标签体:填写页面的相对路径

三、配置详解

1、struts.xml配置

struts.xml基本配置在上一节的最后已经给出来了,那么只在这里补充一条,引入外部的struts.xml文件,这需要用到:

    <include file="action/struts.xml" />

2、struts2常量配置

我们先来查看一下struts2-core.jar中有关struts2的常量的默认配置吧配置,在这个jar包的org.apache.struts2的default.properties

根据这个默认的配置文件,我们来配置我们的struts.xml文件:

<!-- i18n:国际化. 解决post提交乱码 -->
<constant name="struts.i18n.encoding" value="UTF-8" />
<!-- 指定反问action时的后缀名 
	http://localhost:8080/struts2_day01/hello/HelloAction.do
-->
<constant name="struts.action.extension" value="action" />
<!-- 指定struts2是否以开发模式运行
		1.热加载主配置.(不需要重启即可生效)
		2.提供更多错误信息输出,方便开发时的调试
 -->
<constant name="struts.devMode" value="true" />

这里配置的常量是按照配置的顺序顺序执行的~

当然,配置struts2常量的方式不止这么一条,也可以在src/struts.properties或者是web.xml中配置,这里就不仔细说明了。

3、struts2配置进阶

我们在struts.xml文件当中配置如下内容。

<!-- 动态方法调用方式1:配置动态方法调用是否开启常量
		默认是关闭的,需要开启
     选用这个方式的话,那么在调用时有如下格式:/action/Demo!find.action
     重点是这个叹号!,是格式要求
 -->
<constant name="struts.enable.DynamicMethodInvocation" value="false"></constant>

<package name="dynamic" namespace="/dynamic" extends="struts-default" >
	<!-- 动态方法调用方式2:通配符方式
		 使用{1} 取出第一个星号通配的内容
	  -->
	<action name="Demo1Action_*" class="cn.itheima.b_dynamic.Demo1Action" method="{1}" >
		<result name="success" >/hello.jsp</result>
	</action>
</package>

我们主要使用的是动态方法调用方式2!!!

四、Action类详解

Action类的书写方式大致有三种:一种是直接创建一种POJO,不继承任何父类也不实现任何方法;另一种是实现一个Action接口,里面有execute方法,并且提供实现的规范;最后一种最常用,继承ActionSupport类

//方式3: 继承一个类.ActionSupport
// 帮我们实现了 Validateable, ValidationAware, TextProvider, LocaleProvider .
//如果我们需要用到这些接口的实现时,不需要自己来实现了.
public class Demo5Action  extends ActionSupport{

}

五、Struts进阶

1、结果跳转方式

  1.转发

<!--  转发 -->
<action name="Demo1Action" class="cn.itheima.a_result.Demo1Action" method="execute" >
	<result name="success" type="dispatcher" >/hello.jsp</result>
</action>

  2.重定向

<!-- 重定向 -->
<action name="Demo2Action" class="cn.itheima.a_result.Demo2Action" method="execute" >
	<result name="success" type="redirect" >/hello.jsp</result>
</action>

  3.转发到Action

<!-- 转发到Action -->
<action name="Demo3Action" class="cn.itheima.a_result.Demo3Action" method="execute" >
	<result name="success" type="chain">
		<!-- action的名字 -->
		<param name="actionName">Demo1Action</param>
			<!-- action所在的命名空间 -->
		<param name="namespace">/</param>
	</result>
</action>

  4.重定向到Action

<!-- 重定向到Action -->
<action name="Demo4Action" class="cn.itheima.a_result.Demo4Action" method="execute" >
	<result  name="success"  type="redirectAction">
		<!-- action的名字 -->
		<param name="actionName">Demo1Action</param>
		<!-- action所在的命名空间 -->
		<param name="namespace">/</param>
	</result>
</action>

 2、访问ServletAPI方式

在这里最重要的一个类就是——ActionContext,我们昵称它为数据中心,因为通过它,我们能够获得所有的Servlet使用的API!见下图:

怎么使用ActionContext呢?这里也给出一个Demo吧ლ(・´ェ`・ლ)

import java.util.Map;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;

//如何在action中获得原生ServletAPI
public class Demo5Action extends ActionSupport {

	public String execute() throws Exception {
		//request域 => map (struts2并不推荐使用原生request域)
		//不推荐
		Map<String, Object> requestScope = (Map<String, Object>) ActionContext.getContext().get("request");

		//推荐
		ActionContext.getContext().put("name", "requestTom");
		//session域 => map
		Map<String, Object> sessionScope = ActionContext.getContext().getSession();
		sessionScope.put("name", "sessionTom");
		//application域 => map
		Map<String, Object> applicationScope = ActionContext.getContext().getApplication();
		applicationScope.put("name", "applicationTom");
		
		return SUCCESS;
	}
	
}

我们也能通过ServletActionContext或者通过实现如ServletRequestAware(在Struts2的jar包当中有很多以Aware结尾的类,都是我们可以继承过来的类),由于Struts2 并不推荐这两种方式,那我们就不再仔细讲述。

3、如何获得参数

与Servlet一点不同是,Action是线程安全的,可以使用成员变量来接受参数。

获得参数的方式有三种:

  1.属性驱动

  2.对象驱动

  3.模型驱动

4、集合类型参数封装

在实际的开发当中,有时候我们需要批量插入用户或其他对象,在Action中需要接收到这多个Action中的封装对象,然后传递给业务层。那么这个时候就需要将表单的数据封装。

Struts2有两种集合类型的参数封装——list和map。

我们给出示例代码吧~

先编写页面:

<form action="${pageContext.request.contextPath}/Demo11Action" method="post" >
	list:<input type="text" name="list" /><br>
	list:<input type="text" name="list[3]" /><br>
	map:<input type="text" name="map['haha']" /><br>
	<input type="submit" value="提交" />
</form>

然后是工程代码:

import java.util.List;
import java.util.Map;

import com.opensymphony.xwork2.ActionSupport;

//struts2 封装集合类型参数
public class Demo11Action extends ActionSupport  {
	//list
	private List<String> list;
	//Map
	private Map<String,String> map;
	
	
	public String execute() throws Exception { 
		
		System.out.println("list:"+list);
		System.out.println("map:"+map);
		
		return SUCCESS;
	}

	public List<String> getList() {
		return list;
	}

	public void setList(List<String> list) {
		this.list = list;
	}

	public Map<String, String> getMap() {
		return map;
	}

	public void setMap(Map<String, String> map) {
		this.map = map;
	}

}

对于list而言,我们可以在表单当中直接设置传递的参数,如上面写的list[3],表示直接将参数传递到list集合当中属于 3 的位置,也可以不指定位置,而让list根据传递的参数自动向后;对于map集合,我们则需要给出对应的键,如上面的map['haha'],这样才能从表单当中获取到相应的value值。

5、OGNL表达式

OGNL是Object-Graph Navigation Language的缩写,它是一种功能强大的表达式语言,通过它简单一致的表达式语法,可以存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能。它使用相同的表达式去存取对象的属性。

Struts2默认的表达式语言就是OGNL,它有下面这几个特点:

OGNL表达式有三个要素:表达式(表示做什么)、根对象(Root,表示对谁操作)、Context对象(规定在哪里进行操作,在表达式中访问对象的格式为#对象名称)。

Valuestack是 Struts的一个接口,字面意义为值栈, Ognl Valuestack是 Valuestack的实现类,客户端发起一个请求 struts2架构会创建一个 action实例同时创建一个 Ognl Valuestack值栈实例Ognl Valuestack(包括两个部分,值栈和map即ognl上下文)贯穿整个 Action的生命周期, struts2中使用OGNL将请求 Action的参数封装为对象存储到值栈中,并通过OGNL表达式读取值栈中的对象属性值。

我们如何操作值栈呢?

  · #号

<s:property value="#request.name" />    获取context的数据

<s:radio list="#{'1':'男', '2':'女'}" name="sex" />    构建map集合等等

  · %号

强制解析OGNL表达式

<s:textfield name="name" value="%{#request.name}" />

强制不解析OGNL表达式

<s:peoperty value="%{'#request.name'}" />

  · $号

可以在配置文件当中使用OGNL表达式

6、拦截器

拦截器,在AOP( Aspect-oriented Programming)中用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作。拦截是AOP的一种实现策略。

在 Webwork的中文文档的解释为拦截器是动态拦截 Action调用的对象。它提供了一种机制可以使开发者可以定义在一个 action执行的前后执行的代码,也可以在一个 action执行前阻止其执行。同时也是提供了一种可以提取 action中可重用的部分的方式。

谈到拦截器,还有一个词大家应该知道一一拦截器链( Interceptor Chain,在 Struts2中称为拦截器栈 Interceptor Stack)。拦截器链就是将拦祓器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。

拦截器的实现原理是什么?

大部分时候,拦截器方法都是通过代理的方式来调用的。 Struts2的拦截器实现相对简单。当请求到达 Struts2的 Servletdispatcher时, Struts2会查找配置文件,并根据其配置实例化相对的拦截器对象,然后串成一个列表,最后一个一个地调用列表中的拦截器。

Struts2拦截器是可插拔的,拦截器是AOP的一种实现。 Struts2拦截器栈就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,Suts2拦截器链中的拦截器就会按其之前定义的顺序被调用。

Struts2的执行流程大约如下图:

在程序开发过程中,为了满足我们不同的需要,我们有时需要创建自己的拦截器类,这就需要直接或间接的实现com.opensymphony.xwork2.interceptor.Interceptor接口。它定义的代码如下:

public interface Interceptor extends Serializable {
    void init();
    void destory();
    String Intercept(ActionInvacation invocation) throws Exception;
}

在实际开发当中,为了更好的实现自定义拦截器,我们更常用继承抽象拦截器类AbstractInterceptor,它提供了init和destroy的空实现,使用实可以直接继承而不必要实现不需要的方法。

它的配置方法十分简单,给个例子~

<!-- name:指定拦截器名称
     class:指定拦截器实现类
     param:指定拦截器传入参数
 -->
<interceptor name="interceptorName" class="interceptorClass">
    <param name="paramName">paramValue</param>
</interceptor>

在实际开发中,我们经常使用多个拦截器,这时我们将拦截器组成拦截器栈组合使用。语法如下:

<!-- 指定拦截器 -->
<interceptors>
    <!-- 指定拦截器栈 -->
    <interceptor-stack name="inteceptorStackName">
        <!-- 申明多个拦截器 -->
        <interceptor-ref name="interceptorName" />
        ...
    </interceptor-stack>
</interceptors>

Struts2的内容比我想象的要多emmm

现在才复习完一遍blbl

一会儿继续学习,我是小昶,我们明天再见~~

欢迎关注我们的公众号:落饼枫林,一起交流讨论学习那点事儿

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值