struts2工作原理

Struts2是一款非常成熟的MVC架构。
1.体系架构图
在这里插入图片描述
图中的key:
servlet filters:过滤器链,客户端所有的请求都要经过Filter链的处理.
struts core:struts2的核心部分,struts2已经做好封装的部分.
interceptors:struts2的拦截器.struts2提供了许多默认的拦截器,可以完成日常开发的绝大部分工作,而我们自定义的拦截器,则用来实现客户的实际业务需求.
user created:由开发人员创建的,包括配置文件/action以及Template.
2.工作机制
<1>当用户的发出请求,比如http:localhost:8080/Struts2/helloworld/helloworldAction.action,请求会被Tomcat接收到,Tomcat服务器来选择处理这个请求的Web应用,那就是由helloworld这个web工程来处理这个请求。
<2>Web容器会去读取helloworld这个工程的web.xml,在web.xml中进行匹配,经过一系列的过滤器(Filter)。如(ActionContextCleanUp、其他过滤器SiteMesh等、 FilterDispatcher)。
注:这里是有顺序的,先ActionContextCleanUp,再其他过滤器(Othter Filters、SiteMesh等),最后到FilterDispatcher;
ActionContextCleanUp过滤器对于Struts2和其他框架的集成很有帮助;
从struts2.1.3后就不需要配置ActionContextCleanUp过滤器了,该过滤器的作用是清空值栈等,但struts会留下自己session和Attribute等;
FilterDispatcher是控制器的核心,就是MVC的Struts 2实现中控制层(Controller)的核心。

<3>然后会获取FilterDispatcher实例,然后回调doFilter方法,进行真正的处理
注:早期struts用FilterDispatcher过滤器,现在普遍都用StrutsPrepareAndExecuteFilter。 就名字而言,prepare与execute前者表示准备说指filterinit方法即配置导入;后者表示进行过滤指doFilter方法即request请求转发给对应action去处理
<4>这时FilterDispatcher会将请求转发给ActionMapper。ActionMapper负责识别当前的请求是否需要Struts2做出处理。
<5>如果需要Struts2处理,ActionMapper会通知FilterDispatcher,需要处理这个请求,FilterDispatcher会停止过滤器链以后的部分,(这也就是为什么,FilterDispatcher应该出现在过滤器链的最后的原因)。然后建立一个ActionProxy实例,这个对象作为Action与xwork之间的中间层,会代理Action的运行过程。
<6>ActionProxy对象在被创建出来的时候,并不知道要运行哪个Action,它手里只有从FilterDispatcher中拿到的请求的URL。而真正知道要运行哪个Action的是ConfigurationManager。因为只有它才能读取我们的strtus.xml
注:在服务器启动的时候,ConfigurationManager就会把struts.xml中的所有信息读到内存里,并缓存,当ActionProxy带着URL向他询问要运行哪个Action的时候,就可以直接匹配、查找并回答了
<7>ActionProxy知道自己该干什么事之后(运行哪个Action、相关的拦截器以及所有可能使用的result信息),然后马上建立ActionInvocation对象了,ActionInvocation对象描述了Action运行的整个过程。
注:Action完整的调用过程都是由ActionInvocation对象负责
<8>在execute方法之前,好像URL请求中的参数已经赋值到了Action的属性上,这就是我们的拦截器。拦截器的运行被分成两部分,一部分在Action之前运行,一部分在Result之后运行,而且顺序是刚好反过来的。也就是在Action执行前的顺序,比如是拦截器1、拦截器2、拦截器3,那么运行Result之后,再次运行拦截器的时候,顺序就变成拦截器3、拦截器2、拦截器1了。所以ActionInvocation对象执行的时候需要通过很多复杂的过程,按照指定拦截器的顺序依次执行。
<9>执行Action的execute方法,根据execute方法返回的结果(Result),去struts.xml中匹配选择下一个页面
注:返回结果通常是(但不总是,也可能是另外的一个Action链)一个需要被表示的JSP或者FreeMarker的模版
<10>根据结果(Result)找到页面后,在页面上(有很多Struts2提供的模板),可以通过Struts2自带的标签库来访问需要的数据,并生成最终页面
注:这时还没有给客户端应答,只是生成了页面
<11>ActionInvocation对象倒序执行拦截器,得到响应对象(HttpServletResponse)了,最后按与过滤器(Filter)配置定义相反的顺序依次经过过滤器,向客户端展示出响应的结果
3.组件作用
FilterDispatcher是整个Struts2的调度中心,也就是MVC中的C(控制中心),根据ActionMapper的结果来决定是否处理请求,如果ActionMapper指出该URL应该被Struts2处理,那么它将会执行Action处理,并停止过滤器链上还没有执行的过滤器。
ActionMapper 会判断这个请求是否应该被Struts2处理,如果需要Struts2处理,ActionMapper会返回一个对象来描述请求对应的ActionInvocation的信息。
ActionProxy,它会创建一个ActionInvocation实例,位于Action和xwork之间,使得我们在将来有机会引入更多的实现方式,比如通过WebService来实现等。
ConfigurationManager是xwork配置的管理中心,可以把它看做struts.xml这个配置文件在内存中的对应。
struts.xml,是开发人员必须光顾的地方。是Stuts2的应用配置文件,负责诸如URL与Action之间映射关系的配置、以及执行后页面跳转的Result配置等。
ActionInvocation:真正调用并执行Action,它拥有一个Action实例和这个Action所依赖的拦截器实例。ActionInvocation会按照指定的顺序去执行这些拦截器、Action以及相应的Result。
Interceptor(拦截器):是Struts2的基石,类似于JavaWeb的Filter,拦截器是一些无状态的类,拦截器可以自动拦截Action,它们给开发者提供了在Action运行之前或Result运行之后来执行一些功能代码的机会。
Action:用来处理请求,封装数据。
4.代码举例
页面发起请求
test.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript">
	function doSend(){
	    var obj = {};
	    var rtData = $.ajax({
	        url:'/byyfsg/checkXgcl.action?zlId='+ $("#yfxmids").val(),
	        async:false
	    }).responseText;
	    var result = $.parseJSON(rtData);
	    if(result.hasOwnProperty("message")){
	        alert(result['message']);
	    }else{
	        alert("OK");
	    }
	}
