springmvc知识

一、Spring MVC基础

Spring MVC简介

基于java的实现MVC设计模式的请求驱动类型的轻量级Web框架,通过注解,无需实现任何接口,处理请求,支持restful。

三层结构:表现层、业务层、持久层

设计模式:Model(模型)、View(视图)、Controller(控制器)

Spring Web MVC工作流程

SpringMvc请求处理流程:

\1. 前端用户发送请求到前端控制器DispatcherServlet

\2. DispatcherServlet收到请求之后调用处理映射器HandlerMapping

\3. 处理映射器根据url找到对应的后端控制器handler,生成处理器对象和处理器拦截器返回前端控制器

\4. 前端控制器再去调用处理适配器HandlerAdapter去调用具体的后端控制器

\5. 后端控制器执行完毕之后,把ModelAndView返回给处理适配器

\6. 处理适配器把ModelAndView返回给前端控制器。

\7. 前端控制器调用视图解析器ViewResolver进行解析,解析完毕返回视图view

\8. 前端控制器进行视图渲染,就是数据填充

\9. 前端控制器向用户响应结果

img

SpringMvc九大组件:

HandlerMapping(处理器映射器)、

HandlerAdapter(处理器适配器)、

HandlerExceptionResolver(异常处理)、

ViewResolver(视图解析器)、

RequestToViewNameTranslator(请求在查找视图名称,视图名转化器组件)

LocaleResolver(区域化解析,表示所在地)、ThemeResolver(主题解析)

MultipartResolver(多部件解析器文件上传处理)、FlashMapManager(flash属性管理组件 重定向参数传递)

web.xml中url-pattern配置三种方式:

方式一:带后缀,比如*.action *.do *.aaa

方式二:/ 不会拦截 .jsp,但是会拦截.html等静态资源(静态资源:除了servlet和jsp之外的js、css、png等)

因为tomcat容器中有一个web.xml(父),你的项目中也有一个web.xml(子),是一个继承关系父web.xml中有一个DefaultServlet, url-pattern 是一个 /此时我们自己的web.xml中也配置了一个 / ,覆写了父web.xml的配置

为什么不拦截.jsp呢?

因为父web.xml中有一个JspServlet,这个servlet拦截.jsp文件,而我们并没有覆写这个配置,所以springmvc此时不拦截jsp,jsp的处理交给了tomcat

