SpringMVC架构设计

MVC是一种架构模式,它把业务的实现和展示相分离。

SpringMVC与struts2的区别

  1. Struts2是类级别的拦截, 一个类对应一个request上下文,SpringMVC是方法级别的拦截,一个方法对应一个request上下文,而方法同时又跟一个url对应,所以说从架构本身上SpringMVC就容易实现restful url,而struts2的架构实现起来要费劲,因为Struts2中Action的一个方法可以对应一个url,而其类属性却被所有方法共享,这也就无法用注解或其他方式标识其所属方法了。
  2. springmvc可以进行单例开发,并且建议使用单例开发,struts2通过类的成员变量接收参数,无法使用单例,只能使用多例。
  3. 由于Struts2需要针对每个request进行封装,把request,session等servlet生命周期的变量封装成一个一个Map,供给每个Action使用,并保证线程安全,所以在原则上,是比较耗费内存的。
  4. 拦截器实现机制上,Struts2有以自己的interceptor机制,SpringMVC用的是独立的AOP方式,这样导致Struts2的配置文件量还是比SpringMVC大。
  5. servlet和filter的区别了。
  6. SpringMVC集成了Ajax,使用非常方便,只需一个注解@ResponseBody就可以实现,然后直接返回响应文本即可,而Struts2拦截器集成了Ajax,在Action中处理时一般必须安装插件或者自己写代码集成进去,使用起来也相对不方便。
  7. SpringMVC验证支持JSR303,处理起来相对更加灵活方便,而Struts2验证比较繁琐,感觉太烦乱。
  8. spring MVC和Spring是无缝的。从这个项目的管理和安全上也比Struts2高(当然Struts2也可以通过不同的目录结构和相关配置做到SpringMVC一样的效果,但是需要xml配置的地方不少)。
  9. 设计思想上,Struts2更加符合OOP的编程思想, SpringMVC就比较谨慎,在servlet上扩展。
  10. SpringMVC开发效率和性能高于Struts2。
  11. SpringMVC可以认为已经100%零配置。

SpringAOP整合SpringMVC

spring容器不注册controller层组件,controller组件由springMVC容器单独注册。

// applicationContext.xml
<context:component-scan base-package="com.shuyun.channel">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
<context:exclude-filter type="annotation" expression="org.springframework.web.bind.annotation.RestController" />
<context:exclude-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice" />
</context:component-scan> // springmvc-servlet.xml
<context:component-scan base-package="com.shuyun.channel" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
<context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.RestController" />
<context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice" />
</context:component-scan>

注意

关于<context:annotation-config /> <context:component-scan />:

component-scan会自动加上annotation-config功能,有了component-scan不用再写annotation-config了。参见spring官方reference

配置层次化Spring容器

参考 配置层次化Spring容器

我们知道,在开发基于spring的Web应用时,通常使用两个IoC容器,一个是由DispatchServlet初始化的WebApplicationContext,一个是由ContextLoaderListener初始化的ApplicationContext。对于Spring容器,Spring的官方参考手册详细地讲解了依赖注入的配置方式,对于容器本身的配置和多个容器之间的关系却不曾提及。于是,很多人以为在一个应用中只有一个全局的Spring容器,或者不了解MVC使用的WebApplicationContext和根ApplicationContext的关系。

通过查看Spring的源码和API,发现Spring可以配置为多个容器,容器之间可以配置为层级关系,一个根容器可以配置许多子容器,子容器还可以配置子容器,从而形成一个单根的层次化结构。对于该容器结构中的每个容器,在其中查找特定的bean时,会首先在本容器内查找,如果找到对应的bean,就返回该bean;如果没有找到,就会从直接父容器中去查找,依此类推,直到根容器为止。

从上面的示例中可以看到,从子容器中可以取得父容器中配置的bean,而父容器中不能够取得子容器中的bean。

在Spring MVC中WebApplicationContext配置为根ApplicationContext的子容器,所以,MVC使用的容器中能够取得根ApplicationContext中的bean。在一个web程序中可以配置多个DispatchSerlvet,每个Servlet对应一个容器,所有这些容器都作为根容器的子容器,这样,我们就可以把通用的bean放在根容器中,而针对特定DispatchServlet的bean,可以放在各自的子容器中。

文件上传

  • Controller的方法中需要接受一个Spring MVC提供的MultipartFile接口作为方法的参数,该参数接收前台表单type为file提交的对象,使用@RequestParam注解指明参数,那么Spring就会自动将表单传递过来的对象的类型转换为MultipartFile类型。

  • MultipartFile中提供了getName()、getSize()、getByte()

    getContentType()、isEmpty()、getInputStream()、getOriginalFilename()方法来访问文件。getOriginalFilename()方法是获取最初文件名,即本地文件名。

  • 在Controller方法中使用FileUtils下的copyInputStreamToFile(InputStream in,File file)方法来完成文件的拷贝.第一个参数是文件拷贝源的输入流,直接使用MultipartFile下的getInputStream()方法.第二个参数是文件将要保存的位置.

