概述

  • Spring MVC通过一套MVC注解,让POJO变成处理请求的控制器,无需实现任何接口,同时,SpringMVC还支持REST风格的URL请求:注解驱动和REST风格的Spring MVC是Spring 3.0最出彩的功能之一。
  • Spring MVC框架围绕 DispatcherServlet这个核心展开,DispatcherServlet是SpringMVC的总导演,它负责截获请求,并将其分派给相应的处理器处理。
  • 和大多数WEB MVC一样,Spring MVC通过一个前端Servlet接收所有的请求,并将具体工作委托给其他组件进行处理,DispatcherServlet就是Spring MVC的前端Servlet。

本文主要讲了一些什么

Spring MVC的基本原理  -->

用一个简单的示例对基本原理有个具体了解 -->

分别描述MVC的几个重量级角色:过滤请求、绑定请求、封装对象、处理XML和JSON、处理模型数据。

本篇文章重在知识点整合,作为读书笔记,语言简洁,删繁就简,由浅入深,引人入胜。通读本文,你将对Spring MVC有一个深入的了解。如果读,请深读。如果爱,请读完。

基本原理

基本原理及入门示例已在微信订阅号上发布,为防止原创性的冲突检测,故删去这一部分,详情扫码关注查看:

过滤请求

使用@RequestMapping可以过滤请求URL、请求参数、请求方法,请求头这4个方面的信息项。比如:

绑定请求信息到方法入参中

Spring MVC会将HTTP请求的信息绑定到相应的方法入参中,并根据方法返回值类型作出相应的后续处理。比如:

将请求信息封装成对象

使用HttpMessageConverter<T>可以将请求信息转换成一个对象,或者将对象输出为响应信息。(T就是对象类型)。

两把利剑:

1.使用RequestBody、ResponseBody。

2.使用HttpEntity<T>/ResponseEntity<T>

示例1:

客户端:

服务端:

示例2:

客户端:

服务端:

与RequestBody、ResponseBody不同的是,HttpEntity不仅可以访问请求、响应报文体的数据,还可以访问请求和响应报文头的数据。

示例1:

客户端:

服务端:

示例2:

客户端:

服务端:

怎么做到的?

HttpMessageConverter<T>提供了众多的实现类,它组成了一个功能强大、用途广泛的HttpMessageConverter<T>家族。

比如:

  StringHttpMessageConverter负责将请求信息转换成字符串;

  FormHttpMessageConverter负责将表单数据读取到MultiValueMap中;

  还有诸如读写XML、Resource、JSON等等对应的实现类。

  AnnotationMethodHandlerAdapter适配器默认装配了基本的Converter(String、ByteArray、Source、XmlAwareForm),容器会根据需要自动调用不同的HttpMessageConverter实现类。

  如果不能满足需求,那么继续在xml中配置其他的converter:

处理XML和JSON

从上文可知,HttpMessageConverter有一个很强大的家族,能够处理各种格式的请求及响应。当然也可以处理XML和JSON。

处理XML和JSON的Converter分别是:

MarsHallingHttpMessageConverter(处理xml)。

Jaxb2RootElementHttpMessageConverter(同上,底层使用JAXB)。

MappingJacksonHttpMessageConverter(处理JSON)。

按照前文的思路,首先要在配置文件中装配好相应的Converter,但是还有其他必要的步骤:

步骤1:XML中配置Converter以及Marshaller:

步骤2:测试客户端发出请求:

步骤3:响应(服务)端:

步骤4:User的注解:

步骤5:用tcptrace监听测试

其实,如果把第92行和第93行代码的头部格式换成json,就变成传送json格式的数据了。这个时候,用tcptrace监听传送json的结果:

可以看到,请求中,我们的报文头格式变成了json,报文体也是json格式的。而响应中报文体也是json格式的。

为什么我直接截图了json格式的测试结果而没有测试请求xml的测试结果呢?

因为在xml测试时,报出了415 Unsupported media type的错误,尚未发现原因。

但是思路就是这样了。 读者如果知道“不支持此类型”的原因,欢迎评论留言。

处理模型数据

