MVC框架之SpringMVC

简介

Spring MVC 是 Spring 给我们提供的⼀个⽤于简化 Web 开发的框架。在说Spring MVC前,我们需要了解下什么是MVC架构以及三层架构?

1 MVC 体系结构

三层架构

在 JavaEE 开发中,⼏乎全都是基于 B/S 架构的开发。那么在 B/S 架构中,系统标准的三层架构包括:表现层、业务层、持久层。
三层架构中,每⼀层各司其职,接下来我们就说说每层都负责哪些⽅⾯:
表现层 :也就是我们常说的web 层。它负责接收客户端请求,向客户端响应结果,通常客户端使⽤http 协议请求web 层,web 需要接收 http 请求,完成 http 响应。表现层包括展示层和控制层:控制层负责接收请求,展示层负责结果的展示。表现层的设计⼀般都使⽤ MVC 模型。(MVC 是表现层的设计模型,和其他层没有关系)。
业务层 :也就是我们常说的 service 层。它负责业务逻辑处理,和我们开发项⽬的需求息息相关。web 层依赖业务层,但是业务层不依赖 web 层。业务层在业务处理时可能会依赖持久层,如果要对数据持久化需要保证事务⼀致性。(也就是我们说的, 事务应该放到业务层来控制)
持久层 :也就是我们是常说的 dao 层。负责数据持久化,包括数据层即数据库和数据访问层,数据库是对数据进⾏持久化的载体,数据访问层是业务层和持久层交互的接⼝,业务层需要通过数据访问层将数据持久化到数据库中。通俗的讲,持久层就是和数据库交互,对数据库表进⾏增删改查的。

MVC设计模式

MVC 全名是 Model View Controller,是 模型(model)-视图(view)-控制器(controller) 的缩写, 是⼀
种⽤于设计创建 Web 应⽤程序表现层的模式。MVC 中每个部分各司其职:
Model(模型):模型包含业务模型和数据模型,数据模型⽤于封装数据,业务模型⽤于处理业务。
View(视图): 通常指的就是我们的 jsp 或者 html。作⽤⼀般就是展示数据的。通常视图是依据模型数据创建的。
Controller(控制器): 是应⽤程序中处理⽤户交互的部分。作⽤⼀般就是处理程序逻辑的。MVC提倡:每⼀层只编写⾃⼰的东⻄,不编写任何其他的代码;分层是为了解耦,解耦是为了维护⽅便和分⼯协作。

2 Spring MVC 是什么?

SpringMVC 全名叫 Spring Web MVC,是⼀种基于 Java 的实现 MVC 设计模型的请求驱动类型的轻量级Web 框架,属于 SpringFrameWork 的后续产品。

Spring MVC 本质可以认为是对servlet的封装,简化了我们serlvet的开发。
作⽤:(1)接收请求 (2)返回响应,跳转⻚⾯

在这里插入图片描述
Spring MVC ⼯作流程
需求:前端浏览器请求url:http://localhost:8080/demo/handle01,前端⻚⾯显示后台服务器的时间开发过程
1)配置DispatcherServlet前端控制器
2)开发处理具体业务逻辑的Handler(@Controller、@RequestMapping)
3)xml配置⽂件配置controller扫描,配置springmvc三⼤件
4)将xml⽂件路径告诉springmvc(DispatcherServlet)

Spring MVC 请求处理流程
在这里插入图片描述
第⼀步:⽤户发送请求⾄前端控制器DispatcherServlet
第⼆步:DispatcherServlet收到请求调⽤HandlerMapping处理器映射器
第三步:处理器映射器根据请求Url找到具体的Handler(后端控制器),⽣成处理器对象及处理器拦截器(如果 有则⽣成)⼀并返回DispatcherServlet
第四步:DispatcherServlet调⽤HandlerAdapter处理器适配器去调⽤Handler
第五步:处理器适配器执⾏Handler
第六步:Handler执⾏完成给处理器适配器返回ModelAndView
第七步:处理器适配器向前端控制器返回 ModelAndView,ModelAndView 是SpringMVC 框架的⼀个底层对 象,包括 Model 和 View
第⼋步:前端控制器请求视图解析器去进⾏视图解析,根据逻辑视图名来解析真正的视图。
第九步:视图解析器向前端控制器返回View
第⼗步:前端控制器进⾏视图渲染,就是将模型数据(在 ModelAndView 对象中)填充到 request 域
第⼗⼀步:前端控制器向⽤户响应结果

