一 servlet - 体系(组织)结构图
图1 - servlet体系(组织)结构图 - 网
参考:
错题小笔记21——文本文件,Servlet体系_福尔摩斯est的博客-CSDN博客
Java Web编程之Servlet技术详解-计算机技术学习分享
二 servlet - 运行流程
图1 - servlet运行详解(下) - dainner
三 servlet - 生命周期
图1 - servlet生命周期(五) - dainner
四 servlet - cookie
图1 - cookie的使用细节 - dainner
五 servlet - session
图1 - 比较cookie和session - dainner
六 servlet - 过滤器
参考:百度安全验证
七 struts2 - 体系结构图
一个请求在Struts2框架中的处理流程大概分为以下几个步骤:
- 客户端初始化一个指向Servlet容器(例如Tomcat)的(HTTP)请求。
- (官网)Struts 使用 Introspection 将 HTTP 参数转换为 JavaBean 属性并从 JavaBean 属性填充 HTML 字段。这种技术使得在 HTML 表单和 JavaBeans 之间“往返”属性变得容易。
- struts2框架会创建HttpServletRequest对象和HttpServletResponse对象,所以,在struts2.0中,可以通过ServletActionContext.getRequest()获取request对象。
- 这个请求经过一系列的过滤器(Filter)(这些过滤器中有一个叫做ActionContextCleanUp的可选过滤器,这个过滤器对于Struts2和其他框架的集成很有帮助,例如:SiteMesh Plugin)。
- 请求发送给 StrutsPrepareAndExecuteFilter。
- StrutsPrepareAndExecuteFilter 询问 ActionMapper(Action映射器-包含了name and namespace ): 该请求是否是一个 Struts2 请求(即是否返回一个非空的 ActionMapping 对象)。
- 若 ActionMapper 认为该请求是一个 Struts2 请求,则 StrutsPrepareAndExecuteFilter 把请求的处理交给 ActionProxy(Action代理,是Xwork和Action的中间层)。
- ActionProxy 通过 Configuration Manager (配置管理器)询问框架的配置文件,确定需要调用的 Action 类及 Action 方法。
- ActionProxy 创建一个 ActionInvocation ( ActionInvocation就是Action的调用者。ActionInvocation在Action的执行过程中,负责Interceptor、Action和Result等一系列元素的调度。)的实例,并进行初始化。ActionInvocation初始化时,根据配置,加载Action相关的所有Interceptor。通过ActionInvocation.invoke方法调用Action实现时,执行Interceptor。一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。
- ActionInvocation 实例在使用命名模式来调用Action,在调用Action的过程前后,涉及到相关拦截器(Intercepter)的调用。
- 一旦Action 执行完毕,ActionInvocation 负责根据 struts.xml 中的配置找到对应的返回结果,返回结果通常是(但不总是,也可能是另外的一个Action链)一个需要被表示的JSP或者FreeMarker的模版。并调用结果的 execute 方法,渲染结果。在渲染的过程中可以使用Struts2 框架中的标签。在表示的过程中可以使用Struts2框架中继承的标签。
- 执行各个拦截器 invocation.invoke() 之后的代码。
- 把结果发送到客户端。
FilterDispatcher是控制器的核心,就是mvc中c控制层的核心。下面粗略的分析下我理解的FilterDispatcher工作流程和原理:FilterDispatcher进行初始化并启用核心doFilter
其代码如下:
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException ...{
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
ServletContext servletContext = filterConfig.getServletContext();
// 在这里处理了HttpServletRequest和HttpServletResponse。
DispatcherUtils du = DispatcherUtils.getInstance();
du.prepare(request, response);//正如这个方法名字一样进行locale、encoding以及特殊request parameters设置
try ...{
request = du.wrapRequest(request, servletContext);//对request进行包装
} catch (IOException e) ...{
String message = "Could not wrap servlet request with MultipartRequestWrapper!";
LOG.error(message, e);
throw new ServletException(message, e);
}
ActionMapperIF mapper = ActionMapperFactory.getMapper();//得到action的mapper
ActionMapping mapping = mapper.getMapping(request);// 得到action 的 mapping
if (mapping == null) ...{
// there is no action in this request, should we look for a static resource?
String resourcePath = RequestUtils.getServletPath(request);
if ("".equals(resourcePath) && null != request.getPathInfo()) ...{
resourcePath = request.getPathInfo();
}
if ("true".equals(Configuration.get(WebWorkConstants.WEBWORK_SERVE_STATIC_CONTENT))
&& resourcePath.startsWith("/webwork")) ...{
String name = resourcePath.substring("/webwork".length());
findStaticResource(name, response);
} else ...{
// this is a normal request, let it pass through
chain.doFilter(request, response);
}
// WW did its job here
return;
}
Object o = null;
try ...{
//setupContainer(request);
o = beforeActionInvocation(request, servletContext);
//整个框架最最核心的方法,下面分析
du.serviceAction(request, response, servletContext, mapping);
} finally ...{
afterActionInvocation(request, servletContext, o);
ActionContext.setContext(null);
}
}
du.serviceAction(request, response, servletContext, mapping);
//这个方法询问ActionMapper是否需要调用某个Action来处理这个(request)请求,如果ActionMapper决定需要调用某个Action,FilterDispatcher把请求的处理交给ActionProxy
public void serviceAction(HttpServletRequest request, HttpServletResponse response, String namespace, String actionName, Map requestMap, Map parameterMap, Map sessionMap, Map applicationMap) ...{
HashMap extraContext = createContextMap(requestMap, parameterMap, sessionMap, applicationMap, request, response, getServletConfig()); //实例化Map请求 ,询问ActionMapper是否需要调用某个Action来处理这个(request)请求
extraContext.put(SERVLET_DISPATCHER, this);
OgnlValueStack stack = (OgnlValueStack) request.getAttribute(ServletActionContext.WEBWORK_VALUESTACK_KEY);
if (stack != null) ...{
extraContext.put(ActionContext.VALUE_STACK,new OgnlValueStack(stack));
}
try ...{
ActionProxy proxy = ActionProxyFactory.getFactory().createActionProxy(namespace, actionName, extraContext);
//这里actionName是通过两道getActionName解析出来的, FilterDispatcher把请求的处理交给ActionProxy,下面是ServletDispatcher的 TODO:
request.setAttribute(ServletActionContext.WEBWORK_VALUESTACK_KEY, proxy.getInvocation().getStack());
proxy.execute();
//通过代理模式执行ActionProxy
if (stack != null)...{
request.setAttribute(ServletActionContext.WEBWORK_VALUESTACK_KEY,stack);
}
} catch (ConfigurationException e) ...{
log.error("Could not find action", e);
sendError(request, response, HttpServletResponse.SC_NOT_FOUND, e);
} catch (Exception e) ...{
log.error("Could not execute action", e);
sendError(request, response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e);
}
}
FilterDispatcher询问ActionMapper是否需要调用某个Action来处理这个(request)请求,如果ActionMapper决定需要调用某个Action,FilterDispatcher把请求的处理交给ActionProxy。
ActionProxy通过Configuration Manager(struts.xml)询问框架的配置文件,找到需要调用的Action类.
如上文的struts.xml配置
<?xml version="1.0" encoding="GBK"?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<include file="struts-default.xml"/>
<package name="struts2" extends="struts-default">
<action name="add"
class="edisundong.AddAction" >
<result>add.jsp</result>
</action>
</package>
</struts>
如果提交请求的是add.action,那么找到的Action类就是edisundong.AddAction。
ActionProxy创建一个ActionInvocation的实例,同时ActionInvocation通过代理模式调用Action。但在调用之前ActionInvocation会根据配置加载Action相关的所有Interceptor。(Interceptor是struts2另一个核心级的概念)
下面我们来看看ActionInvocation是如何工作的:
ActionInvocation 是Xworks 中Action 调度的核心。而对Interceptor 的调度,也正是由ActionInvocation负责。ActionInvocation 是一个接口, 而DefaultActionInvocation 则是Webwork 对ActionInvocation的默认实现。
Interceptor 的调度流程大致如下:
1. ActionInvocation初始化时,根据配置,加载Action相关的所有Interceptor。
2. 通过ActionInvocation.invoke方法调用Action实现时,执行Interceptor。
Interceptor将很多功能从我们的Action中独立出来,大量减少了我们Action的代码,独立出来的行为具有很好的重用性。XWork、WebWork的许多功能都是有Interceptor实现,可以在配置文件中组装Action用到的Interceptor,它会按照你指定的顺序,在Action执行前后运行。
那么什么是拦截器。
拦截器就是AOP(Aspect-Oriented Programming)的一种实现。(AOP是指用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作。)
拦截器的例子这里就不展开了。
struts-default.xml文件摘取的内容:
< interceptor name ="alias" class ="com.opensymphony.xwork2.interceptor.AliasInterceptor" />
< interceptor name ="autowiring" class ="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor" />
< interceptor name ="chain" class ="com.opensymphony.xwork2.interceptor.ChainingInterceptor" />
< interceptor name ="conversionError" class ="org.apache.struts2.interceptor.StrutsConversionErrorInterceptor" />
< interceptor name ="createSession" class ="org.apache.struts2.interceptor.CreateSessionInterceptor" />
< interceptor name ="debugging" class ="org.apache.struts2.interceptor.debugging.DebuggingInterceptor" />
< interceptor name ="external-ref" class ="com.opensymphony.xwork2.interceptor.ExternalReferencesInterceptor" />
< interceptor name ="execAndWait" class ="org.apache.struts2.interceptor.ExecuteAndWaitInterceptor" />
< interceptor name ="exception" class ="com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor" />
< interceptor name ="fileUpload" class ="org.apache.struts2.interceptor.FileUploadInterceptor" />
< interceptor name ="i18n" class ="com.opensymphony.xwork2.interceptor.I18nInterceptor" />
< interceptor name ="logger" class ="com.opensymphony.xwork2.interceptor.LoggingInterceptor" />
< interceptor name ="model-driven" class ="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor" />
< interceptor name ="scoped-model-driven" class ="com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor" />
< interceptor name ="params" class ="com.opensymphony.xwork2.interceptor.ParametersInterceptor" />
< interceptor name ="prepare" class ="com.opensymphony.xwork2.interceptor.PrepareInterceptor" />
< interceptor name ="static-params" class ="com.opensymphony.xwork2.interceptor.StaticParametersInterceptor" />
< interceptor name ="scope" class ="org.apache.struts2.interceptor.ScopeInterceptor" />
< interceptor name ="servlet-config" class ="org.apache.struts2.interceptor.ServletConfigInterceptor" />
< interceptor name ="sessionAutowiring" class ="org.apache.struts2.spring.interceptor.SessionContextAutowiringInterceptor" />
< interceptor name ="timer" class ="com.opensymphony.xwork2.interceptor.TimerInterceptor" />
< interceptor name ="token" class ="org.apache.struts2.interceptor.TokenInterceptor" />
< interceptor name ="token-session" class ="org.apache.struts2.interceptor.TokenSessionStoreInterceptor" />
< interceptor name ="validation" class ="com.opensymphony.xwork2.validator.ValidationInterceptor" />
< interceptor name ="workflow" class ="com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor" />
< interceptor name ="store" class ="org.apache.struts2.interceptor.MessageStoreInterceptor" />
< interceptor name ="checkbox" class ="org.apache.struts2.interceptor.CheckboxInterceptor" />
< interceptor name ="profiling" class ="org.apache.struts2.interceptor.ProfilingActivationInterceptor" />
一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。如上文中将结构返回“add.jsp”,但大部分时候都是返回另外一个action,那么流程又得走一遍………
参考:
Struts2学习总结(一):Struts2结构体系 - 程序员大本营 (pianshen.com)
(59条消息) Struts2体系结构图以及详解_weixin_33938733的博客-CSDN博客
struts2基础 - fight139 - 博客园 (cnblogs.com)
(64条消息) struts2和Springmvc原理及比较_钟渊博客-CSDN博客
七 struts2源码分析
Struts2的工作机制及分析_jiab的专栏-CSDN博客
八 struts2与servlet的区别与联系
1 联系
- 都能实现mvc架构的java web项目。
- servlet只是一个接口,一种规范。其没有任何逻辑可言。底层的网络io,编码解码由web容器(常见的如:tomcat,jetty)处理,实现servlet接口,将http请求封装成HttpServletRequest(是这个对象没错吧?)。而对于web开发者来说,我们只需要实现servlet接口,根据不同的http请求实现不同的业务逻辑,然后封装成HttpServletResponse返回给web容器,由web容器进行编码解码然后将数据写回客户端。那么struts,springmvc之类的mvc框架无非就是为了简化我们对于request,response中繁琐的api处理,让web开发者关注于业务逻辑而对上层request,response做了一层封装。仅此而已。
- struts2做了本应该servlet做的事。但是struts2实现的核心不是基于servlet的(Struts1的action完全就是Servlet,因为ActionServlet类继承自Servlet),struts2是基于拦截器。struts2比servlet优于这个框架实现前台页面与后台的分离,也就是解耦合,mvc知道吧。
2 区别
- 线程安全。Servlet是单例的(多个请求一个servlet实例),而Struts2是多例的(一个请求一个Action)。servlet是单实例,多线程。而struts是多实例,多线程,因此在多用户同时访问的时候,servlet中定义的属性可能会被覆盖掉,而struts2则不会出现这种情况。
- 容器依赖。1、servlet需要依赖容器,httprequest,httpresponse必须有容器才能初始化。action完全与容器松耦合,由struts2本身创建httprequest,httpresponse。2、Servlet从Web容器直接被调用。Action不直接被Web容器调用,而是被Web容器中的Strtus框架调用。3、需要把Action看成一个前端的逻辑单元,甚至是独立于Struts框架本身(所以建议在Action中尽量不要使用Struts2的API,比如HttpRequest, ActionContext等等)。Servlet完全是容器相关的,所以从这一点上说,Action更加抽象化了一层。当然如果从MVC模式看的话Struts 1中的Servlet应该算是Controller部分,Action应该看成是Model部分;而在Struts 2中用FilterDispatcher代替了Servlet。
- 启动。Servlet:servlet要在web.xml配置。Struts:配置过滤器,设置struts入口。
- 创建。Servlet:继承HttpServlet,重写doGet与doPost方法,添加注解或配置web.xml。Struts:继承ActionSupport,写一个返回值为String而且抛出一个异常的函数,并且要配置struts.xml。
- 封装数据。Servlet:使用BeanUtils工具通过name封装,BeanUtils.populate(user,request.getParameterMap())。Struts:实现ModelDriven接口,实现getModel方法,返回一个封装数据的对象(必须要先把对象new出来),也是通过name属性进行封装。struts2能够通过默认的拦截器自动获取请求参数,而且能够自动转换成对应的数据类型。前提要求是在对应的action类中 定义对应的属性 而且属性名要与对应的请求参数的key保持一致,并提供set,get方法。主要是set方法。
- 重定向。Servlet重定向:response.sendRedirect(request.getContextPath() + "/index.html")。servlet重定向:<result name="success" type="redirect">/index.html</result>。
- 转发。Servlet转发:request.getRequestDispatcher("login.jsp").forward(request, response)。Struts转发:<result name="error">/login.jsp</result>。
- 结果集。servlet要么转发、要么重定向。struts2可以自定义结果集。
- 页面数据获取。servlet页面的值,request.getParameter("user")。struts2的action可以用属性驱动,模型驱动获取。
- 错误处理。servlet处理错误用http状态码(404,500),struts2用的是模板页面。
参考:
servlet和struts2的区别和联系_lishaheshizan的博客-CSDN博客_servlet和struts2区别
Servlet与Struts的区别 - Lam9207 - 博客园
Struts2中Action与Servlet的联系与区别_m0_37541228的博客-CSDN博客
Struts2的Action和Servlet有什么联系,区别?_xyjikl-CSDN博客
struts2和servlet的区别_weixin_41010390的博客-CSDN博客_struts2和servlet的区别
Struts2与Servlet的关系_huangyimo的专栏-CSDN博客
(64条消息) struts2和Springmvc原理及比较_钟渊博客-CSDN博客
九 springmvc的体系结构
图1-dljd
图1-springmvc体系结构-百度百科
图2 - springmvc体系结构 - 网站
图3 - springmvc体系结构 - 网站
图4 - springmvc体系结构 - 网站
运行流程:
- 发起请求到前端控制器(DispatcherServlet);
- 前端控制器请求HandlerMapping查找并获取Handler,可以根据xml配置、注解进行查找;
- 处理器映射器根据请求url找到具体的处理器Handler,生成处理器对象及处理器拦截器(如果有则生成),一并返回给DispatcherServlet;
- DispatcherServlet 调用 HandlerAdapter处理器适配器,请求执行Handler;;
- HandlerAdapter 经过适配调用具体Handler进行处理业务逻辑;
- Handler执行完成给适配器返回ModelAndView;
- 处理器适配器HandlerAdapter向前端控制器返回ModelAndView(是springmvc框架的一个底层对象,包括Model和View);
- 前端控制器DispatcherServlet请求,将ModelAndView传给ViewResolver视图解析器进行解析。视图解析器去进行视图解析,根据逻辑视图名称解析真正的视图(jsp…);
- 视图解析器向前端控制器返回View;
- 前端控制器进行视图渲染,视图渲染就是将模型数据(在ModelAndView对象中)填充到视图中(request域中)。
- 前端控制器向用户响应用户。
组件:
- 前端控制器(DispatcherServlet,不需要攻城狮开发):作用:接收请求,响应结果,相当于转发器,中央处理器。有了 dispatcherServlet 减少了其它组件之间的耦合度。用户请求到达前端控制器,它就相当于mvc模式中的c,dispatcherServlet是整个流程控制的中心,由它调用其它组件处理用户的请求,dispatcherServlet的存在降低了组件之间的耦合性。
- 处理器映射器(HandlerMapping,不需要攻城狮开发):根据请求的URL来查找Handler。HandlerMapping负责根据用户请求找到Handler即处理器,springmvc提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。
- 处理器适配器(HandlerAdapter):作用:按照特定规则( HandlerAdapter 要求的规则)去执行 Handler。通过HandlerAdapter对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。
- 处理器(Handler。需要攻城狮开发):主要负责处理前端请求,完成业务逻辑,生成ModelAndView对象返回给HandlerAdapter。注意:编写 Handler 时按照 HandlerAdapter 的要求去做,这样适配器才可以去正确执行 Handler。Handler 是继DispatcherServlet前端控制器的后端控制器,在DispatcherServlet的控制下Handler对具体的用户请求进行处理。由于Handler涉及到具体的用户业务请求,所以一般情况需要攻城狮根据业务需求开发Handler。
- 视图解析器 (View Resolver。不需要攻城狮开发 ,由框架提供):作用:进行视图解析,根据逻辑视图名解析成真正的视图( view )。View Resolver负责将处理结果生成View视图,View Resolver首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成View视图对象,最后对View进行渲染将处理结果通过页面展示给用户。 springmvc框架提供了很多的View视图类型,包括:jstlView、freemarkerView、pdfView等。一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展示给用户,需要由攻城狮根据业务需求开发具体的页面。
- 视图(View。需要攻城狮开发 jsp… ):是一个接口, 它的实现类支持不同的View类型,比如jsp,freemarker,pdf等等
参考:
springMVC学习笔记(一)—–springMVC原理-Harries Blog™ (liuhaihua.cn)
SpringMVC架构-阿里云开发者社区 (aliyun.com)
20180110225024064583.png (793×579) (aliyuncs.com)
20180110225024064583.png (793×579) (aliyuncs.com)
springmvc - 世界基于代码 - 博客园 (cnblogs.com)
springmvc体系结构的搜索结果_百度图片搜索 (baidu.com)
SpringMVC 组件类大全 - Java天堂 (javatt.com)
(64条消息) struts2和Springmvc原理及比较_钟渊博客-CSDN博客
十 springmvc与servlet的联系与区别
1 联系
- springmvc是对Servlet的封装,核心的DispatcherServlet最终继承自HttpServlet
2 区别
- 本质。Servlet:是JavaEE规范的一种,主要是为了扩展Java作为Web服务的功能,统一接口。由其他内部厂商如tomcat,jetty内部实现web的功能。SpringMVC:是一个mvc框架。
-
在web层的位置与作用。Servlet作用在web层
SpringMVC也作用在web层但是MVC使用Handler来处理参数,还有前端控制器DispatcherServlet,springmvc就是对Servlet的封装 - 拦截:Servlet:是类级别的拦截, 一个类对应一个request上下文(XxxServlet是单例的,而一个请求对应一个request)。SpringMVC:是方法级别的拦截,SpringMVC的方法之间基本上独立的,一个方法对应分别一个request上下文和一个response上下文,而方法同时又跟一个url对应,
- 跳转:Servlet:手写跳转servlet(转发 / 重定向),开发效率比较低,所以就涌现除了很多框架,比如struct2,springmvc等等。SpringMVC:的跳转通过视图解析器ViewResolver+ModelAndView+配置进行可配置的跳转。
参考: (62条消息) 菜鸟学SpringMVC之——SpringMVC和Servlet的区别与联系_菜鸟琪-CSDN博客_springmvc和servlet的关系
SpringMvc和servlet对比 - 这才是真的阿呆云飞 - 博客园 (cnblogs.com)
(63条消息) SpringMVC是方法级别的测试_龙腾四海365的专栏-CSDN博客
(63条消息) SpringMVC和Struts2的区别_龙腾四海365的专栏-CSDN博客
十一 springmvc与struts2的联系与区别
1 联系
都是mvc框架
2 区别
- 设计思想。Struts2更加符合OOP的编程思想。SpringMVC就比较谨慎,在servlet上扩展。
- 框架机制。SpringMVC的入口是servlet,而Struts2是filter(这里要指出,filter和servlet是不同的。以前认为filter是servlet的一种特殊),这就导致了二者的机制不同,这里就牵涉到servlet和filter的区别了。
- 拦截机制。
- a、struts2是基于类开发,传递参数是通过类的属性,只能设计为多例。struts采用值栈存储请求和响应的数据,通过OGNL存取数据 .
b、Struts2框架是类级别的拦截,每次请求就会创建一个Action,和Spring整合时Struts2的ActionBean注入作用域是原型模式prototype(否则会出现线程并发问题),然后通过setter,getter把request数据注入到属性。struts2实际上是通过属性的setter getter方法与request打交道的,
c、Struts2:值栈存储请求和响应的数据,通过OGNL存取数据。Struts2中,一个Action对应一个request,response上下文,在接收参数时,可以通过属性接收,这说明属性参数是让多个方法共享的。
d、Struts2中Action的一个方法可以对应一个url,而其类属性却被所有方法共享,这也就无法用注解或其他方式标识其所属方法了。 - a、springmvc是基于方法开发,传递参数是通过方法形参,可以设计为单例。springmvc通过参数解析器是将request对象内容进行解析成方法形参,将响应数据和页面封装成ModelAndView对象,最后又将模型数据通过request对象传输到页面,jsp视图解析器默认使用的是jstl。
b、SpringMVC是方法级别的拦截,一个方法对应一个Request上下文、Response上下文,所以方法直接基本上是独立的,独享request,response数据。而每个方法同时又何一个url对应,参数的传递是直接注入到方法中的,是方法所独有的。处理结果通过ModeMap返回给框架。
c、在Spring整合时,SpringMVC的Controller Bean默认单例模式Singleton,所以默认对所有的请求,只会创建一个Controller,有应为没有共享的属性,所以是线程安全的,如果要改变默认的作用域,需要添加@Scope注解修改。
- a、struts2是基于类开发,传递参数是通过类的属性,只能设计为多例。struts采用值栈存储请求和响应的数据,通过OGNL存取数据 .
- 拦截器机制。拦截器实现机制上,Struts2有以自己的interceptor机制,SpringMVC用的是独立的AOP方式,这样导致Struts2的配置文件量还是比SpringMVC大。
- spring集成。Spring MVC和Spring是无缝的。从这个项目的管理和安全上也比Struts2高(当然Struts2也可以通过不同的目录结构和相关配置做到SpringMVC一样的效果,但是需要xml配置的地方不少)。
- ajax集成。SpringMVC集成了Ajax,使用非常方便,只需一个注解@ResponseBody就可以实现,然后直接返回响应文本即可。而Struts2拦截器集成了Ajax,在Action中处理时一般必须安装插件或者自己写代码集成进去,使用起来也相对不方便。
- JSR303集成。SpringMVC验证支持JSR303,处理起来相对更加灵活方便,而Struts2验证比较繁琐,感觉太烦乱。
- 零配置。SpringMVC可以认为已经100%零配置。spring MVC和Spring是无缝的。从这个项目的管理和安全上也比Struts2高(当然Struts2也可以通过不同的目录结构和相关配置做到SpringMVC一样的效果,但是需要xml配置的地方不少)。
- 性能。spring mvc 在性能上会稍微比struts2快。(1)SpringMVC实现了零配置。(2)由于SpringMVC基于方法的拦截,有加载一次单例模式bean注入。而Struts2是类级别的拦截,每次请求对应实例一个新的Action,需要加载所有的属性值注入,所以,SpringMVC开发效率和性能高于Struts2。。
- 开发效率。SpringMVC开发效率和性能高于Struts2。
- 参数传递/数据共享。struts2在接受参数的时候,可以用成员属性来接受参数,这就说明参数是让多个方法共享的,即其类属性却所有方法共享;spring mvc的方法之间基本上独立的,独享request response数据,请求数据通过参数获取,处理结果通过ModelMap交回给框架,方法之间不共享变量;
- RESTful架构的实现。spring mvc是方法级别的拦截,一个方法对应一个request上下文,而方法同时又跟一个url对应,所以说从架构本身上spring mvc就容易实现restful url;
struts2是类级别的拦截,一个类对应一个request上下文,struts2 action的一个方法可以对应一个url;而其类属性却被所有方法共享,这也就无法用注解或其他方式标识其所属方法了,所以实现restful url比较费劲。
参考:
SpringMVC和Struts2区别比较 - 空谷幽澜 - 博客园 (cnblogs.com)
SpringMVC与Struts2区别与比较总结(四个概念详细分析servlet、filter、listener、interceptor的区别与联系?)
SpringMVC——MVC、springMVC认识及理解、与Struts2的区别
Struts2 和 SpringMVC的区别? - SegmentFault 思否
Struts2框架和SpringMvc框架的区别 - 丹寻 - 博客园 (cnblogs.com)
同为框架,Struts2和SpringMVC比较的区别(提出“数据共享”的概念)
(64条消息) struts2和Springmvc原理及比较_钟渊博客-CSDN博客
十二 Struts2疑难杂症
十三 spingmvc疑难杂症
1 <mvc:annotation-driven/>与HttpMessageConverter(消息转换器)
参考:
spring mvc的<mvc:annotation-driven/>有什么用?