SpringMVC笔记

SpringMVC


## 第一章 SpringMVC概述

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4UBPskPW-1641461177888)(C:\Users\屑海\AppData\Roaming\Typora\typora-user-images\1638951290660.png)]

由以上Spring的结构图可以看出,Spring由四大部分组成:Dao部分(DAO与ORM)、AOP部分、Web部分(JEE与WEB)。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2HEBcKhZ-1641461177889)(C:\Users\屑海\AppData\Roaming\Typora\typora-user-images\1638951308710.png)]

SpringMVC执行流程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7GmbB3Eo-1641461177889)(C:\Users\屑海\AppData\Roaming\Typora\typora-user-images\1638951563083.png)]

​ 执行流程简单分析
​ (1)浏览器提交请求到中央调度器
​ (2)中央调度器直接将请求转发给处理器映射器
​ (3)处理器映射器会根据请求,找到处理该请求的处理器,并将其封装为处理器执行链后返回给中央调度器
​ (4)中央调度器根据处理器执行链中的处理器,找到能够执行该处理器的处理器适配器。
​ (5)处理器适配器调用执行处理器
​ (6)处理器将处理结果及要跳转的视图封装到一个对象ModelAndView中,并将其返回给处理器适配器
​ (7)处理器适配器直接将结果返回给中央调度器
​ (8)中央调度器调用视图解析器,将ModelAndView中的视图名称封装为视图对象
​ (9)视图解析器将封装了的视图对象返回给中央调度器
​ (10)中央调度器调用视图对象,让其自己进行渲染,即进行数据填充,形成响应对象
​ (11)中央调度器响应浏览器

Hello SpringMVC–我的第一个SpringMVC程序

导入jar包

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gFQJ9Qx0-1641461177889)(C:\Users\屑海\AppData\Roaming\Typora\typora-user-images\1638951364411.png)]

都是Spring的Jar包,根据此基础添加了:

​ spring-context-support: 包含支持UI模板,邮件服务,缓存Cache等方面的类。

​ spring-webmvc: 对springmvc的实现。

