struts2框架详解

一、struts2简介

Struts2是一个基于MVC设计模式的Web应用框架,它本质上相当于一个servlet,在MVC设计模式中,Struts2作为控制器(Controller)来建立模型与视图的数据交互。Struts 2是Struts的下一代产品,是在 struts 1和WebWork的技术基础上进行了合并的全新的Struts 2框架。

其全新的Struts 2的体系结构与Struts 1的体系结构差别巨大。Struts 2以WebWork为核心,采用拦截器的机制来处理用户的请求,这样的设计也使得业务逻辑控制器能够与ServletAPI完全脱离开,所以Struts 2可以理解为WebWork的更新产品。虽然从Struts 1到Struts 2有着太大的变化,但是相对于WebWork,Struts 2的变化很小。经过六年多的发展,Struts1已经成为了一个高度成熟的框架,不管是稳定性还是可靠性都得到了广泛的证明。市场占有率超过20%,拥有丰富的开发人群,几乎已经成为了事实上的工业标准。但是随着时间的流逝,技术的进步,Struts1的局限性也越来越多地暴露出来,并且制约了Struts1的继续发展。

二、什么是struts2?

说白了struts2就是WEB项目中不同页面之间的跳转的控制器,但是该控制器是架设在MVC之上的,比MVC框架更有先天的技术优势和模型实现优势。是一个WEB开发的组件,通常和spring,hibernate,MyBitis等框架整合使用。这整个WEB项目中扮演着页面跳转控制器。

其中,首当其冲的是struts2特有的拦截器,该拦截器是通过配置文件中定义好的页面访问前或者访问后进行的编写的拦截器调用的实现来做的。可以说struts2是拦截器驱动页面跳转。

三、struts2工作流程

1)、客户端(Client)向Action发用一个请求(Request)
2)、Container通过web.xml映射请求,并获得控制器(Controller)的名字
3)、容器(Container)调用控制器(StrutsPrepareAndExecuteFilter或FilterDispatcher)。在Struts2.1以前调用FilterDispatcher,Struts2.1以后调用StrutsPrepareAndExecuteFilter
4)、控制器(Controller)通过ActionMapper获得Action的信息
5)、控制器(Controller)调用ActionProxy
6)、ActionProxy读取struts.xml文件获取action和interceptor stack的信息。
7)、ActionProxy把request请求传递给ActionInvocation
8)、ActionInvocation依次调用action和interceptor
9)、根据action的配置信息,产生result
10)、Result信息返回给ActionInvocation
11)、产生一个HttpServletResponse响应
12)、产生的响应行为发送给客服端。


四、开发Struts 2 最少用到的jar文件:
1)、Struts-core-2.x.x.jar : Struts 2 框架的核心类库
2)、xwork-2.x.x.jar : XWork类库,Struts 2 在其上构建
3)、ognl-2.6.x.jar : Object Graph Navigation Language , Struts 2 框架通过其读写对象的属性。
4)、freemarker-2.3.x.jar : Struts 2 的UI标签的模版使用 Freemarker编写。
5)、commons-logging-1.1.x.jar : ASF出品的日志包。
6)、commons-fileupload-1.2.1.jar : 文件上传组件。

五、下面贴出我用struts2实现的一个简单的WEB项目页面之间的控制器

1、导入jar包,编写struts2.xml配置文件,创建一个Xml文件,重命名为struts2.xml文件,这里我直接将xml约束copy到struts2.xml文件中,下面是我的头信息。

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

2、编写拦截器

拦截器原理:当请求到达Struts 2ServletDispatcher时,Struts 2会查找配置文件,并根据其配置实例化相对的拦截器对象,然后串成一个列表(list),最后一个一个地调用列表中的拦截器。