@RequestMapping("/doUpload")
public Result doUpload(@RequestParam("file") MultipartFile file) throws IOException {
if (!file.isEmpty()) {
FileUtils.copyInputStreamToFile(file.getInputStream(), new File("E://", file.getOriginalFilename()));
}
return ResultUtil.SUCCESS_RESULT;
}

Jackson

SpringMVC拦截器

拦截器好比你要去取经,那么,你就必须经过九九八十一关,主要用来解决请求的共性问题,如:乱码问题、权限验证问题等

实现SpringMVC拦截器的三个步骤

  1. 创建一个实现HandlerInterceptor接口,并实现接口的方法的类
  2. 将创建的拦截器注册到SpringMVC的配置文件中实现注册
    <mvc:interceptors>
    <bean class="路径下的类">
    </mvc:interceptors>
  3. 配置拦截器的拦截规则:
    <mvc:interceptors>
    <mvc:interceptor>
    <mvc:mapping path="拦截的action">
    <bean class="路径下的类">
    </mvc:interceptor>
    </mvc:interceptors>

拦截器中三个方法的介绍:

  1. preHandle()方法是否将当前请求拦截下来。(返回true请求继续运行,返回false请求终止(包括action层也会终止),Object arg代表被拦截的目标对象。)
  2. postHandle()方法的ModelAndView对象可以改变发往的视图或修改发往视图的信息。
  3. afterCompletion()方法表示视图显示之后在执行该方法。(一般用于资源的销毁)

拦截器和过滤器

共同:他们都是用来检查程序的共同场景,只不过拦截器是面向Action的,过滤器是面向整个web应用的。

  1. 解决权限验证问题
  2. 解决乱码问题

拦截器和过滤器的区别:

  1. 拦截器是基于java的反射机制的,而过滤器是基于函数回调。
  2. 拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
  3. 拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
  4. 拦截器可以访问action上下文、值栈 里的对象,而过滤器不能访问。
  5. 在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。
  6. 拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑

拦截器方法的作用顺序

拦截器的其它实现方式:

  1. 拦截器的类还可以通过实现WebRequestInterceptor(HandlerInterceptor)接口来编写。
  2. 向SpringMVC框架注册的写法不变。
  3. 弊端:preHandler方法没有返回值,不能终止请求。

Ps:建议使用功能更强大的实现方式,实现HandlerInterceptor接口。

Spring4增加功能

Spring4主要在Web服务方面有下面两个方面提升:

  1. 控制器使用@ResponseBody@RestController
  2. 异步调用。

Spring整合Struts2

Spring默认是单例,Struts2默认是多实例的。

如果是spring配置文件中的 bean的名字的话就是spring创建,那么单实例还是多实例就由spring的action Bean中的业务逻辑控制器类是否配置为scope=”prototype”,有就是多实例的,没有就是单实例的,顺序是先从spring中找,找不到再从struts配置文件中找。

  1. 对于无Spring插件(Struts2-spring-plugin-XXX.jar)的整合方式,需要在spring的action Bean中加业务逻辑控制器类配scope="prototype"。
    <bean id="user" class="modle.User" scope="prototype"/>
  2. 对于有Spring插件(Struts2-spring-plugin-XXX.jar)的整合方式:反编译StrutsSpringObjectFactory以及相关的代码才发现,如果在struts action的配置文件 <action name=".." class=".."/> 中class写的如果是完整的包名和类名的话就是struts创建action对象,也就是多实例的;

参考文档

  1. 史上最全最强SpringMVC详细示例实战教程
  2. Spring MVC快速入门
  3. Web MVC framework - Part VI. The Web
  4. Spring 注解学习手札(七) 补遗——@ResponseBody,@RequestBody,@PathVariable
  5. SpringMVC4.1之Controller层最佳实践