注册中央调度器
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <!--这是前端控制器,在spring-webmvc包里。我们将它写入,这样就可以使用了-->
        <servlet-class>
            org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <!--springmvc的配置文件-->
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
        <!--
    	标记是在Web服务器启动时会创建这个Servlet实例,还是等到使用时再创建
    	它的值必须是一个整数。
        当值大于等于0时,表示容器在启动时就加载并初始化这个Servlet
    		数值越小,该Servlet的优先级就越高,其被创建的也就越早。
     	当值大于等于0且相同时
      		容器会自己选择创建顺序。
     	当值小于0或者没有指定时
      		则表示该Servlet在真正被使用时才会去创建。
   -->
        <load-on-startup>1</load-on-startup>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <!--不能写为/*,最好也不要写为/, 建议写为 *.do 的形式-->
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>
</web-app>
为什么最好写为*.do的形式
		在没有特殊要求的情况下,SpringMVC的重要调度器DispatcherServlet的<url-pattern/>常使用后缀匹配方式,如写为*.do。
​```basic
	这里的url-pattern不能写为/*,因为DispatcherServlet会将动态页面的跳转请求,即向JSP页面的跳转请求也当作是一个普通的Controller请求。重要调度器会调用处理器映射器为其查找相应的处理器。当然是找不到的,所以在这种情况下,所有的JSP页面跳转均会报404错误。
​```

​```mariadb
	最好也不要写为/,因为DispatcherServlet会将向静态资源的获取请求,例如.css、.js、.jpg、.png等资源的获取请求,当作是一个普通的Controller请求。中央调度器会调用处理器为其查找相应的处理器。当然也是找不到的,所以在这种情况下,所有的静态资源获取请求也会包404错误。
​```

​```mariadb
	需求:在welcome.jsp页面中存在一个访问图片的链接。该项目用于演示将<url-pattern/>写为*.do可以访问到图片,而写为/,则无法访问。
​```
SpringMVC配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/tx
       http://www.springframework.org/schema/tx/spring-tx.xsd
       http://www.springframework.org/schema/mvc
       http://www.springframework.org/schema/mvc/spring-mvc.xsd">


</beans>
定义处理器

需要实现Controller接口 它在spring-webmvc包下

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-d6gZl0qg-1641461177890)(C:\Users\屑海\AppData\Roaming\Typora\typora-user-images\1638952636903.png)]

可以在视图解析器里设置 在处理器返回的页面添加前后缀

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P5TgH9LY-1641461177890)(C:\Users\屑海\AppData\Roaming\Typora\typora-user-images\1638952646480.png)]

处理器需要在配置文件下定义

​ [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xacBjFFZ-1641461177890)(C:\Users\屑海\AppData\Roaming\Typora\typora-user-images\1638952528764.png)]

定义web下的目标页面

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PJTidxHZ-1641461177891)(C:\Users\屑海\AppData\Roaming\Typora\typora-user-images\1638952562547.png)]

使用< mvc:resources/>标签

​ 在Spring3.0.4版本后,Spring中定义了专门用于处理静态资源访问请求的处理器ResourceHttpRequestHandler。并且添加了< mvc:resources/>标签,专门用于解决静态资源无法访问问题。需要在springmvc.xml中添加如下形式的配置:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bgUBzbaL-1641461177891)(file:///C:\Users\屑海\AppData\Local\Temp\ksohtml\wpsF634.tmp.jpg)]

​ location 表示静态资源所在目录。

​ mapping 表示对该资源的请求。注意,后面是两个星号**。

​ 该配置会把对该静态资源的访问请求添加到SimpleUrlHandlerMapping的urlMap中,key就是真正与mapping的URI匹配的URI,而value则为静态资源处理器对象ResourcesHttpRequestHandler

第二章 SpringMVC配置文件开发

​ “处理器类是程序员手工定义的、实现了特定接口的类,然后再在SpringMVC配置文件中对该类进行显式的、明确的注册”的开发方式。

​ 当第一个SpringMVC程序写完,我们发现有很多执行流程出现的对象,在程序中并没有写到。因为它们都存在前端控制器里面,虽然我们不需要写这些对象,但是我们还是得了解一下

处理器映射器HandlerMapping

​ HandlerMapping负责根据request请求找到对应的Handler处理器及Interceptor拦截器,并将它们封装在HandlerExecutionChain对象中,返回给中央调度器。
​ 其常用的实现类有两种:
BeanNameUrlHandlerMapping
​ SimpleUrlHandlerMapping

*BeanNameUrlHandlerMapping

​ BeanNameUrlHandlerMappging处理器映射器,会根据请求的url与spring容器中定义的处理器bean的name(id属性)属性值进行匹配,从而在spring容器中找到处理器bean实例。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BMGFRp3D-1641461177892)(file:///C:\Users\屑海\AppData\Local\Temp\ksohtml\wpsC7E4.tmp.jpg)]

​ 打开类的源码,**从处理器映射器的方法可以看出,对于处理器的Bean的名称,必须以“/”开头,否则无法加入到urls集合中。urls集合中的url则是中央调度器用于判定“该url所对应的类是否作为处理器交给处理器适配器进行适配”的依据。**这也是处理器与其他普通Bean的区别。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-drIhJ57s-1641461177892)(C:\Users\屑海\AppData\Roaming\Typora\typora-user-images\1638953667392.png)]

SimpleUrlHandlerMapping

​ 使用BeanNameUrlHandlerMapping映射器有两点明显不足:

	处理器Bean的id为一个url请求路径,而不是Bean的名称,有些不伦不类。

	处理器Bean的定义与请求url绑定在了一起。若出现多个url请求同一个处理器的情况,就需要在Spring容器中配置多个该处理器类的<Bean/>。这将导致容器会创建多个该处理器类实例。

​ SimpleUrlHandlerMapping处理器映射器,不仅可以将url与处理器的定义分离,还可以对url进行统一映射管理。

​ SimpleUrlHandlerMapping处理器映射器,会根据请求的url与spring容器中定义的处理器子标签的key属性进行匹配。匹配上后,再将该key的value值与处理器bean的id值进行匹配,从而在spring容器中找到处理器bean。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3qXufY6I-1641461177892)(C:\Users\屑海\AppData\Roaming\Typora\typora-user-images\1638953758714.png)]

处理器适配器HandlerAdapter

​ 适配器模式解决的问题是,使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作。

​ 所以处理器适配器所起的作用是:将多种处理器(实现了不同接口的处理器),通过处理器适配器的适配,使它们可以进行统一标准的工作,对请求进行统一方式的处理。

​ 只所以要将Handler定义为Controller接口的实现类,就是因为这里使用的处理器适配器是SimpleControllerHandlerAdapter。打开其源码,可以看到将handler强转为了Controller。在定义Handler时,若不将其定义为Controller接口的实现类,这里的强转要出错的。

​ 当然,中央调度器首先会调用该适配器的supports()方法,判断该handler是否与Controller具有is-a关系。在具有is-a关系的前提下,才会强转。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eYxulc5w-1641461177892)(C:\Users\屑海\AppData\Roaming\Typora\typora-user-images\1638953950380.png)]

HandlerAdapter接口会根据处理器所实现接口的不同,对处理器进行适配,适配后即可对处理器进行执行。通过扩展处理器适配器,可以指定多种类型的处理器。常用的HandlerAdapter接口实现类有两种:

SimpleControllerHandlerAdapter

所有实现了Controller接口的处理器Bean,均是通过此适配器进行适配、执行的。

Controller接口中有一个方法:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3tG8oQh1-1641461177893)(file:///C:\Users\屑海\AppData\Local\Temp\ksohtml\wps9E76.tmp.jpg)]

该方法用于处理用户提交的请求。通过调用Service层代码,实现对用户请求的计算响应 ,并最终将计算所得数据及要响应的页面,封装为一个对象ModelAndView,返回给中央调度器。

HttpRequestHandlerAdapter

​ **所有实现了HttpRequestHandler接口的处理器Bean,均是通过此适配器进行适配、执行的。**HttpRequestHandler接口中有一个方法:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hDVkRayR-1641461177893)(file:///C:\Users\屑海\AppData\Local\Temp\ksohtml\wpsE19B.tmp.jpg)]

该方法没有返回值,不能向ModelAndView一样,将数据及目标视图封装为一个对象。

但可以将数据直接放入到request、session等域属性中,并由request或response完成到目标页面的跳转。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VxIbtd9d-1641461177893)(file:///C:\Users\屑海\AppData\Local\Temp\ksohtml\wpsE19C.tmp.jpg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pvlmElNF-1641461177893)(C:\Users\屑海\AppData\Roaming\Typora\typora-user-images\1638954000528.png)]

处理器

​ 处理器除了实现Controller接口外,还可以继承自一些其他的类来完成一些特殊的功能。

处理器若继承自AbstractController类

​ 若处理器继承自AbstractController类,那么该控制器就具有了一些新的功能。因为AbstractController类还继承自一个父类WebContentGenerator。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j4lXM69L-1641461177894)(file:///C:\Users\屑海\AppData\Local\Temp\ksohtml\wps6813.tmp.jpg)]

​ WebContentGenerator类具有supportedMethod属性,可以设置支持的HTTP数据提交方式。

默认支持GET、POST。(必须大写)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Xk6EO9ui-1641461177894)(C:\Users\屑海\AppData\Roaming\Typora\typora-user-images\1638955256179.png)]

​ 那就意味着该请求只能通过表单或AJAX请求方式进行提交而不能通过地址栏、超链接、HTML标签中的src方式进行提交。因为地址栏、超链接、HTML标签中的src方式都是GET提交。否则,会给出请求方式不允许的405错误

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-awBUYt6T-1641461177894)(file:///C:\Users\屑海\AppData\Local\Temp\ksohtml\wps7B04.tmp.jpg)]

​ 若处理器继承自AbstractController类,那么处理器就可以通过属性supportedMethods来限制HTTP请求提交方式了。例如,指定只支持POST的HTTP请求提交方式。

​ 不过,需要注意的是,AbstractController类中有一个抽象方法需要实现:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eIuWfWoZ-1641461177894)(file:///C:\Users\屑海\AppData\Local\Temp\ksohtml\wpsE067.tmp.jpg)]

AbstractController类实现了Controller接口

​ 即定义处理器时,就需要实现其抽象方法handleRequestInternal()。那么我们的处理器中实现的这个方法是什么时候被调用执行的呢?

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0u1aVknt-1641461177895)(file:///C:\Users\屑海\AppData\Local\Temp\ksohtml\wpsE068.tmp.jpg)]

所以AbstractController类就实现了Controller接口的handleRequest()方法。但查看AbstractController类的handleRequest()方法源码,发现该方法最终返回的却是抽象方法handleRequestInternal()。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JIFd2Hdy-1641461177895)(file:///C:\Users\屑海\AppData\Local\Temp\ksohtml\wpsFB2A.tmp.jpg)]

AbstractController抽象类的实现类即我们自定义的子类,实现了该抽象方法。即,我们自定义的处理器的处理器方法handleRequestInternal()最终被AbstractController类的handleRequest()方法调用执行。而AbstractController类的handleRequest()方法就是被处理器适配器调用执行的。

处理器若继承自MultiActionController类

MultiActionController类继承自AbstractController,所以继承自MultiActionController类的子类也可以设置HTTP请求提交方式。

除此之外,继承自类的处理器中可以定义多个处理器方法。这些方法的签名为公共的方法,返回值为ModelAndView,包含参数HttpServletRequest与HttpServletResponse,抛出Exception异常,方法名随意。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ayTsHljJ-1641461177895)(file:///C:\Users\屑海\AppData\Local\Temp\ksohtml\wps660B.tmp.jpg)]

注意处理器类的映射路径的写法:要求必须以/xxx/的路径方式定义映射路径。其中为通配符,在访问时使用要访问的方法名代替。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cBU43pq9-1641461177895)(file:///C:\Users\屑海\AppData\Local\Temp\ksohtml\wps661B.tmp.jpg)]

对doFirst()方法的访问请求是:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XUc8T8tI-1641461177896)(file:///C:\Users\屑海\AppData\Local\Temp\ksohtml\wps661C.tmp.jpg)]

对doSecond()方法的访问请求时:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tSRRzu2j-1641461177896)(file:///C:\Users\屑海\AppData\Local\Temp\ksohtml\wps661D.tmp.jpg)]

之所以通过在请求URI中写上方法名就可以访问到指定方法,是因为在MultiActionController类中有一个专门处理方法名称的解析器MethodNameResolver。该解析器作为一个属性出现,具有get与set方法。

MethodNameResolver是一个接口,不同的解析器实现类,其对方法名在URI中的写法要求也是不同的。

InternalPathMethodNameResolver方法名解析器(默认)

MultiActionController类具有一个默认的MethodNameResolver解析器。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EXkQivxp-1641461177896)(file:///C:\Users\屑海\AppData\Local\Temp\ksohtml\wpsA68E.tmp.jpg)]

该方法名解析器要求方法名以URI中资源名称的身份出现,即方法名作为一种可以被请求的资源出现。也就是前面的写法:/xxx/方法名。

PropertiesMethodNameResolver方法名解析器

该方法名解析器中的方法名是作为资源名称中的一部分出现的,即方法名并非单独作为一种资源名称出现。例如请求时可以写为/xxx_doFirst,则会访问xxx所映射的处理器的doFirst()方法。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hO0sB9fY-1641461177896)(file:///C:\Users\屑海\AppData\Local\Temp\ksohtml\wpsA68F.tmp.jpg)]

对doFirst()方法的访问请求是:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xprnaEKx-1641461177897)(file:///C:\Users\屑海\AppData\Local\Temp\ksohtml\wpsA690.tmp.jpg)]

ParameterMethodNameResolver方法名解析器

该方法名解析器中的方法名作为请求参数的值出现。例如请求时可以写为/xxx?ooo=doFirst,则会访问xxx所映射的处理器的doFirst()方法。其中ooo为该请求所携带的参数名,而doFirst则作为其参数值出现。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZYSoCnis-1641461177897)(file:///C:\Users\屑海\AppData\Local\Temp\ksohtml\wpsA691.tmp.jpg)]

对doFirst()方法的访问请求是:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yOYDxPRz-1641461177897)(file:///C:\Users\屑海\AppData\Local\Temp\ksohtml\wpsA692.tmp.jpg)]

不过,打开ParameterMethodNameResolver源码,发现该类中有一个默认的参数action。即若不指定参数名称,则可以使用action作为参数。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MhFq8aMC-1641461177897)(file:///C:\Users\屑海\AppData\Local\Temp\ksohtml\wpsA693.tmp.jpg)]

也就是说,对于方法名称解析器ParameterMethodNameResolver的注册,可以修改为如下形式,即不指定paramName的属性值:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FrYbpxtd-1641461177897)(file:///C:\Users\屑海\AppData\Local\Temp\ksohtml\wpsA694.tmp.jpg)]

对doFirst()方法的访问请求是:

[

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值