</script>
</head>
<body>
<input type="button" name="button" id="button" value="转出" onClick="doSend();"/>
<span id="yfxmids">1</span>
</body>
</html>

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>ExampleProject</display-name>
  
	<!--配置Struts2核心拦截器  -->
	<filter>
		<filter-name>struts2</filter-name>
		<filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>struts2</filter-name>
		<url-pattern>/*</url-pattern> 	
	</filter-mapping>
  
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
</web-app>

xwork_test.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xwork PUBLIC "-//OpenSymphony Group//XWork 1.1.1//EN" "http://www.opensymphony.com/xwork/xwork-1.1.1.dtd">
<xwork>
    <package name="byyfsg" extends="common" namespace="/byyfsg">
		<!--检查图片是否上传-->
        <action name="checkXgcl" class="com.hzfc.soar.byfz.xfbyyf.byyfsg.action.BizXfByyfSgAction" method="checkXgcl">
            <interceptor-ref name="defaultStack"/>
        </action>
        <!--查看附件-->
        <action name="viewYfsghk" class="com.hzfc.soar.byfz.xfbyyf.byyfsg.action.BizXfByyfSgAction" method="viewYfsghk">
            <interceptor-ref name="defaultStack"/>
        </action>
        <!--删除附件-->
        <action name="delYfsghk" class="com.hzfc.soar.byfz.xfbyyf.byyfsg.action.BizXfByyfSgAction" method="delYfsghk">
            <interceptor-ref name="defaultStack"/>
            <result type="redirect-action" name="success">
                goViewYfsghk?businessId=${businessId}&amp;zlId=${zlId}
            </result>
        </action>
        <!--跳转查看附件页面-->
        <action name="goViewYfsghk" class="com.hzfc.soar.byfz.xfbyyf.byyfsg.action.BizXfByyfSgAction" method="goViewYfsghk">
            <interceptor-ref name="defaultStack"/>
            <result type="dispatcher" name="success">
                /soar/byfz/xfbyyf/sg/viewYfsghk.jsp
            </result>
        </action>
    </package>
</xwork>

或者如查看附件的action,返回结果在另一个页面显示,也可以如删除附件的action一样,返回结果后,执行另一个action
Action.java

public class BizXfByyfSgAction{
    private Log log = LogFactory.getLog(BizXfByyfSgAction.class);

	private Long zlId;
    private YfsghkService yfsghkService;
	
    /**
     * 校验是否上传图片
     * @return
     */
    public void checkXgcl() throws IOException {
        log.debug("验证图片是否上传");
        JSONObject ja = new JSONObject();
        yfsghkService.checkXgclByXmid(ja,zlId);
        PrintWriter pw = this.getResponse().getWriter();
        pw.print(ja.toString());
        pw.flush();
        pw.close();
    }

    public Long getZlId() {
        return zlId;
    }

    public void setZlId(Long zlId) {
        this.zlId = zlId;
    }

	public YfsghkService getYfsghkService() {
        return yfsghkService;
    }

    public void setYfsghkService(YfsghkService yfsghkService) {
        this.yfsghkService = yfsghkService;
    }
}

action中接收参数通过参数的get/set方法进行传递,同样也可以这样的方式传回页面,也可以通过写入到response中传递到前端页面
注:代码中json中包含了message,页面获取json的message对应value.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值