我们在Controller控制器中接收请求参数,把处理后得到的数据封装起来,然后返回到一个JSP,在JSP中就可以获取封装的数据。那么,在这个例子中,封装的数据就是模型数据,而JSP就是渲染模型数据的视图。这在MVC框架中是最重要的步骤。

在控制器方法中输出模型数据有四种方法:

方法一:ModelAndView

在控制器方法中新建ModelAndView对象,把“视图”和“模型数据”封装到该对象中,然后返回该对象即可。

方法二:@ModelAttribute

加到入参的前面,就自动把入参绑定为模型数据;加到方法A的前面,那么Spring MVC就会在执行任何目标处理方法之前,先执行方法A(B\C等等),然后把这些加了标注的方法的返回值绑定为模型数据。

举例1:

Spring MVC会先把模型数据储存到ServletRequest的属性列表中(使用setAttribute保存)。

然后在返回的jsp(视图对象)中,使用${user.userName}来访问user的属性。

举例2:

在执行handle62之前,spring扫描到有方法头部标注了@ModelAttribute,那么,spring就会先去执行getUser,并把返回值user作为模型数据,键为”user”。

这时执行handle62,入参前面的@ModelAttribute键为”user”,正好匹配了刚封装的模型数据的键,那么就把模型数据赋值给入参User user,然后285行对user做了覆盖操作,最后交给视图层处理。

方法三:Map and Model

如果处理方法的入参类型为Map或者Model(或者具备二者功能的对象如:ModelMap),那么spring会将隐含的模型数据传给该入参,在处理方法中,我们可以从该入参中取出隐含的模型数据,也可以继续添加模型数据。

标注了@ModelAttribute的方法的返回值(getUser方法返回的user)就是隐含的模型数据。

由于handle63的入参为ModelMap类型,所以,spring会把user这个隐含模型数据授予modelMap,在300行,我们通过该入参取出模型数据,在302行,我们通过该入参继续添加模型数据。

方法四:@SessionAttributes

如果Controller类的头部标注了@SessionAttributes(”xxx”),那么spring会把键为xxx的模型数据暂存到HttpSession中,以便多个请求之间可以共享该数据。

... ...

61行的标注表示:后面处理器在处理任何方法时,看到属性名为user的模型属性就会把它存到session中共享。由于328行把user作为了模型数据,那么这个user就放到了session中。

当转发请求到handle72时,就可以从modelMap中拿到该对象。

当使用完成时,在338行表示把该对象从session中移除。否则它会一直存在。

然而程序是跑不起来的,会报HttpSessionRequiredException。为什么呢?

这是因为,如果有了61行标注的会话属性user,那么spring就会尝试从会话中获取该属性,然后把它赋给入参。

也就是说,spring看到61行的标注,会从会话中找user为键的模型数据,找到后把它赋值给334行的modelMap。

但是现在从代码看来,在执行61行标注之前,会话中并没有键为user的模型数据。

所以,解决方法很简单:

只需要像方法二那样,加一个:

就好了。这样,在执行61行之前,先执行getUser,把user作为隐含模型数据。那么执行61行时,该会话中就已经有user了。

当你读到这里,你已经百毒不侵了。亲,不点个赞吗?