方式三:/* 拦截所有,包括.jsp

img

数据输入类型ModelMap、Model、Map

运行的时候都会使用BindingAwareModelMap类型,而这个类型是上面三种接口的实现

Spring MVC请求参数绑定

前后端交互传输数据都是http,简称超文本传输协议。SpringMvc对serlvet封装,接收整形参数时直接在Handler⽅法中声明形参。

简单数据类型:⼋种基本数据类型及其包装类型

参数类型推荐使⽤包装数据类型,因为基础数据类型不可以为null

整型:Integer、int

字符串:String

单精度:Float、float

双精度:Double、double

布尔型:Boolean、boolean

说明:对于布尔类型的参数,请求的参数值为true或false。或者1或0

注意:绑定简单数据类型参数,只需要直接声明形参即可(形参参数名和传递的参数名要保持⼀致,建议 使⽤包装类型,当形参参数名和传递参数名不⼀致时可以使⽤@RequestParam注解进⾏⼿动映射)

自定义类型,比如日期处理,需要实现Converter接口,并注册自定义转换器

img

Restful请求支持

Restful 是⼀种 web 软件架构⻛格,它不是标准也不是协议,它倡导的是⼀个资源定位及资源操作的⻛格。

优点:

结构清晰、符合标准、易于理解、扩展⽅便

特性:

⽹络上的⼀个实体,或者说是⽹络上的⼀个具体信息。它可以是⼀段⽂本、⼀张图⽚、⼀⾸歌曲、⼀种服务,总之就是⼀个具体的存在。可以⽤⼀个 URI(统⼀资源定位符)指向它,每种资源对应⼀个特定的 URI 。要获取这个资源,访问它的 URI 就可以,因此URI 即为每⼀个资源的独⼀⽆⼆的识别符。

img

乱码过滤器web.xml配置,如果是put和delete请求需要配置请求方式转换,但是此方式不常用

img

Ajax Json交互

Json是⼀种与语⾔⽆关的数据交互格式,就是⼀种字符串,只是⽤特殊符号{}内表示对象、[]内表示数组、””内是属性或值、:表示后者是前者的值。

{“name”: “Michael”}可以理解为是⼀个包含name为Michael的对象

[{“name”: “Michael”},{“name”: “Jerry”}]就表示包含两个对象的数组

前端到后台:前端ajax发送json格式字符串,后台直接接收为pojo参数,使⽤注解@RequstBody

后台到前端:后台直接返回pojo对象,前端直接接收为json对象或者字符串,使⽤注解@ResponseBody,此注解不走视图解析器,而是直接将数据写入流中。

Spring高级技术之监听器、拦截器、过滤器

过滤器(Filter):对Request请求起到过滤的作⽤,作⽤在Servlet之前,如果url-pattern配置为/*可以对所有的资源访问(servlet、js/css静态资源等)进⾏过滤处理

监听器(Listener):实现了javax.servlet.ServletContextListener 接⼝的服务器端组件,它随Web应⽤的启动⽽启动,只初始化⼀次,然后会⼀直运⾏监视,随Web应⽤的停⽌⽽销毁,做一些初始化工作以及监听特定事件对其处理,比如从A方法进入B方法,A方法需要知道B方法执行完继续进行下一步,那么A方法就可以监听B方法的运行情况。

拦截器(Interceptor):拦截访问的控制器⽅法(Handler),一个拦截器拦截三次。

\1. 在Handler业务逻辑执⾏之前拦截⼀次

\2. 在Handler逻辑执⾏完毕但未跳转⻚⾯之前拦截⼀次

\3. 在跳转⻚⾯之后拦截⼀次

img

拦截器执行流程:多个拦截器执行顺序是按照配置文件拦截器的前后顺序执行的,按照先进后出的顺序,第一个拦截器先进去最后出来。

\1. 程序先执⾏preHandle()⽅法,如果该⽅法的返回值为true,则程序会继续向下执⾏处理器中的⽅法,否则将不再向下执⾏。

\2. 在业务处理器(即控制器Controller类)处理完请求后,会执⾏postHandle()⽅法,然后会通过DispatcherServlet向客户端返回响应。

\3. 在DispatcherServlet处理完请求后,才会执⾏afterCompletion()⽅法。

img

img

img

multipart形式(文件上传)数据、异常捕获、重定向参数传递

文件上传

客户端:POST请求;enctype=multipart;file组件

服务端: 重命名uuid;存储到磁盘,按日期建文件夹;把文件储存路径存入数据库,方便根据路径获取想要的资源。

img

img

异常捕获

需要实现HandlerExceptionResolver接口把程序所有或者单一异常都捕获做统一返回处理,比如专门做一个错误页面告知用户,给用户更好的反馈和体验。单类捕获就写在当前类就行了,全局捕获自定义一个类添加@ControllerAdvice注解。

img

重定向参数传递

重定向时请求参数会丢失,我们往往需要重新携带请求参数,在路径中手动拼接,解决办法声明RedirectAttributes类,可以添加flash属性,框架会在session中记录该属性值,进行重定向参数传递,而且完成之后会自动被清理。

img

二、自定义MVC框架

MVC框架运行原理

\1. Tomcat加载web.xml,前端控制器DispatcherServlet加载指定的配置文件springmvc.xml

\2. 根据配置文件扫描包和注解

img

\3. IOC容器进行相应的Bean初始化和依赖注入维护

\4. SpringMvc相关组件的初始化,建立url和method之间的映射关系,也就是处理映射器HandlerMapping

img

\5. 等待请求进来,处理请求。

自定义框架实现步骤

\1. 加载配置文件springmvc.properties,把文件加载成字节流然后转化成字符流存入properties。

img

\2. 从properties中取出配置的地址,拼接成绝对路径,扫描该路径下所有文件,找到class文件对应集合中

img

\3. 初始化Bean对象,变量全限定类名集合中每一个元素,进行注解判断,如果存在注解,进行反射实例化,然后存入bean对象集合中。

img

\4. 实现依赖注入,遍历上面的beanMap集合,然后再对遍历出来的类,取出所有属性再遍历,判断属性上面是否存在@Autowired注解,存在再进行相应处理。

img

\5. 构造一个HandlerMapping处理映射器,将配置好的url和method建立映射关系,遍历beanMap集合,判断类和方法上面是否存在@Controller注解,如果存在取出两个值拼接成url存入一个自定义的普通类中,类里面有所属类、方法、url以及参数位置四个属性。

img

img

img

\6. 执行dopost方法,接受前端请求,执行自定义MVC框架,从handler中取出参数,进行请求处理,进行参数绑定最后调用该handler所属方法的invoke方法,执行到控制层。

img

img

三、Spring MVC源码剖析

前端控制器DispatcherServlet继承结构

前端控制配置在web.xml中,执行前后端交互的重要组件,比如接收请求,调用处理器,渲染视图等等,他的继承结构如下:DispatcherServlet extends FrameworkServlet extends HttpServletBean extends HttpServlet。

\1. HttpServlet里面定义两个方法doGet、doPost方法用于获取协议等等参数,但是并没有进行具体的业务逻辑处理

img

\2. 在继承类FrameworkServlet中,重写了doGet、doPost方法,在这两个方法内对前端发送的请求调用自己内部定义的processRequest方法进行处理。

img

img

\3. 在processRequest方法结束调用了一个doSercive方法,他是一个抽象方法,交给了最底层类DispatcherServlet来实现。在方法内进行参数存储,设置属性值以及重定向参数管理,结尾又调用了自己内部的doDispatch方法进行请求派发。

img

img

\4. 在doDispatch方法内主要是检查是否是文件上传请求,获取处理当前请求的处理器handler,再获取处理请求的适配器,处理请求返回视图对象,最后对视图对象进行处理。

img

img

完整走向图

img

SpringMVC请求处理大致走向流程

\1. 前端用户发送请求,执行到控制层

img

\2. 接着走doGet/doPost请求,跟上面DispatcherServlet继承结构走向一致,进入到doDispatch方法开始真正的执行逻辑处理。doDispatch方法核心步骤:

1)调取getHandler()获取到能够处理当前请求的执行链HandlerExecutionChain

img

2)调用getHandlerAdapter方法获取能够执行1)的Handler的适配器

img

3)适配器调用Handler执行ha.handle,返回一个视图ModelAndView对象

img

4)调用processDispatchResult方法完成视图渲染调转

img

\3. getHandler方法剖析

如何获取适配器Handler对象?

在容器启动初始化过程中,扫描@RequestMapping注解建立url和Handler方法的对应映射关系,handlerMappings是一个接口,里面有两个实现类,通过遍历获取requestHandlerMapping实现类,通过传进来的请求request进行筛选,得到匹配的handlder并返回。

img

\4. getHandlerAdapter方法剖析

如何获取处理器getHandlerAdapter对象

HandlerInterceptor也是一个接口,里面有三个实现类,对不同方式请求进行分别处理,遍历获取能处理当前handler的处理器,通过supports方法内是否是这个接口的实现就能判断是否是他的处理器,返回是否处理的布尔值结果。

img

SpringMVC九大组件初始化

九大组件,全部定义在DispatcherServlet中,他们都定义成了接口,接口定义了规范。

img

Spring容器启动时,AbstractApplicationContext类中的核心方法refresh中调用了onRefresh方法,由子类实现了DispatcherServlet做了实现(完成九大件初始化),通过onRefresh方法内调用initStrategies方法完成.

img

多部件解析的id是固定multipartResolver,因为内部定义了一个常量就叫multipartResolver

img

Handler方法执行细节剖析

此方法就是上面doDispatch方法核心步骤第三步,调用ha.handle方法,针对他内部实现进行剖析。根据外部这个方法进入handleInternal方法,创建一个视图,然后判断这个session是否需要同步处理,因为session是线程不安全的,如果需要同步,则获取当前session对象并且一个唯一key增加synchronized关键字进行锁定保证线程安全。在锁里面调用invokeHandlerMethod方法对handler进行适配,如果不需要同步处理则直接进入此方法。在该方法内部进行一系列检查和前置处理,走到invokeAndHandle方法这里,开始对请求参数进行处理,调用目标的HandlerMethod,将返回值封装返回成一个ModelAndView对象。

img

img

在invokeAndHandle方法内部又请求了自己类的invokeForRequest方法,,把参数和请求以及类传递下去调用doInvoke方法使用反射对目标方法调用,并且一个Object来接收并返回。

img

接着回到invokeHandlerMethod方法,进行下一步,调用getModelAndView方法对上面获取的ModelAndView对象进行处理。

img

视图渲染细节剖析

此方法就是上面doDispatch方法核心步骤第四步,调用processDispatchResult方法,针对他内部实现进行剖析。

进入方法内部,进行异常判断和非空判断走到render方法进行渲染

img

在方法内部定义了一个视图对象,从getViewName方法中取出视图名称,比如success,如果不为空根据视图名进行内部视图封装方法。

img

在方法内部用视图解析器viewResolver进行封装。在内部的buildView方法根据配置的视图解析器在内部进行组装完整视图名称。

img

img

当完成一系列数据填充后,我们的modelMap中就有了对应数据,这时候他会把里面的数据暴露到request域中,所以当model.add完成之后,jsp就可以直接从请求域中获取数据的原因。完成数据暴露之后就调用RequestDispatcher进行请求分发,根据前面拼接的jsp完整路径调转到对应页面。

img

注意:转发和重定向都会走不同的视图解析,并且视图解析是走缓存的,缓存存在就直接返回,没有才重新创建。

img

四、Spring + Spring MVC + Mybatis整合

整合目标

数据库连接池以及事务管理都交给Spring容器来完成

SqlSessionFactory对象应该放到Spring容器中作为单例对象管理

Mapper动态代理对象交给Spring管理,我们从Spring容器中直接获得Mapper的代理对象

把SpringMVC的⼊⻔案例整合进来

所需jar包

Junit测试jar(4.12版本)

Mybatis的jar(3.4.5)

Spring相关jar(spring-context、spring-test、spring-jdbc、spring-tx、spring-aop、

aspectjweaver)

Mybatis/Spring整合包jar(mybatis-spring-xx.jar)

Mysql数据库驱动jar

Druid数据库连接池的jar

完整整合项目截图

img

具体引入jir包

junit

junit

4.12

test

log4j

log4j

1.2.12

org.mybatis

mybatis

3.4.5

org.springframework

spring-context

5.1.12.RELEASE

org.springframework

spring-test

5.1.12.RELEASE

org.springframework

spring-jdbc

5.1.12.RELEASE

org.springframework

spring-tx

5.1.12.RELEASE

org.springframework

spring-aop

5.1.12.RELEASE

org.aspectj

aspectjweaver

1.8.9

org.mybatis

mybatis-spring

2.0.3

mysql

mysql-connector-java

5.1.46

com.alibaba

druid

1.1.21

org.springframework

spring-webmvc

5.1.12.RELEASE

javax.servlet

jsp-api

2.0

provided

javax.servlet

javax.servlet-api

3.1.0

provided

jstl

jstl

1.2

taglibs

standard

1.1.2

com.fasterxml.jackson.core

jackson-core

2.9.0

com.fasterxml.jackson.core

jackson-databind

2.9.0

com.fasterxml.jackson.core

jackson-annotations

2.9.0

commons-fileupload

commons-fileupload

1.3.1

applicationContext.xml配置

<context:component-scan base-package=”com.lg”/>

<context:property-placeholder location=”classpath:jdbc.properties”/>

<tx:annotation-driven transaction-manager=”transactionManager”>

springmvc.xml配置

<context:component-scan base-package=”com.lg.controller”>

mvc:annotation-driven

<mvc:annotation-driven conversion-service=”conversionServiceBean”>

mvc:default-servlet-handler

<mvc:resources location=”/WEB-INF/js/“ mapping=”/js/**”/>

mvc:interceptors

mvc:interceptor

<mvc:mapping path=”/**”/>

web.xml配置

contextConfigLocation

classpath*:applicationContext.xml

org.springframework.web.context.ContextLoaderListener

springmvc

org.springframework.web.servlet.DispatcherServlet

contextConfigLocation

classpath*:springmvc.xml

springmvc

/*

------ 本文结束感谢您的阅读 ------
请我一杯咖啡吧!
itingyu 微信打赏 微信打赏