3 Spring MVC 九⼤组件

  1. HandlerMapping(处理器映射器)
  2. HandlerAdapter(处理器适配器)
  3. HandlerExceptionResolver(处理 Handler 产⽣的异常情况)
  4. ViewResolver(视图解析器)
  5. RequestToViewNameTranslator(请求地址自动映射跳转视图名转换器)
  6. LocaleResolver(国际化解析器)
  7. ThemeResolver(主题解析器)
  8. MultipartResolver(文件上传请求解析器)
  9. FlashMapManager(重定向时的参数传递管理器)

4 SpringMVC请求参数绑定

  1. 默认⽀持 Servlet API 作为⽅法参数,只需要直接声明形参即可
    当需要使⽤HttpServletRequest、HttpServletResponse、HttpSession等原⽣servlet对象时,直接在handler⽅法中形参声明使⽤即可。

    @RequestMapping("/handle02")
     public ModelAndView handle02(HttpServletRequest request,HttpServletResponse response,
     HttpSession session){
     //此处代码省略
     }
    
  2. 绑定简单类型参数,只需要直接声明形参即可
    简单数据类型:⼋种基本数据类型及其包装类型
    参数类型推荐使⽤包装数据类型,因为基础数据类型不可以为null
    整型:Integer、int
    字符串:String
    单精度:Float、float
    双精度:Double、double
    布尔型:Boolean、boolean
    说明:对于布尔类型的参数,请求的参数值为true或false。或者1或0
    注意:绑定简单数据类型参数,只需要直接声明形参即可(形参参数名和传递的参数名要保持⼀致,建议 使⽤包装类型,当形参参数名和传递参数名不⼀致时可以使⽤@RequestParam注解进⾏⼿动映射)

    @RequestMapping("/handle03")
     public ModelAndView handle03(@RequestParam("ids") Integer id,Boolean flag){
     //此处代码省略
    }
    
  3. 绑定Pojo类型参数
    接收pojo类型参数,直接形参声明即可,类型就是Pojo的类型,形参名⽆所谓,但是要求传递的参数名必须和Pojo的属性名保持⼀致

    @RequestMapping("/handle04")
     public ModelAndView handle04(User user){
     //此处代码省略
     }
    
  4. 绑定Pojo包装对象参数
    不管包装Pojo与否,它⾸先是⼀个pojo,那么就可以按照上述pojo的要求来
    (1)绑定时候直接形参声明即可
    (2)传参参数名和pojo属性保持⼀致,如果不能够定位数据项,那么通过属性名 + “.” 的⽅式进⼀步锁定数据

  5. 绑定⽇期类型参数(需要配置⾃定义类型转换器)
    前端

    <fieldset>
     <p>测试⽤例:SpringMVC接收⽇期类型参数</p>
     <a href="/demo/handle06?birthday=2019-10-08">点击测试</a>
    </fieldset>
    

    后端,定义⼀个SpringMVC的类型转换器 接⼝,扩展实现接⼝接⼝,注册你的实现

    package com.lagou.edu.converter;
    import org.springframework.core.convert.converter.Converter;
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    /**
    * ⾃定义类型转换器
    * S:source,源类型
    * T:target:⽬标类型
    */
    public class DateConverter implements Converter<String, Date> {
     @Override
     public Date convert(String source) {
     // 完成字符串向⽇期的转换
     SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
     try {
     	Date parse = simpleDateFormat.parse(source);
     return parse;
     } catch (ParseException e) {
    	 e.printStackTrace();
     }
     return null;
     }
    }
    

    配置文件注册⾃定义类型转换器

    <!--
     ⾃动注册最合适的处理器映射器,处理器适配器(调⽤handler⽅法)
     -->
     <mvc:annotation-driven conversionservice="conversionServiceBean"/>
     <!--注册⾃定义类型转换器-->
     <bean id="conversionServiceBean" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
     <property name="converters">
    	 <set>
    	 <bean class="com.lagou.edu.converter.DateConverter"></bean>
    	 </set>
     </property>
     </bean>
    

    controller方法

    @RequestMapping("/handle06")
     public ModelAndView handle06(Date birthday){
    //此处代码省略
    }
    

5 SpringMVC与Ajax Json交互

@ResponseBody注解

@responseBody注解的作⽤是将controller的⽅法返回的对象通过适当的转换器转换为指定的格式之后,写⼊到response对象的body区,通常⽤来返回JSON数据或者是XML数据。 注意:在使⽤此注解之后不会再⾛视图处理器,⽽是直接将数据写⼊到输⼊流中,他的效果等同于通过response对象输出指定格式的数据。

Spring MVC 使⽤ Json 交互

所需jar包

<!--json数据交互所需jar,start-->
<dependency>
 <groupId>com.fasterxml.jackson.core</groupId>
 <artifactId>jackson-core</artifactId>
 <version>2.9.0</version>