<struts><!-- struts2标签 -->
	<constant value="utf-8" name="struts.i18.cn.encoding" /><!-- struts的编码集为UTF-8 -->
	<constant value="2097152088888" name="struts.multipart.maxSize" /><!-- 最大支持的内存空间 -->
	<constant value="true" name="struts.devMode" /><!-- 开发模式为true -->
	<constant value="action" name="struts.action.extension" /><!-- struts只处理action异常 -->
	<!-- 自定义的包,继承自struts-default,该包是struts的直栈,直栈是struts2的核心,主要作用是在加载程序时启动一个栈(内存空间),前台将数据放到 
		这个内存空间中,后台再到这个内存空间取数据 -->
	<package name="default" extends="struts-default">
		<interceptors>
			<!-- 定义一个自定义的拦截器栈,指向自定义拦截器实体类 -->
			<interceptor name="vl" class="com.zzy.frqs.interceptor.UserLoingInterceptor"></interceptor>
			<!-- 加载拦截器栈,拦截器栈由两部分组成,一种是默认的拦截器栈,一种是自定义栈 -->
			<interceptor-stack name="vt">
				<!-- 加载自定义栈 -->
				<interceptor-ref name="vl"></interceptor-ref>
				<!-- 加载默认的拦截器栈 -->
				<interceptor-ref name="defaultStack"></interceptor-ref>
			</interceptor-stack>
		</interceptors>
		<!-- 给拦截器栈重新定义一个名称 -->
		<default-interceptor-ref name="vt"></default-interceptor-ref>
		<!-- 设置成全局有效 -->
		<global-results>
			<result name="nologin" type="redirect">/login/no_login.jsp</result>
		</global-results>
	</package>
	<!-- incude是引入的关键字,这里按照工作做了一个分割,将权限管理的功能分离成一个struts文件,数据管理又分离成一个文件 -->
	<include file="struts_user.xml"></include>
	<include file="struts_file.xml"></include>    
</struts>
下编写sturts_user.xml文件,同样是xml文件,同样有tat约束

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC  
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"  
    "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
	<!-- 必须继承自default包,该包是我们自定义的拦截器包 -->
	<package name="user" extends="default">  
	<!-- 定义Action指向标签,该标签对应jsp中表单提交的Action地址,表单中的action=login.action。另一方面对应该Action的处理类并指定方法 -->
        <action name="login" class="com.zzy.frqs.action.LoginAction" method="login">
		<!-- 在跳转页面之前进行拦截过滤,不过这是登录功能,所以这里没有必要调用自定义的过否登录拦截器检验了 -->
        	<interceptor-ref name="defaultStack"></interceptor-ref><!-- 如果是其他功能,上面必须的加载调用vl自定义拦截栈 -->
            <result name="success">/success.jsp</result><!-- 不同结果返回,跳转到不同页面 -->
            <result name="defeated">/login/defeated_login.jsp</result>
            <result name="error">/login/verify_defeated_login.jsp</result>
        </action>  
	</package>
</struts>
3、定义自定义拦截器类,有两种方式

a、所有的Struts 2的拦截器都直接或间接实现接口com.opensymphony.xwork2.interceptor.Interceptor。下面贴出的代码就使用这种方式。该接口提供了三个方法:
1) void init(); 在该拦截器被初始化之后,在该拦截器执行拦截之前,系统回调该方法。对于每个拦截器而言,此方法只执行一次。
2) void destroy();该方法跟init()方法对应。在拦截器实例被销毁之前,系统将回调该方法。
3) String intercept(ActionInvocation invocation) throws Exception; 该方法是用户需要实现的拦截动作。该方法会返回一个字符串作为逻辑视图。
b、除此之外,继承类com.opensymphony.xwork2.interceptor.AbstractInterceptor是更简单的一种实现拦截器类的方式,因为此类提供了init()和destroy()方法的空实现,这样我们只需要实现intercept方法。

public class UserLoingInterceptor implements Interceptor{
	/**
	 * 拦截器版本ID
	 */
	private static final long serialVersionUID = 1L;