SpringMVC 知识整理的更多相关文章

  1. 二:SpringMVC知识整理

    springmvc复习: 1.SpringMVC介绍 2.SpringMVC入门程序 1)创建web工程 2)导入jar包 3)在web.xml中配置前端控制器(指定上下文件的路径 classpath ...

  2. js事件(Event)知识整理

    事件(Event)知识整理,本文由网上资料整理而来,需要的朋友可以参考下   鼠标事件 鼠标移动到目标元素上的那一刻,首先触发mouseover 之后如果光标继续在元素上移动,则不断触发mousemo ...

  3. Kali Linux渗透基础知识整理(四):维持访问

    Kali Linux渗透基础知识整理系列文章回顾 维持访问 在获得了目标系统的访问权之后,攻击者需要进一步维持这一访问权限.使用木马程序.后门程序和rootkit来达到这一目的.维持访问是一种艺术形式 ...

  4. Kali Linux渗透基础知识整理(二)漏洞扫描

    Kali Linux渗透基础知识整理系列文章回顾 漏洞扫描 网络流量 Nmap Hping3 Nessus whatweb DirBuster joomscan WPScan 网络流量 网络流量就是网 ...

  5. wifi基础知识整理

    转自 :http://blog.chinaunix.net/uid-9525959-id-3326047.html WIFI基本知识整理 这里对wifi的802.11协议中比较常见的知识做一个基本的总 ...

  6. 数据库知识整理<一>

    关系型数据库知识整理: 一,关系型数据库管理系统简介: 1.1使用数据库的原因: 降低存储数据的冗余度 提高数据的一致性 可以建立数据库所遵循的标准 储存数据可以共享 便于维护数据的完整性 能够实现数 ...

  7. 【转载】UML类图知识整理

    原文:UML类图知识整理 UML类图 UML,进阶必备专业技能,看不懂UML就会看不懂那些优秀的资料. 这里简单整理 类之间的关系 泛化关系(generalization) 泛化(generalize ...

  8. Linux进程管理知识整理

    Linux进程管理知识整理 1.进程有哪些状态?什么是进程的可中断等待状态?进程退出后为什么要等待调度器删除其task_struct结构?进程的退出状态有哪些? TASK_RUNNING(可运行状态) ...

  9. js事件(Event)知识整理[转]

    事件注册 平常我们绑定事件的时候用dom.onxxxx=function(){}的形式 这种方式是给元素的onxxxx属性赋值,只能绑定有一个处理句柄. 但很多时候我们需要绑定多个处理句柄到一个事件上 ...

随机推荐

  1. mmap函数实现

    转自:https://www.cnblogs.com/huxiao-tee/p/4660352.htmlmmap是一种内存映射文件的方法,即将一个文件或者其它对象映射到进程的地址空间,实现文件磁盘地址 ...

  2. deeplearning.ai 作业中的Python常用命令

    1. print大法 test = Hello World print ("test:" + test) 2. math和numpy的区别:math只对单个元素,numpy会bro ...

  3. (亲测)1分钟破解IDM权限,傻瓜都能学会的破解方法(番外篇:利用破解工具直接破解IDM)

    Internet Download Manager (IDM)是比较好用的一款下载工具~ 上一节我讲到一种利用修改防火墙来进行阻止访问服务器,请参看这篇文章(亲测)躺着破解IDM下载权限,治疗不用破解 ...

  4. Codeforces Round #409 (rated, Div. 2, based on VK Cup 2017 Round 2)(A.思维题,B.思维题)

    A. Vicious Keyboard time limit per test:2 seconds memory limit per test:256 megabytes input:standard ...

  5. codeforces 746C 模拟

    C. Tram time limit per test 1 second memory limit per test 256 megabytes input standard input output ...

  6. 二维数组模拟实现酒店管理系统-java

    业务分析 1.需要一个房间类,包含房间的属性,比如房间编号.房间类型.是否占用. 2.需要一个旅馆类,旅馆有房间,提供的方法需要有 预订房间.打印房间信息.初始化房间.退房. 3.测试类,测试预订房间 ...

  7. 用NPOI导出Excel,生成下拉列表、以及下拉联动列表(第1篇/共3篇)

    最近帅帅的小毛驴遇到一个很奇葩的需求: 导出Excel报表,而且还要带下拉框,更奇葩的是,下拉框还是联动的. 小毛驴一天比较忙,所以这等小事自然由我来为她分忧了.经历了两天,做了几种解决方案,最后完美 ...

  8. 启动tomcat时,一直卡在Deploying web application directory这块的解决方案

    本来今天正常往服务器上扔一个tomcat 部署一个项目的, 最后再启动tomcat 的时候 发现项目一直都访问不了,看了一下日志: [root@iz8vbdzx7y7owm488t4d89z bin] ...

  9. laravel中数据库在哪个文件中配置

    我们使用 mysql 数据库,修改 .env: DB_HOST=localhost DB_DATABASE=laravel DB_USERNAME=root DB_PASSWORD= 在mysql中创 ...

  10. Struts2 04--- 值栈 ognl(S标签)

           OGNL是Object-Graph Navigation Language的缩写,它是一种功能强大的表达式语言,通过它简单一致的表达式语法,可以存取对象的任意属性,调用对象的方法,遍历整 ...