</dependency> <dependency>
 <groupId>com.fasterxml.jackson.core</groupId>
 <artifactId>jackson-databind</artifactId>
 <version>2.9.0</version>
</dependency> <dependency>
 <groupId>com.fasterxml.jackson.core</groupId>
 <artifactId>jackson-annotations</artifactId>
 <version>2.9.0</version>
</dependency>
<!--json数据交互所需jar,end-->

前端jsp⻚⾯及js代码

<div>
 <h2>Ajax json交互</h2>
 <fieldset>
 <input type="button" id="ajaxBtn" value="ajax提交"/>
 </fieldset>
</div>
$(function () {
 $("#ajaxBtn").bind("click",function () {
 // 发送ajax请求
 $.ajax({
 url: '/demo/handle07',
 type: 'POST',
 data: '{"id":"1","name":"李四"}',
 contentType: 'application/json;charset=utf-8',
 dataType: 'json',
 success: function (data) {
 alert(data.name);
 }
 })
 })
})

后台Handler⽅法

@RequestMapping("/handle07")
// 添加@ResponseBody之后,不再⾛视图解析器那个流程,⽽是等同于response直接输出数据
public @ResponseBody User handle07(@RequestBody User user) {
 // 业务逻辑处理,修改name为张三丰
 user.setName("张三丰");
 return user; 
}

6 SpringMVC之拦截器

监听器、过滤器和拦截器对⽐

过滤器(Filter):对Request请求起到过滤的作⽤,作⽤在Servlet之前,如果配置为/*可以对所有的资源访问(servlet、js/css静态资源等)进⾏过滤处理
监听器(Listener):实现了javax.servlet.ServletContextListener 接⼝的服务器端组件,它随Web应⽤的启动⽽启动,只初始化⼀次,然后会⼀直运⾏监视,随Web应⽤的停⽌⽽销毁
作⽤⼀:做⼀些初始化⼯作,web应⽤中spring容器启动ContextLoaderListener
作⽤⼆:监听web中的特定事件,⽐如HttpSession,ServletRequest的创建和销毁;变量的创建、销毁和修改等。可以在某些动作前后增加处理,实现监控,⽐如统计在线⼈数,利⽤HttpSessionLisener等。
拦截器(Interceptor):是SpringMVC、Struts等表现层框架⾃⼰的,不会拦截jsp/html/css/image的访问等,只会拦截访问的控制器⽅法(Handler)。

从配置的⻆度也能够总结发现:serlvet、filter、listener是配置在web.xml中的,⽽interceptor是配置在表现层框架⾃⼰的配置⽂件中的
在这里插入图片描述
拦截器的执⾏流程

在运⾏程序时,拦截器的执⾏是有⼀定顺序的,该顺序与配置⽂件中所定义的拦截器的顺序相关。 单个拦截器,在程序中的执⾏流程如下图所示:
在这里插入图片描述
1)程序先执⾏preHandle()⽅法,如果该⽅法的返回值为true,则程序会继续向下执⾏处理器中的⽅法,否则将不再向下执⾏。
2)在业务处理器(即控制器Controller类)处理完请求后,会执⾏postHandle()⽅法,然后会通过DispatcherServlet向客户端返回响应。
3)在DispatcherServlet处理完请求后,才会执⾏afterCompletion()⽅法。

多个拦截器的执⾏流程

多个拦截器(假设有两个拦截器Interceptor1和Interceptor2,并且在配置⽂件中, Interceptor1拦截器配置在前),在程序中的执⾏流程如下图所示:
在这里插入图片描述
从图可以看出,当有多个拦截器同时⼯作时,它们的preHandle()⽅法会按照配置⽂件中拦截器的配置顺序执⾏,⽽它们的postHandle()⽅法和afterCompletion()⽅法则会按照配置顺序的反序执⾏。

乱码问题解决

Post请求乱码,web.xml中加⼊过滤器

<!-- 解决post乱码问题 -->
<filter>
	 <filter-name>encoding</filter-name>
	 <filter-class>
	 	org.springframework.web.filter.CharacterEncodingFilter
	 </filter-class>
	 <!-- 设置编码参是UTF8 -->
	 <init-param>
		 <param-name>encoding</param-name>
		 <param-value>UTF-8</param-value>
	 </init-param>
	 <init-param>
		 <param-name>forceEncoding</param-name>
		 <param-value>true</param-value>
	 </init-param>
</filter> 
<filter-mapping>
	 <filter-name>encoding</filter-name>
	 <url-pattern>/*</url-pattern>
</filter-mapping>

Get请求乱码(Get请求乱码需要修改tomcat下server.xml的配置)

<Connector URIEncoding="utf-8" connectionTimeout="20000" port="8080"
protocol="HTTP/1.1" redirectPort="8443"/>
  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值