	@Override
	public String intercept(ActionInvocation arg0) throws Exception {
		// TODO Auto-generated method stub
		String username = (String) ActionContext.getContext().getSession().get("user");
		if(username == null){
			System.out.println("过滤器的容器为空,用户没有登录");
			return "nologin";
		}
		System.out.println("已有用户登录:"+username);
		//不拦截,直接放过
		return arg0.invoke();
	}
	
	@Override
	public void destroy() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void init() {
		// TODO Auto-generated method stub
		
	}
}


4、定义处理action请求的Action逻辑处理类

该类是对应action请求内容的,比如说表单提交的内容有用户名和密码,那么这该处理类中必须创建相同类型的两个属性用来接收提交的参数。因为可以接收到表单提交过来的参数,主要就是因为该类需要实现com.opensymphony.xwork2.ActionSupport类,同时实现org.apache.struts2.interceptor.ServletRequestAware;org.apache.struts2.interceptor.ServletResponseAware;org.apache.struts2.interceptor.SessionAware;org.apache.struts2.util.ServletContextAware这四个接口。所以这里我们将创建一个自定义的父类,该类实现和继承了上面的类和接口,并且在该类创建了javax.servlet.ServletContext;javax.servlet.http.HttpServletRequest;javax.servlet.http.HttpServletResponse这三个WEB请求相应,session,Context对象为属性,并定义了一个Map集合,该集合是存储用户登录信息的。如果用户登录成功之后,该集合就会有值,是拦截器类中对该集合判断来判断是否用户登录。

下面贴出BaseAction类

public class BaseAction extends ActionSupport implements SessionAware,ServletRequestAware,ServletResponseAware,ServletContextAware{

	public Map<String,Object> session;
	public HttpServletRequest request;
	public HttpServletResponse response;
	public ServletContext application;
	
	
	
	public Map<String, Object> getSession() {
		return session;
	}


	public HttpServletRequest getRequest() {
		return request;
	}



	public void setRequest(HttpServletRequest request) {
		this.request = request;
	}



	public HttpServletResponse getResponse() {
		return response;
	}



	public void setResponse(HttpServletResponse response) {
		this.response = response;
	}



	public ServletContext getContext() {
		return application;
	}



	public void setContext(ServletContext application) {
		this.application = application;
	}

	@Override
	public void setServletContext(ServletContext arg0) {
		// TODO Auto-generated method stub
		this.application = arg0;
	}


	@Override
	public void setServletResponse(HttpServletResponse arg0) {
		// TODO Auto-generated method stub
		this.response = arg0;
	}


	@Override
	public void setServletRequest(HttpServletRequest arg0) {
		// TODO Auto-generated method stub
		this.request = arg0;
	}


	@Override
	public void setSession(Map<String, Object> arg0) {
		// TODO Auto-generated method stub
		this.session = arg0;
	}
}


下面贴出登录的Action类,其中并且必须和struts_user.xml中action标签指定的method一样,创建相同方法名称的方法和表单参数相同的属性。

public class LoginAction extends BaseAction{
        //表单中用户名参数
	public String username;
       //表单中提交的密码参数
	public String password;
	
        //struts_user.xml中的method指定方法
	public String login(){
		/*
                *从这里开始就是使用hibernate操作访问数据库的dao层代码了。
                */
		UserDao userDao = new UserService();
		boolean username_verify = this.username == null || this.username.equals("") || this.username.equals(" ");
		boolean password_verify = this.password == null || this.password.equals("") || this.password.equals(" ");
		if(username_verify == true || password_verify == true){
			System.out.println("return 了 Error");
			return "error";
		}else{
			User user = userDao.userLogin(this.username, this.password);
	
			if(user == null){
				return "defeated";
			}else{
				return "success";
			}
		}	
	}
}
然后return返回的字符串回到struts_user.xml的result标签,根据name和返回值对比,最后跳转到不同的页面上。



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值