(spring-第21回【MVC基础篇】)SpringMVC一点就通的更多相关文章

  1. spring 5.x 系列第2篇 —— springmvc基础 (代码配置方式)

    文章目录 一.搭建hello spring工程 1.1 项目搭建 1.2 相关注解说明 二.配置自定义拦截器 三.全局异常处理 四.参数绑定 4.1 参数绑定 4.2 关于日期格式转换的三种方法 五. ...

  2. spring 5.x 系列第1篇 —— springmvc基础 (xml配置方式)

    文章目录 一.搭建hello spring工程 1.1 项目搭建 1.2 相关配置讲解 二.配置自定义拦截器 三.全局异常处理 四.参数绑定 4.1 参数绑定 4.2 关于日期格式转换的三种方法 五. ...

  3. Spring MVC 基础篇4

    Spring MVC Controller中返回数据到页面 1.使用ModelAndView 进行数据返回到请求页面 2.利用Map类型的入参进行Controller返回到页面上 3.将数据放到Ses ...

  4. Spring MVC基础篇4

    Spring MVC操作原生Servlet 对象 Spring MVC 可以操作原生的Servlet API,如下的这些原生API,可以各自 自由混合使用,也可以和其他非原生 参数组合使用 实例代码: ...

  5. MVC基础篇—控制器与视图数据的传递

    Viewdata,Viewbag,Tempdata 1  Vewdata:简单来说就是数据字典,通过键值对的形式来存放数据.举例如下: //后台控制器代码: public ActionResult V ...

  6. Java基础-SSM之Spring MVC入门篇

    Java基础-SSM之Spring MVC入门篇 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Spring MVC简介 1>.什么是Spring MVC 答:Sprin ...

  7. Spring+SpringMVC+MyBatis+easyUI整合基础篇(一)项目简介

    很久之前就打算开始写一下自己的技术博客了,实在抽不出时间所以计划一直搁置了,最近项目进度渐渐缓了下来,不那么忙了,也因此开始筹备自己的博客.说到这次博客的主角,也是无心插柳找到的,来源于两年前自己写的 ...

  8. Spring+SpringMVC+MyBatis+easyUI整合基础篇(六)maven整合SSM

    写在前面的话   承接前文<Spring+SpringMVC+MyBatis+easyUI整合基础篇(五)讲一下maven>,本篇所讲述的是如何使用maven与原ssm项目整合,使得一个普 ...

  9. Spring+SpringMVC+MyBatis+easyUI整合基础篇(八)mysql中文查询bug修复

    写在前面的话 在测试搜索时出现的问题,mysql通过中文查询条件搜索不出数据,但是英文和数字可以搜索到记录,中文无返回记录.本文就是写一下发现问题的过程及解决方法.此bug在第一个项目中点这里还存在, ...

随机推荐

  1. PHP redis 批量操作

    参考网站 phpredis扩展 :https://github.com/phpredis/phpredis#pconnect-popen 命令参考:http://doc.redisfans.com   ...

  2. Linux上如何执行java程序

    想要在Ubuntu上运行java程序,可以将java程序编译成功后打包,然后在Ubuntu上用命令执行jar文件 具体操作如下: 1.Windows上使用eclipse编译java工程,编译完成后导出 ...

  3. 《精通MVC5.0》路由笔记

    MVC使用路由系统处理请求的URL.路由系统主要功能 检查请求的URL,并理解该URL对应的控制器和方法 生成URL地址 在MVC程序中有两种方式创建路由:convention-based routi ...

  4. 今天遇到了批量删除 redis 某个前缀的所有 key,发现只能是这么解决。

    redis-cli KEYS "php*" | xargs redis-cli DEL 利用 linux的 管道输出命令 xargs 根据返回结果逐条 删除.   上面这条命令 可 ...

  5. SVN使用教程

    SVN简介: 为什么要使用SVN? 程序员在编写程序的过程中,每个程序员都会生成很多不同的版本,这就需要程序员有效的管理代码,在需要的时候可以迅速,准确取出相应的版本. Subversion是什么? ...

  6. 绑定多个ddl

    添加材料,需要绑定材料类型.设备名称.省份和所属终端客户等信息,前台页面如下: 前台.aspx <asp:Content ID="Content2" ContentPlace ...

  7. iOS_开发中引导页的设置及代码

    在iOS 手机App 软件的开发中, 基本上每一个完整的App 都有与之相对应的引导页的设置,引导页也会有很多种设置的方式,根据不同的情况,选择不同的编码,在这里,我分享一下自己关于引导页的一些看法和 ...

  8. 第十讲(LINQ)

    一..LINQ查询 例如: static void LINQQuery() { var query = from r in Formula1.GetChampions() where r.Countr ...

  9. Java中使用二重循环打印沙漏图形

    1.首先判断外层,A .B.C.D都符合条件 2.那么再看内层 A :int i=0;i<5;i++ 当i=1时;带入到第二个内层循环中 int j=0;j<Math.abs(i)*2+1 ...

  10. RabbitMQ Step by step(一) 安装

    RabbitMQ是一个消息中间件,可以存储转发消息,个人感觉优越于MSMQ RabbitMQ官方网站(http://www.rabbitmq.com)可以获取到安装文件,建议大家详细浏览官方网站,官方 ...