Spring Mvc 的原理 理解 使用 笔记
Spring Mvc 它是属于Spring基本架构里面的一个组成部分,属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面,所以我们在后期和 Spring 进行整合的时候,几乎不需要别的什么配置。
什么是Spring Mvc SpringMVC 是类似于 Struts2 的一个 MVC 框架,在实际开发中,接收浏览器的请求响应,对数据进行处理,然后返回页面进行显示,但是上手难度却比 Struts2 简单多了。而且由于 Struts2 所暴露出来的安全问题,SpringMVC 已经成为了大多数企业优先选择的框架。
为什么要学
轻量级
高效,基于请求相应的Mvc框架
与Spring无缝结合
约定优于配置
功能强大,restful、数据验证、格式化、本地化、主题…..
简洁灵活
用的人多 …..
原理 中心控制器介绍 SpringWebMVC框架与许多其他WebMVC框架一样,是请求驱动的,围绕一个中央Servlet设计,该Servlet将请求分派给控制器并提供其他功能以促进web应用程序的开发。 然而,Spring 的 DispatcherServlet 作用不止于此。它与 Spring IoC 容器完全集成,因此允许您使用 Spring 具有的所有其他功能。(比如ioc、aop等等) SpringWebMVC的请求处理工作流程DispatcherServlet如下图所示。精通模式的读者会认识到这 DispatcherServlet是 “前端控制器” 设计模式的一种表达 (这是 Spring Web MVC 与许多其他领先的 Web 框架共享的模式)。
流程
客户端(浏览器)发送请求,直接请求到 DispatcherServlet。
DispatcherServlet 根据请求信息调用 HandlerMapping,解析请求对应的 Handler。
解析到对应的 Handler(也就是我们平常说的 Controller 控制器)后,开始由 HandlerAdapter 适配器处理。
HandlerAdapter 会根据 Handler 来调用真正的处理器开处理请求,并处理相应的业务逻辑。
处理器处理完业务后,会返回一个 ModelAndView 对象,Model 是返回的数据对象,View 是个逻辑上的 View。
ViewResolver 会根据逻辑 View 查找实际的 View。
DispaterServlet 把返回的 Model 传给 View(视图渲染)。
把 View 返回给请求者(浏览器)
DispatcherServlet? 如图所示:DispatcherServlet
是一个实际的 Servlet ,继承自 HttpServlet 。
因此在您需要在您的 Web 应用程序中声明,DispatcherServlet
使用URL映射来映射要处理的请求。
示例 在下面的示例中,所有以/example
开头的请求都将由名为DispatcherServlet
的实例处理。
1 2 3 4 5 6 7 8 9 public class MyWebApplicationInitializer implements WebApplicationInitializer { @Override public void onStartup (ServletContext container) { ServletRegistration.Dynamic registration = container.addServlet("example" , new DispatcherServlet()); registration.setLoadOnStartup(1 ); registration.addMapping("/example/*" ); } }
WebApplicationInitializer
是 SpringMVC 提供的接口,通过简单地指定它的 servlet 映射和列出配置类,可确保检测到基于代码的配置并自动用于初始化任何 Servlet 3 容器。 这个接口的抽象基类实现 AbstractAnnotationConfigDispatcherServletInitializer
使得DispatcherServlet
注册变得更加容易 。 下面是web.xml上述基于代码的示例的等价物:
1 2 3 4 5 6 7 8 9 10 11 12 13 <web-app > <servlet > <servlet-name > example</servlet-name > <servlet-class > org.springframework.web.servlet.DispatcherServlet</servlet-class > <load-on-startup > 1</load-on-startup > </servlet > <servlet-mapping > <servlet-name > example</servlet-name > <url-pattern > /example/*</url-pattern > </servlet-mapping > </web-app >
组件 WebApplicationContext 中的特殊 bean 类型
Bean type
名称
解释
DispatcherServlet
前端控制器
Spring MVC 的入口函数。 接收请求,响应结果,相当于转发器,中央处理器。 有了 DispatcherServlet 减少了其它组件之间的耦合度。 用户请求到达前端控制器,它就相当于mvc模式中的c, DispatcherServlet是整个流程控制的中心,由它调用其它组件处理用户的请求, DispatcherServlet的存在降低了组件之间的耦合性。
HandlerMapping
处理器映射器
根据请求的url查找Handler。 HandlerMapping负责根据用户请求找到Handler即处理器(Controller), SpringMVC提供了不同的映射器实现不同的映射方式。 例如:配置文件方式,实现接口方式,注解方式等。
HandlerAdapter
处理器适配器
按照特定规则(HandlerAdapter要求的规则)去执行Handler 通过HandlerAdapter对处理器进行执行, 这是适配器模式 的应用,通过扩展适配器可以对更多类型的处理器进行执行。
Handler
处理器
写Handler时按照HandlerAdapter的要求去做 这样适配器才可以去正确执行Handler Handler 是继DispatcherServlet前端控制器的后端控制器, 在DispatcherServlet的控制下Handler对具体的用户请求进行处理。 由于Handler涉及到具体的用户业务请求,所以一般情况需要工程师根据业务需求开发Handler
HandlerExceptionResolver
处理异常解析器
将异常映射到视图还允许更复杂的异常处理代码。
ViewResolver
视图解析器
进行视图解析,根据逻辑视图名解析成真正的视图(view) 首先根据逻辑视图名解析成物理视图名(页面地址), 再生成View视图对象, 最后对View进行渲染将结果页面展示给用户。 springmvc框架提供了很多的View视图类型,包括:jstlView、freemarkerView、pdfView等。 一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展示给用户, 需要由工程师根据业务需求开发具体的页面。
LocaleResolver LocaleContextResolver
语言环境解析器
解析客户端正在使用的区域设置以及可能的时区,以便能够提供国际化的视图
ThemeResolver
主题解析器
解决您的 Web 应用程序可以使用的主题,例如,提供个性化布局
MultipartResolver
多部分分解器
例如,解析多部分请求以支持处理从HTML表单上载的文件。
FlashMapManager
Flash地图管理器
存储并检索可用于将一个请求属性传递到另一个请求的input和output的FlashMap,<br/通常用于重定向
使用 写一个复杂的小demo来理解SpringMVC工作流 引入Maven依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 <dependencies > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-web</artifactId > <version > 5.2.12.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-webmvc</artifactId > <version > 5.2.12.RELEASE</version > </dependency > <dependency > <groupId > javax.servlet</groupId > <artifactId > servlet-api</artifactId > <version > 2.5</version > </dependency > <dependency > <groupId > javax.servlet.jsp</groupId > <artifactId > jsp-api</artifactId > <version > 2.2</version > </dependency > <dependency > <groupId > javax.servlet</groupId > <artifactId > jstl</artifactId > <version > 1.2</version > </dependency > </dependencies >
在web.xmi中配置 DispatcherServlet
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <?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_4_0.xsd" version ="4.0" > <servlet > <servlet-name > springmvc</servlet-name > <servlet-class > org.springframework.web.servlet.DispatcherServlet</servlet-class > <init-param > <param-name > contextConfigLocation</param-name > <param-value > classpath:springmvc-servlet.xml</param-value > </init-param > </servlet > <servlet-mapping > <servlet-name > springmvc</servlet-name > <url-pattern > /</url-pattern > </servlet-mapping > </web-app >
新建springmvc-servlet.xml
并配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns ="http://www.springframework.org/schema/beans" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" > <bean class ="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" /> <bean class ="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" /> <bean class ="org.springframework.web.servlet.view.InternalResourceViewResolver" id ="internalResourceViewResolver" > <property name ="prefix" value ="/WEB_NIF/jsp" /> <property name ="suffix" value =".jsp" /> </bean > </beans >
写一个HelloController.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 import org.springframework.web.servlet.ModelAndView;import org.springframework.web.servlet.mvc.Controller;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class HelloController implements Controller { public ModelAndView handleRequest (HttpServletRequest request, HttpServletResponse response) throws Exception { ModelAndView modelAndView = new ModelAndView(); String result = "hello Spring mvc" ; modelAndView.addObject("msg" ,result); modelAndView.setViewName("hello" ); return modelAndView; } }
在 springmvc-servlet.xml 中注配置 HelloController
1 <bean id ="/hello" class ="com.wx.HelloController" />
写一个View
1 2 3 4 5 6 7 8 <html > <head > <title > Hello</title > </head > <body > ${msg} </body > </html >
访问链接http://localhost:8080/hello 结果
使用注解开发 引入依赖: 与上述示例一致 在web.xmi中配置DispatcherServlet: 与上述示例一致 新建springmvc-servlet.xml
并配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <?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:context ="http://www.springframework.org/schema/context" xmlns:mvc ="http://www.springframework.org/schema/mvc" xsi:schemaLocation ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd" > <context:component-scan base-package ="com.wx.controller" /> <mvc:default-servlet-handler /> <mvc:annotation-driven /> <bean class ="org.springframework.web.servlet.view.InternalResourceViewResolver" id ="internalResourceViewResolver" > <property name ="prefix" value ="/WEB-INF/jsp/" /> <property name ="suffix" value =".jsp" /> </bean > </beans >
写一个HelloController.java
1 2 3 4 5 6 7 8 9 10 11 12 13 import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.RequestMapping;@Controller public class HelloController { @RequestMapping("/hello") public String hello (Model model) { model.addAttribute("msg" , "hello,spring mvc annotation" ); return "hello" ; } }
写一个View
1 2 3 4 5 6 7 8 <html > <head > <title > Hello</title > </head > <body > ${msg} </body > </html >
访问链接http://localhost:8080/hello 结果
总结 Controller 控制器复杂提供访问应用程序的行为,通常通过接、定义或注解定义两种方法实现 控制器负责解析用户的请求并将其转换为一个模型 在Spring MVC中一个控制器类可以包含多个方法 在Spring MVC中,对于Controller的配置方式有很多种:
实现接口 实现Controller接口
1 2 3 4 5 6 7 public class HelloController1 implements Controller { public ModelAndView handleRequest (HttpServletRequest request, HttpServletResponse response) throws Exception { ModelAndView mv = new ModelAndView(); mv.addObject("msg" , "hello,spring mvc" ); return mv; } }
在 springmvc-servlet.xml 中注配置 HelloController
1 <bean id ="/hello" class ="com.wx.HelloController" />
注解实现 1 2 3 4 5 6 7 8 9 10 11 <?xml version="1.0" encoding="UTF-8"?> <beans > <context:component-scan base-package ="com.wx.controller" /> <mvc:default-servlet-handler /> <mvc:annotation-driven /> <bean class ="org.springframework.web.servlet.view.InternalResourceViewResolver" id ="internalResourceViewResolver" > <property name ="prefix" value ="/WEB-INF/jsp/" /> <property name ="suffix" value =".jsp" /> </bean > </beans >
-
1 2 3 4 5 6 7 8 @Controller public class HelloController { @RequestMapping("/hello") public String hello (Model model) { model.addAttribute("msg" , "hello,spring mvc annotation" ); return "hello" ; } }
重定向和转发 转发 1 2 3 4 5 6 7 8 9 10 11 @Controller public class HelloController { @RequestMapping("/hello") public String hello () { return "/WEB-INF/jsp/test.jsp" ; } @RequestMapping("/hello2") public String hello () { return "forward:/WEB-INF/jsp/test.jsp" ; } }
重定向 1 2 3 4 5 6 7 @Controller public class HelloController { @RequestMapping("/hello") public String hello () { return "redirect:/WEB-INF/jsp/test.jsp" ; } }
数据处理 接收数据
链接中名称与方法参数名称一致
http://localhost:8080/hello?name=test
1 2 3 4 5 6 7 8 @Controller public class HelloController { @RequestMapping("/hello") public String hello (String name) { System.out.println(name); return "hello" ; } }
链接中名称与方法参数名称不一致
http://localhost:8080/hello?username=test
1 2 3 4 5 6 7 8 @Controller public class HelloController { @RequestMapping("/hello") public String hello (@RequestParam("username") String name) { System.out.println(name); return "hello" ; } }
提交的是一个对象
http://localhost:8080/hello?id=1&username=test
1 2 3 4 5 public class User { private int id; private String username; }
1 2 3 4 5 6 7 8 @Controller public class HelloController { @RequestMapping("/hello") public String hello (User user) { System.out.println(user); return "hello" ; } }
对象会匹配对象中的字段名称,匹配到了就会自动装配对象
返回数据
ModelAndView1 2 3 4 5 6 7 public class HelloController1 implements Controller { public ModelAndView handleRequest (HttpServletRequest request, HttpServletResponse response) throws Exception { ModelAndView mv = new ModelAndView(); mv.addObject("msg" , "hello,spring mvc" ); return mv; } }
Model1 2 3 4 5 6 7 8 @Controller public class HelloController { @RequestMapping("/hello") public String hello (@RequestParam("username") String name,Model model) { model.addAttribute("msg" ,name); return "hello" ; } }
ModelMap1 2 3 4 5 6 7 8 9 @Controller public class HelloController { @RequestMapping("/hello") public String hello (ModelMap modelMap) { modelMap. mv.addAttribute("msg" ,name); return "hello" ; } }
如图我们可以看出: ModelAndView 则是统合了 View 和 ModeMapl 个人认为是 ModelMap 扩展,基本不用。 ModelMap 继承自 LinkedHashMap 所以 ModelMap 可以使用 LinkedHashMap的方法。
乱码过滤器 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <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_4_0.xsd" version ="4.0" > <filter > <filter-name > characterEncodingFilter</filter-name > <filter-class > org.springframework.web.filter.CharacterEncodingFilter</filter-class > <init-param > <param-name > encoding</param-name > <param-value > UTF-8</param-value > </init-param > </filter > <filter-mapping > <filter-name > characterEncodingFilter</filter-name > <url-pattern > /*</url-pattern > </filter-mapping > </web-app >
拦截器 拦截器是Aop思想的具体应用 类似于Servlet开发中的过滤器filter,用于对处理器进行预处理和后处理,卡发着可以定义一些拦截器来实现特定功能。
过滤器 Servlet 规范中的一部分,任何javaweb工程都可以使用 在url-pattern中配置了/*之后可以对所有要访问的资源进行拦截
拦截器 拦截器是Spring《Mvc框架自己的,只有使用了SpringMVC框架的工程才能使用。 拦截器只访问的控制器方法,如果访问的是jsp/html/css/image/js是不会拦截的
自定义拦截器 继承接口 org.springframework.web.servlet.HandlerInterceptor;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 package com.wx.interceotor;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.springframework.web.servlet.HandlerInterceptor;import org.springframework.web.servlet.ModelAndView;public class DiyInterceptor implements HandlerInterceptor { public boolean preHandle (HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("preHandle======" ); return false ; } public void postHandle (HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("postHandle======" ); } public void afterCompletion (HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("afterCompletion======" ); } }
配置拦截器
1 2 3 4 5 6 <mvc:interceptors > <mvc:interceptor > <mvc:mapping path ="/**" /> <bean class ="com.wx.interceotor.DiyInterceptor" /> </mvc:interceptor > </mvc:interceptors >
SSM springmvc + mybatis + mysql 框架整合实战 请移步此文章《SSM框架整合实战》
感谢查阅